mcp2cli

Ponte CLI que encapsula servidores MCP como comandos invocáveis via bash, recuperando ~11K tokens de janela de contexto por sessão https://github.com/rodaddy/mcp2cli

Documentação

mcp2cli

Buy Me A Coffee

Ponte CLI que encapsula servidores MCP (Model Context Protocol) como comandos invocáveis via bash. Em vez de carregar todas as definições de ferramentas MCP no prompt de sistema de um LLM (~13K+ tokens permanentemente), agentes invocam ferramentas via bash com custo zero de contexto.

Inspirado no Google Workspace CLI, que encapsulava as APIs complexas do Google em comandos CLI simples — toda a funcionalidade, sem complicação. O mcp2cli faz o mesmo para servidores MCP.

Início 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 desenvolvimento sem compilar:

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

Instalação

Pré-requisitos: Bun v1.0+

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

O binário compilado fica em dist/mcp2cli. Adicione-o ao seu PATH ou crie um symlink.

Atualizações do Binário no macOS

No macOS, não sobrescreva um binário compilado existente no mesmo local com cp new dist/mcp2cli. Substituir o conteúdo do mesmo inode pode invalidar a assinatura de código ad-hoc e fazer a próxima execução ser encerrada com SIGKILL / código de saída 137.

Use um novo inode:

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

Se o daemon da UI local for gerenciado pelo launchd, reinicie-o após substituir o binário:

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

O daemon já em execução mantém o inode antigo aberto até a reinicialização, então isso é seguro de fazer enquanto o daemon está ativo.

Configuração

Registro de Serviços

O mcp2cli descobre servidores MCP a partir de ~/.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 serviço espelha o formato do Claude Desktop mcpServers — mesmos campos command, args e env.

Bootstrap a partir da Config do Claude

Se você já tem servidores MCP configurados em ~/.claude.json:

mcp2cli bootstrap

Isso lê suas entradas mcpServers e gera services.json automaticamente.

Comandos

Listar Serviços

mcp2cli services

Listar Ferramentas de um Serviço

mcp2cli <service> --help

Invocar uma Ferramenta

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

O valor --params deve ser JSON válido correspondente ao esquema de entrada da ferramenta.

Inspecionar Esquema da Ferramenta

mcp2cli schema <service>.<tool>

Retorna o JSON Schema para os parâmetros de entrada da ferramenta — útil para descobrir campos obrigatórios.

Execução Simulada (Dry Run)

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

Valida a entrada e mostra o que seria enviado sem executar a chamada da ferramenta.

Filtragem de Campos

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

Extrai apenas os campos especificados da resposta — reduz ruído na saída para scripts.

Gerar Arquivos de Skill

mcp2cli generate-skills <service>

Gera arquivos de skill PAI a partir dos esquemas de ferramentas MCP, tornando as ferramentas detectáveis por agentes de IA.

Gerenciamento do Daemon

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

Formato de Saída

Todas as respostas são JSON estruturado no stdout. Logs vão para o stderr.

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

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

Isso torna o mcp2cli componível com jq, pipes e 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 Saída

CódigoSignificado
0Sucesso
1Erro de validação (entrada inválida, incompatibilidade de esquema)
2Erro de autenticação (credenciais ausentes, permissão negada)
3Erro de ferramenta (a ferramenta MCP retornou um erro)
4Erro de conexão (daemon inacessível, falha de transporte)
5Erro interno

Use os códigos de saída 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

Variáveis de Ambiente

VariávelPadrãoDescrição
MCP2CLI_LOG_LEVELsilentNível de log: silent, error, warn, info, debug
MCP2CLI_IDLE_TIMEOUT60Tempo limite de inatividade do daemon em segundos
MCP2CLI_STARTUP_TIMEOUT10000Tempo de espera do CLI pela prontidão de inicialização do daemon em milissegundos
MCP2CLI_TOOL_TIMEOUT60000Tempo limite de chamada de ferramenta em milissegundos. Um timeout por serviço em services.json o substitui, e o valor resolvido é passado ao SDK MCP, então ele limita a chamada de verdade
MCP2CLI_REQUEST_TIMEOUT_MS60000Tempo limite de solicitação do CLI para chamadas locais ao daemon via socket Unix em milissegundos. Aumente junto com um timeout longo por serviço, caso contrário o CLI desiste antes do verbo terminar
MCP2CLI_REMOTE_REQUEST_TIMEOUT_MS60000Tempo limite de solicitação HTTP do CLI para chamadas remotas explícitas ao daemon em milissegundos
MCP2CLI_REMOTE_RETRIES3Tentativas de solicitação remota para chamadas remotas explícitas ao daemon
MCP2CLI_REMOTE_FALLBACK_TIMEOUT_MS10000Tempo limite HTTP do CLI para cada sonda remote-local antes de recorrer ao daemon local
MCP2CLI_REMOTE_FALLBACK_RETRIES1Tentativas de sonda remota antes que chamadas remote-local recorram ao daemon local
MCP2CLI_POOL_MAX50Máximo de conexões MCP simultâneas no pool
MCP2CLI_LOG_DIR~/.cache/mcp2cli/logsDiretório para logs de captura do stderr
MCP2CLI_NO_DAEMON(não definido)Se definido, ignora o daemon e conecta diretamente
MCP2CLI_DEBUG(não definido)Se 1, imprime linhas descartadas do stdout de servidores MCP

Exemplo:

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

Chamadas de ferramenta com mais de 60 segundos

Um verbo lento passa por dois prazos independentes, e aumentar apenas um não muda nada — o outro dispara primeiro:

  1. Daemon → servidor MCP. O timeout por serviço em services.json (recorrendo a MCP2CLI_TOOL_TIMEOUT, padrão 60s) é passado ao SDK MCP em cada chamada de ferramenta. Sem ele, o SDK aplica seu próprio DEFAULT_REQUEST_TIMEOUT_MSEC de 60s e falha com MCP error -32001: Request timed out.
  2. CLI → daemon. MCP2CLI_REQUEST_TIMEOUT_MS (padrão 60s) limita a solicitação local via socket Unix. Quando dispara, o CLI reporta CONNECTION_ERROR: The operation timed out. mesmo que o daemon e o servidor MCP ainda estejam trabalhando.

Então, um verbo que pode rodar por 20 minutos precisa de ambos:

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

Uma chamada com tempo esgotado não é um verbo falho: o trabalho no lado do servidor pode muito bem ter sido concluído depois que o cliente parou de esperar. Não tente novamente às cegas um verbo não idempotente em caso de timeout.

Arquitetura

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

Principais Decisões de Design

Daemon persistente. Servidores MCP têm um custo de inicialização de 2 a 5 segundos por conexão. O daemon mantém conexões ativas em um pool, então chamadas subsequentes retornam em milissegundos em vez de segundos. O daemon sai automaticamente após o tempo limite de inatividade (padrão 60s).

Pool de conexões com verificações de saúde. Conexões são validadas antes do uso e recicladas em caso de falha. O pool impõe um tamanho máximo para evitar esgotamento de recursos.

JSON estruturado em todo lugar. O stdout é sempre JSON analisável — sem saída de texto misturada. Logs (quando habilitados) vão para o stderr como linhas JSON estruturadas. Isso torna o mcp2cli confiável para scripts e pipes.

Códigos de saída semânticos. Diferentes modos de falha recebem diferentes códigos de saída para que chamadores possam ramificar com base no tipo de erro sem analisar a saída.

Validação de entrada. Todos os parâmetros de ferramentas são validados contra o esquema MCP antes de a chamada ser despachada. A camada de validação lida com 48 padrões adversários (tentativas de injeção, coerção de tipo, estouro) para falhar rapidamente com erros claros.

Integração com Agentes

O mcp2cli é projetado para ser chamado por agentes de IA via uso de ferramenta bash. Um fluxo de trabalho 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"}'

Esse padrão mantém as definições de ferramentas MCP completamente fora do prompt de sistema do agente. O agente só paga custo de contexto quando realmente precisa chamar uma ferramenta, e mesmo assim apenas para o esquema da ferramenta específica — não todas as ferramentas de todos os servidores.

Autenticação Multiusuário

O mcp2cli suporta RBAC multiusuário via ~/.config/mcp2cli/tokens.json. Cada usuário ou agente recebe um token de portador com um papel.

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"
    }
  ]
}

Gere tokens seguros: openssl rand -base64 32

Papéis RBAC

Permissãovieweragentadmin
Listar serviços, statussimsimsim
Chamar ferramentas, listar ferramentas, esquemanãosimsim
Ler credenciaisnãosimsim
Adicionar/atualizar/remover serviçosnãonãosim
Escrever credenciais, gerenciar gruposnãonãosim
Recarregar, importar, encerrarnãonãosim

Os campos username/password habilitam login na web UI na URL raiz do daemon. Autenticação baseada em token (cabeçalho Bearer) funciona para todo acesso à API e CLI.

O campo opcional expiresAt habilita expiração e renovação de tokens. Tokens expirados são rejeitados. Tokens próximos da expiração de tokens.json podem ser rotacionados via POST /api/auth/refresh; o daemon grava o novo token de volta em tokens.json e recarrega edições do arquivo de tokens a quente. Clientes CLI locais renovam proativamente tokens admin próximos da expiração antes de chamadas à API do daemon.

Comportamento de Fallback

  • Sem tokens.json, sem token de ambiente: Autenticação desabilitada, todas as solicitações tratadas como admin (compatível com versões anteriores)
  • Apenas variável de ambiente MCP2CLI_AUTH_TOKEN: Modo legado de token único, tratado como admin
  • tokens.json existe: RBAC multiusuário completo

Gerenciamento de Credenciais por Identidade

Diferentes usuários e agentes podem ter suas próprias chaves de API para serviços de backend. Quando o rico chama o open-brain, ele usa a chave dele. Quando o skippy chama, a chave compartilhada dos agentes é usada.

credentials.json

Crie ~/.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" } }
  }
}

Cadeia de Resolução

Quando uma chamada de ferramenta chega, as credenciais são resolvidas em ordem de prioridade:

  1. Específica do usuário — credentials[userId][service]
  2. Grupo — primeiro grupo correspondente ao qual o usuário pertence
  3. Padrões — defaults[service]
  4. services.json — o que estiver embutido na configuração do serviço (compatível com versões anteriores)

Para serviços http/websocket, cabeçalhos de credenciais são mesclados na conexão. Para serviços stdio, variáveis de ambiente de credenciais são mescladas no ambiente do processo.

Para serviços sensíveis à identidade, defina requiresCredentials: true em services.json. Se não existir credencial de usuário, grupo ou padrão explícito, o daemon rejeita a chamada em vez de usar cabeçalhos base do serviço.

CLI de Credenciais

# 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"

Exemplo Open Brain

Open Brain (OBv2) é um serviço MCP HTTP onde o token de portador controla a identidade do namespace. Não coloque um cabeçalho Authorization do Open Brain em services.json; armazene-o apenas como credencial por identidade.

services.json — configuração base para um daemon hospedado (sem credenciais, apenas endpoint):

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

Use source: "remote" quando o CLI estiver roteando por um daemon mcp2cli hospedado. requiresCredentials: true faz credenciais por identidade ausentes falharem de forma segura, e preconnect: false impede que a inicialização do daemon abra uma conexão base não autenticada com o Open Brain.

credentials.json — chaves por identidade:

{
  "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" } }
    }
  }
}

Agora, quando o rico chama mcp2cli open-brain search_all --params '{"query": "kubernetes"}', a chave pessoal dele é injetada. Quando o skippy chama a mesma ferramenta, a chave compartilhada dos agentes é usada. Cada um recebe sua própria conexão no pool.

Bootstrap Vaultwarden — se o item Open Brain - Per-User Tokens tiver campos personalizados como AUTH_TOKEN_USER_RICO, AUTH_TOKEN_USER_SKIPPY e AUTH_TOKEN_USER_BILBY, execute:

mcp2cli credentials bootstrap-open-brain

O sufixo do campo é convertido para minúsculas e usado como identidade (AUTH_TOKEN_USER_RICO -> rico). Credenciais existentes são ignoradas a menos que --force seja passado. O comando imprime apenas contagens e nomes de identidade; não imprime tokens de portador.

Cabeçalhos de Identidade do Chamador

Valores de cabeçalho e ambiente suportam variáveis de modelo ${caller.id} e ${caller.role}. Elas são substituídas pela identidade do chamador autenticado no momento da chamada.

Em services.json — injete cabeçalhos de identidade para serviços cujo backend confia em metadados do chamador em vez de tokens de portador por usuário:

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

Quando o bilby chama o serviço, os cabeçalhos da solicitação se tornam X-Agent-Id: bilby e X-Role: agent.

Em credentials.json — combine chaves por identidade com cabeçalhos de identidade:

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

Modelos funcionam tanto em cabeçalhos quanto em valores de ambiente. Variáveis desconhecidas (por exemplo, ${caller.email}) são deixadas sem expansão.

Segurança

  • Saída de lista redigida -- GET /api/credentials retorna Bear*** em vez de valores completos
  • Proteção IDOR -- agentes só podem resolver suas próprias credenciais, admin necessário para outras
  • Permissões de arquivo -- credentials.json é escrito com 0600 (somente leitura/escrita do proprietário)
  • Validação de entrada -- valores de cabeçalho rejeitam injeção CRLF, cabeçalhos perigosos (Host, Transfer-Encoding) e variáveis de ambiente (PATH, LD_PRELOAD, NODE_OPTIONS) são bloqueados
  • Escritas atômicas -- arquivo temporário + renomeação evita escritas parciais em caso de falha
  • Invalidação de pool -- alterar credenciais remove conexões obsoletas automaticamente

Recursos Avançados

Cache de Esquema

Os esquemas são armazenados em cache localmente para evitar re-busca a cada invocação. Os esquemas em cache ficam em ~/.cache/mcp2cli/schemas/ com TTL de 24 horas. A derivação do cache é detectada via hash SHA-256 -- se o esquema upstream mudar, o cache é invalidado automaticamente.

# 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

Substitua o diretório de cache com MCP2CLI_CACHE_DIR.

Controle de Acesso

Restrinja quais ferramentas são expostas por serviço usando allowTools e blockTools em services.json. Ambos aceitam padrões glob.

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

Quando ambos estão presentes, allowTools é avaliado primeiro (whitelist), depois blockTools remove correspondências do conjunto permitido.

Pesquisa de Ferramentas entre Serviços

Pesquise ferramentas em todos os serviços usando esquemas em cache:

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

# Regex patterns work
mcp2cli grep "delete|remove"

Isso pesquisa apenas esquemas em cache -- nenhuma conexão MCP é feita.

Transporte WebSocket

Conecte-se a servidores MCP via WebSocket. Suporta fallback opcional para stdio e controle de acesso, igual ao 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"]
      }
    }
  }
}

Os serviços WebSocket se beneficiam do mesmo disjuntor e comportamento de fallback que os serviços HTTP.

Chamadas de Ferramentas em Lote

Execute várias chamadas de ferramentas em uma única invocação canalizando NDJSON para mcp2cli batch. Cada linha é um objeto JSON com campos service, tool e 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

A saída é NDJSON -- um resultado por linha com o serviço/ferramenta original para correlação:

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

Erros para chamadas individuais são relatados inline sem abortar o lote.

Resiliência de Gateway

Serviços HTTP/SSE podem definir uma configuração stdio fallback. Se o gateway remoto estiver inacessível, o mcp2cli cai transparentemente para um processo 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"]
      }
    }
  }
}

Um disjuntor protege contra falhas repetidas: após 5 falhas consecutivas, o circuito abre e roteia diretamente para o fallback por 60 segundos antes de re-testar o primário. O estado do circuito é persistido em ~/.cache/mcp2cli/circuit-breaker/ para sobreviver a reinicializações do processo.

Formatos de Saída

Controle o formato de saída com a flag --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
FormatoDescrição
jsonPadrão. JSON estruturado (inalterado desde v1.0)
tableColunas alinhadas -- saída de terminal legível por humanos
yamlSaída YAML
csvRFC 4180 CSV -- canalize para planilhas ou csvtool
ndjsonUm objeto JSON por linha -- para pipelines de streaming

As respostas de erro são sempre JSON, independentemente da flag --format.

Regeneração Automática de Habilidades

Arquivos de habilidade gerados podem ser pré-visualizados e mantidos em sincronia com mudanças de esquema upstream:

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

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

Edições manuais dentro dos marcadores MANUAL:START / MANUAL:END são preservadas entre regenerações. Quando a derivação de esquema é detectada (via camada de cache), a regeneração de habilidades pode ser acionada automaticamente.

Para mudanças no Open Brain MCP, use o caminho apoiado por registro em vez de atualizar diretamente um daemon local como prova de lançamento:

# 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

A validação local deve usar um MCP2CLI_HOME/config/cache temporário isolado para que os testes não possam alterar o estado local real do operador ~/.config/mcp2cli. A verificação final deve ser executada contra o daemon hospedado e provar que as novas ferramentas estão visíveis e chamáveis lá.

Variáveis de Ambiente Adicionais

VariávelPadrãoDescrição
MCP2CLI_CACHE_DIR~/.cache/mcp2cliDiretório base para cache de esquema e estado do disjuntor
MCP2CLI_TOKENS_FILE~/.config/mcp2cli/tokens.jsonCaminho para configuração de token multiusuário
MCP2CLI_TOKEN_REFRESH_WINDOW_MS86400000Janela de renovação para tokens expirando (padrão 24h)
MCP2CLI_TOKEN_TTL_MS2592000000Tempo de vida para tokens renovados (padrão 30d)
MCP2CLI_CREDENTIALS_FILE~/.config/mcp2cli/credentials.jsonCaminho para mapeamentos de credenciais por identidade
MCP2CLI_IMPORT_TOKEN(não definido)Token Bearer usado apenas para importações de configuração importUrl
MCP2CLI_IMPORT_ALLOWED_HOSTS(necessário para importUrl)Lista de permissões separada por vírgulas para hostnames importUrl
MCP2CLI_IMPORT_ALLOW_DNS(não definido)Defina como 1 para permitir hostnames DNS para alvos importUrl não privados
MCP2CLI_IMPORT_ALLOW_HTTP(não definido)Defina como 1 para permitir alvos importUrl não HTTPS
MCP2CLI_IMPORT_ALLOW_PRIVATE(não definido)Defina como 1 para permitir alvos importUrl loopback/privados/link-local
MCP2CLI_METRICS_INCLUDE_CALLER(não definido)Defina como 1 para incluir rótulos brutos do chamador em /metrics público; desabilitado por padrão
MCP2CLI_VAULTWARDEN_TIMEOUT_MS10000Tempo limite para consultas ${secret:...} apoiadas por Vaultwarden

Implantação em Rede

O mcp2cli pode ser executado como um daemon TCP centralizado, permitindo que várias máquinas compartilhem um único conjunto de conexões de servidor MCP. Instale e configure os backends MCP uma vez em um servidor e conecte-se de qualquer máquina usando o cliente CLI ou o wrapper bash (apenas curl + jq -- sem necessidade de Bun).

Início Rápido (Modo TCP)

Servidor -- inicie o daemon com bind 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 -- aponte qualquer máquina para o 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 '{}'

Quando MCP2CLI_REMOTE_URL está definido, o CLI pula completamente a inicialização do daemon local e envia solicitações diretamente via HTTP.

Variáveis de Ambiente de Rede

Além das variáveis de ambiente base, o modo de rede adiciona:

VariávelPadrãoDescrição
MCP2CLI_LISTEN_HOST(não definido)Endereço de bind para modo TCP. Definir isso habilita TCP em vez de socket Unix. Use 0.0.0.0 para escutar em todas as interfaces
MCP2CLI_LISTEN_PORT9500Porta TCP quando MCP2CLI_LISTEN_HOST está definido
MCP2CLI_AUTH_TOKEN(não definido)Token Bearer para autenticação TCP. Necessário para implantações em produção. Alias: MCP_TOKEN
MCP2CLI_REMOTE_URL(não definido)URL do daemon mcp2cli remoto (ex.: https://mcp2cli.rodaddy.live). Habilita o modo cliente remoto. Alias: MCP_HOST
MCP2CLI_CONFIG~/.config/mcp2cli/services.jsonCaminho para definições de serviço (útil para configuração do lado do servidor em /etc/mcp2cli/)
MCP2CLI_TOKENS_FILE~/.config/mcp2cli/tokens.jsonCaminho para configuração de token/RBAC multiusuário
MCP2CLI_CREDENTIALS_FILE~/.config/mcp2cli/credentials.jsonCaminho para mapeamentos de credenciais por identidade

Autenticação

O daemon suporta dois modos de autenticação (veja Autenticação Multiusuário acima):

  1. RBAC multiusuário via tokens.json -- cada usuário/agente recebe seu próprio token e papel
  2. Token único legado via variável de ambiente MCP2CLI_AUTH_TOKEN -- tratado como admin

Todas as comparações de token usam igualdade segura contra timing para prevenir ataques de timing.

Caminhos isentos de autenticação -- estes pulam a autenticação para que balanceadores de carga e monitoramento possam sondar sem credenciais:

  • GET /health -- verificação de saúde com uptime, memória e contagem de conexões ativas
  • GET /metrics -- endpoint de métricas Prometheus com métricas agregadas de serviço/ferramenta

Métricas Prometheus

O daemon expõe métricas em GET /metrics no formato de exposição de texto Prometheus. Métricas principais:

MétricaTipoDescrição
mcp2cli_requests_totalcontadorTotal de solicitações por {service, tool}
mcp2cli_requests_errors_totalcontadorSolicitações com falha por {service, tool}
mcp2cli_request_duration_mshistogramaLatência de solicitação com buckets (10ms - 30s)
mcp2cli_requests_activegaugeSolicitações atualmente em andamento
mcp2cli_pool_connections_activegaugeTamanho atual do pool de conexões
mcp2cli_pool_servicesgaugeServiços conectados (rótulo {service})
mcp2cli_connection_events_totalcontadorConectar/desconectar/falha de verificação de saúde por {service}
mcp2cli_auth_failures_totalcontadorTotal de falhas de autenticação
mcp2cli_process_uptime_secondsgaugeUptime do daemon
mcp2cli_process_memory_rss_bytesgaugeTamanho do conjunto residente

Rótulos brutos do chamador em /metrics público são desabilitados por padrão para evitar expor IDs de usuário a scrapers não autenticados. Defina MCP2CLI_METRICS_INCLUDE_CALLER=1 apenas em ambientes de monitoramento confiáveis para adicionar séries {service, tool, caller}.

Para uma análise JSON rápida por identidade, chame GET /api/metrics/user/:userId com um token bearer que tenha permissão status. Chamadores não-admin só podem ler suas próprias métricas de usuário; admins podem ler qualquer usuário.

Clientes remotos descobrem o inventário de serviços do daemon através de GET /api/services/discovery autenticado, não da sonda pública /health.

Adicione à sua configuração do Prometheus:

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

Wrapper Bash (clientes apenas com curl)

Para máquinas que só têm curl e jq (sem runtime Bun), use o wrapper 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 '{}'

Implantação LXC

O diretório deploy/ contém tudo o que é necessário para executar o mcp2cli como um serviço systemd em um contêiner LXC (ou qualquer host Linux):

ArquivoFinalidade
deploy/mcp2cli.servicearquivo de unidade systemd (endurecido com NoNewPrivileges, ProtectSystem=strict)
deploy/env.exampleModelo de arquivo de ambiente -- copie para /etc/mcp2cli/env
deploy/services-server.jsonExemplo de configuração de serviço do lado do servidor

Configuração:

# 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

Exemplos com 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 .

Desenvolvimento

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

Licença

MIT