Pular para o conteúdo principal

Documentação oficial desta página · v0.20.6

Referência de Configuração do MCP

Esta página é a referência compacta que acompanha a documentação principal de MCP.

Para a parte conceitual, veja:

Formato da configuração raiz​

mcp_servers:
<nome_do_servidor>:
command: "..." # servidores stdio
args: []
env: {}

# OU
url: "..." # servidores HTTP
headers: {}

# Opções de TLS para HTTP/SSE (opcionais):
ssl_verify: true # booleano ou caminho de um pacote de CAs (PEM)
client_cert: "/caminho/do/cert.pem" # certificado de cliente para mTLS (veja abaixo)
# client_key: "/caminho/da/key.pem" # opcional, quando a chave fica em arquivo separado

enabled: true
timeout: 120
connect_timeout: 60
supports_parallel_tool_calls: false
tools:
include: []
exclude: []
resources: true
prompts: true

Chaves do servidor​

ChaveTipoVale paraSignificado
commandstringstdioExecutável a iniciar
argslistastdioArgumentos do subprocesso
envmapastdioAmbiente passado ao subprocesso
urlstringHTTPEndpoint MCP remoto
headersmapaHTTPCabeçalhos das requisições ao servidor remoto
ssl_verifybooleano ou stringHTTPVerificação de TLS. true (padrão) usa as CAs do sistema, false desliga a verificação (inseguro), ou uma string com o caminho de um pacote de CAs próprio (PEM)
client_certstring ou listaHTTPCertificado de cliente para mTLS. String = caminho de um arquivo PEM com certificado + chave. Lista [cert, key] = arquivos separados. Lista [cert, key, password] = chave criptografada
client_keystringHTTPCaminho da chave privada do cliente, quando client_cert é uma string e a chave está em arquivo separado
enabledbooleanoambosIgnora o servidor por completo quando for false
timeoutnúmeroambosTempo limite da chamada de ferramenta, em segundos (padrão: 300)
connect_timeoutnúmeroambosTempo limite da conexão inicial, em segundos (padrão: 60)
protocolstringambosNegociação de era do protocolo: auto (padrão — tenta primeiro o handshake initialize antigo e cai para a sondagem sem estado server/discover de 2026-07-28 quando o servidor rejeita o handshake por só aceitar o formato moderno), stateless (sonda server/discover primeiro; uma retentativa no formato antigo) ou legacy (só o handshake, sem alternativa)
supports_parallel_tool_callsbooleanoambosPermite que as ferramentas deste servidor rodem em paralelo
skip_preflightbooleanoHTTPPula a sondagem de content-type que falha rápido, para endpoints Streamable HTTP válidos cujo HEAD/GET responde com um content-type que não é de MCP (padrão: false)
transportstringHTTPDefina como sse para usar o transporte SSE em vez do Streamable HTTP
keepalive_intervalnúmeroambosCadência do ping de vivacidade, em segundos (padrão: 180, com piso de 5s). Deixe abaixo do TTL de sessão do servidor, para servidores que descartam sessões ociosas rápido
idle_timeout_secondsnúmerostdioReciclagem opcional do servidor stdio depois de um tempo ocioso (0 desliga). Também pode ficar sob um mapa lifecycle:
max_lifetime_secondsnúmerostdioReciclagem opcional do servidor stdio por idade (0 desliga). Também pode ficar sob um mapa lifecycle:
toolsmapaambosPolítica de filtragem e de ferramentas utilitárias
authstringHTTPMétodo de autenticação. Defina como oauth para habilitar OAuth 2.1 com PKCE
samplingmapaambosPolítica de requisições de LLM iniciadas pelo servidor (veja o guia de MCP)
elicitationmapaambosPedidos de entrada do usuário iniciados pelo servidor. enabled (padrão true) e timeout em segundos (padrão 300). Pedidos em modo de formulário passam pela superfície de aprovação; o modo de URL é recusado (veja o guia de MCP)
truststringambosNível de confiança: full (padrão) ou untrusted. Em um servidor untrusted, toda chamada de ferramenta capaz de escrever (qualquer ferramenta sem a anotação readOnlyHint: true) exige aprovação do usuário pela superfície de aprovação padrão antes de rodar. O readOnlyHint é uma dica fornecida pelo servidor — um servidor mentiroso, no máximo, pula a aprovação de ferramentas que ele diz serem só de leitura, nunca ganha acesso extra — então marque como untrusted qualquer servidor que não esteja totalmente sob o seu controle. Valores desconhecidos são tratados como untrusted (falha fechada)

Referências a variáveis de ambiente​

Valores de string em qualquer ponto da entrada de um servidor (env, headers, args, url, …) podem referenciar variáveis de ambiente com ${VAR} ou com a forma SecretRef no estilo do Cursor, ${env:VAR} — as duas resolvem para a mesma variável, então trechos de MCP copiados de configurações do Cursor / do Claude funcionam sem mudança:

mcp_servers:
github:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-github"]
env:
GITHUB_PERSONAL_ACCESS_TOKEN: "${env:GITHUB_TOKEN}" # o mesmo que "${GITHUB_TOKEN}"

Os valores resolvem a partir do escopo de segredos do perfil ativo (caindo para o ambiente do processo), então coloque o segredo em ~/.hermes/.env. Uma variável não definida mantém o placeholder literal.

Variáveis de contexto​

Além das variáveis de ambiente, as variáveis de contexto no estilo do Cursor também são interpoladas (os nomes diferenciam maiúsculas de minúsculas):

VariávelResolve para
${userHome}O diretório home do usuário atual
${workspaceFolder}A raiz do espaço de trabalho da sessão (o cwd do terminal da sessão quando conhecido, senão o cwd do processo)
${workspaceFolderBasename}O nome final de ${workspaceFolder}
${pathSeparator} / ${/}O separador de caminho do sistema (os.sep)
mcp_servers:
filesystem:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "${workspaceFolder}"]
env:
CACHE_DIR: "${userHome}${/}.cache${/}mcp"

Qualquer outra referência ${...} cai na busca por variável de ambiente descrita acima.

Chaves da política tools​

ChaveTipoSignificado
includestring ou listaLista de permissão das ferramentas MCP nativas do servidor. As entradas podem ser nomes exatos ou globs no estilo fnmatch (*_radar_*, get_zones_*)
excludestring ou listaLista de bloqueio das ferramentas MCP nativas do servidor. Mesma semântica de nome exato / glob do include
resourcestipo booleanoHabilita/desabilita list_resources + read_resource
promptstipo booleanoHabilita/desabilita list_prompts + get_prompt

Semântica da filtragem​

include​

Se include estiver definido, só aquelas ferramentas MCP nativas do servidor são registradas.

tools:
include: [create_issue, list_issues]

exclude​

Se exclude estiver definido e include não, toda ferramenta MCP nativa do servidor é registrada, menos aqueles nomes.

tools:
exclude: [delete_customer]

Precedência​

Se os dois estiverem definidos, include vence.

tools:
include: [create_issue]
exclude: [create_issue, delete_issue]

Resultado:

  • create_issue continua permitida
  • delete_issue é ignorada, porque include tem precedência

Política de ferramentas utilitárias​

O Hermes pode registrar estes invólucros utilitários por servidor MCP:

Recursos:

  • list_resources
  • read_resource

Prompts:

  • list_prompts
  • get_prompt

Desabilitar recursos​

tools:
resources: false

Desabilitar prompts​

tools:
prompts: false

Registro consciente de capacidades​

Mesmo com resources: true ou prompts: true, o Hermes só registra essas ferramentas utilitárias se a sessão MCP de fato expuser a capacidade correspondente.

Então isto é normal:

  • você habilita prompts
  • mas nenhum utilitário de prompt aparece
  • porque o servidor não suporta prompts

enabled: false​

mcp_servers:
legacy:
url: "https://mcp.legacy.internal"
enabled: false

Comportamento:

  • nenhuma tentativa de conexão
  • nenhuma descoberta
  • nenhum registro de ferramenta
  • a configuração continua no lugar, para uso posterior

Comportamento com resultado vazio​

Se a filtragem remover todas as ferramentas nativas do servidor e nenhuma ferramenta utilitária for registrada, o Hermes não cria um conjunto de ferramentas MCP vazio para aquele servidor.

Exemplos de configuração​

Lista de permissão segura para o GitHub​

mcp_servers:
github:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-github"]
env:
GITHUB_PERSONAL_ACCESS_TOKEN: "***"
tools:
include: [list_issues, create_issue, update_issue, search_code]
resources: false
prompts: false

Lista de bloqueio no Stripe​

mcp_servers:
stripe:
url: "https://mcp.stripe.com"
headers:
Authorization: "Bearer ***"
tools:
exclude: [delete_customer, refund_payment]

Servidor de documentação só com recursos​

mcp_servers:
docs:
url: "https://mcp.docs.example.com"
tools:
include: []
resources: true
prompts: false

Certificado de cliente TLS (mTLS)​

Para servidores HTTP/SSE que exigem certificado de cliente, defina client_cert (e, se precisar, client_key):

mcp_servers:
# Certificado + chave juntos em um único arquivo PEM
internal_api:
url: "https://mcp.internal.example.com/mcp"
client_cert: "~/secrets/mcp-client.pem"

# Arquivos separados de certificado e chave
partner_api:
url: "https://mcp.partner.example.com/mcp"
client_cert: "~/secrets/client.crt"
client_key: "~/secrets/client.key"

# Chave criptografada com senha (forma de lista com 3 elementos)
bank_api:
url: "https://mcp.bank.example.com/mcp"
client_cert: ["~/secrets/client.crt", "~/secrets/client.key", "minha-senha"]

# Pacote de CAs próprio (CA privada / servidor autoassinado)
lab_api:
url: "https://mcp.lab.local/mcp"
ssl_verify: "~/secrets/lab-ca.pem"
client_cert: "~/secrets/lab-client.pem"

Observações:

  • Os caminhos aceitam expansão de ~. Arquivos que não existem falham logo na conexão, com uma mensagem de erro por servidor.
  • ssl_verify: false desliga por completo a verificação do certificado do servidor. Não use isso com serviços de verdade.
  • Funciona tanto no transporte Streamable HTTP quanto no SSE.

Recarregar a configuração​

Depois de mudar a configuração de MCP, recarregue os servidores com:

/reload-mcp

Nomes das ferramentas​

As ferramentas MCP nativas do servidor viram:

mcp__<server>__<tool>

Exemplos:

  • mcp__github__create_issue
  • mcp__filesystem__read_file
  • mcp__my_api__query_data

As ferramentas utilitárias seguem o mesmo padrão de prefixo:

  • mcp__<server>__list_resources
  • mcp__<server>__read_resource
  • mcp__<server>__list_prompts
  • mcp__<server>__get_prompt

O delimitador de underscore duplo (mcp__…__…) segue a convenção usada por Claude Code, Codex e OpenCode, e deixa clara a fronteira entre servidor e ferramenta mesmo quando um dos dois tem underscore no nome.

Saneamento de nomes​

Todo caractere que não seja letra, dígito ou underscore (hífen, ponto, espaço, etc.), tanto em nomes de servidor quanto de ferramenta, é trocado por underscore antes do registro. Isso garante que os nomes de ferramenta sejam identificadores válidos para as APIs de chamada de função dos LLMs.

Por exemplo, um servidor chamado my-api que expõe uma ferramenta chamada list-items.v2 vira:

mcp__my_api__list_items_v2

Tenha isso em mente ao escrever filtros include / exclude — use o nome original da ferramenta MCP (com hífen/ponto), não a versão saneada.

Autenticação OAuth 2.1​

Para servidores HTTP que exigem OAuth, defina auth: oauth na entrada do servidor:

mcp_servers:
protected_api:
url: "https://mcp.example.com/mcp"
auth: oauth

Comportamento:

  • O Hermes usa o fluxo OAuth 2.1 com PKCE do SDK do MCP (descoberta de metadados, identificação do cliente, troca de token e renovação)
  • Na primeira conexão, abre uma janela do navegador para autorização
  • Os tokens são gravados em ~/.hermes/mcp-tokens/<server>.json e reaproveitados entre sessões
  • A renovação de token é automática; a reautorização só acontece quando a renovação falha
  • Só vale para o transporte HTTP/StreamableHTTP (servidores baseados em url)

Identificação do cliente: CIMD e DCR​

O Hermes se identifica para os servidores de autorização com um Client ID Metadata Document (CIMD), o mecanismo que a especificação MCP 2026-07-28 adotou no lugar do Dynamic Client Registration. O documento é publicado em https://nousresearch.github.io/hermes-agent/docs/oauth/client-metadata.json, e essa URL é o client_id — o servidor de autorização busca ela para descobrir o nome, o logo e as URIs de redirecionamento permitidas do Hermes. Nada é registrado por instalação, e nada é específico do usuário.

A escolha final é do servidor de autorização: o SDK manda a URL do documento como client_id só quando o servidor anuncia client_id_metadata_document_supported: true nos metadados dele, e nos outros casos registra por DCR exatamente como antes. O DCR está descontinuado na especificação do MCP, mas ainda é o que quase todo servidor em produção usa hoje.

Portas de callback​

O documento declara um conjunto fixo de URIs de redirecionamento de loopback, e a especificação exige que a URI de redirecionamento em uma requisição de autorização seja uma correspondência exata de string com uma delas — então um fluxo CIMD não pode usar a porta alta aleatória que o Hermes normalmente escolhe. Por isso o Hermes fixa o callback em uma das portas 27890–27894.

Essa fixação precisa ser escolhida antes de as capacidades do servidor serem conhecidas, porque a URI de redirecionamento é definida no começo do fluxo enquanto os metadados do servidor só chegam no meio do caminho. Então o Hermes fixa a porta em todo fluxo que possa acabar usando CIMD, e volta para uma porta aleatória nos demais:

  • Um servidor ao qual o Hermes já se conectou antes, e cujos metadados em cache não anunciam CIMD, mantém a porta aleatória que sempre usou.
  • Um servidor que o Hermes nunca alcançou ganha uma porta fixa nesse primeiro login, já que chutar é o único jeito de o CIMD chegar a ser usado.
  • Qualquer coisa que mudaria o callback de lugar também faz voltar: um oauth.client_id já registrado, um oauth.client_secret, um oauth.client_name ou oauth.token_endpoint_auth_method personalizado, um oauth.redirect_uri ou oauth.redirect_port sobrescrito, um login vindo do painel ou do desktop, um registro de cliente já existente em disco, ou as cinco portas ocupadas por outros processos.

Cada porta fixada é reservada assim que é escolhida e mantida até o redirecionamento do navegador chegar, então dois logins simultâneos — um segundo perfil, ou outro servidor no mesmo processo — não caem no mesmo ouvinte.

Quando um servidor rejeita o documento​

Se um servidor busca o documento e recusa ele no endpoint de token (invalid_client), o Hermes registra a rejeição, anota em ~/.hermes/mcp-tokens/<server>.cimd-off e passa a usar DCR para aquele servidor dali em diante.

Um servidor que não consegue nem buscar nem validar o documento aborta antes, no endpoint de autorização, sem nenhum redirecionamento. Não há sinal que o Hermes consiga observar ali, então o navegador mostra um erro de cliente inválido e o login expira depois de cinco minutos. A mensagem de expiração cita o documento e aponta para cimd: false. Rodar hermes mcp login <server> limpa a rejeição registrada, então um documento corrigido ganha outra chance.

Chaves opcionais por servidor​

mcp_servers:
protected_api:
url: "https://mcp.example.com/mcp"
auth: oauth
oauth:
client_metadata_url: "https://example.com/my-cimd.json" # documento hospedado por você
cimd: false # força o DCR
user_agent: "My-MCP-Client/1.0" # User-Agent das requisições de token

O client_metadata_url tem que ser uma URL HTTPS com caminho (sem origem pelada, sem fragmento, sem userinfo, sem segmentos ./..) que devolva 200 e Content-Type: application/json sem redirecionamento — servidores de autorização são proibidos de seguir redirecionamentos ao buscar ela. O Hermes continua fixando o callback na mesma faixa 27890–27894, então um documento hospedado por você precisa declarar todas as dez URIs de loopback (http://127.0.0.1:<port>/callback e http://localhost:<port>/callback para cada porta), e o client_id dele tem que ser a própria URL.

O user_agent substitui o User-Agent padrão da biblioteca HTTP só nas requisições ao endpoint de token (troca do código de autorização e renovação) — alguns servidores de autorização e WAFs rejeitam ali o valor padrão python-httpx/.... Ele nunca vale para o tráfego MCP nem para a descoberta de OAuth, e nenhum outro cabeçalho da requisição de token é configurável. Valores vazios ou nulos são ignorados.

Fornecedores e sites de documentação de MCP podem oferecer um botão de um clique "Add to Hermes" que abre o aplicativo desktop do Hermes com a configuração do servidor já preenchida, espelhando o esquema cursor://anysphere.cursor-deeplink/mcp/install do Cursor:

hermes://mcp/install?name=NAME&config=BASE64
  • name — o nome do servidor. Tem que casar com ^[A-Za-z0-9._-]{1,64}$.
  • config — o objeto de configuração do servidor como JSON codificado em base64url (base64 padrão também é aceito). O JSON decodificado tem que ser um objeto com um campo string url (só http:///https://) ou um campo string command, e pode trazer qualquer uma das chaves de servidor documentadas acima. Payloads acima de 32KB são rejeitados.

Exemplo (JavaScript):

const config = { url: 'https://mcp.example.com/mcp' }
const link = `hermes://mcp/install?name=example&config=${btoa(JSON.stringify(config))
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')}`

Abrir o link nunca instala nada por conta própria: o aplicativo desktop mostra um diálogo de confirmação com o nome do servidor e a configuração completa formatada (com um aviso extra para servidores baseados em command, que rodam um processo local), e o usuário precisa confirmar explicitamente. Nomes de servidor já existentes nunca são sobrescritos — o usuário é convidado a renomear ou cancelar.