Onde guardar as chaves de um servidor MCP sem commitar segredo no repositório?

Configuração de servidor MCP pode ser versionada, credencial não. No Claude Code o escopo project grava um .mcp.json na raiz do repositório (feito pra ser compartilhado), enquanto local e user ficam no ~/.claude.json, fora do projeto. A saída pra guardar chaves MCP em time é deixar no arquivo commitado só a referência ${VAR}, que o Claude Code expande em command, args, env, url e headers, e cada dev define a própria variável na máquina dele. Fecha a conta plugando o Gitleaks no pre-commit pra barrar segredo antes do commit.
Chave de API vazada é aquele erro silencioso: ela não quebra nada no seu dia, ela só aparece depois, quando o repo já foi clonado por meio time
E configurar um servidor MCP é o cenário perfeito pra isso acontecer, porque a configuração mistura duas coisas de naturezas totalmente diferentes
De um lado tem o que o time PRECISA compartilhar: nome do servidor, comando que sobe ele, endpoint, argumentos
Do outro tem a credencial, que é individual, e que jamais deveria sair da máquina de cada pessoa
O .mcp.json é justamente onde essas duas coisas se encontram… por isso ele é o arquivo mais fácil de estragar num projeto que usa MCP
Bora separar o que é do projeto do que é da máquina?
Escopos de MCP no Claude Code: local, project e user
Antes de decidir onde a chave vai morar, tu precisa saber onde cada configuração é gravada
O Claude Code organiza os servidores MCP em três escopos, e cada um vive num lugar diferente do disco:
| Escopo | Onde é gravado | Vai pro Git? | Quem enxerga | Como registrar |
|---|---|---|---|---|
| local | ~/.claude.json, dentro do objeto projects | Não, está fora do repositório | Só você, naquele projeto | é o padrão, não precisa de flag |
| project | .mcp.json na raiz do projeto | Sim, é feito pra ser versionado e compartilhado | Todo mundo que clonar o repo | –scope project |
| user | ~/.claude.json, no nível raiz do arquivo | Não, está fora do repositório | Só você, em todos os projetos | –scope user |
Formação Claude Code
Domine Claude Code do absoluto zero até o avançado
- 120 aulas
- 4 projetos
- 9h 45min
E quando o mesmo nome de servidor aparece em mais de um escopo, existe uma ordem de precedência: local vence project, que vence user
Se liga no que essa tabela está dizendo na real: só o escopo project cria arquivo DENTRO do repositório
Então a regra nasce sozinha: .mcp.json é lugar de configuração, nunca de segredo 🙂
O que você precisa antes de começar
Nada aqui exige plano específico nem ferramenta paga, é tudo arquivo de texto e variável de ambiente
- Claude Code instalado e um projeto com Git inicializado
- A chave do serviço em mãos (a que o servidor MCP vai usar pra autenticar)
- Acesso ao arquivo de perfil do seu shell, pra exportar variáveis de ambiente
- O .gitignore do projeto aberto, porque tu vai mexer nele
E um combinado que vale pro post inteiro: o valor do segredo nunca é digitado dentro de arquivo versionado
Ele mora no ambiente da sua máquina, e o arquivo compartilhado só aponta pra ele
Se o teu caso é o contrário, ou seja, tu nem quer configurar servidor por servidor, dá uma olhada em como funcionam os MCPs já embutidos no agente antes de montar tudo na mão
Como configurar um servidor MCP sem escrever a chave no repositório
- Exporte a chave como variável de ambiente
Primeiro o segredo vira variável, no ambiente onde tu abre o Claude Code:
export MINHA_API_KEY="cole-aqui-o-valor-da-sua-chave"
Pra não repetir isso toda vez, joga a linha no arquivo de perfil do teu shell (.bashrc, .zshrc, o que tu usar)
Erro comum deste passo: criar a variável só na sessão do terminal atual e esquecer do perfil, aí amanhã tu abre outro terminal e o servidor não conecta
- Registre o servidor no escopo certo
O claude mcp add grava em escopo local por padrão, que é o que tu quer quando a configuração é só tua
Se o time inteiro precisa do mesmo servidor, aí sim entra a flag:
claude mcp add --scope project
Isso gera o .mcp.json na raiz do projeto, que é o arquivo pensado pra ser versionado
Erro comum deste passo: usar –scope project achando que é "só uma config local"… não é, esse arquivo nasce na raiz do repo e vai pro Git junto com o resto
- Referencie o segredo com ${VAR} em vez de escrever o valor
O Claude Code faz expansão de variáveis de ambiente dentro do .mcp.json
Então no arquivo compartilhado fica a referência, nunca a chave:
"env": {
"API_KEY": "${MINHA_API_KEY}"
}
E em servidor HTTP, o mesmo vale pro cabeçalho de autenticação:
"headers": {
"Authorization": "Bearer ${MEU_TOKEN}"
}
A expansão funciona em campos específicos da configuração do servidor: command, args, env, url (servidores HTTP) e headers (autenticação HTTP)
Erro comum deste passo: colar a chave literal "só pra testar rápido" e esquecer ela ali… é assim que o valor real acaba indo pro histórico do repo sem ninguém perceber
- Use ${VAR:-default} quando fizer sentido ter um fallback
A sintaxe suportada tem duas formas: ${VAR} expande pro valor da variável, e ${VAR:-default} usa o default quando a variável não está definida
"url": "${MCP_URL:-https://exemplo-do-servidor.local}"
Erro comum deste passo: usar o default pra segredo
Fallback é pra valor não sensível (endpoint padrão, região, nome de ambiente), nunca pra token
- Abra a sessão, aprove o servidor e confira a conexão
Por segurança, o Claude Code pede aprovação interativa antes de carregar servidores de escopo project vindos de um .mcp.json
Eles ficam pendentes até serem aceitos em sessão interativa
Depois de aceitar, roda o comando de barra dentro da sessão pra ver a lista e o status de cada servidor:
/mcp
Erro comum deste passo: abrir a sessão antes de exportar a variável, ver o servidor falhando e sair caçando bug na configuração, quando o problema é que o ambiente estava vazio
Mesmo MCP no time, cada dev com a própria chave
Esse é o caso que mais gera dúvida, e a solução é bem elegante
O .mcp.json que vai pro Git carrega só o esqueleto: nome do servidor, comando, argumentos e o ${VAR} no lugar do segredo
Cada pessoa que clona o repo define a própria variável na máquina dela, com a própria credencial
Mesma configuração pra todo mundo, chave diferente pra cada um, e nenhum segredo no histórico do repositório
E quando alguém precisa de uma config diferente do resto do time?
Aqui a precedência trabalha a teu favor
A pessoa registra o MESMO nome de servidor em escopo local, que fica no ~/.claude.json dela
Como local vence project, a versão dela é a que vale, e o arquivo compartilhado do time continua intocado
E o MCP que tu usa em TODOS os projetos?
Esse não tem por que morar em repo nenhum
claude mcp add --scope user
Com –scope user ele é gravado no nível raiz do ~/.claude.json e passa a valer em todos os projetos, sem sujar nenhum .mcp.json
E se a lista de servidores aprovados do projeto precisar ser reavaliada?
Existe comando pra zerar essas escolhas e decidir tudo de novo:
claude mcp reset-project-choices
Útil quando o .mcp.json mudou bastante e tu quer revisar servidor por servidor em vez de confiar no que foi aceito meses atrás
Trave o commit de segredo com Gitleaks e pre-commit
O passo a passo acima resolve o problema por disciplina
Só que disciplina falha, principalmente às 18h de sexta, então bora colocar uma rede de segurança embaixo 😀
- Garanta que os arquivos com segredo estão no .gitignore
Se tu guarda variáveis num arquivo tipo .env, ele precisa estar ignorado ANTES de existir, não depois
.env
.env.local
Erro comum deste passo: adicionar no .gitignore um arquivo que o Git já está rastreando… o ignore não vale pro que já foi commitado
- Adicione o hook do Gitleaks no .pre-commit-config.yaml
O Gitleaks é uma ferramenta open source de detecção de segredos em repositórios Git, mantida na organização gitleaks no GitHub (repositório oficial: github.com/gitleaks/gitleaks), e ele plugga no framework pre-commit
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: coloque-aqui-a-tag-da-versao
hooks:
- id: gitleaks
O rev tu preenche com a tag que escolher no repositório oficial
Erro comum deste passo: errar o id do hook, que é gitleaks
- Rode o install pra gerar o hook de verdade
pre-commit install
Esse comando é o que cria o .git/hooks/pre-commit
Erro comum deste passo: e esse é O erro clássico… criar o .pre-commit-config.yaml, commitar, e nunca rodar o install
O arquivo existe, o time acha que está protegido, e o hook simplesmente não existe na máquina de ninguém
- Valide rodando o scan no repositório inteiro
pre-commit run --all-files
Esse comando roda o scan em todos os arquivos do repositório de uma vez, e serve justamente pra validar que a instalação do hook funcionou
Ou seja, tu não precisa esperar um commit real pra descobrir se a rede está de pé, e de quebra tu descobre se já tem algo esquisito lá atrás
Vale lembrar que essa rede também protege de commit automático, principalmente se tu costuma delegar o Git pro Claude Code
Problemas comuns e como resolver
O servidor do .mcp.json não aparece na sessão
Causa: servidores de escopo project ficam pendentes de aprovação até serem aceitos em sessão interativa, é o comportamento de segurança do Claude Code
Solução: abre uma sessão interativa e aceita o servidor quando o Claude Code perguntar
Como prevenir: avisa o time que, ao clonar o repo, a primeira sessão vai pedir aprovação… assim ninguém acha que o arquivo veio quebrado
Editei a configuração e nada mudou
Causa: provavelmente existe um servidor com o MESMO nome em outro escopo vencendo pela precedência (local vence project, que vence user)
Solução: roda /mcp e confere qual servidor está realmente ativo antes de continuar editando o arquivo errado
Como prevenir: evita repetir nome de servidor entre escopos, a não ser quando o override é intencional
Conecta na minha máquina e falha na do colega
Causa: o ${VAR} só expande se a variável existir no ambiente, e na máquina dele ela não foi definida
Solução: ele exporta a variável com a chave dele e confere o status pelo /mcp
Como prevenir: documenta no README quais variáveis o .mcp.json espera, só os NOMES delas, nunca os valores
Já commitei a chave sem querer
Causa: o segredo entrou no histórico, e histórico é público pra qualquer um com acesso ao repo
Solução: revoga e rotaciona a chave no provedor ANTES de qualquer outra coisa
Apagar a linha do arquivo e commitar por cima não resolve nada, o valor antigo continua lá atrás no histórico
Como prevenir: hook do Gitleaks instalado, e .mcp.json só com ${VAR}
Chegou aqui sem contexto do que é MCP?
Pra começar do zero com servidores MCP, este vídeo do canal mostra o DevTools MCP do Chrome funcionando e dá o contexto do protocolo:
Conclusão
A regra que resume o post inteiro cabe numa linha: configuração é do projeto, credencial é da máquina
O .mcp.json existe pra ser versionado e é ótimo nisso, desde que dentro dele só more o ${VAR} e nunca o valor
O que é pessoal fica em escopo local ou user, dentro do ~/.claude.json, longe do repositório
Próximo passo prático, e leva uns cinco minutos: abre o .mcp.json que já existe no teu repo, procura qualquer valor que pareça chave, troca por ${VAR} e instala o hook do Gitleaks antes do próximo commit
Se achar alguma chave viva ali, revoga primeiro e conserta depois, beleza?
até o próximo post!
Perguntas frequentes
Dá pra versionar o .mcp.json com a chave dentro só até o time se organizar melhor?
Não é recomendado, porque o .mcp.json é feito pra ser compartilhado e uma vez que a chave entra no histórico do Git ela fica lá mesmo se for removida depois. O caminho certo é usar ${VAR} no arquivo e deixar o valor real só na variável de ambiente de cada máquina.
Como impedir que uma chave seja commitada por engano num projeto que usa MCP?
O Gitleaks é uma ferramenta open source de detecção de segredos, mantida no repositório github.com/gitleaks/gitleaks, e pode ser plugado no framework pre-commit. Basta adicionar o hook de id gitleaks no .pre-commit-config.yaml e rodar pre-commit install pra ele barrar o commit antes do segredo entrar no histórico.
Como testo se o Gitleaks está mesmo bloqueando segredo antes de confiar nele?
Depois de instalar o hook com pre-commit install, roda pre-commit run –all-files pra escanear todo o repositório de uma vez. Isso valida a instalação sem precisar esperar um commit real pra descobrir se o hook funciona.
Um colega aprovou um .mcp.json com configuração errada, dá pra desfazer essa aprovação?
Sim, existe o comando claude mcp reset-project-choices, que zera as escolhas de aprovação de servidores do projeto. Depois de rodar ele, os servidores project-scoped voltam a ficar pendentes de aprovação na próxima sessão interativa.
A configuração do escopo local do Claude Code também vai pro repositório?
Não. O escopo local é gravado em ~/.claude.json, dentro do objeto projects, fora do repositório do projeto. Só o escopo project grava dentro do repo, no arquivo .mcp.json.
Dá pra usar variável de ambiente em servidor MCP que fala HTTP, ou só em comando local?
Dá sim. A expansão de variáveis do Claude Code funciona nos campos command, args, env, url e headers, então tanto o endpoint de um servidor HTTP quanto o cabeçalho de autenticação podem referenciar ${VAR} em vez de carregar o valor fixo.
Formações
Formação Vibe Coding
Do Prompt ao Produto: Crie Software Real com IA
- 474 aulas
- 20 projetos
- 39h 27min
Blog | Mais populares
Supabase MCP no Claude Code: como conectar o agente ao schema do seu banco
Supabase MCP no Claude Code conecta o agente ao schema real do seu banco: veja como instalar, autenticar via OAuth e por que usar só em desenvolvimento.
O que são servidores MCP no Claude Code e quando eles valem a pena?
Servidores MCP no Claude Code conectam o agente a bancos, docs e ferramentas externas. Entenda como funcionam e quando realmente valem a pena usar.
Context7 MCP no Claude Code: como parar de receber código de uma versão antiga da biblioteca
Context7 MCP no Claude Code busca a documentação atual da biblioteca e evita código desatualizado. Veja como instalar, os comandos e os planos Free e Pro.
