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

chaves MCP guardadas em variáveis de ambiente fora do repositório Git
Resposta rápida

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
Formação Recomendada

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

  1. 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

  1. 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

  1. 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

  1. 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

  1. 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 😀

  1. 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

  1. 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

  1. 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

  1. 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.




Escrito por | Matheus Battisti

Matheus Battisti
Fundador da Hora de Codar

Programador apaixonado pelo mundo das tecnologias, sempre buscando em aprender e se aprofundar em linguagens, frameworks e o que mais for necessário para executar um bom trabalho. Agora tem uma nova missão que é de passar seu conhecimento adiante para formar novos programadores e especializar mais os que já são.

Subscribe
Notify of
guest

0 Comentários
Oldest
Newest Most Voted

Formações

Formação Vibe Coding

Formação Vibe Coding

Do Prompt ao Produto: Crie Software Real com IA

  • 474 aulas
  • 20 projetos
  • 39h 27min

Blog | Mais populares