FluxGit MCP Server
Servidor MCP de Git con 23 herramientas de solo lectura. Las propuestas de escritura se ejecutan solo después de que una persona revise el impacto específico de la operación y las apruebe en FluxGit Desktop.
Documentación
fluxgit-mcp-sidecar
mcp-name: io.github.fluxgit-hq/fluxgit-mcp-server
Servidor de Protocolo de Contexto de Modelo (MCP) con prioridad en la seguridad para Git.
Los agentes de IA inspeccionan. FluxGit mantiene el control.
Un servidor MCP en Rust con 38 contratos para agentes de código de IA: 25 herramientas de solo lectura y 13 herramientas de operación con aprobación humana (12 propuestas más la cancelación de una propuesta pendiente). El sidecar nunca ejecuta una escritura de Git; conecta propuestas aprobadas a la aplicación de escritorio FluxGit.

Para comparaciones de presupuesto de contexto, consulte el benchmark público de tokens de contexto de Git. Publica el fixture, las salidas sin procesar, los scripts y las sumas de verificación, incluyendo tanto el barrido amplio de CLI como un contraejemplo más pequeño ajustado manualmente.
Por qué existe esto
Cada vez se pide más a los agentes de codificación de IA que naveguen por repositorios reales: explicar el estado de las ramas, resumir diffs, encontrar commits perdidos, recomendar pasos seguros a seguir. Para hacerlo bien, un agente necesita un contexto de Git más rico que git status y lo suficientemente estructurado para razonar sobre él. Para hacerlo de forma segura, un agente nunca debe poder mutar refs silenciosamente, hacer force-push, descartar trabajo o aplicar parches sin que un humano apruebe la consecuencia.
Otros servidores MCP de Git enfrentan una elección: mantenerse estrictamente de solo lectura (utilidad limitada) o exponer herramientas de escritura directamente (peligroso — los agentes alucinan, las indicaciones pueden ser envenenadas, los errores son destructivos). Este sidecar no elige ninguna de las dos. La inspección está validada por esquema y acotada; las operaciones pasan por un manejo de escritura con confirmación en la interfaz: el agente propone, FluxGit muestra la vista previa, el usuario aprueba en la aplicación, y FluxGit ejecuta a través de su pipeline de seguridad con puntos de restauración y auditoría.
Qué se expone
25 herramientas de solo lectura
| Herramienta | Propósito |
|---|---|
repo.brief | Conciencia situacional en una sola llamada — rama, adelante/atrás, operación en curso, resumen del árbol de trabajo, stashes, deriva agregada de submódulos, commits recientes, convenciones detectadas y sugerencias de próximos pasos. La primera llamada recomendada en una sesión de agente; reemplaza 6-10 llamadas crudas de git y está presupuestada en tokens por diseño |
repo.scope | Delimitación de monorepo — cambios del árbol de trabajo de un subárbol, commits recientes, churn (commits + autores en una ventana) y propietarios de CODEOWNERS en una sola llamada |
repo.status | Árbol de trabajo, rama actual, rutas sucias |
repo.refs | Ramas, etiquetas, remotos, stashes |
repo.branchStack | Rama actual vs upstream / base / relacionada |
repo.history | Historial de commits paginado |
repo.reflog | Línea de tiempo de movimientos con sugerencias de recuperación |
repo.conflictPreflight | Predecir el resultado de merge/rebase antes de ejecutarlo |
conflict.read | Conflicto activo como datos estructurados — operación en curso, commits productores nuestro/suyo, clasificación de etapas por archivo, contenidos base/nuestro/suyo (con límite de tamaño, marcado binario) y rangos de líneas de la región de marcadores. No más análisis de sopa <<<<<<< |
commit.details | Metadatos de un solo commit + archivos modificados |
worktree.changes | Resumen de cambios del árbol de trabajo por ruta |
worktree.list | Todos los worktrees (principal + vinculados) con rama/detached, SHA de HEAD y banderas de bloqueado/podable — la base de solo lectura para worktrees paralelos de agentes |
submodule.status | Lista y estado de submódulos |
diff.text | Parche de texto estándar (compatible con git diff) |
diff.semantic | Explicación semántica negociada por capacidades |
diff.semanticFallbacks | Rutas que retrocedieron de semántico a texto |
fleet.radar | Cola de atención multi-repositorio |
fleet.digest | Qué cambió en la flota desde un momento — movimientos de HEAD y reflog de ramas locales de muchos repositorios, más recientes primero, limitados por maxEvents (predeterminado 200, máximo 1000). repoPaths, o los repositorios registrados de FluxGit dentro de las raíces permitidas cuando se omite. identity es exactamente lo que Git registró (la identidad configurada, no prueba de una persona o un agente); rewrote marca movimientos que descartaron el tip anterior (reset, amend, rebase, movimientos forzados). Solo lee archivos de reflog; no se obtiene ni escribe nada |
agents.presence | Qué otros agentes de codificación están trabajando en este repositorio — solo de fuentes locales (procesos de agentes en ejecución y sus hijos, los almacenes de sesión de los propios agentes, archivos que mantienen en el repositorio, editores con agentes integrados y registros de presencia de FluxGit MCP). Por agente: state (trabajando/abierto/reciente), sources, rama, última herramienta y archivos relativos al repositorio cuando se conocen. Los nombres son lo que cada herramienta o cliente MCP declara sobre sí mismo. Su propio registro MCP está excluido; los hallazgos que probablemente sean de su propia sesión se marcan como likelyCaller. Nunca devuelve indicaciones, mensajes o contenidos de archivos |
safety.timeline | Eventos de seguridad sintetizados a partir de puntos de restauración + reflog |
safety.eventDetails | Profundización en un evento de la línea de tiempo |
flux.latestRestorePoint | Punto de restauración más reciente de FluxGit |
flux.restorePoints | Lista de puntos de restauración |
flux.restorePointDetails | Un punto de restauración con refs antes/después |
operation.status | Estado asíncrono autoritativo por previewId; consulte después de que una vista previa devuelva accepted: true y no informe un resultado de Git antes de que sea terminal |
13 herramientas de escritura con confirmación en la interfaz
Las 12 propuestas de operation.preview.* se envían a través de la puerta de enlace de FluxGit cuando
está configurada. El sidecar publica la propuesta, realiza una lectura de estado acotada,
y normalmente regresa de inmediato con accepted: true, el previewId canónico,
el estado actual y nextAction.tool: "operation.status". La
aplicación FluxGit muestra una tarjeta de aprobación "Solicitado por agente de IA" mientras la revisión humana
continúa de forma asíncrona. El código 10003 está reservado para un puente que está ausente,
inválido o inalcanzable; no es un tiempo de espera de aprobación humana.
Los 12 esquemas de vista previa aceptan un idempotencyKey acotado opcional. Reutilícelo
solo al reintentar la misma intención lógica; el sidecar lo delimita al
tipo de operación para que el reintento se resuelva a la propuesta de puerta de enlace existente. Omítalo
para una intención nueva—incluso cuando los otros argumentos coincidan—y el sidecar envía
una clave nueva respaldada por UUID. Las herramientas de vista previa por lo tanto continúan anunciando
idempotentHint: false.
| Herramienta | Propósito | Envío a puerta de enlace |
|---|---|---|
operation.preview.merge | Proponer un merge para revisión humana | POST /v1/mcp/operation/preview/merge → tarjeta de aprobación en FluxGit |
operation.preview.rebase | Proponer un rebase no interactivo | interactive: true falla la validación de esquema antes del POST/creación de tarjeta; las solicitudes aceptadas hacen POST /v1/mcp/operation/preview/rebase y abren una tarjeta de advertencia de reescritura de historial |
operation.preview.discard | Proponer descartar cambios del árbol de trabajo | POST /v1/mcp/operation/preview/discard → advertencia específica de ruta; FluxGit requiere un stash de seguridad antes de descartar cambios coincidentes |
operation.preview.reset | Proponer reset suave / mixto / duro | POST /v1/mcp/operation/preview/reset → tarjeta consciente del modo (el modo duro fuerza confirmación fuerte) |
operation.preview.patch | Proponer aplicar un parche generado por agente | POST /v1/mcp/operation/preview/patch → vista previa de parche en monoespacio + alternancia applyToIndex |
operation.preview.plan | Proponer una secuencia de 1-10 pasos usando los cinco tipos de pasos de plan compatibles (merge, rebase, discard, reset, patch) | POST /v1/mcp/operation/preview/plan → tarjeta de pasos numerados; los pasos destructivos requieren una casilla de verificación explícita. Un paso rebase con interactive: true es rechazado por validación de esquema antes del envío; la ejecución se detiene en el primer fallo. Su punto de control previo al plan ancla solo el commit de la rama: la recuperación protegida restaura HEAD/archivos rastreados, mientras que el índice original, el árbol de trabajo y los archivos no rastreados requieren las superficies de recuperación separadas de snapshots/Safety Timeline |
operation.preview.worktree | Proponer crear un worktree aislado para una tarea paralela (no destructivo; nunca toca el historial) | POST /v1/mcp/operation/preview/worktree → tarjeta de aprobación con rama + ruta de destino + motivo; se ejecuta a través de la misma acción de creación de worktree que usa un clic manual |
operation.preview.commit | Proponer staging + commit con un mensaje (no destructivo; amend no compatible) | POST /v1/mcp/operation/preview/commit → la tarjeta de aprobación lista los archivos exactos que se agregarán al staging y se confirmarán; se ejecuta a través del pipeline de commit normal (hooks, firma, política); la finalización devuelve el nuevo SHA |
operation.preview.push | Proponer push de una rama a un remoto (set-upstream opcional; force-with-lease muestra una advertencia de ALTO riesgo) | POST /v1/mcp/operation/preview/push → tarjeta de aprobación con remoto + rama + advertencia de fuerza cuando corresponda; ejecuta el flujo de push protegido |
operation.preview.branch | Proponer crear (y opcionalmente hacer checkout de) una rama desde un punto de inicio | POST /v1/mcp/operation/preview/branch → tarjeta de aprobación con nombre + punto de inicio + elección de checkout |
operation.preview.branchDelete | Proponer eliminar ramas locales fusionadas en uno o más repositorios (targets, hasta 20 repositorios × 20 ramas, 100 en total). El agente nombra las ramas; FluxGit decide cuáles son eliminables. Las ramas remotas nunca se tocan | POST /v1/mcp/operation/preview/branchDelete → la tarjeta inspecciona cada rama de forma nativa y conserva cualquier rama con commits que no estén en HEAD o su upstream, con checkout en cualquier lugar, o cuyo tip se haya movido; cada tip eliminado se registra en el historial de eliminación de ramas de Fleet, donde Restore lo recrea. La finalización devuelve resultados por rama deleted/failed/skipped |
operation.preview.submodulePointer | Proponer registrar (record, requiere message) o volver a (return) un puntero de submódulo a cualquier profundidad (parentPath + relativePath). Pines opcionales expectedRecordedOid / expectedCheckedOutOid, según se leen de submodule.status | POST /v1/mcp/operation/preview/submodulePointer → record confirma solo el gitlink en el padre a través del propio commit de Git (los hooks y la firma se aplican; no se empuja nada); return hace checkout del commit registrado en modo detached, registrando el checkout anterior como punto de restauración. El submódulo debe estar inicializado, limpio y diferir de su puntero registrado |
operation.cancel | Cancelar la propuesta aún pendiente del propio agente por previewId | POST cancel; la tarjeta desaparece de la cola del usuario como una propuesta caducada |
Todas las propuestas de escritura requieren un reason de texto libre para que el usuario vea la justificación del agente en el modal de aprobación. Todas reutilizan el mismo ciclo de vida de puerta de enlace duradero (pending → approved → executing → completed|failed, con ramas de rechazo/cancelación/caducidad) y el mismo puente Tauri en la interfaz. Seis shims cubren pendiente, recuperable, aprobar, reclamar, rechazar y completar. Después de un reinicio, las propuestas Aprobadas pueden reanudarse solo después de la revalidación de repo/ref y la reclamación; las propuestas en Ejecución se muestran para reconciliación explícita y nunca se re-ejecutan a ciegas. Cuando una operación aprobada captura un punto de restauración, el result de finalización expone esos metadatos de recuperación para que el agente pueda informarlos sin adivinar.
El límite está deliberadamente cerrado por fallo en el momento de la aprobación. FluxGit resuelve
el repoPath de la propuesta a su id canónico de repositorio abierto y requiere que
coincida con el repositorio que el humano está revisando; una ruta no resuelta, discrepancia o
cambio de repositorio bloquea la ejecución. Los argumentos de la herramienta se validan antes del
envío y nuevamente por la puerta de enlace. Una política de agente declarativa opcional puede
denegar propuestas antes de que se abra una tarjeta. Sus reglas coinciden con el agentId que el sidecar
reenvía (el clientInfo.name saneado y autodeclarado, como claude-code)
y puede limitar a ese agente a operaciones, refs y, con pathConstraints,
prefijos de ruta de repositorio y worktree. Si FLUXGIT_MCP_AGENT_POLICY está configurado
pero el archivo falta, es ilegible, está malformado o no es compatible, la puerta de enlace
no se inicia. Sin política configurada, la compatibilidad sigue siendo permisiva,
pero la aprobación humana por operación sigue siendo obligatoria.
Otros agentes en el mismo repositorio (sugerencias de colisión)
Every operation.preview.* result may carry an optional otherAgents object:
the other agents agents.presence finds in the proposal's repository and, when
both sides name their files (discard and commit paths, patch headers, plan
steps, the submodule directory of submodulePointer), the overlappingPaths. It is informational only: it is added after
the gateway decided, never blocks a proposal and never changes how it is
approved. It is absent when agent detection is disabled.
"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: ..."
}
La detección es local y de solo lectura: los almacenes SQLite de otros agentes se abren
en modo de solo lectura y solo las rutas relativas al repositorio, nombres de herramientas, ramas y tiempos
salen del detector. FLUXGIT_MCP_AGENT_DETECTION_DISABLED (cualquier valor) lo desactiva:
agents.presence entonces devuelve 10011 y las vistas previas no llevan ninguna pista.
Cada sidecar también registra qué repositorios usó su cliente, para que el escritorio
y otros sidecars puedan verlo: <run_dir>/presence/mcp/<pid>.json (0600) con
el nombre y la versión autodeclarados de clientInfo y, por repositorio, la
ruta canónica, la hora y el último nombre de herramienta. Solo se registran las llamadas que fueron aceptadas
(una propuesta que la política del agente o un FluxGit ausente rechazó no se registra);
el archivo se elimina al salir limpiamente. FLUXGIT_MCP_PRESENCE_DISABLED lo desactiva.
Detalles del protocolo de escritura
Cada llamada a operation.preview.* sigue el mismo protocolo de cable. Ejemplo para operation.preview.merge:
1. El sidecar envía la propuesta por POST:
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. La puerta de enlace responde 202 Aceptado:
{ "previewId": "1f3c5b9a-...-uuid", "status": "pending", "expiresAt": "2026-05-28T11:47:09.512Z" }
3. El sidecar realiza una lectura de estado acotada:
GET /v1/mcp/operation/status/1f3c5b9a-...-uuid HTTP/1.1
Host: 127.0.0.1:59647
Si la propuesta sigue activa, la herramienta de vista previa responde rápidamente:
{
"tool": "operation.preview.merge",
"readOnly": false,
"accepted": true,
"previewId": "1f3c5b9a-...-uuid",
"status": "pending",
"nextAction": {
"tool": "operation.status",
"data": { "previewId": "1f3c5b9a-...-uuid" }
}
}
Esto es un envío de propuesta exitoso, no una operación Git exitosa.
4. El cliente consulta operation.status hasta que la puerta de enlace informa un estado terminal:
{
"previewId": "1f3c5b9a-...-uuid",
"operationType": "merge",
"status": "completed",
"result": {
"commitSha": "9a8b7c6d...",
"restorePointId": "rp_2026_05_28_1142",
"conflicts": []
}
}
completed devuelve isError: false. Una propuesta activa de pending o approved
también se devuelve como un resultado aceptado exitoso, pero no afirma que Git haya cambiado.
Cualquier estado terminal no completado (rejected, failed, expired, cancelled)
devuelve isError: true con la carga estructurada, para que el agente pueda informar el
resultado real en lugar de inventar uno.
El mismo patrón se aplica a las 12 herramientas de operation.preview.*. Solo los campos
del cuerpo de la solicitud y la forma del resultado difieren; el envío de propuestas, la única lectura
inmediata, la continuación asíncrona de operation.status y la semántica de errores son
compartidos. El resumen del contrato público se mantiene en
fluxgit.com/features/mcp-agent-git.
Límite: shell libre vs. impulsado por FluxGit
El sidecar habla MCP sin FluxGit instalado. La inspección estándar de Git funciona (estado, refs, historial, reflog, diff.text, etc.). Las herramientas que requieren FluxGit devuelven el código de error JSON-RPC 10001 con un upgradeHint que apunta al agente al flujo de instalación/configuración.
Clasificación por niveles:
- Shell libre — trabaje solo con
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.presencetampoco necesita FluxGit: lee el estado local del agente (y los registros de presencia MCP de FluxGit cuando están presentes). - Híbrido — trabaje localmente con respaldo documentado, enriquecido por FluxGit:
fleet.radar,diff.semantic,diff.semanticFallbacks,repo.conflictPreflight. - Requiere FluxGit — devuelve
gateway_not_configuredsin FluxGit porque sintetizarlos solo a partir de refs locales engañaría al agente:safety.timeline,safety.eventDetails,flux.latestRestorePoint,flux.restorePoints,flux.restorePointDetails. - Protocolo de escritura — se enruta a través de la aprobación de la interfaz de FluxGit mediante el servidor de
protocolo de la puerta de enlace. Las 12 herramientas de
operation.preview.*devuelven una propuesta activa aceptada rápidamente y continúan a través deoperation.status;operation.cancelretira una propuesta pendiente propiedad del mismo agente. El código10003se usa solo cuando el puente no puede aceptar o servir el protocolo.
Inicio rápido
Instale el crate publicado (coloca fluxgit-mcp-sidecar en su PATH):
cargo install fluxgit-mcp-sidecar --locked
Para instalar la rama fuente actual en su lugar:
cargo install --git https://github.com/fluxgit-hq/fluxgit-mcp-server fluxgit-mcp-sidecar --locked
O compile desde un clon:
# Build
cargo build --release
# Run as MCP server (stdin/stdout transport)
./target/release/fluxgit-mcp-sidecar
Conecte cualquier agente compatible con MCP
Pegue el bloque genérico a continuación en cualquier configuración de host MCP. No se requiere instalación específica del cliente.
{
"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 es la dirección de puente canónica generada por
FluxGit Quick Connect. FLUXGIT_GATEWAY_ADDR y FLUXGIT_GATEWAY_URL siguen siendo
resguardos de compatibilidad. El sidecar acepta solo HTTP simple en un host de bucle local
con un puerto explícito; un host remoto, credenciales, ruta, consulta, fragmento, HTTPS,
o un puerto faltante se rechaza. Sin un puente local válido, el nivel de shell libre
sigue funcionando.
FLUXGIT_MCP_AUDIT_LOG habilita un registro de auditoría JSONL de solo agregar de cada tools/call. Los argumentos se codifican con hash; las rutas e identificadores sin procesar nunca se escriben textualmente.
Contrato de diff semántico
diff.semantic es la herramienta más utilizada para agentes de IA y la más fácil de usar incorrectamente. La regla es estricta:
Un resultado solo puede llamarse semántico si
data.supportedes exactamentetrue.
Cuando el motor semántico de FluxGit no está disponible (la aplicación FluxGit no se está ejecutando, la dirección de la puerta de enlace no está configurada o el repositorio no está registrado en FluxGit), diff.semantic devuelve:
{
"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": "..." }
}
}
Con la aplicación FluxGit ejecutándose y el repositorio registrado en FluxGit, la misma llamada es atendida por el motor de diff de FluxGit a través del puente de solo lectura de la puerta de enlace y devuelve supported: true con fragmentos semánticos por archivo:
{
"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
}
}
La honestidad es por archivo, no solo por llamada: los archivos que el motor no pudo analizar llegan con fallbackToText: true, una razón y textDiffArguments listo para usar — nunca como fragmentos semánticos sintetizados. diff.semanticFallbacks sigue la misma división y, cuando está conectado, enumera los registros de respaldo reales por archivo del motor.
Los agentes conectados deben:
- Llamar a
diff.semantic. - Leer
data.supported. - Si
true, usar la carga semántica y etiquetar los resultados como semánticos — excepto las entradas confallbackToText: true, que deben presentarse como respaldos de texto. - Si
false, llamar adiff.textcondata.textDiffArgumentsy presentar los resultados como un respaldo de diff de texto. - Nunca inferir movimientos a nivel de función o clase solo a partir de un parche de texto.
Redacción permitida: "FluxGit informó un respaldo de diff de texto para este archivo".
Redacción prohibida: "Este es un diff semántico" cuando supported=false.
Archivo de presencia (qué agente trabaja dónde)
A menos que FLUXGIT_MCP_PRESENCE_DISABLED esté configurado, cada proceso de sidecar mantiene un
archivo local, <FluxGit run dir>/presence/mcp/<pid>.json, para que la aplicación de escritorio de FluxGit
pueda mostrar qué agente de codificación está conectado y en qué repositorio está trabajando.
Contiene solo el nombre y la versión del cliente que el agente declaró en
initialize, y por repositorio (como máximo 16) el repoPath verificado, la hora
de la última llamada y el nombre de la herramienta. Sin otros argumentos, sin resultados. A diferencia del
registro de auditoría, la ruta del repositorio se almacena tal cual para que el escritorio pueda coincidir; el
archivo es privado (0600 en un directorio 0700), se reescribe atómicamente, se elimina al
salir limpiamente, se barre después de 24 horas, y escribirlo nunca afecta una llamada de herramienta.
El nombre del cliente es autodeclarado, no una identidad autenticada.
Registro de auditoría
A menos que FLUXGIT_MCP_AUDIT_DISABLED esté configurado, el sidecar intenta agregar cada
tools/call al libro mayor JSONL compartido. La puerta de enlace intenta agregar decisiones
humanas a través del mismo escritor. FLUXGIT_MCP_AUDIT_LOG anula la ruta;
de lo contrario, ambos procesos usan <FluxGit run dir>/audit/mcp.jsonl (incluyendo
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
}
Las rutas e identificadores sensibles se codifican con hash, nunca se almacenan textualmente. Un bloqueo estable entre procesos protege la validación, la rotación y la adición completa más la sincronización. Las líneas están limitadas a 256 KiB. El segmento activo rota a 4 MiB y se retienen como máximo cuatro segmentos rotados, con un punto de control firmado cuando la firma está configurada.
Firmas Ed25519 por entrada (enviado el 2026-05-28)
La firma de auditoría es opcional. Cuando FLUXGIT_MCP_AUDIT_SIGN_KEY apunta a una clave privada Ed25519 PEM PKCS8, cada entrada agregada se firma con esa clave. Las entradas firmadas agregan:
signature— firma Ed25519 en base64url (sin relleno) sobre el JSON canónico de la entrada sin el campo de firma.signatureKeyId— prefijo hex de 16 caracteres de la clave pública correspondiente, para que las claves rotadas puedan coexistir en el mismo JSONL.signatureVersion: 3— dominio de firma encadenado actual; el id de clave, la secuencia, el hash anterior y el hash de entrada se incluyen en los bytes firmados.
Regla de JSON canónico (el verificador debe coincidir exactamente): ordenar recursivamente las
claves de cada objeto lexicográficamente por orden de bytes UTF-8; las matrices preservan el orden;
eliminar signature; serializar de forma compacta. Para las versiones 2 y 3, mantener
signatureKeyId y signatureVersion en el objeto firmado. Para entradas firmadas
heredadas sin versión, el verificador también elimina signatureKeyId.
Si la variable de entorno no está configurada, las nuevas entradas se encadenan pero no se firman por compatibilidad hacia atrás. Si está configurada explícitamente, una clave vacía, faltante, insegura, demasiado grande o inválida hace que el inicio de la auditoría falle de forma cerrada; nunca degrada a salida sin firmar.
Verificación de un registro de auditoría
El binario del sidecar también funciona como verificador:
fluxgit-mcp-sidecar verify-audit /path/to/mcp.jsonl --pubkey /path/to/install.pub.pem
La CLI transmite el archivo activo y las rotaciones retenidas con memoria acotada. Valida
secuencia, hashes, nombres de segmentos, puntos de control y firmas, luego
informa solo contadores acotados (entries, chained, legacy, signed,
unsigned, segments y el rango de secuencia retenido). Los registros heredados por entrada
siguen siendo legibles y verificables, pero se informan como legacy, nunca como
parte de la cadena a prueba de manipulación. Para una puerta de evidencia estricta, ejecute:
fluxgit-mcp-sidecar verify-audit /path/to/mcp.jsonl --pubkey /path/to/install.pub.pem --require-signed
El código de salida es 0 en éxito, 3 para datos malformados, cadena/rotación rota, una
firma incorrecta y, en modo estricto, cualquier entrada sin firmar; los errores de uso devuelven 2.
La verificación programática del libro mayor completo usa verify_audit_ledger; el más antiguo
verify_audit_event_signature sigue disponible para verificaciones compatibles por entrada.
Una cadena local no puede probar la eliminación o el reemplazo de todo el
historial retenido (o su punto de control local) sin un ancla externa independientemente
confiable. Las entradas retenidas firmadas sí impiden que un atacante sin la
clave privada recalcule una cadena modificada.
La configuración de auditoría (incluida una clave de firma explícita) falla de forma cerrada al inicio. Una falla posterior de agregado en el sistema de archivos/disco completo se registra como degradada pero no deshace una respuesta de herramienta ni una transición de ciclo de vida de la puerta de enlace ya duradera; el diario del ciclo de vida de la puerta de enlace sigue siendo autoritativo para la recuperación.
Detalles del protocolo
El servidor admite dos eras de protocolo:
2026-07-28(preferido, sin estado): llame aserver/discover, luego incluyaparams._meta.io.modelcontextprotocol/protocolVersionyparams._meta.io.modelcontextprotocol/clientCapabilitiesen cada solicitud. Los resultados modernos llevanresultType: "complete"y metadatos del servidor; los resultados de lista agreganttlMsycacheScope.tools/listincluyetitle,inputSchema,outputSchemay anotaciones.tools/callincluye tantocontentpresentacional como la misma carga enstructuredContent. Solo las herramientas de propuesta yoperation.statusanuncianpreviewId,status,acceptedynextActionen suoutputSchema; los objetos de esquema están abiertos a menos que digan"additionalProperties": false.2024-11-05(compatibilidad heredada): los hosts más antiguos continúan usandoinitialize. Los campos solo modernos se omiten de los resultados heredados. La salida estándar es JSON-RPC 2.0 delimitado por nuevas líneas: exactamente un valor JSON compacto por línea. El JSON en elcontent[0].textde un resultado también es compacto (sin indentación), con las mismas claves y valores questructuredContent. El enmarcadoContent-Lengthpre-estándar sigue siendo aceptado como entrada únicamente para clientes FluxGit antiguos; el servidor nunca lo emite. Los marcos están limitados a 8 MiB. Las notificaciones JSON-RPC no reciben respuesta, y los métodos de solicitud enviados sin un id no se ejecutan.
Hay 38 herramientas en el tools/list moderno: 25 anuncian annotations.readOnlyHint: true; las 12 herramientas operation.preview.* y operation.cancel anuncian readOnlyHint: false. Estas anotaciones describen efectos para el host; no son autorización.
Códigos de error:
| Código | Significado |
|---|---|
-32700 | Error de análisis |
-32600 | Solicitud no válida (JSON-RPC malformado) |
-32601 | Método no encontrado |
-32602 | Parámetros no válidos o herramienta desconocida |
-32603 | Error interno |
-32022 | Versión MCP moderna no compatible; data contiene supported y requested |
10001 | Gateway no configurado — instale/inicie FluxGit para usar las herramientas requeridas por FluxGit |
10002 | Un puente FluxGit configurado no tenía carga útil que servir (por ejemplo, una alternativa local carecía de un repoPath absoluto) |
10003 | El puente local de handshake de escritura está ausente, no es válido o es inalcanzable; no se debe inferir ninguna propuesta aceptada |
10004 | La propuesta terminó sin completarse (rejected, failed, expired o cancelled) |
10005 | El gateway no conoce el previewId solicitado (id incorrecto/nunca aceptado o poda después de la retención terminal). Reiniciar solo no justifica una nueva propuesta: los registros Aprobado/En ejecución se recuperan de forma duradera y un resultado de Git posiblemente iniciado debe reconciliarse primero. |
10006 | El gateway rechazó la propuesta antes de abrir una tarjeta (política, validación o cuota) |
10007 | El gateway devolvió un previewId canónico malformado/inseguro; el sidecar se niega a seguirlo |
10010 | El comando Git local de solo lectura falló |
10011 | La detección de agentes está deshabilitada (FLUXGIT_MCP_AGENT_DETECTION_DISABLED); agents.presence no puede responder |
Estado
Este es un servidor MCP funcional. La superficie de solo lectura y las 12 rutas operation.preview.* están implementadas; operation.cancel gestiona únicamente una propuesta pendiente propiedad del mismo id de agente autoinformado. El handshake de escritura renderiza una tarjeta de aprobación en FluxGit y se completa a través del pipeline protegido de la aplicación. Los clientes reciben resultados de ciclo de vida estructurados en lugar de un éxito sintético. clientInfo.name es atribución saneada para política, cuota y auditoría; es autoinformado y nunca debe tratarse como identidad autenticada.
Hoja de ruta
- Video de demostración de extremo a extremo — grabación pública del ciclo agente-propone → usuario-aprueba → FluxGit-ejecuta, capturada desde una instalación en vivo.
- Registro de auditoría exportable CSV/JSON — enviado: firma Ed25519 por entrada (2026-05-28). Pendiente: CSV/JSON exportable y política de retención para el panel de auditoría de la aplicación FluxGit.
- Transporte HTTP / SSE — para implementaciones en la nube / hosts MCP compartidos.
- Registro MCP oficial —
io.github.fluxgit-hq/fluxgit-mcp-serverestá activo y resuelve al cratefluxgit-mcp-sidecarpublicado.
Licencia
Apache-2.0. Ver LICENSE.
Relacionado
- FluxGit — la aplicación de escritorio que produce el contexto impulsado por FluxGit.
- MCP agent Git — descripción general pública del producto y protocolo.
- Claude Code, Cursor y Codex — guías de configuración y flujos de trabajo.
- Benchmark de token de contexto Git — fixture reproducible, salidas sin procesar, scripts y sumas de verificación.
- Código fuente público — este servidor Apache-2.0.