GitMCP
permite que assistentes de IA explorem repositórios do GitHub, código-fonte, issues, pull requests e commits por meio de 14 ferramentas validadas e somente leitura, além de 4 ferramentas de escrita opcionais que ficam desativadas por padrão.
Documentação
GitMCP
Um servidor GitHub para assistentes de IA: permite que Claude e outros clientes MCP leiam repositórios, issues, pull requests e commits por meio de ferramentas validadas, com gravações desabilitadas, a menos que você opte por ativá-las.
- 14 ferramentas somente leitura, além de 4 ferramentas de gravação opcionais, cada uma com um esquema de entrada Pydantic estrito
- Falhas transitórias (429, 5xx, timeouts) são repetidas dentro de um orçamento rígido; erros de autenticação, permissão e 404 nunca são repetidos
- Seguro por padrão: gravações desativadas, token nunca é registrado ou retornado, tamanhos de resposta limitados, sem acesso arbitrário a URL/shell
- Funciona com Claude Code e Claude Desktop via stdio; repositórios públicos não precisam de token
Expectativas honestas: apenas stdio, então cada usuário executa sua própria cópia local. Pesquisa de código e repositórios privados precisam de um token GitHub. Leituras de arquivos são somente texto UTF-8.
O que eu construí
GitMCP é um servidor MCP em Python que adapta a API REST do GitHub em 18 ferramentas que um assistente de IA pode descobrir e
chamar. A lógica do GitHub (github/*.py) é independente do MCP, então é testada sem um servidor em execução; uma camada fina
server.py registra as ferramentas e transforma cada falha em uma mensagem curta, segura e acionável. Foi
construído com o SDK oficial atual do MCP Python (2.x) e verificado com um cliente MCP stdio real.
Resultados em resumo
Medido em um laptop Windows 11, Python 3.14, anônimo (sem token) contra a API GitHub ao vivo.
| Métrica | Resultado |
|---|---|
| Testes automatizados | 112 passando, 1 ignorado (teste de integração ao vivo, precisa de token), ~13 s |
| Lint / tipos | ruff limpo, mypy --strict limpo (18 arquivos de origem) |
| Início a frio: processo de spawn, handshake MCP, listar 14 ferramentas | 1,3 s |
Latência github_get_repository | 0,6 s na primeira chamada (configuração TLS), ~0,02 s mediana em conexão reutilizada |
| Tamanho do código | ~2.100 linhas em src/, ~1.400 linhas de testes |
A latência é dominada pelo GitHub e pela rede, não pelo servidor. As decisões de design estão em DECISIONS.md.
Arquitetura
flowchart LR
Client["MCP client<br/>(Claude Code / Desktop)"] -- "stdio JSON-RPC" --> Server["server.py<br/>tool registration + error guard"]
Server --> Repos["github/repositories.py"]
Server --> Issues["github/issues.py"]
Server --> PRs["github/pull_requests.py"]
Server --> Commits["github/commits.py"]
Repos & Issues & PRs & Commits --> GH["github/client.py<br/>auth, errors, size limit"]
GH --> Retry["retry.py<br/>backoff + jitter + Retry-After"]
GH -- HTTPS --> API[("GitHub REST API")]
Server -. validates with .-> Schemas["schemas/<br/>Pydantic in/out models"]
Config["config.py<br/>env settings"] --> Server
| Módulo | Responsabilidade |
|---|---|
server.py | Cria o MCPServer, registra ferramentas, converte erros em erros seguros de ferramenta, fecha o cliente HTTP no encerramento |
github/*.py | Lógica de negócio. Sem imports MCP, então é testável sem um servidor |
github/client.py | Cliente httpx autenticado, mapeamento de status HTTP → erro tipado, limite de tamanho de resposta |
retry.py | Política de repetição (429 / 5xx / rede), tratamento de Retry-After e cabeçalho de reset |
schemas/ | Modelos de entrada Pydantic estritos (extra="forbid") e modelos de saída |
errors.py | Exceções tipadas com mensagens seguras e dicas |
logging_utils.py | Registro em stderr com redação de segredos |
Por que foi construído assim: veja DECISIONS.md.
Início rápido
Requer Python 3.11+. Repositório: https://github.com/wablevaibhav/gitmcp
python -m pip install git+https://github.com/wablevaibhav/gitmcp
python -m gitmcp # starts the server (waits silently for an MCP client)
Depois, conecte-o ao seu cliente de IA: veja Claude Code ou Claude Desktop. Você não precisa clonar o repositório para usar o GitMCP.
Última versão: v0.1.0. Para instalar exatamente essa versão:
python -m pip install git+https://github.com/wablevaibhav/gitmcp@v0.1.0
Para atualizar depois:
python -m pip install --upgrade --force-reinstall git+https://github.com/wablevaibhav/gitmcp
Alternativas (não obrigatórias): pipx install git+https://github.com/wablevaibhav/gitmcp, ou com
uv: uvx --from git+https://github.com/wablevaibhav/gitmcp gitmcp.
Instalação para desenvolvimento (contribuidores)
git clone https://github.com/wablevaibhav/gitmcp.git
cd gitmcp
python -m venv .venv
# Windows (PowerShell): .venv\Scripts\Activate.ps1
# macOS / Linux: source .venv/bin/activate
pip install -e ".[dev]"
requirements-lock.txt fixa as versões exatas com as quais o projeto foi testado
(pip install -r requirements-lock.txt, depois pip install -e . --no-deps).
Configuração do token GitHub
O token é opcional para repositórios públicos (limite anônimo: 60 requisições/hora), mas obrigatório para repositórios privados, pesquisa de código e ferramentas de gravação.
Crie um token de acesso pessoal de granularidade fina em GitHub → Configurações → Configurações de desenvolvedor → Tokens de acesso pessoal → Tokens de granularidade fina, restrito apenas aos repositórios que você quer que o assistente veja.
| Capacidade | Permissão do repositório |
|---|---|
| Repositórios, conteúdos, leitura de arquivos, commits | Conteúdos: Leitura (Metadados: Leitura é implícita) |
| Issues e comentários | Issues: Leitura |
| Pull requests, arquivos, revisões | Pull requests: Leitura |
github_create_issue, github_add_issue_comment | Issues: Leitura e gravação |
github_create_branch | Conteúdos: Leitura e gravação |
github_create_pull_request | Pull requests: Leitura e gravação |
Comece com permissões somente leitura. Adicione permissões de gravação apenas se você ativar as ferramentas de gravação.
Público vs. autenticado: sem token, apenas dados públicos são visíveis e o GitHub retorna 404 para recursos
privados. Com um token, você vê exatamente o que o token pode ver, nada mais; o GitMCP nunca contorna a autorização do GitHub.
Configuração
Variáveis de ambiente (ou um arquivo .env no diretório de trabalho; copie .env.example):
| Variável | Padrão | Significado |
|---|---|---|
GITHUB_TOKEN | (nenhum) | Token de acesso pessoal |
GITHUB_API_URL | https://api.github.com | Base da API (GitHub Enterprise: https://HOST/api/v3) |
GITHUB_API_VERSION | 2022-11-28 | Cabeçalho X-GitHub-Api-Version |
GITHUB_REQUEST_TIMEOUT | 30 | Tempo limite por requisição, em segundos |
GITHUB_MAX_RETRIES | 3 | Repetições após a primeira tentativa (0–10) |
GITHUB_MAX_RATE_LIMIT_WAIT | 60 | Maior espera por limite de taxa que o GitMCP vai aguardar, em segundos |
GITHUB_ENABLE_WRITE_TOOLS | false | Registrar ferramentas de gravação |
GITMCP_LOG_LEVEL | INFO | DEBUG/INFO/WARNING/ERROR (stderr) |
GITMCP_MAX_FILE_BYTES | 200000 | Maior arquivo que github_get_file_contents retorna |
GITMCP_MAX_PATCH_CHARS | 8000 | Truncamento de diff por arquivo |
GITMCP_MAX_COMMENT_CHARS | 4000 | Truncamento de corpo de comentário/revisão |
GITMCP_MAX_RESPONSE_BYTES | 5000000 | Limite rígido em qualquer corpo de resposta do GitHub |
Executando o servidor
python -m gitmcp # or simply: gitmcp
O servidor fala MCP via stdio, então, por conta própria, ele imprime uma linha "pronto" no stderr e aguarda. Ele foi feito para ser iniciado por um cliente MCP. Para confirmar que ele é detectável e chamável usando um cliente MCP stdio real (a partir de um clone deste repositório):
python scripts/verify_tools.py # lists the tools
python scripts/verify_tools.py octocat/Hello-World # also calls github_get_repository
Mantenha seu token em segredo. Nunca cole em chats, issues, capturas de tela ou faça commit. Se um token for exposto, revogue-o imediatamente em https://github.com/settings/personal-access-tokens e crie um novo.
Claude Code
macOS / Linux / Git Bash:
claude mcp add gitmcp --scope user -e GITHUB_TOKEN="$GITHUB_TOKEN" -- python -m gitmcp
Windows PowerShell (o Windows PowerShell 5.1 engole o separador --, então execute via cmd):
$env:GITHUB_TOKEN = "your-token" # type it in your own terminal only
cmd /c "claude mcp add gitmcp --scope user -e GITHUB_TOKEN=%GITHUB_TOKEN% -- python -m gitmcp"
Verifique com claude mcp list (ou /mcp dentro do Claude Code). Se python não for o interpretador no qual você instalou
o GitMCP, use o caminho completo (where python / which python), por exemplo,
C:\Users\you\AppData\Local\Programs\Python\Python312\python.exe.
Você também pode compartilhar um .mcp.json em nível de projeto, referenciando a variável de ambiente de cada pessoa (nunca
escreva o token no arquivo):
{
"mcpServers": {
"gitmcp": {
"command": "python",
"args": ["-m", "gitmcp"],
"env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" }
}
}
}
Claude Desktop
Edite claude_desktop_config.json (Windows: %APPDATA%\Claude\, macOS:
~/Library/Application Support/Claude/) e reinicie o Claude Desktop:
{
"mcpServers": {
"gitmcp": {
"command": "python",
"args": ["-m", "gitmcp"],
"env": {
"GITHUB_TOKEN": "your-token",
"GITHUB_ENABLE_WRITE_TOOLS": "false"
}
}
}
}
Se o Claude Desktop não conseguir encontrar python, defina command para o caminho completo do interpretador, com barras invertidas duplicadas
no Windows ("C:\\Users\\you\\AppData\\Local\\Programs\\Python\\Python312\\python.exe").
Usando com outras pessoas
Cada pessoa executa sua própria cópia local; nenhum servidor é compartilhado e tokens nunca são compartilhados. Todos fazem:
python -m pip install git+https://github.com/wablevaibhav/gitmcp- Cria seu próprio token GitHub de granularidade fina (veja abaixo).
- Adiciona o servidor ao seu cliente usando uma das configurações acima.
Repositórios públicos funcionam sem token (60 requisições/hora); repositórios privados, pesquisa de código e ferramentas de gravação exigem um.
Instalar o pacote não faz o servidor aparecer em um cliente por conta própria; o cliente deve ser configurado como acima. O servidor e o comando foram verificados com
scripts/verify_tools.py(um cliente MCP stdio real). Os trechos do Claude Code / Desktop seguem os formatos documentados desses produtos.
Uso
Saída real de python scripts/verify_tools.py octocat/Hello-World (um cliente MCP conversando com o servidor
via stdio, sem token):
Connected. 14 tools:
- github_search_repositories
- github_get_repository
- github_list_repository_contents
- github_get_file_contents
...
is_error: False
{'full_name': 'octocat/Hello-World', 'owner': 'octocat', 'name': 'Hello-World',
'visibility': 'public', 'stars': 3842, 'default_branch': 'master', ...}
Erros são curtos, tipados e acionáveis (saída real, anônima):
github_get_repository -> NotFoundError: Resource not found. Hint: Check owner, repo, path and ref.
Private resources also return 404 when the token lacks access.
No GITHUB_TOKEN is configured, so only public data is visible.
github_search_code -> AuthenticationError: GitHub code search requires authentication.
Hint: Set GITHUB_TOKEN, and scope the query with repo:, org: or user:.
Ferramentas
Cada ferramenta aceita um argumento de objeto chamado params. Todas as entradas rejeitam campos desconhecidos. Ferramentas de listagem aceitam
page (1–1000) e per_page (1–100, padrão 30) e retornam has_next_page. owner/repo/ref/path são
validados (sem travessia, sem caracteres de referência inválidos).
| Ferramenta | Argumentos principais | Retorna |
|---|---|---|
github_search_repositories | query, language, topic, min_stars, sort, order, paginação | contagem total; itens com nome completo, proprietário, descrição, URL, visibilidade, linguagem, estrelas, branch padrão |
github_get_repository | owner, repo | resumo + licença, forks, issues abertas, tópicos, URLs de clone/API, carimbos de data/hora |
github_list_repository_contents | owner, repo, path, ref | entradas: nome, caminho, tipo, tamanho, sha, URLs web/API/download |
github_get_file_contents | owner, repo, path, ref | content UTF-8, sha, tamanho. Erros para diretórios, binários, > limite de tamanho |
github_search_code | query (precisa de repo:/org:/user:), paginação | itens: caminho, repositório, URL, trechos. Requer token |
github_list_issues | owner, repo, state, labels, assignee, include_pull_requests, paginação | resumos com flag is_pull_request |
github_get_issue | owner, repo, issue_number | detalhes: corpo, rótulos, responsáveis, marco, carimbos de data/hora, URL |
github_list_issue_comments | owner, repo, issue_number, paginação | comentários (corpos truncados, sinalizados) |
github_list_pull_requests | owner, repo, state, base, head (owner:branch), paginação | resumos de PR |
github_get_pull_request | owner, repo, pull_number | branches, SHAs, autor, rascunho/mesclado/mesclável, tamanho, revisores |
github_list_pull_request_files | owner, repo, pull_number, paginação | arquivos: status, +/−, patch (truncado, sinalizado) |
github_list_pull_request_reviews | owner, repo, pull_number, paginação | revisões: autor, APPROVED/CHANGES_REQUESTED/…, corpo |
github_list_commits | owner, repo, ref, path, author, paginação | resumos de commits |
github_get_commit | owner, repo, ref | mensagem, autor, pais, estatísticas, arquivos (máx. 100, patches truncados) |
github_create_issue ⚠ | owner, repo, title, body, labels, assignees | número, URL |
github_add_issue_comment ⚠ | owner, repo, issue_number, body | id do comentário, URL |
github_create_branch ⚠ | owner, repo, branch, from_ref | nova referência, SHA |
github_create_pull_request ⚠ | owner, repo, title, head, base, body, draft | número, URL |
⚠ Ferramenta de gravação: registrada apenas quando GITHUB_ENABLE_WRITE_TOOLS=true.
Exemplos de prompts
- Exploração de repositório: "Veja
octocat/Hello-World. Qual é o branch padrão, o que está na raiz e o que o README diz?" - Pesquisa de código: "Encontre onde
parse_configestá definido emacme/api." (precisa de token) - Investigação de issue: "Liste issues abertas rotuladas como
bugemacme/api, depois resuma a discussão na mais comentada." - Revisão de PR: "Revise o PR 482 em
acme/api: mostre os metadados, os arquivos alterados e patches, revisões existentes e aponte mudanças arriscadas." - Histórico: "Quem tocou
src/auth.pypor último emacme/apie o que esses commits mudaram?"
Limites de taxa e tratamento de erros
| Situação | Comportamento |
|---|---|
429, ou 403 com sinais de limite de taxa | Repetido, respeitando Retry-After / x-ratelimit-reset. Se a espera exceder GITHUB_MAX_RATE_LIMIT_WAIT, falha imediatamente com RateLimitError informando a espera. Nunca dorme além desse limite |
500/502/503/504, timeouts, erros de conexão | Repetido até GITHUB_MAX_RETRIES com backoff exponencial e jitter total (base de 0,5 s, teto de 8 s) |
401 | AuthenticationError — sem repetição |
403 (permissão) | AuthorizationError — sem repetição; a dica nomeia a permissão a conceder |
404 | NotFoundError — sem repetição; a dica observa que recursos privados também retornam 404 |
400/409/422 | InputValidationError — sem repetição |
| Corpo malformado / muito grande / não-JSON | GitHubAPIError |
Requisições de escrita (POST) nunca são repetidas após timeout ou 5xx, pois a escrita pode ter sido concluída; elas só são repetidas quando o GitHub as rejeitou por limite de taxa.
Os clientes recebem ErrorType: message Hint: .... Tracebacks, corpos de resposta e tokens nunca chegam ao cliente.
Segurança
- O token vem apenas do ambiente, é mantido como
SecretStre é ocultado de logs e erros (correspondência exata mais padrões deghp_…/github_pat_…/Authorization:). - Ferramentas de escrita não são registradas a menos que
GITHUB_ENABLE_WRITE_TOOLS=true, e cada método de serviço de escrita recusa independentemente se a flag estiver desligada. O GitHub ainda aplica as permissões próprias do token. - Sem execução de shell, sem busca arbitrária de URLs, sem GraphQL, sem proxy genérico de API: cada ferramenta mapeia para um endpoint REST fixo e os argumentos da ferramenta são codificados em percentual no caminho.
- Tamanhos de arquivo, patch, comentário e resposta total são limitados; logs nunca contêm código-fonte ou respostas completas.
- Use um token de granularidade fina com escopo para repositórios específicos e defina uma expiração.
- Transporte HTTP Streamable é intencionalmente não implementado; um servidor exposto à rede precisaria de sua própria autenticação, o que está fora do escopo desta versão.
Desenvolvimento
A partir de uma instalação de desenvolvimento:
pytest # unit + MCP tests (no token, no network)
ruff check . && ruff format --check .
mypy # strict, on src/
Testes ao vivo opcionais (somente leitura, ignorados a menos que configurados):
GITMCP_TEST_TOKEN=github_pat_xxx GITMCP_TEST_REPO=owner/repo pytest -m integration
Solução de problemas
| Sintoma | Causa provável / correção |
|---|---|
| Cliente não mostra ferramentas | Python errado na configuração do cliente. Execute python -m gitmcp com esse interpretador exato; use o caminho completo dele na configuração |
error: unknown option '-m' (PowerShell) | PowerShell 5.1 descarta --. Use a forma cmd /c "claude mcp add ..." acima |
No module named gitmcp | Instalado em um Python/venv diferente do que o cliente inicia |
NotFoundError em um repositório que você pode abrir no navegador | Repositório privado e token ausente/com escopo insuficiente |
AuthorizationError | O token não tem a permissão da tabela acima ou o repositório não está selecionado para o token |
RateLimitError imediatamente | A redefinição está mais distante que GITHUB_MAX_RATE_LIMIT_WAIT; defina um token ou aguarde |
github_search_code falha | Precisa de GITHUB_TOKEN e um qualificador repo:/org:/user: |
| Ferramentas de escrita ausentes | Intencional: defina GITHUB_ENABLE_WRITE_TOOLS=true e reinicie o cliente |
invalid configuration na inicialização | Uma configuração falhou na validação; os nomes dos campos são impressos em stderr |
| Saída de protocolo distorcida | Algo escreveu em stdout; use stderr para qualquer depuração |
Limitações e roteiro
- As ferramentas de leitura retornam a primeira fatia de um resultado (paginação é explícita); não há acompanhamento automático de todas as páginas.
- O conteúdo dos arquivos é somente texto UTF-8; arquivos binários e arquivos acima de
GITMCP_MAX_FILE_BYTESsão recusados. - A busca de código depende do índice de busca do GitHub e de seus limites (máximo de 1000 resultados, consulta ≤ 256 caracteres).
github_get_commitlimita arquivos a 100 e não pagina a paginação de arquivos de commit do GitHub.- GitHub Actions, releases, comentários de revisão (inline) e Projects não são cobertos.
- Somente stdio; planejado: HTTP Streamable autenticado, cache de requisição condicional (ETag), ferramenta de árvore de repositório.
- Python 3.14 e
mcp2.3 foram usados no desenvolvimento; o código tem como alvo Python ≥ 3.11.