restic-defensive-mcp

Servidor MCP stdio estructuralmente de solo lectura para inspeccionar repositorios restic. Los repositorios y credenciales se sellan al inicio; solo se puede ejecutar un subconjunto fijo de subcomandos de restic (snapshots/ls/find/stats). Sin shell, sin backup/restore/forget/prune.

Documentación

restic-defensive-mcp

Servidor MCP estructuralmente de solo lectura (stdio) para inspeccionar repositorios de restic a través de un cliente MCP no confiable sin exponer un shell, CLI de forma libre o ruta de mutación.

¿Están mis respaldos presentes y recientes, es legible su metadato, y contiene una instantánea los archivos que espero?

¿Por qué no exponer restic directamente?

Restic es una herramienta de respaldo poderosa. Un llamador sin restricciones puede:

  • eliminar el historial de retención (forget / prune)
  • sobrescribir o extraer datos (backup / restore / dump)
  • desbloquear o reescribir el estado del repositorio
  • aceptar URLs de repositorio arbitrarias y comandos de contraseña

Los envoltorios delgados que exponen "ejecuta restic con estos argumentos" o anulaciones de repositorio por llamada recrean ese radio de explosión dentro de MCP.

Este proyecto es diferente por construcción:

  1. Los repositorios están declarados y sellados al inicio del proceso
  2. La superficie MCP es exclusivamente de solo lectura (sin indicador de función para escrituras)
  3. Solo se puede compilar un subconjunto incorporado de subcomandos de restic
  4. Sin shell: exec.CommandContext con argv fijo solamente
  5. Hosts, etiquetas, rutas y tamaños de resultados están acotados
  6. Los secretos provienen de archivos con permisos verificados, nunca de RESTIC_PASSWORD_COMMAND
  7. Los errores están estructurados y redactados
  8. Cada herramienta reporta una clase de costo explícita (light / moderate / expensive)

Requisitos

  • Go 1.25+ (compilación)
  • restic 0.17.1+ en PATH (o restic_binary en configuración); probado con 0.19.x
  • Un cliente MCP que admita servidores stdio locales

Instalación (desde fuente)

git clone https://github.com/ThomasCrouzet/restic-defensive-mcp.git
cd restic-defensive-mcp
make build
./bin/restic-defensive-mcp --version

Inicio rápido

  1. Crea archivos de contraseña y ubicación del repositorio (archivos regulares, sin enlaces simbólicos). Evita colocar la contraseña en el historial del shell:
secret_dir="${XDG_CONFIG_HOME:-$HOME/.config}/restic-defensive-mcp"
install -d -m 700 "$secret_dir"
install -m 600 /dev/null "$secret_dir/repository"
printf '%s\n' '/path/to/your/repo' > "$secret_dir/repository"
install -m 600 /dev/null "$secret_dir/password"
"${EDITOR:-vi}" "$secret_dir/password"
  1. Copia y edita config.example.yaml, incluyendo las dos rutas de archivo anteriores.

  2. Ejecuta el binario recién compilado:

./bin/restic-defensive-mcp --config /path/to/config.yaml
  1. Apunta tu host MCP al binario con --config (solo transporte stdio).

Ejemplo de fragmento de host MCP (ilustrativo):

{
  "mcpServers": {
    "restic-defensive": {
      "command": "/absolute/path/to/restic-defensive-mcp",
      "args": ["--config", "/etc/restic-defensive-mcp/config.yaml"]
    }
  }
}

Herramientas (exactamente siete)

HerramientaCostoPropósito
restic_capabilitiesligeroVersiones, límites, backends, advertencias
list_repositoriesligeroIDs configurados y listas permitidas (sin URLs)
list_snapshotsligeroLista de instantáneas acotada
get_snapshotligeroMetadato de una instantánea
browse_snapshotmoderadoListado de directorio dentro de ruta permitida
find_filesmoderado–costosoBúsqueda simple con glob (no regex arbitrario)
repository_statsmoderado–costosoEstadísticas de tamaño/conteo para modos permitidos

No hay run_restic, backup, restore, forget, prune, unlock, check --read-data, ni argumento de URL de repositorio.

Formas completas de solicitud/respuesta: docs/tool-contract.md.

Configuración

Consulta config.example.yaml. Principios:

  • Los llamadores MCP pasan solo repository_id
  • Prefiere repository_file + password_file sobre secretos en línea
  • Las ubicaciones del repositorio y las credenciales del backend se cargan y sellan al arrancar; cambiar sus archivos fuente no redirige un servidor en ejecución
  • allowed_hosts / allowed_tags / allowed_paths son aplicación de reglas, no cosmética
  • Las listas permitidas vacías significan sin restricción para esa dimensión; el servidor registra una advertencia al arrancar (empty_allowlist) para que los operadores lo noten
  • Las claves YAML desconocidas y los documentos YAML múltiples se rechazan
  • Los archivos de secretos deben ser archivos regulares, sin enlaces simbólicos; Unix requiere modo 0600 o más estricto, mientras que las implementaciones de Windows deben aplicar ACLs NTFS equivalentes
  • find_files requiere un path explícito cuando se permiten múltiples raíces
  • Límites de tiempo de ejecución: los ceros se convierten en valores predeterminados; los valores fuera del mínimo/máximo absoluto se rechazan (no se ajustan silenciosamente). Los valores predeterminados son el punto de partida recomendado; los valores pueden aumentarse solo hasta esos techos

Backends compatibles (v0.1)

BackendCompatible
sistema de archivos localsí (solo rutas absolutas)
S3sí (credenciales mediante archivos de entorno permitidos)
Backblaze B2
servidor REST
SFTPno (genera ssh)
rcloneno (genera rclone)
otrono

Notas de compatibilidad: docs/restic-compatibility.md.

Efectos locales: caché y bloqueos

La inspección no es una operación pura sin efectos en el disco ni en la tabla de bloqueos del repositorio:

  • restic puede crear o actualizar una caché local (cache_dir o predeterminada)
  • restic puede tomar un bloqueo de repositorio durante instantáneas/ls/find/stats

Este servidor nunca muta intencionalmente contenidos de respaldo o conjuntos de instantáneas. Tampoco ejecuta verificación completa de datos (restic check --read-data). repository_stats responde solo preguntas de tamaño/conteo.

Detalles: SECURITY.md.

Límites de privacidad

Los nombres de archivos de instantáneas, rutas, hosts, etiquetas, tamaños y marcas de tiempo son sensibles. Este servidor:

  • nunca devuelve contenidos de archivos
  • nunca devuelve URLs de repositorio ni rutas de archivos de secretos
  • acota listados y resultados de búsqueda
  • sanitiza caracteres de control en nombres
  • mantiene los registros de auditoría libres de rutas completas por defecto

Demo (repositorio temporal local)

make demo

Ejecuta el arnés de extremo a extremo contra un repositorio restic desechable creado por internal/testrepo. Ejercita cada herramienta MCP, prueba la denegación de rutas y la ausencia de herramientas de mutación, luego elimina el accesorio. Las operaciones del repositorio permanecen locales; las descargas normales de módulos Go pueden ocurrir en una copia nueva.

Desarrollo

make fmt
make lint
make test          # unit tests
make race          # race detector
make fuzz-smoke    # short run of every fuzz target
make integration   # real restic temp repo (requires restic)
make vet

Dependencias

MóduloPor qué
github.com/modelcontextprotocol/go-sdkSDK oficial de MCP Go (servidor/cliente stdio)
gopkg.in/yaml.v3Análisis de archivos de configuración

Restic en sí es un binario externo, no un módulo Go.

No objetivos

  • Orquestación o programación de respaldos
  • Restaurar / olvidar / podar / desbloquear / reparar
  • Proxy genérico de CLI de restic
  • Importación de configuración de Autorestic
  • API remota multiinquilino
  • restic check --read-data completo como herramienta casual
  • Telemetría o actualización automática

Licencia

MIT, consulta LICENSE.