FluxGit MCP Server
Servidor MCP do Git com 23 ferramentas somente leitura. Propostas de escrita são executadas apenas após uma pessoa revisar o impacto específico da operação e aprová-las no FluxGit Desktop.
Documentação
fluxgit-mcp-sidecar
mcp-name: io.github.fluxgit-hq/fluxgit-mcp-server
Servidor Model Context Protocol (MCP) com foco em segurança para Git.
Agentes de IA inspecionam. FluxGit mantém o controle.
Um servidor MCP em Rust com 38 contratos para agentes de código de IA: 25 ferramentas somente leitura e 13 ferramentas de operação com aprovação humana (12 propostas mais cancelamento de uma proposta pendente). O sidecar nunca executa uma escrita no Git; ele faz a ponte entre propostas aprovadas e o aplicativo de desktop FluxGit.

Para comparações de orçamento de contexto, veja o benchmark público de tokens de contexto do Git. Ele publica o fixture, saídas brutas, scripts e checksums, incluindo tanto a varredura ampla de CLI quanto um contraexemplo menor ajustado manualmente.
Por que isso existe
Agentes de codificação com IA são cada vez mais solicitados a navegar em repositórios reais: explicar o estado do branch, resumir diffs, encontrar commits perdidos, recomendar próximos passos seguros. Para fazer isso bem, um agente precisa de contexto do Git mais rico que git status e estruturado o suficiente para raciocinar. Para fazer isso com segurança, um agente nunca deve ser capaz de mutar refs silenciosamente, forçar push, descartar trabalho ou aplicar patches sem que um humano aprove a consequência.
Outros servidores MCP para Git enfrentam uma escolha: permanecer estritamente somente leitura (utilidade limitada) ou expor ferramentas de escrita diretamente (perigoso — agentes alucinam, prompts podem ser envenenados, erros são destrutivos). Este sidecar não escolhe nenhum dos dois. A inspeção é validada por esquema e limitada; as operações passam por um handshake de escrita com UI: o agente propõe, o FluxGit mostra a prévia, o usuário aprova no aplicativo, e o FluxGit executa através de seu pipeline de segurança com pontos de restauração e auditoria.
O que está exposto
25 ferramentas somente leitura
| Ferramenta | Propósito |
|---|---|
repo.brief | Consciência situacional em uma chamada — branch, ahead/behind, operação em andamento, resumo da árvore de trabalho, stashes, drift agregado de submódulos, commits recentes, convenções detectadas e dicas de próximos passos. A primeira chamada recomendada de uma sessão de agente; substitui 6-10 chamadas brutas ao git e é orçada por tokens por design |
repo.scope | Escopo de monorepo — alterações da árvore de trabalho de uma subárvore, commits recentes, churn (commits + autores em uma janela) e proprietários do CODEOWNERS em uma única chamada |
repo.status | Árvore de trabalho, branch atual, caminhos sujos |
repo.refs | Branches, tags, remotes, stashes |
repo.branchStack | Branch atual vs upstream / base / relacionado |
repo.history | Histórico de commits paginado |
repo.reflog | Linha do tempo de movimentação com dicas de recuperação |
repo.conflictPreflight | Prever resultado de merge/rebase antes de executar |
conflict.read | Conflito ativo como dados estruturados — operação em andamento, commits produtores ours/theirs, classificação de estágio por arquivo, conteúdos base/ours/theirs (limitados por tamanho, sinalizados como binários) e intervalos de linhas da região de marcadores. Chega de analisar sopa de <<<<<<< |
commit.details | Metadados de um único commit + arquivos alterados |
worktree.changes | Resumo de alterações da árvore de trabalho por caminho |
worktree.list | Todos os worktrees (principal + vinculados) com branch/detached, SHA do HEAD e flags de bloqueado/removível — a base somente leitura para worktrees paralelos de agentes |
submodule.status | Lista e estado de submódulos |
diff.text | Patch de texto padrão (compatível com git diff) |
diff.semantic | Explicação semântica negociada por capacidade |
diff.semanticFallbacks | Caminhos que caíram de semântico para texto |
fleet.radar | Fila de atenção multi-repositório |
fleet.digest | O que mudou na frota desde um momento — movimentos de reflog do HEAD e de branches locais de muitos repositórios, do mais novo ao mais antigo, limitados por maxEvents (padrão 200, máximo 1000). repoPaths, ou repositórios registrados do FluxGit dentro das raízes permitidas quando omitido. identity é exatamente o que o Git registrou (a identidade configurada, não prova de uma pessoa ou agente); rewrote sinaliza movimentos que descartaram o tip anterior (reset, amend, rebase, movimentos forçados). Lê apenas arquivos de reflog; nada é buscado ou escrito |
agents.presence | Quais outros agentes de codificação estão trabalhando neste repositório — apenas de fontes locais (processos de agentes em execução e seus filhos, os armazenamentos de sessão dos próprios agentes, arquivos que eles mantêm no repositório, editores com agentes integrados e registros de presença do FluxGit MCP). Por agente: state (trabalhando/aberto/recente), sources, branch, última ferramenta e arquivos relativos ao repositório quando conhecidos. Nomes são o que cada ferramenta ou cliente MCP declara sobre si mesmo. Seu próprio registro MCP é excluído; descobertas que provavelmente são da sua própria sessão são marcadas como likelyCaller. Nunca retorna prompts, mensagens ou conteúdos de arquivos |
safety.timeline | Eventos de segurança sintetizados de pontos de restauração + reflog |
safety.eventDetails | Aprofundamento em um evento da linha do tempo |
flux.latestRestorePoint | Ponto de restauração mais recente do FluxGit |
flux.restorePoints | Lista de pontos de restauração |
flux.restorePointDetails | Um ponto de restauração com refs antes/depois |
operation.status | Status assíncrono autoritativo por previewId; faça polling após uma prévia retornar accepted: true e não relate um resultado do Git antes que ele se torne terminal |
13 ferramentas de escrita com handshake de UI
Todas as 12 propostas de operation.preview.* são despachadas através do gateway do FluxGit quando
configurado. O sidecar faz POST da proposta, realiza uma leitura de status limitada,
e normalmente retorna imediatamente com accepted: true, o previewId canônico,
status atual e nextAction.tool: "operation.status". O
aplicativo FluxGit renderiza um cartão de aprovação "Solicitado por agente de IA" enquanto a revisão humana
continua assíncronamente. O código 10003 é reservado para uma ponte ausente,
inválida ou inalcançável; não é um timeout de aprovação humana.
Todos os 12 esquemas de prévia aceitam um idempotencyKey limitado opcional. Reutilize-o
apenas ao tentar novamente a mesma intenção lógica; o sidecar o limita ao
tipo de operação para que a nova tentativa resolva para a proposta existente no gateway. Omita-o
para uma nova intenção—mesmo quando os outros argumentos correspondem—e o sidecar envia
uma nova chave baseada em UUID. As ferramentas de prévia continuam, portanto, a anunciar
idempotentHint: false.
| Ferramenta | Propósito | Despacho no gateway |
|---|---|---|
operation.preview.merge | Propor um merge para revisão humana | POST /v1/mcp/operation/preview/merge → cartão de aprovação no FluxGit |
operation.preview.rebase | Propor um rebase não interativo | interactive: true falha na validação de esquema antes do POST/criação do cartão; solicitações aceitas fazem POST /v1/mcp/operation/preview/rebase e abrem um cartão de aviso de reescrita de histórico |
operation.preview.discard | Propor descarte de alterações da árvore de trabalho | POST /v1/mcp/operation/preview/discard → aviso específico do caminho; o FluxGit exige um stash de segurança antes de descartar alterações correspondentes |
operation.preview.reset | Propor reset soft / mixed / hard | POST /v1/mcp/operation/preview/reset → cartão ciente do modo (modo hard força confirmação forte) |
operation.preview.patch | Propor aplicação de um patch gerado por agente | POST /v1/mcp/operation/preview/patch → prévia de patch em monoespaço + alternância applyToIndex |
operation.preview.plan | Propor uma sequência de 1 a 10 passos usando os cinco tipos de passos de plano suportados (merge, rebase, discard, reset, patch) | POST /v1/mcp/operation/preview/plan → cartão de passos numerados; passos destrutivos exigem uma caixa de seleção explícita. Um passo rebase com interactive: true é rejeitado pela validação de esquema antes do despacho; a execução para na primeira falha. Seu checkpoint pré-plano ancora apenas o commit do branch: a recuperação protegida restaura HEAD/arquivos rastreados, enquanto o índice original, a árvore de trabalho e arquivos não rastreados exigem os snapshots de passos separados/superfícies de recuperação da Safety Timeline |
operation.preview.worktree | Propor criação de um worktree isolado para uma tarefa paralela (não destrutivo; nunca toca no histórico) | POST /v1/mcp/operation/preview/worktree → cartão de aprovação com branch + caminho de destino + motivo; passa pela mesma ação de criação de worktree que um clique manual usa |
operation.preview.commit | Propor staging + commit com uma mensagem (não destrutivo; amend não suportado) | POST /v1/mcp/operation/preview/commit → cartão de aprovação lista os arquivos exatos que serão colocados em staging e commitados; passa pelo pipeline normal de commit (hooks, assinatura, política); a conclusão retorna o novo SHA |
operation.preview.push | Propor push de um branch para um remote (set-upstream opcional; force-with-lease mostra um aviso de ALTO risco) | POST /v1/mcp/operation/preview/push → cartão de aprovação com remote + branch + aviso de força quando aplicável; executa o fluxo de push protegido |
operation.preview.branch | Propor criação (e opcionalmente checkout) de um branch a partir de um ponto inicial | POST /v1/mcp/operation/preview/branch → cartão de aprovação com nome + ponto inicial + escolha de checkout |
operation.preview.branchDelete | Propor exclusão de branches locais mesclados em um ou mais repositórios (targets, até 20 repositórios × 20 branches, 100 no total). O agente nomeia os branches; o FluxGit decide quais são excluíveis. Branches remotos nunca são tocados | POST /v1/mcp/operation/preview/branchDelete → o cartão inspeciona cada branch nativamente e mantém qualquer branch com commits fora do HEAD ou de seu upstream, com checkout em qualquer lugar, ou cujo tip se moveu; cada tip excluído é registrado no histórico de exclusão de branches da Fleet, onde Restore o recria. A conclusão retorna resultados por branch deleted/failed/skipped |
operation.preview.submodulePointer | Propor registrar (record, requer message) ou retornar a (return) um ponteiro de submódulo em qualquer profundidade (parentPath + relativePath). Pins opcionais expectedRecordedOid / expectedCheckedOutOid, conforme lidos de submodule.status | POST /v1/mcp/operation/preview/submodulePointer → record commita apenas o gitlink no pai através do próprio commit do Git (hooks e assinatura se aplicam; nada é enviado por push); return faz checkout do commit registrado em detached, registrando o checkout anterior como um ponto de restauração. O submódulo deve estar inicializado, limpo e diferente de seu ponteiro registrado |
operation.cancel | Cancelar a proposta ainda pendente do próprio agente por previewId | POST cancel; o cartão desaparece da fila do usuário como uma proposta expirada |
Todas as propostas de escrita exigem um reason de texto livre para que o usuário veja a justificativa do agente no modal de aprovação. Todas reutilizam o mesmo ciclo de vida durável do gateway (pending → approved → executing → completed|failed, com ramificações de rejeição/cancelamento/expiração) e a mesma ponte Tauri na UI. Seis shims cobrem pendente, recuperável, aprovar, reivindicar, rejeitar e concluir. Após reinicialização, propostas Aprovadas podem ser retomadas apenas após revalidação de repo/ref e reivindicação; propostas em Execução são mostradas para reconciliação explícita e nunca são reexecutadas cegamente. Quando uma operação aprovada captura um ponto de restauração, o result de conclusão expõe esses metadados de recuperação para que o agente possa relatá-los sem adivinhar.
O limite é deliberadamente fail-closed no momento da aprovação. O FluxGit resolve
o repoPath da proposta para seu id canônico de repositório aberto e exige que ele
corresponda ao repositório que o humano está revisando; um caminho não resolvido, incompatibilidade, ou
troca de repositório bloqueia a execução. Os argumentos da ferramenta são validados antes do
despacho e novamente pelo gateway. Uma política de agente declarativa opcional pode
negar propostas antes de um cartão abrir. Suas regras correspondem ao agentId que o sidecar
encaminha (o clientInfo.name sanitizado e autodeclarado, como claude-code)
e podem limitar esse agente a operações, refs e, com pathConstraints,
prefixos de caminho de repositório e worktree. Se FLUXGIT_MCP_AGENT_POLICY estiver configurado
mas o arquivo estiver ausente, ilegível, malformado ou não suportado, o gateway
não inicia. Sem política configurada, a compatibilidade permanece permissiva,
mas a aprovação humana por operação ainda é obrigatória.
Outros agentes no mesmo repositório (dicas de colisão)
Cada resultado operation.preview.* pode carregar um objeto otherAgents opcional:
os outros agentes agents.presence encontra no repositório da proposta e, quando
ambos os lados nomeiam seus arquivos (descarte e commit paths, cabeçalhos de patch, etapas
do plano, o diretório de submódulo de submodulePointer), o overlappingPaths. É apenas informativo: é adicionado após
a decisão do gateway, nunca bloqueia uma proposta e nunca muda como ela é
aprovada. Está ausente quando a detecção de agente está desabilitada.
"otherAgents": {
"informational": true,
"agents": [{ "agent": "codex", "state": "working", "sources": ["process", "session"],
"branch": "codex/fix-login", "lastTool": "apply_patch",
"files": ["src/login.rs"], "overlappingPaths": ["src/login.rs"],
"pid": 4242, "lastActivityMs": 1790000000000, "mcpClient": null,
"sameAgentAsCaller": false }],
"agentCount": 1, "overlappingAgentCount": 1, "proposalPathsKnown": true,
"omittedLikelyCaller": 1, "note": "Informational only: ..."
}
A detecção é local e somente leitura: os armazenamentos SQLite de outros agentes são abertos
somente leitura e apenas caminhos relativos ao repositório, nomes de ferramentas, branches e horários
saem do detector. FLUXGIT_MCP_AGENT_DETECTION_DISABLED (qualquer valor) desativa
isso: agents.presence então retorna 10011 e as prévias não trazem nenhuma dica.
Cada sidecar também registra quais repositórios seu cliente usou, para que o desktop
e outros sidecars possam ver: <run_dir>/presence/mcp/<pid>.json (0600) com
o nome e versão autodeclarados de clientInfo e, por repositório, o
caminho canônico, horário e último nome de ferramenta. Apenas chamadas aceitas são
registradas (uma proposta que a política do agente ou um FluxGit ausente recusou não é);
o arquivo é removido na saída limpa. FLUXGIT_MCP_PRESENCE_DISABLED desativa
isso.
Detalhes do protocolo de escrita
Toda chamada operation.preview.* segue o mesmo protocolo de rede. Exemplo para operation.preview.merge:
1. O sidecar faz POST da proposta:
POST /v1/mcp/operation/preview/merge HTTP/1.1
Host: 127.0.0.1:59647
Content-Type: application/json
{
"previewId": "1f3c5b9a-...-uuid",
"agentId": "external-mcp-sidecar",
"operationType": "merge",
"repoPath": "/Users/dev/projects/checkout",
"sourceRef": "feature/cart-redesign",
"targetRef": "main",
"reason": "Cart redesign work is complete; tests pass on the feature branch.",
"strategy": "merge",
"requestedAt": "2026-05-28T11:42:09.512Z"
}
2. O gateway responde 202 Accepted:
{ "previewId": "1f3c5b9a-...-uuid", "status": "pending", "expiresAt": "2026-05-28T11:47:09.512Z" }
3. O sidecar realiza uma leitura de status limitada:
GET /v1/mcp/operation/status/1f3c5b9a-...-uuid HTTP/1.1
Host: 127.0.0.1:59647
Se a proposta ainda estiver ativa, a ferramenta de prévia retorna prontamente:
{
"tool": "operation.preview.merge",
"readOnly": false,
"accepted": true,
"previewId": "1f3c5b9a-...-uuid",
"status": "pending",
"nextAction": {
"tool": "operation.status",
"data": { "previewId": "1f3c5b9a-...-uuid" }
}
}
Isso é um envio de proposta bem-sucedido, não uma operação Git bem-sucedida.
4. O cliente consulta operation.status até o gateway reportar um estado terminal:
{
"previewId": "1f3c5b9a-...-uuid",
"operationType": "merge",
"status": "completed",
"result": {
"commitSha": "9a8b7c6d...",
"restorePointId": "rp_2026_05_28_1142",
"conflicts": []
}
}
completed retorna isError: false. Uma proposta pending ou approved ativa
também retorna como um resultado aceito bem-sucedido, mas não afirma que o Git mudou.
Qualquer estado terminal não concluído (rejected, failed, expired, cancelled)
retorna isError: true com o payload estruturado, para que o agente possa reportar o
resultado real em vez de inventar um.
O mesmo padrão se aplica a todas as 12 ferramentas operation.preview.*. Apenas os campos
do corpo da requisição e o formato do resultado diferem; o envio da proposta, a leitura
imediata única, a continuação assíncrona operation.status e a semântica de erro são
compartilhados. O resumo do contrato público é mantido em
fluxgit.com/features/mcp-agent-git.
Limite: shell livre vs. com FluxGit
O sidecar fala MCP sem o FluxGit instalado. A inspeção Git padrão funciona (status, refs, histórico, reflog, diff.text, etc.). As ferramentas que exigem FluxGit retornam o código de erro JSON-RPC 10001 com um upgradeHint apontando o agente para o fluxo de instalação/configuração.
Classificação por camadas:
- Shell livre — trabalha apenas com
gitlocal:repo.brief,repo.scope,repo.status,repo.refs,repo.branchStack,repo.history,repo.reflog,commit.details,worktree.changes,worktree.list,submodule.status,diff.text,conflict.read,fleet.digest.agents.presencetambém não precisa de FluxGit: lê o estado local do agente (e registra a presença MCP do FluxGit quando presente). - Híbrido — trabalha localmente com fallback documentado, enriquecido pelo FluxGit:
fleet.radar,diff.semantic,diff.semanticFallbacks,repo.conflictPreflight. - Exige FluxGit — retorna
gateway_not_configuredsem FluxGit porque sintetizá-los apenas a partir de refs locais enganaria o agente:safety.timeline,safety.eventDetails,flux.latestRestorePoint,flux.restorePoints,flux.restorePointDetails. - Handshake de escrita — roteia pela aprovação da UI do FluxGit via servidor de
handshake do gateway. As 12 ferramentas
operation.preview.*retornam uma proposta ativa aceita prontamente e continuam viaoperation.status;operation.cancelretira uma proposta pendente de propriedade do mesmo agente. O código10003é usado apenas quando a ponte não consegue aceitar ou servir o handshake.
Início rápido
Instale o crate publicado (coloca fluxgit-mcp-sidecar no seu PATH):
cargo install fluxgit-mcp-sidecar --locked
Para instalar o branch de código-fonte atual:
cargo install --git https://github.com/fluxgit-hq/fluxgit-mcp-server fluxgit-mcp-sidecar --locked
Ou compile a partir de um clone:
# Build
cargo build --release
# Run as MCP server (stdin/stdout transport)
./target/release/fluxgit-mcp-sidecar
Conecte qualquer agente compatível com MCP
Cole o bloco genérico abaixo em qualquer configuração de host MCP. Nenhuma instalação específica de cliente é necessária.
{
"mcpServers": {
"fluxgit": {
"type": "stdio",
"command": "/absolute/path/to/fluxgit-mcp-sidecar",
"env": {
"FLUXGIT_MCP_HANDSHAKE_ADDR": "127.0.0.1:59647",
"FLUXGIT_MCP_AUDIT_LOG": "/optional/path/to/audit.jsonl"
}
}
}
}
FLUXGIT_MCP_HANDSHAKE_ADDR é o endereço canônico da ponte gerado pelo
FluxGit Quick Connect. FLUXGIT_GATEWAY_ADDR e FLUXGIT_GATEWAY_URL permanecem
como fallbacks de compatibilidade. O sidecar aceita apenas HTTP simples em um host de loopback
com uma porta explícita; um host remoto, credenciais, caminho, consulta, fragmento, HTTPS,
ou porta ausente é rejeitado. Sem uma ponte local válida, a camada de shell livre
ainda funciona.
FLUXGIT_MCP_AUDIT_LOG habilita um log de auditoria JSONL somente anexação de cada tools/call. Os argumentos são hashados; caminhos brutos e identificadores nunca são gravados literalmente.
Contrato de diff semântico
diff.semantic é a ferramenta mais usada por agentes de IA e a mais fácil de usar incorretamente. A regra é estrita:
Um resultado só pode ser chamado de semântico se
data.supportedfor exatamentetrue.
Quando o mecanismo semântico do FluxGit não está disponível (app FluxGit não está em execução, endereço do gateway não configurado, ou o repositório não registrado no FluxGit), diff.semantic retorna:
{
"tool": "diff.semantic",
"readOnly": true,
"data": {
"supported": false,
"fallback": "diff.text",
"reason": "Semantic diff is not available in local sidecar fallback mode.",
"textDiffArguments": { "repoPath": "...", "base": "...", "head": "...", "path": "..." }
}
}
Com o app FluxGit em execução e o repositório registrado no FluxGit, a mesma chamada é atendida pelo mecanismo de diff do FluxGit através da ponte somente leitura do gateway e retorna supported: true com hunks semânticos por arquivo:
{
"tool": "diff.semantic",
"readOnly": true,
"source": "fluxgit-gateway",
"data": {
"supported": true,
"engine": "fluxgit-diff-engine",
"files": [
{
"path": "src/main.rs",
"fallbackToText": false,
"hunks": [{
"header": "fn main",
"lines": [{
"type": "modified", "oldLine": 3, "newLine": 3,
"content": "let x = 2;", "oldContent": "let x = 1;",
"changedTokens": ["2"], "oldChangedTokens": ["1"]
}]
}]
},
{
"path": "logo.bin",
"fallbackToText": true,
"hunks": [],
"reason": "The semantic engine could not parse this file (unsupported language, binary or unreadable source); use a text diff for it.",
"textDiffArguments": { "repoPath": "...", "base": "...", "head": "...", "path": "logo.bin" }
}
],
"changedFiles": 2,
"filesTruncated": false
}
}
A honestidade é por arquivo, não apenas por chamada: arquivos que o mecanismo não conseguiu analisar chegam com fallbackToText: true, um motivo e textDiffArguments prontos para uso — nunca como hunks semânticos sintetizados. diff.semanticFallbacks segue a mesma divisão e, quando conectado, lista os registros reais de fallback por arquivo do mecanismo.
Agentes conectados devem:
- Chamar
diff.semantic. - Ler
data.supported. - Se
true, usar o payload semântico e rotular os resultados como semânticos — exceto entradas comfallbackToText: true, que devem ser apresentadas como fallbacks de texto. - Se
false, chamardiff.textcomdata.textDiffArgumentse apresentar os resultados como fallback de diff de texto. - Nunca inferir movimentos de função ou classe apenas a partir de um patch de texto.
Redação permitida: "O FluxGit relatou um fallback de diff de texto para este arquivo".
Redação proibida: "Este é um diff semântico" quando supported=false.
Arquivo de presença (qual agente está trabalhando onde)
A menos que FLUXGIT_MCP_PRESENCE_DISABLED esteja definido, cada processo sidecar mantém um
arquivo local, <FluxGit run dir>/presence/mcp/<pid>.json, para que o app desktop do FluxGit
possa mostrar qual agente de codificação está conectado e em qual repositório está trabalhando.
Ele contém apenas o nome e a versão do cliente que o agente declarou em
initialize, e por repositório (no máximo 16) o repoPath verificado, o horário
da última chamada e o nome da ferramenta. Nenhum outro argumento, nenhum resultado. Diferente do
log de auditoria, o caminho do repositório é armazenado como está para que o desktop possa correspondê-lo; o
arquivo é privado (0600 em um diretório 0700), reescrito atomicamente, excluído na
saída limpa, varrido após 24 horas, e escrevê-lo nunca afeta uma chamada de ferramenta.
O nome do cliente é autodeclarado, não uma identidade autenticada.
Log de auditoria
A menos que FLUXGIT_MCP_AUDIT_DISABLED esteja definido, o sidecar tenta anexar cada
tools/call ao ledger JSONL compartilhado. O gateway tenta anexos de decisão humana
através do mesmo gravador. FLUXGIT_MCP_AUDIT_LOG substitui o caminho;
caso contrário, ambos os processos usam <FluxGit run dir>/audit/mcp.jsonl (incluindo
FLUXGIT_RUN_DIR):
{
"id": "bdeca765-488c-4e2a-b86b-25cd734f2988",
"timestamp": 1712345678901,
"auditSchemaVersion": 1,
"auditChainVersion": 1,
"sequence": 42,
"segmentId": "7ab6fa7a-c5bf-4d82-86a8-26b4728b5acd",
"previousHash": "sha256:...",
"entryHash": "sha256:...",
"tool": "repo.status",
"event_type": "tool_call",
"repo_scope": "repoPath:sha256:...",
"args_fingerprint": "sha256:...",
"risk": "read",
"approval": "none",
"result": "success",
"session_id": "my-agent",
"duration_ms": 12,
"summary": "...",
"readOnly": true,
"sidecarReadOnly": true,
"signature": "base64url-ed25519",
"signatureKeyId": "1a2b3c4d5e6f7a8b",
"signatureVersion": 3
}
Caminhos e identificadores sensíveis são hashados, nunca armazenados literalmente. Um bloqueio estável entre processos protege validação, rotação e a anexação completa mais sincronização. As linhas são limitadas a 256 KiB. O segmento ativo rotaciona em 4 MiB e no máximo quatro segmentos rotacionados são retidos, com um checkpoint assinado quando a assinatura está configurada.
Assinaturas Ed25519 por entrada (enviado em 2026-05-28)
A assinatura de auditoria é opcional. Quando FLUXGIT_MCP_AUDIT_SIGN_KEY aponta para uma chave privada Ed25519 PEM PKCS8, cada entrada anexada é assinada com essa chave. Entradas assinadas adicionam:
signature— assinatura Ed25519 base64url (sem preenchimento) sobre o JSON canônico da entrada sem o campo de assinatura.signatureKeyId— prefixo hex de 16 caracteres da chave pública correspondente, para que chaves rotacionadas possam coexistir no mesmo JSONL.signatureVersion: 3— domínio de assinatura encadeado atual; o id da chave, sequência, hash anterior e hash da entrada são incluídos nos bytes assinados.
Regra de JSON canônico (o verificador deve corresponder exatamente): classificar recursivamente as
chaves de cada objeto lexicograficamente por ordem de bytes UTF-8; arrays preservam ordem;
remover signature; serializar compactamente. Para versões 2 e 3, manter
signatureKeyId e signatureVersion no objeto assinado. Para entradas assinadas
legadas sem versão, o verificador também remove signatureKeyId.
Se a variável de ambiente não estiver definida, novas entradas são encadeadas mas não assinadas para compatibilidade retroativa. Se estiver explicitamente definida, uma chave vazia, ausente, insegura, superdimensionada ou inválida falha a inicialização da auditoria de forma fechada; nunca degrada para saída não assinada.
Verificando um log de auditoria
O binário do sidecar também funciona como verificador:
fluxgit-mcp-sidecar verify-audit /path/to/mcp.jsonl --pubkey /path/to/install.pub.pem
A CLI transmite o arquivo ativo e as rotações retidas com memória limitada. Ela
valida sequência, hashes, nomes de segmentos, checkpoints e assinaturas, depois
relata apenas contadores limitados (entries, chained, legacy, signed,
unsigned, segments e o intervalo de sequência retido). Registros legados por entrada
permanecem legíveis e verificáveis, mas são relatados como legacy, nunca como
parte da cadeia à prova de adulteração. Para um portão de evidência estrito, execute:
fluxgit-mcp-sidecar verify-audit /path/to/mcp.jsonl --pubkey /path/to/install.pub.pem --require-signed
O código de saída é 0 em sucesso, 3 para dados malformados, cadeia/rotação quebrada, uma
assinatura ruim e, em modo estrito, qualquer entrada não assinada; erros de uso retornam 2.
A verificação programática do ledger completo usa verify_audit_ledger; o mais antigo
verify_audit_event_signature permanece disponível para verificações compatíveis por entrada.
Uma cadeia local não pode provar exclusão ou substituição de todo o histórico
retido (ou seu checkpoint local) sem uma âncora externa independentemente confiável.
Entradas retidas assinadas impedem que um atacante sem a chave privada
recalcule uma cadeia modificada.
A configuração de auditoria (incluindo uma chave de assinatura explícita) falha de forma fechada na inicialização. Uma falha posterior de anexação no sistema de arquivos/disco cheio é registrada como degradada, mas não desfaz uma resposta de ferramenta ou uma transição de ciclo de vida do gateway já durável; o diário do ciclo de vida do gateway permanece autoritativo para recuperação.
Detalhes do protocolo
O servidor suporta duas eras de protocolo:
2026-07-28(preferido, sem estado): chameserver/discover, depois incluaparams._meta.io.modelcontextprotocol/protocolVersioneparams._meta.io.modelcontextprotocol/clientCapabilitiesem cada requisição. Resultados modernos carregamresultType: "complete"e metadados do servidor; resultados de lista adicionamttlMsecacheScope.tools/listincluititle,inputSchema,outputSchemae anotações.tools/callinclui tantocontentapresentacional quanto o mesmo payload emstructuredContent. Apenas as ferramentas de proposta eoperation.statusanunciampreviewId,status,acceptedenextActionem seuoutputSchema; objetos de esquema são abertos a menos que digam"additionalProperties": false.2024-11-05(compatibilidade legada): hosts mais antigos continuam usandoinitialize. Campos apenas modernos são omitidos dos resultados legados. A saída Stdio é JSON-RPC 2.0 padrão delimitado por novas linhas: exatamente um valor JSON compacto por linha. O JSON nocontent[0].textde um resultado também é compacto (sem indentação), com as mesmas chaves e valores questructuredContent. O enquadramentoContent-Lengthpré-padrão permanece aceito como entrada apenas para clientes FluxGit antigos; o servidor nunca o emite. Os quadros são limitados a 8 MiB. Notificações JSON-RPC não recebem resposta, e métodos de solicitação enviados sem um id não são executados.
Existem 38 ferramentas no tools/list moderno: 25 anunciam annotations.readOnlyHint: true; as 12 ferramentas operation.preview.* e operation.cancel anunciam readOnlyHint: false. Essas anotações descrevem efeitos para o host; elas não são autorização.
Códigos de erro:
| Código | Significado |
|---|---|
-32700 | Erro de análise |
-32600 | Solicitação inválida (JSON-RPC malformado) |
-32601 | Método não encontrado |
-32602 | Parâmetros inválidos ou ferramenta desconhecida |
-32603 | Erro interno |
-32022 | Versão MCP moderna não suportada; data contém supported e requested |
10001 | Gateway não configurado — instale/inicie o FluxGit para usar as ferramentas exigidas pelo FluxGit |
10002 | Uma ponte FluxGit configurada não tinha payload para servir (por exemplo, um fallback local não tinha um repoPath absoluto) |
10003 | A ponte local de handshake de escrita está ausente, inválida ou inacessível; nenhuma proposta aceita deve ser inferida |
10004 | A proposta terminou sem conclusão (rejected, failed, expired ou cancelled) |
10005 | O gateway não conhece o previewId solicitado (id errado/nunca aceito ou poda após retenção terminal). Apenas reiniciar não justifica uma nova proposta: registros Aprovado/Executando se recuperam de forma durável e um resultado Git possivelmente iniciado deve ser reconciliado primeiro. |
10006 | O gateway recusou a proposta antes de abrir um cartão (política, validação ou cota) |
10007 | O gateway retornou um previewId canônico malformado/inseguro; o sidecar se recusa a segui-lo |
10010 | Comando Git local somente leitura falhou |
10011 | A detecção de agente está desabilitada (FLUXGIT_MCP_AGENT_DETECTION_DISABLED); agents.presence não pode responder |
Status
Este é um servidor MCP funcional. A superfície somente leitura e todas as 12 rotas operation.preview.* estão implementadas; operation.cancel gerencia apenas uma proposta pendente de propriedade do mesmo id de agente auto-relatado. O handshake de escrita renderiza um cartão de aprovação no FluxGit e completa através do pipeline protegido do aplicativo. Os clientes recebem resultados de ciclo de vida estruturados em vez de um sucesso sintético. clientInfo.name é atribuição saneada para política, cota e auditoria; é auto-relatado e nunca deve ser tratado como identidade autenticada.
Roadmap
- Vídeo de demonstração ponta a ponta — gravação pública do loop agente-propõe → usuário-aprova → FluxGit-executa, capturado de uma instalação ao vivo.
- Log de auditoria exportável em CSV/JSON — enviado: assinatura Ed25519 por entrada (2026-05-28). Restante: CSV/JSON exportável e política de retenção para o painel de auditoria do aplicativo FluxGit.
- Transporte HTTP / SSE — para implantações em nuvem / hosts MCP compartilhados.
- Registro MCP oficial —
io.github.fluxgit-hq/fluxgit-mcp-serverestá ativo e resolve para o cratefluxgit-mcp-sidecarpublicado.
Licença
Apache-2.0. Veja LICENSE.
Relacionados
- FluxGit — o aplicativo de desktop que produz o contexto alimentado pelo FluxGit.
- MCP agent Git — visão geral pública do produto e protocolo.
- Claude Code, Cursor e Codex — guias de configuração e fluxo de trabalho.
- Benchmark de token de contexto Git — fixture reproduzível, saídas brutas, scripts e somas de verificação.
- Código-fonte público — este servidor Apache-2.0.