mcp2cli

Puente CLI que envuelve servidores MCP como comandos invocables desde bash, recuperando ~11K tokens de ventana de contexto por sesión https://github.com/rodaddy/mcp2cli

Documentación

mcp2cli

Buy Me A Coffee

Puente CLI que envuelve servidores MCP (Protocolo de Contexto de Modelo) como comandos invocables desde bash. En lugar de cargar todas las definiciones de herramientas MCP en el prompt del sistema de un LLM (~13K+ tokens permanentemente), los agentes invocan herramientas a través de bash con costo de contexto cero.

Inspirado en Google Workspace CLI, que envolvió las APIs complejas de Google en comandos CLI simples — toda la funcionalidad, sin las complicaciones. mcp2cli hace lo mismo para servidores MCP.

Inicio Rápido

# Install
git clone <repo-url>
cd mcp2cli
bun install
bun run build        # produces dist/mcp2cli

# Bootstrap from existing Claude config
mcp2cli bootstrap    # reads ~/.claude.json mcpServers -> ~/.config/mcp2cli/services.json

# Use it
mcp2cli services                                    # list available services
mcp2cli n8n --help                                   # list tools for a service
mcp2cli n8n n8n_list_workflows --params '{}'         # invoke a tool
mcp2cli schema n8n.n8n_list_workflows                # inspect tool schema

Para desarrollo sin compilar:

bun run dev -- services
bun run dev -- n8n n8n_list_workflows --params '{}'

Instalación

Requisitos previos: Bun v1.0+

git clone <repo-url>
cd mcp2cli
bun install
bun run build

El binario compilado se encuentra en dist/mcp2cli. Agréguelo a su PATH o cree un enlace simbólico.

Actualizaciones del Binario en macOS

En macOS, no sobrescriba un binario compilado existente en su lugar con cp new dist/mcp2cli. Reemplazar el contenido del mismo inodo puede invalidar la firma de código ad-hoc y causar que la siguiente ejecución sea terminada con SIGKILL / código de salida 137.

Use un inodo nuevo en su lugar:

rm dist/mcp2cli
cp /path/to/new/mcp2cli dist/mcp2cli

Si el daemon de la interfaz local está gestionado por launchd, reinícielo después de reemplazar el binario:

launchctl kickstart -k gui/501/com.mcp2cli.local-ui

El daemon ya en ejecución mantiene el inodo antiguo abierto hasta el reinicio, por lo que esto es seguro de hacer mientras el daemon está activo.

Configuración

Registro de Servicios

mcp2cli descubre servidores MCP desde ~/.config/mcp2cli/services.json:

{
  "services": {
    "n8n": {
      "description": "n8n workflow automation",
      "backend": "stdio",
      "command": "npx",
      "args": ["-y", "@anthropic-ai/n8n-mcp"],
      "env": {
        "N8N_BASE_URL": "https://n8n.example.com",
        "N8N_API_KEY": "your-api-key"
      }
    },
    "homekit": {
      "description": "HomeKit smart home control",
      "backend": "stdio",
      "command": "node",
      "args": ["/path/to/homekit-mcp/dist/index.js"],
      "env": {}
    }
  }
}

Cada entrada de servicio refleja el formato mcpServers de Claude Desktop — los mismos campos command, args y env.

Arranque desde Configuración de Claude

Si ya tiene servidores MCP configurados en ~/.claude.json:

mcp2cli bootstrap

Esto lee sus entradas de mcpServers y genera services.json automáticamente.

Comandos

Listar Servicios

mcp2cli services

Listar Herramientas para un Servicio

mcp2cli <service> --help

Invocar una Herramienta

mcp2cli <service> <tool> --params '<json>'

El valor de --params debe ser JSON válido que coincida con el esquema de entrada de la herramienta.

Inspeccionar Esquema de Herramienta

mcp2cli schema <service>.<tool>

Devuelve el Esquema JSON para los parámetros de entrada de la herramienta — útil para descubrir campos obligatorios.

Ejecución de Prueba

mcp2cli <service> <tool> --params '{"query": "test"}' --dry-run

Valida la entrada y muestra lo que se enviaría sin ejecutar la llamada a la herramienta.

Filtrado de Campos

mcp2cli <service> <tool> --params '{}' --fields "id,name,status"

Extrae solo los campos especificados de la respuesta — reduce el ruido de salida para scripts.

Generar Archivos de Habilidades

mcp2cli generate-skills <service>

Genera archivos de habilidades PAI a partir de esquemas de herramientas MCP, haciendo que las herramientas sean descubribles por agentes de IA.

Gestión del Daemon

mcp2cli daemon status    # check if daemon is running, connection pool stats
mcp2cli daemon stop      # graceful shutdown

Formato de Salida

Todas las respuestas son JSON estructurado en stdout. Los registros van a stderr.

// Success
{ "success": true, "result": { "workflows": [...] } }

// Error
{ "error": true, "code": "TOOL_ERROR", "message": "Workflow not found", "reason": "..." }

Esto hace que mcp2cli sea componible con jq, tuberías y scripts:

# Get workflow names
mcp2cli n8n n8n_list_workflows --params '{}' | jq '.result.workflows[].name'

# Check for errors
mcp2cli n8n n8n_get_workflow --params '{"id": "123"}' | jq 'if .error then .message else .result end'

Códigos de Salida

CódigoSignificado
0Éxito
1Error de validación (entrada incorrecta, discrepancia de esquema)
2Error de autenticación (credenciales faltantes, permiso denegado)
3Error de herramienta (la herramienta MCP devolvió un error)
4Error de conexión (daemon inalcanzable, fallo de transporte)
5Error interno

Use los códigos de salida para scripts:

mcp2cli n8n n8n_get_workflow --params '{"id": "123"}' 2>/dev/null
if [ $? -eq 4 ]; then
  echo "Connection failed -- is the MCP server configured?"
fi

Variables de Entorno

VariablePredeterminadoDescripción
MCP2CLI_LOG_LEVELsilentVerbosidad de registro: silent, error, warn, info, debug
MCP2CLI_IDLE_TIMEOUT60Tiempo de espera de inactividad del daemon en segundos
MCP2CLI_STARTUP_TIMEOUT10000Tiempo de espera de la CLI para la preparación del arranque del daemon en milisegundos
MCP2CLI_TOOL_TIMEOUT60000Tiempo de espera de llamada a herramienta en milisegundos. Un timeout por servicio en services.json lo anula, y el valor resuelto se pasa al SDK de MCP, por lo que limita la llamada de verdad
MCP2CLI_REQUEST_TIMEOUT_MS60000Tiempo de espera de solicitud de la CLI para llamadas al daemon local por socket Unix en milisegundos. Auméntelo junto con un timeout por servicio largo; de lo contrario, la CLI se rinde antes de que el verbo termine
MCP2CLI_REMOTE_REQUEST_TIMEOUT_MS60000Tiempo de espera de solicitud HTTP de la CLI para llamadas explícitas a daemon remoto en milisegundos
MCP2CLI_REMOTE_RETRIES3Intentos de solicitud remota para llamadas explícitas a daemon remoto
MCP2CLI_REMOTE_FALLBACK_TIMEOUT_MS10000Tiempo de espera HTTP de la CLI para cada sonda remote-local antes de recurrir al daemon local
MCP2CLI_REMOTE_FALLBACK_RETRIES1Intentos de sonda remota antes de que las llamadas remote-local recurran al daemon local
MCP2CLI_POOL_MAX50Máximo de conexiones MCP concurrentes en el grupo
MCP2CLI_LOG_DIR~/.cache/mcp2cli/logsDirectorio para registros de captura de stderr
MCP2CLI_NO_DAEMON(sin establecer)Si se establece, omite el daemon y se conecta directamente
MCP2CLI_DEBUG(sin establecer)Si 1, imprime líneas de stdout descartadas de servidores MCP

Ejemplo:

MCP2CLI_LOG_LEVEL=debug mcp2cli n8n n8n_list_workflows --params '{}'
MCP2CLI_NO_DAEMON=1 mcp2cli n8n n8n_list_workflows --params '{}'

Llamadas a herramientas de más de 60 segundos

Un verbo lento pasa por dos plazos independientes, y aumentar solo uno no cambia nada — el otro se dispara primero:

  1. Daemon → servidor MCP. El timeout por servicio en services.json (con respaldo a MCP2CLI_TOOL_TIMEOUT, predeterminado 60s) se entrega al SDK de MCP en cada llamada a herramienta. Sin él, el SDK aplica su propio DEFAULT_REQUEST_TIMEOUT_MSEC de 60s y falla con MCP error -32001: Request timed out.
  2. CLI → daemon. MCP2CLI_REQUEST_TIMEOUT_MS (predeterminado 60s) limita la solicitud local por socket Unix. Cuando se dispara, la CLI informa CONNECTION_ERROR: The operation timed out. aunque el daemon y el servidor MCP sigan trabajando.

Entonces, un verbo que puede ejecutarse durante 20 minutos necesita ambos:

// services.json
{ "services": { "runner-boxes": { "timeout": 1200000 /* ...*/ } } }
MCP2CLI_REQUEST_TIMEOUT_MS=1200000 mcp2cli runner-boxes runner_done --params '{}'

Una llamada con tiempo de espera agotado no es un verbo fallido: el trabajo del lado del servidor puede haberse completado después de que el cliente dejó de esperar. No reintente a ciegas un verbo no idempotente ante un tiempo de espera agotado.

Arquitectura

CLI Entry (src/cli/index.ts)
  |-- Command Dispatch (services, schema, bootstrap, generate-skills, daemon)
  |-- Tool Call Handler -> Daemon Client (Unix socket)
  |                          \-- Daemon Server (src/daemon/server.ts)
  |                                |-- Connection Pool (src/daemon/pool.ts)
  |                                |     \-- MCP Transport (src/connection/transport.ts)
  |                                |-- Idle Timer (src/daemon/idle.ts)
  |                                \-- Health Endpoint (/health with memory stats)
  |-- Input Validation (src/validation/) -- 48 adversarial patterns
  |-- Schema Introspection (src/schema/)
  |-- Skill Generation (src/generation/)
  \-- Structured Logger (src/logger/) -- JSON on stderr

Decisiones Clave de Diseño

Daemon persistente. Los servidores MCP tienen un costo de arranque de 2-5 segundos por conexión. El daemon mantiene las conexiones activas en un grupo, por lo que las llamadas posteriores regresan en milisegundos en lugar de segundos. El daemon se cierra automáticamente después del tiempo de espera de inactividad (predeterminado 60s).

Grupo de conexiones con verificaciones de salud. Las conexiones se validan antes de usarse y se reciclan ante fallos. El grupo impone un tamaño máximo para prevenir el agotamiento de recursos.

JSON estructurado en todas partes. stdout siempre es JSON analizable — sin salida de texto mixta. Los registros (cuando están habilitados) van a stderr como líneas JSON estructuradas. Esto hace que mcp2cli sea confiable para scripts y tuberías.

Códigos de salida semánticos. Diferentes modos de fallo obtienen diferentes códigos de salida para que los llamadores puedan ramificar según el tipo de error sin analizar la salida.

Validación de entrada. Todos los parámetros de herramientas se validan contra el esquema MCP antes de que se envíe la llamada. La capa de validación maneja 48 patrones adversariales (intentos de inyección, coerción de tipos, desbordamiento) para fallar rápidamente con errores claros.

Integración con Agentes

mcp2cli está diseñado para ser llamado desde agentes de IA mediante el uso de herramientas bash. Un flujo de trabajo típico de agente:

# Agent discovers available tools
mcp2cli n8n --help

# Agent reads the schema to understand parameters
mcp2cli schema n8n.n8n_get_workflow

# Agent invokes the tool
mcp2cli n8n n8n_get_workflow --params '{"id": "abc123"}'

Este patrón mantiene las definiciones de herramientas MCP completamente fuera del prompt del sistema del agente. El agente solo paga el costo de contexto cuando realmente necesita llamar a una herramienta, y aun así solo por el esquema de esa herramienta específica — no todas las herramientas de todos los servidores.

Autenticación Multi-Usuario

mcp2cli admite RBAC multi-usuario a través de ~/.config/mcp2cli/tokens.json. Cada usuario o agente obtiene un token de portador con un rol.

tokens.json

{
  "tokens": [
    {
      "id": "rico",
      "token": "your-admin-token-here",
      "role": "admin",
      "description": "Full admin access",
      "username": "rico",
      "password": "your-web-ui-password",
      "expiresAt": "2026-07-01T00:00:00.000Z"
    },
    {
      "id": "skippy",
      "token": "your-agent-token-here",
      "role": "agent",
      "description": "AI agent - tools + read, no config mutations",
      "expiresAt": "2026-07-01T00:00:00.000Z"
    },
    {
      "id": "viewer01",
      "token": "your-viewer-token-here",
      "role": "viewer",
      "description": "Read-only access"
    }
  ]
}

Genere tokens seguros: openssl rand -base64 32

Roles RBAC

Permisovieweragentadmin
Listar servicios, estadosísísí
Llamar herramientas, listar herramientas, esquemanosísí
Leer credencialesnosísí
Agregar/actualizar/eliminar serviciosnonosí
Escribir credenciales, gestionar gruposnonosí
Recargar, importar, apagarnonosí

Los campos username/password habilitan el inicio de sesión en la interfaz web en la URL raíz del daemon. La autenticación basada en tokens (encabezado Bearer) funciona para todo acceso API y CLI.

El campo opcional expiresAt habilita la expiración y renovación de tokens. Los tokens expirados se rechazan. Los tokens cercanos a expirar de tokens.json pueden rotarse a través de POST /api/auth/refresh; el daemon escribe el nuevo token de vuelta en tokens.json y recarga en caliente las ediciones del archivo de tokens. Los clientes CLI locales renuevan proactivamente los tokens de administrador cercanos a expirar antes de las llamadas API del daemon.

Comportamiento de Respaldo

  • Sin tokens.json, sin token de entorno: Autenticación deshabilitada, todas las solicitudes se tratan como administrador (compatible hacia atrás)
  • Solo variable de entorno MCP2CLI_AUTH_TOKEN: Modo heredado de token único, tratado como administrador
  • tokens.json existe: RBAC multi-usuario completo

Gestión de Credenciales por Identidad

Diferentes usuarios y agentes pueden tener sus propias claves API para servicios backend. Cuando rico llama a open-brain, usa su clave. Cuando skippy lo llama, se usa la clave compartida de los agentes.

credentials.json

Cree ~/.config/mcp2cli/credentials.json:

{
  "groups": {
    "ai_agents": ["skippy", "bilby", "nagatha", "claude"]
  },
  "credentials": {
    "rico": {
      "open-brain": { "headers": { "Authorization": "Bearer ricos-ob-key" } }
    },
    "ai_agents": {
      "open-brain": { "headers": { "Authorization": "Bearer agents-shared-ob-key" } },
      "n8n": { "env": { "N8N_API_KEY": "agents-n8n-key" } }
    }
  },
  "defaults": {
    "proxmox": { "headers": { "Authorization": "PVEAPIToken=shared-token" } }
  }
}

Cadena de Resolución

Cuando llega una llamada a herramienta, las credenciales se resuelven en orden de prioridad:

  1. Específica del usuario -- credentials[userId][service]
  2. Grupo -- primer grupo coincidente al que pertenece el usuario
  3. Predeterminadas -- defaults[service]
  4. services.json -- lo que esté integrado en la configuración del servicio (compatible hacia atrás)

Para servicios http/websocket, los encabezados de credenciales se fusionan en la conexión. Para servicios stdio, las variables de entorno de credenciales se fusionan en el entorno del proceso.

Para servicios sensibles a la identidad, establezca requiresCredentials: true en services.json. Si no existe credencial de usuario, grupo o predeterminada explícita, el daemon rechaza la llamada en lugar de usar los encabezados base del servicio.

CLI de Credenciales

# Set credentials for an identity on a service
mcp2cli credentials set rico open-brain --header "Authorization: Bearer my-key"

# Set env-based credentials (for stdio services)
mcp2cli credentials set rico n8n --env "N8N_API_KEY=my-n8n-key"

# Set a default credential (used when no user/group match)
mcp2cli credentials set-default proxmox --header "Authorization: PVEAPIToken=shared"

# List all credentials (values are redacted)
mcp2cli credentials list

# Show effective credential source for a user
mcp2cli credentials resolve skippy open-brain
# → {"exists": true, "source": "group"}

# Group management
mcp2cli credentials group add ai_agents skippy bilby nagatha
mcp2cli credentials group add-members ai_agents claude
mcp2cli credentials group remove-members ai_agents bilby
mcp2cli credentials group list

# Remove credentials
mcp2cli credentials remove rico open-brain
mcp2cli credentials remove-default proxmox
mcp2cli credentials group remove ai_agents

# Reload from disk after manual edits
mcp2cli credentials reload

# Populate Open Brain credentials from a Vaultwarden item
mcp2cli credentials bootstrap-open-brain --item "Open Brain - Per-User Tokens"

Ejemplo de Open Brain

Open Brain (OBv2) es un servicio MCP HTTP donde el token de portador controla la identidad del espacio de nombres. No ponga un encabezado Authorization de Open Brain en services.json; guárdelo solo como credencial por identidad.

services.json -- configuración base para un daemon alojado (sin credenciales, solo punto final):

{
  "services": {
    "open-brain": {
      "backend": "http",
      "url": "http://open-brain.example.internal:3100/mcp",
      "source": "remote",
      "requiresCredentials": true,
      "preconnect": false
    }
  }
}

Use source: "remote" cuando la CLI se enruta a través de un daemon mcp2cli alojado. requiresCredentials: true hace que las credenciales por identidad faltantes fallen de forma cerrada, y preconnect: false evita que el arranque del daemon abra una conexión base de Open Brain sin autenticación.

credentials.json -- claves por identidad:

{
  "groups": {
    "ai_agents": ["skippy", "bilby", "claude"]
  },
  "credentials": {
    "rico": {
      "open-brain": { "headers": { "Authorization": "Bearer ricos-ob-api-key" } }
    },
    "ai_agents": {
      "open-brain": { "headers": { "Authorization": "Bearer agents-shared-ob-key" } }
    }
  }
}

Ahora cuando rico llama a mcp2cli open-brain search_all --params '{"query": "kubernetes"}', se inyecta su clave personal. Cuando skippy llama a la misma herramienta, se usa la clave compartida de los agentes. Cada uno obtiene su propia conexión en el grupo.

Arranque de Vaultwarden -- si el elemento Open Brain - Per-User Tokens tiene campos personalizados como AUTH_TOKEN_USER_RICO, AUTH_TOKEN_USER_SKIPPY y AUTH_TOKEN_USER_BILBY, ejecute:

mcp2cli credentials bootstrap-open-brain

El sufijo del campo se convierte a minúsculas y se usa como identidad (AUTH_TOKEN_USER_RICO -> rico). Las credenciales existentes se omiten a menos que se pase --force. El comando imprime solo conteos y nombres de identidad; no imprime tokens de portador.

Encabezados de Identidad del Llamador

Los valores de encabezados y entorno admiten variables de plantilla ${caller.id} y ${caller.role}. Estas se reemplazan con la identidad del llamador autenticado en el momento de la llamada.

En services.json -- inyecte encabezados de identidad para servicios cuyo backend confía en metadatos del llamador en lugar de tokens de portador por usuario:

{
  "services": {
    "example-service": {
      "backend": "http",
      "url": "https://example.internal/mcp",
      "headers": {
        "X-Agent-Id": "${caller.id}",
        "X-Role": "${caller.role}"
      }
    }
  }
}

Cuando bilby llama al servicio, los encabezados de solicitud se convierten en X-Agent-Id: bilby y X-Role: agent.

En credentials.json -- combine claves por identidad con encabezados de identidad:

{
  "credentials": {
    "rico": {
      "open-brain": {
        "headers": {
          "Authorization": "Bearer ricos-ob-key",
          "X-Namespace": "${caller.id}"
        }
      }
    }
  }
}

Las plantillas funcionan tanto en encabezados como en valores de entorno. Las variables desconocidas (p. ej., ${caller.email}) se dejan sin expandir.

Seguridad

  • Salida de lista redactada -- GET /api/credentials devuelve Bear*** en lugar de valores completos
  • Protección IDOR -- los agentes solo pueden resolver sus propias credenciales; se requiere rol de administrador para las de otros
  • Permisos de archivo -- credentials.json se escribe con 0600 (solo lectura/escritura del propietario)
  • Validación de entrada -- los valores de cabecera rechazan inyección CRLF; las cabeceras peligrosas (Host, Transfer-Encoding) y las variables de entorno (PATH, LD_PRELOAD, NODE_OPTIONS) están bloqueadas
  • Escrituras atómicas -- archivo temporal + renombrado evita escrituras parciales ante un fallo
  • Invalidación del pool -- al cambiar las credenciales, las conexiones obsoletas se expulsan automáticamente

Funciones Avanzadas

Caché de Esquemas

Los esquemas se almacenan en caché localmente para evitar volver a obtenerlos en cada invocación. Los esquemas en caché residen en ~/.cache/mcp2cli/schemas/ con un TTL de 24 horas. La desviación de caché se detecta mediante hash SHA-256 -- si el esquema upstream cambia, la caché se invalida automáticamente.

# Check cache status (age, TTL, drift)
mcp2cli cache status

# Clear all cached schemas
mcp2cli cache clear

# Clear cache for a specific service
mcp2cli cache clear n8n

# Bypass cache for a single schema lookup
mcp2cli schema n8n.n8n_list_workflows --fresh

Sobrescribe el directorio de caché con MCP2CLI_CACHE_DIR.

Control de Acceso

Restringe qué herramientas se exponen por servicio usando allowTools y blockTools en services.json. Ambos aceptan patrones glob.

{
  "services": {
    "n8n": {
      "description": "n8n workflow automation",
      "backend": "stdio",
      "command": "npx",
      "args": ["-y", "@anthropic/n8n-mcp"],
      "allowTools": ["n8n_list_*", "n8n_get_*"],
      "blockTools": ["n8n_delete_*"]
    }
  }
}

Cuando ambos están presentes, allowTools se evalúa primero (lista blanca) y luego blockTools elimina coincidencias del conjunto permitido.

Búsqueda de Herramientas entre Servicios

Busca herramientas en todos los servicios usando los esquemas en caché:

# Find all tools matching a pattern
mcp2cli grep "workflow"

# Regex patterns work
mcp2cli grep "delete|remove"

Esto solo busca en los esquemas en caché -- no se realizan conexiones MCP.

Transporte WebSocket

Conéctate a servidores MCP a través de WebSocket. Admite fallback opcional a stdio y control de acceso, igual que HTTP.

{
  "services": {
    "remote-mcp": {
      "description": "Remote MCP server via WebSocket",
      "backend": "websocket",
      "url": "ws://mcp-gateway.local:3000/mcp",
      "fallback": {
        "command": "npx",
        "args": ["-y", "@anthropic/n8n-mcp"]
      }
    }
  }
}

Los servicios WebSocket se benefician del mismo cortacircuitos y comportamiento de fallback que los servicios HTTP.

Llamadas de Herramientas por Lote

Ejecuta múltiples llamadas de herramientas en una sola invocación canalizando NDJSON a mcp2cli batch. Cada línea es un objeto JSON con los campos service, tool y params:

# Sequential execution (default)
cat <<EOF | mcp2cli batch
{"service": "n8n", "tool": "n8n_list_workflows", "params": {}}
{"service": "n8n", "tool": "n8n_get_workflow", "params": {"id": "1"}}
EOF

# Parallel execution
cat <<EOF | mcp2cli batch --parallel
{"service": "n8n", "tool": "n8n_list_workflows", "params": {}}
{"service": "n8n", "tool": "n8n_get_workflow", "params": {"id": "1"}}
EOF

La salida es NDJSON -- un resultado por línea con el servicio/herramienta original para correlación:

{"service":"n8n","tool":"n8n_list_workflows","success":true,"result":{...}}
{"service":"n8n","tool":"n8n_get_workflow","success":true,"result":{...}}

Los errores de llamadas individuales se reportan en línea sin abortar el lote.

Resiliencia del Gateway

Los servicios HTTP/SSE pueden definir una configuración stdio fallback. Si el gateway remoto no está disponible, mcp2cli recurre de forma transparente a un proceso de servidor MCP local.

{
  "services": {
    "n8n": {
      "description": "n8n via HTTP gateway with stdio fallback",
      "backend": "http",
      "url": "http://mcp-gateway:3000/n8n",
      "fallback": {
        "command": "npx",
        "args": ["-y", "@anthropic/n8n-mcp"]
      }
    }
  }
}

Un cortacircuitos protege contra fallos repetidos: después de 5 fallos consecutivos, el circuito se abre y enruta directamente al fallback durante 60 segundos antes de volver a sondear el primario. El estado del circuito se persiste en ~/.cache/mcp2cli/circuit-breaker/ para que sobreviva a los reinicios del proceso.

Formatos de Salida

Controla el formato de salida con la bandera --format:

mcp2cli n8n n8n_list_workflows --params '{}' --format table
mcp2cli n8n n8n_list_workflows --params '{}' --format yaml
mcp2cli n8n n8n_list_workflows --params '{}' --format csv
mcp2cli n8n n8n_list_workflows --params '{}' --format ndjson
FormatoDescripción
jsonPredeterminado. JSON estructurado (sin cambios desde v1.0)
tableColumnas alineadas -- salida de terminal legible para humanos
yamlSalida YAML
csvCSV RFC 4180 -- canaliza a hojas de cálculo o csvtool
ndjsonUn objeto JSON por línea -- para pipelines de streaming

Las respuestas de error son siempre JSON independientemente de la bandera --format.

Auto-Regeneración de Skills

Los archivos de skill generados se pueden previsualizar y mantener sincronizados con los cambios de esquema upstream:

# Preview what would change without writing
mcp2cli generate-skills --diff n8n

# Regenerate (preserves manual sections)
mcp2cli generate-skills n8n

Las ediciones manuales dentro de los marcadores MANUAL:START / MANUAL:END se conservan entre regeneraciones. Cuando se detecta desviación de esquema (a través de la capa de caché), la regeneración de skills se puede activar automáticamente.

Para cambios de Open Brain MCP, usa la ruta respaldada por el registro en lugar de actualizar directamente un daemon local como prueba de la versión:

# First land any required registry/config/process update in rodaddy/rtech-mcps.
# Then make mcp2cli pull the registry-backed service definition and refresh live schemas.
mcp2cli cache diff open-brain
mcp2cli cache warm open-brain
mcp2cli generate-skills open-brain --conflict=merge
mcp2cli open-brain --help

La validación local debe usar un MCP2CLI_HOME/config/caché temporal aislado para que las pruebas no puedan mutar el estado local real de ~/.config/mcp2cli del operador. La verificación final debe ejecutarse contra el daemon alojado y demostrar que las nuevas herramientas son visibles y invocables allí.

Variables de Entorno Adicionales

VariablePredeterminadoDescripción
MCP2CLI_CACHE_DIR~/.cache/mcp2cliDirectorio base para la caché de esquemas y el estado del cortacircuitos
MCP2CLI_TOKENS_FILE~/.config/mcp2cli/tokens.jsonRuta a la configuración de tokens multiusuario
MCP2CLI_TOKEN_REFRESH_WINDOW_MS86400000Ventana de renovación para tokens que expiran (predeterminado 24 h)
MCP2CLI_TOKEN_TTL_MS2592000000Vida útil de los tokens renovados (predeterminado 30 d)
MCP2CLI_CREDENTIALS_FILE~/.config/mcp2cli/credentials.jsonRuta a los mapeos de credenciales por identidad
MCP2CLI_IMPORT_TOKEN(sin definir)Token Bearer usado solo para importaciones de configuración importUrl
MCP2CLI_IMPORT_ALLOWED_HOSTS(requerido para importUrl)Lista blanca separada por comas para nombres de host importUrl
MCP2CLI_IMPORT_ALLOW_DNS(sin definir)Establecer en 1 para permitir nombres de host DNS para objetivos importUrl no privados
MCP2CLI_IMPORT_ALLOW_HTTP(sin definir)Establecer en 1 para permitir objetivos importUrl no HTTPS
MCP2CLI_IMPORT_ALLOW_PRIVATE(sin definir)Establecer en 1 para permitir objetivos importUrl de loopback/privados/link-local
MCP2CLI_METRICS_INCLUDE_CALLER(sin definir)Establecer en 1 para incluir etiquetas de llamante sin procesar en /metrics público; deshabilitado por defecto
MCP2CLI_VAULTWARDEN_TIMEOUT_MS10000Tiempo de espera para búsquedas ${secret:...} respaldadas por Vaultwarden

Despliegue en Red

mcp2cli puede ejecutarse como un daemon TCP centralizado, lo que permite que múltiples máquinas compartan un único conjunto de conexiones de servidor MCP. Instala y configura los backends MCP una sola vez en un servidor y luego conéctate desde cualquier máquina usando el cliente CLI o el wrapper de bash (solo curl + jq -- no se requiere Bun).

Inicio Rápido (Modo TCP)

Servidor -- inicia el daemon con enlace TCP:

export MCP2CLI_LISTEN_HOST=0.0.0.0
export MCP2CLI_LISTEN_PORT=9500
export MCP2CLI_AUTH_TOKEN=$(openssl rand -hex 32)
MCP2CLI_DAEMON=1 mcp2cli

Cliente -- apunta cualquier máquina al daemon remoto:

export MCP2CLI_REMOTE_URL=http://mcp-server.local:9500
export MCP2CLI_AUTH_TOKEN=<same-token-as-server>
mcp2cli n8n n8n_list_workflows --params '{}'

Cuando MCP2CLI_REMOTE_URL está definido, el CLI omite por completo el inicio del daemon local y envía las solicitudes directamente por HTTP.

Variables de Entorno de Red

Además de las variables de entorno base, el modo red añade:

VariablePredeterminadoDescripción
MCP2CLI_LISTEN_HOST(sin definir)Dirección de enlace para el modo TCP. Definir esto habilita TCP en lugar de socket Unix. Usa 0.0.0.0 para escuchar en todas las interfaces
MCP2CLI_LISTEN_PORT9500Puerto TCP cuando MCP2CLI_LISTEN_HOST está definido
MCP2CLI_AUTH_TOKEN(sin definir)Token Bearer para autenticación TCP. Requerido para despliegues de producción. Alias: MCP_TOKEN
MCP2CLI_REMOTE_URL(sin definir)URL del daemon mcp2cli remoto (p. ej. https://mcp2cli.rodaddy.live). Habilita el modo cliente remoto. Alias: MCP_HOST
MCP2CLI_CONFIG~/.config/mcp2cli/services.jsonRuta a las definiciones de servicio (útil para configuración del lado del servidor en /etc/mcp2cli/)
MCP2CLI_TOKENS_FILE~/.config/mcp2cli/tokens.jsonRuta a la configuración de tokens/RBAC multiusuario
MCP2CLI_CREDENTIALS_FILE~/.config/mcp2cli/credentials.jsonRuta a los mapeos de credenciales por identidad

Autenticación

El daemon admite dos modos de autenticación (ver Autenticación Multiusuario arriba):

  1. RBAC multiusuario mediante tokens.json -- cada usuario/agente obtiene su propio token y rol
  2. Token único heredado mediante la variable de entorno MCP2CLI_AUTH_TOKEN -- se trata como administrador

Todas las comparaciones de tokens usan igualdad a prueba de temporización para prevenir ataques de temporización.

Rutas exentas de autenticación -- estas omiten la autenticación para que los balanceadores de carga y el monitoreo puedan sondear sin credenciales:

  • GET /health -- comprobación de salud con tiempo de actividad, memoria y recuento de conexiones activas
  • GET /metrics -- endpoint de métricas Prometheus con métricas agregadas de servicios/herramientas

Métricas de Prometheus

El daemon expone métricas en GET /metrics en formato de exposición de texto de Prometheus. Métricas clave:

MétricaTipoDescripción
mcp2cli_requests_totalcontadorSolicitudes totales por {service, tool}
mcp2cli_requests_errors_totalcontadorSolicitudes fallidas por {service, tool}
mcp2cli_request_duration_mshistogramaLatencia de solicitudes con buckets (10 ms - 30 s)
mcp2cli_requests_activegaugeSolicitudes actualmente en curso
mcp2cli_pool_connections_activegaugeTamaño actual del pool de conexiones
mcp2cli_pool_servicesgaugeServicios conectados (etiqueta {service})
mcp2cli_connection_events_totalcontadorConectar/desconectar/fallo de comprobación de salud por {service}
mcp2cli_auth_failures_totalcontadorFallos de autenticación totales
mcp2cli_process_uptime_secondsgaugeTiempo de actividad del daemon
mcp2cli_process_memory_rss_bytesgaugeTamaño del conjunto residente

Las etiquetas de llamante sin procesar en /metrics público están deshabilitadas por defecto para evitar exponer IDs de usuario a scrapers no autenticados. Define MCP2CLI_METRICS_INCLUDE_CALLER=1 solo en entornos de monitoreo confiables para añadir series {service, tool, caller}.

Para un desglose JSON rápido por identidad, llama a GET /api/metrics/user/:userId con un token Bearer que tenga permiso status. Los llamantes no administradores solo pueden leer sus propias métricas de usuario; los administradores pueden leer las de cualquier usuario.

Los clientes remotos descubren el inventario de servicios del daemon a través de GET /api/services/discovery autenticado, no de la sonda pública /health.

Añade a tu configuración de Prometheus:

scrape_configs:
  - job_name: mcp2cli
    static_configs:
      - targets: ['mcp-server.local:9500']

Wrapper de Bash (clientes solo curl)

Para máquinas que solo tienen curl y jq (sin runtime de Bun), usa el wrapper de bash:

# Install the wrapper
cp scripts/mcp2cli-remote /usr/local/bin/
chmod +x /usr/local/bin/mcp2cli-remote

# Configure
export MCP2CLI_REMOTE_URL=http://mcp-server.local:9500
export MCP2CLI_AUTH_TOKEN=<token>

# Use it like the full CLI
mcp2cli-remote n8n n8n_list_workflows '{}'

Despliegue LXC

El directorio deploy/ contiene todo lo necesario para ejecutar mcp2cli como un servicio systemd en un contenedor LXC (o cualquier host Linux):

ArchivoPropósito
deploy/mcp2cli.serviceArchivo de unidad systemd (endurecido con NoNewPrivileges, ProtectSystem=strict)
deploy/env.examplePlantilla de archivo de entorno -- copia a /etc/mcp2cli/env
deploy/services-server.jsonEjemplo de configuración de servicio del lado del servidor

Configuración:

# Copy files into place
cp deploy/mcp2cli.service /etc/systemd/system/
mkdir -p /etc/mcp2cli
cp deploy/env.example /etc/mcp2cli/env
cp deploy/services-server.json /etc/mcp2cli/services.json

# Edit config
vim /etc/mcp2cli/env           # set MCP2CLI_AUTH_TOKEN
vim /etc/mcp2cli/services.json  # configure your MCP backends

# Enable and start
useradd --system --no-create-home mcp2cli
systemctl daemon-reload
systemctl enable --now mcp2cli

Ejemplos con curl

SERVER=http://mcp-server.local:9500
TOKEN=your-token-here

# Health check (no auth required)
curl -s $SERVER/health | jq .

# Prometheus metrics (no auth required)
curl -s $SERVER/metrics

# List tools for a service
curl -s -X POST $SERVER/list-tools \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"service": "n8n"}' | jq .

# Invoke a tool
curl -s -X POST $SERVER/call \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"service": "n8n", "tool": "n8n_list_workflows", "params": {}}' | jq .

# Get a tool schema
curl -s -X POST $SERVER/schema \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"service": "n8n", "tool": "n8n_list_workflows"}' | jq .

Desarrollo

bun run dev -- <args>     # run without building
bun test                  # run test suite
bun run build             # compile to dist/mcp2cli

Licencia

MIT