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
| Chave | Tipo | Vale para | Significado |
|---|---|---|---|
command | string | stdio | Executável a iniciar |
args | lista | stdio | Argumentos do subprocesso |
env | mapa | stdio | Ambiente passado ao subprocesso |
url | string | HTTP | Endpoint MCP remoto |
headers | mapa | HTTP | Cabeçalhos das requisições ao servidor remoto |
ssl_verify | booleano ou string | HTTP | Verificaçã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_cert | string ou lista | HTTP | Certificado 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_key | string | HTTP | Caminho da chave privada do cliente, quando client_cert é uma string e a chave está em arquivo separado |
enabled | booleano | ambos | Ignora o servidor por completo quando for false |
timeout | número | ambos | Tempo limite da chamada de ferramenta, em segundos (padrão: 300) |
connect_timeout | número | ambos | Tempo limite da conexão inicial, em segundos (padrão: 60) |
protocol | string | ambos | Negociaçã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_calls | booleano | ambos | Permite que as ferramentas deste servidor rodem em paralelo |
skip_preflight | booleano | HTTP | Pula 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) |
transport | string | HTTP | Defina como sse para usar o transporte SSE em vez do Streamable HTTP |
keepalive_interval | número | ambos | Cadê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_seconds | número | stdio | Reciclagem opcional do servidor stdio depois de um tempo ocioso (0 desliga). Também pode ficar sob um mapa lifecycle: |
max_lifetime_seconds | número | stdio | Reciclagem opcional do servidor stdio por idade (0 desliga). Também pode ficar sob um mapa lifecycle: |
tools | mapa | ambos | Política de filtragem e de ferramentas utilitárias |
auth | string | HTTP | Método de autenticação. Defina como oauth para habilitar OAuth 2.1 com PKCE |
sampling | mapa | ambos | Política de requisições de LLM iniciadas pelo servidor (veja o guia de MCP) |
elicitation | mapa | ambos | Pedidos 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) |
trust | string | ambos | Ní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ável | Resolve 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
| Chave | Tipo | Significado |
|---|---|---|
include | string ou lista | Lista de permissão das ferramentas MCP nativas do servidor. As entradas podem ser nomes exatos ou globs no estilo fnmatch (*_radar_*, get_zones_*) |
exclude | string ou lista | Lista de bloqueio das ferramentas MCP nativas do servidor. Mesma semântica de nome exato / glob do include |
resources | tipo booleano | Habilita/desabilita list_resources + read_resource |
prompts | tipo booleano | Habilita/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_issuecontinua permitidadelete_issueé ignorada, porqueincludetem precedência
Política de ferramentas utilitárias
O Hermes pode registrar estes invólucros utilitários por servidor MCP:
Recursos:
list_resourcesread_resource
Prompts:
list_promptsget_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: falsedesliga 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_issuemcp__filesystem__read_filemcp__my_api__query_data
As ferramentas utilitárias seguem o mesmo padrão de prefixo:
mcp__<server>__list_resourcesmcp__<server>__read_resourcemcp__<server>__list_promptsmcp__<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>.jsone 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_idjá registrado, umoauth.client_secret, umoauth.client_nameouoauth.token_endpoint_auth_methodpersonalizado, umoauth.redirect_uriouoauth.redirect_portsobrescrito, 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.
Link "Add to Hermes"
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 stringurl(sóhttp:///https://) ou um campo stringcommand, 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.