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
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ódigo | Significado |
|---|---|
| 0 | Éxito |
| 1 | Error de validación (entrada incorrecta, discrepancia de esquema) |
| 2 | Error de autenticación (credenciales faltantes, permiso denegado) |
| 3 | Error de herramienta (la herramienta MCP devolvió un error) |
| 4 | Error de conexión (daemon inalcanzable, fallo de transporte) |
| 5 | Error 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
| Variable | Predeterminado | Descripción |
|---|---|---|
MCP2CLI_LOG_LEVEL | silent | Verbosidad de registro: silent, error, warn, info, debug |
MCP2CLI_IDLE_TIMEOUT | 60 | Tiempo de espera de inactividad del daemon en segundos |
MCP2CLI_STARTUP_TIMEOUT | 10000 | Tiempo de espera de la CLI para la preparación del arranque del daemon en milisegundos |
MCP2CLI_TOOL_TIMEOUT | 60000 | Tiempo 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_MS | 60000 | Tiempo 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_MS | 60000 | Tiempo de espera de solicitud HTTP de la CLI para llamadas explícitas a daemon remoto en milisegundos |
MCP2CLI_REMOTE_RETRIES | 3 | Intentos de solicitud remota para llamadas explícitas a daemon remoto |
MCP2CLI_REMOTE_FALLBACK_TIMEOUT_MS | 10000 | Tiempo de espera HTTP de la CLI para cada sonda remote-local antes de recurrir al daemon local |
MCP2CLI_REMOTE_FALLBACK_RETRIES | 1 | Intentos de sonda remota antes de que las llamadas remote-local recurran al daemon local |
MCP2CLI_POOL_MAX | 50 | Máximo de conexiones MCP concurrentes en el grupo |
MCP2CLI_LOG_DIR | ~/.cache/mcp2cli/logs | Directorio 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:
- Daemon → servidor MCP. El
timeoutpor servicio enservices.json(con respaldo aMCP2CLI_TOOL_TIMEOUT, predeterminado 60s) se entrega al SDK de MCP en cada llamada a herramienta. Sin él, el SDK aplica su propioDEFAULT_REQUEST_TIMEOUT_MSECde 60s y falla conMCP error -32001: Request timed out. - CLI → daemon.
MCP2CLI_REQUEST_TIMEOUT_MS(predeterminado 60s) limita la solicitud local por socket Unix. Cuando se dispara, la CLI informaCONNECTION_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
| Permiso | viewer | agent | admin |
|---|---|---|---|
| Listar servicios, estado | sí | sí | sí |
| Llamar herramientas, listar herramientas, esquema | no | sí | sí |
| Leer credenciales | no | sí | sí |
| Agregar/actualizar/eliminar servicios | no | no | sí |
| Escribir credenciales, gestionar grupos | no | no | sí |
| Recargar, importar, apagar | no | no | sí |
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:
- Específica del usuario --
credentials[userId][service] - Grupo -- primer grupo coincidente al que pertenece el usuario
- Predeterminadas --
defaults[service] - 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/credentialsdevuelveBear***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.jsonse escribe con0600(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
| Formato | Descripción |
|---|---|
json | Predeterminado. JSON estructurado (sin cambios desde v1.0) |
table | Columnas alineadas -- salida de terminal legible para humanos |
yaml | Salida YAML |
csv | CSV RFC 4180 -- canaliza a hojas de cálculo o csvtool |
ndjson | Un 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
| Variable | Predeterminado | Descripción |
|---|---|---|
MCP2CLI_CACHE_DIR | ~/.cache/mcp2cli | Directorio base para la caché de esquemas y el estado del cortacircuitos |
MCP2CLI_TOKENS_FILE | ~/.config/mcp2cli/tokens.json | Ruta a la configuración de tokens multiusuario |
MCP2CLI_TOKEN_REFRESH_WINDOW_MS | 86400000 | Ventana de renovación para tokens que expiran (predeterminado 24 h) |
MCP2CLI_TOKEN_TTL_MS | 2592000000 | Vida útil de los tokens renovados (predeterminado 30 d) |
MCP2CLI_CREDENTIALS_FILE | ~/.config/mcp2cli/credentials.json | Ruta 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_MS | 10000 | Tiempo 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:
| Variable | Predeterminado | Descripció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_PORT | 9500 | Puerto 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.json | Ruta a las definiciones de servicio (útil para configuración del lado del servidor en /etc/mcp2cli/) |
MCP2CLI_TOKENS_FILE | ~/.config/mcp2cli/tokens.json | Ruta a la configuración de tokens/RBAC multiusuario |
MCP2CLI_CREDENTIALS_FILE | ~/.config/mcp2cli/credentials.json | Ruta a los mapeos de credenciales por identidad |
Autenticación
El daemon admite dos modos de autenticación (ver Autenticación Multiusuario arriba):
- RBAC multiusuario mediante
tokens.json-- cada usuario/agente obtiene su propio token y rol - 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 activasGET /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étrica | Tipo | Descripción |
|---|---|---|
mcp2cli_requests_total | contador | Solicitudes totales por {service, tool} |
mcp2cli_requests_errors_total | contador | Solicitudes fallidas por {service, tool} |
mcp2cli_request_duration_ms | histograma | Latencia de solicitudes con buckets (10 ms - 30 s) |
mcp2cli_requests_active | gauge | Solicitudes actualmente en curso |
mcp2cli_pool_connections_active | gauge | Tamaño actual del pool de conexiones |
mcp2cli_pool_services | gauge | Servicios conectados (etiqueta {service}) |
mcp2cli_connection_events_total | contador | Conectar/desconectar/fallo de comprobación de salud por {service} |
mcp2cli_auth_failures_total | contador | Fallos de autenticación totales |
mcp2cli_process_uptime_seconds | gauge | Tiempo de actividad del daemon |
mcp2cli_process_memory_rss_bytes | gauge | Tamañ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):
| Archivo | Propósito |
|---|---|
deploy/mcp2cli.service | Archivo de unidad systemd (endurecido con NoNewPrivileges, ProtectSystem=strict) |
deploy/env.example | Plantilla de archivo de entorno -- copia a /etc/mcp2cli/env |
deploy/services-server.json | Ejemplo 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