SkillAgentSearch skills...

source-code

MCP-ecosystem CLI adapter — convert MCP servers into discoverable, scriptable CLI tools.

Install / Use

claude mcp add mcp2cli -- npx -y github:mcp2cli/source-code

If the server publishes to npm under a different name, use that package instead — check the repo README.

About this skill
🔌

MCP Server

Model Context Protocol server

Quality Score

71/100

Supported Platforms

Claude Code
Claude Desktop

Tags

mcp2cli

Turn any MCP server into a native command-line application.

Server tools become verbs. Resources become nouns. Prompts become workflows. No MCP protocol knowledge required at the terminal.

# One binary. Any server. Real CLI commands.
email ls
email send --to user@example.com --subject "Hi" --body "Meeting at 3"
email get mail://inbox
staging deploy --version 2.1.0 --background
prod --json doctor | jq '.data.server'

Why mcp2cli?

MCP (Model Context Protocol) defines a powerful standard for servers to expose tools, resources, and prompts. But interacting with an MCP server requires JSON-RPC plumbing, session negotiation, and protocol-level knowledge — none of which belongs in a CLI.

mcp2cli bridges that gap:

| Problem | mcp2cli | |---------|---------| | MCP requires JSON-RPC plumbing | Auto-discovers capabilities → typed --flags from JSON Schema | | Testing MCP servers needs custom client code | Point, shoot: mcp2cli --url http://localhost:3001/mcp ls | | Each server needs its own CLI wrapper | One binary + config files = unlimited server bindings | | AI agents can't easily call MCP tools from shell | --json output → structured envelopes for programmatic parsing | | CI/CD can't orchestrate MCP operations | Exit codes, JSON output, pipes, --timeout, --background | | Server tools have cryptic protocol names | Profile overlays rename, group, and hide commands |


Quick Start

Install

cargo install --path .

Option A: Ad-hoc — zero config

# HTTP server — just point and go
mcp2cli --url http://127.0.0.1:3001/mcp ls
mcp2cli --url http://127.0.0.1:3001/mcp echo --message hello

# Stdio server — just run
mcp2cli --stdio "npx @modelcontextprotocol/server-everything" ls

Option B: Named config + alias

# Create a config
mcp2cli config init --name email --app bridge \
  --transport streamable_http --endpoint https://mcp.example.com/email

# Create a symlink alias
mcp2cli link create --name email

# Authenticate (the email server needs a bearer token)
email auth login

# Use it like a standalone app
email ls                                      # Discover capabilities
email send --to user@example.com \
  --subject "Hi" --body "Meeting at 3"        # Call a tool
email search --query "from:boss"              # Search the mailbox
email get mail://inbox                        # Read a resource
email doctor                                  # Health check

Option C: Demo mode — no server needed

mcp2cli config init --name demo --app bridge \
  --transport streamable_http --endpoint https://demo.invalid/mcp
mcp2cli use demo
mcp2cli ls

Full getting started guide →


How It Works

mcp2cli discovers → builds manifest → generates CLI → parses input → executes MCP call
  1. Discovers the server's tools, resources, resource templates, and prompts
  2. Builds a command manifest — each capability becomes a typed command with flags derived from JSON Schema
  3. Generates a clap CLI tree — dotted names become nested subcommands, required fields become required flags
  4. Parses your input against the generated tree with full type validation
  5. Executes the MCP operation and renders the result

Schema-to-flag mapping

| JSON Schema | CLI flag | Example | |-------------|----------|---------| | string | --name <TEXT> | --message hello | | integer | --count <INT> | --steps 5 | | number | --rate <NUM> | --temperature 0.7 | | boolean | --flag | --include-image | | enum | --kind <A\|B\|C> | --level error | | array | --tags <VAL,...> | --labels bug,urgent | | Complex | --config <JSON> | --config '{"a":1}' |

Namespace grouping

Dotted tool names automatically become nested subcommands:

# Server tools: send, reply, draft.create
email send --to user@example.com --subject "Hi" --body "Hello"
email reply --thread-id 123 --body "Thanks"
email draft create --subject "New draft"

Features at a Glance

Core

Transports

  • Streamable HTTP — JSON-RPC over HTTP with SSE streaming and session negotiation
  • Stdio — spawn local subprocess servers, communicate via stdin/stdout
  • Demo modedemo.invalid file-backed backend for offline learning and testing

Protocol Coverage

Full dual-revision implementation of the Model Context Protocol — MCP 2026-07-28 (stateless, per-request _meta, server/discover, MRTR, the tasks extension) and MCP 2025-11-25 (initialize handshake, sessions). By default mcp2cli probes with server/discover and falls back to the legacy handshake automatically, exactly as the 2026-07-28 backward-compatibility rules describe; pin either revision with server.protocol_version. See the Protocol Coverage reference for per-feature, per-revision detail, source pointers, and CLI examples.

| Category | 2025-11-25 | 2026-07-28 | mcp2cli surface | |---|---|---|---| | Lifecycle | initialize + notifications/initialized, ping | stateless _meta on every request, server/discover | One handshake or probe per session; ping works in both (maps to server/discover on modern servers) | | Discovery | tools/list, resources/list, resources/templates/list, prompts/list + notifications/*/list_changed | same lists + ttlMs/cacheScope freshness hints | ls populates a persistent cache; list-change notifications / TTL hints keep it fresh | | Tool invocation | tools/call | tools/call + resultType, MRTR retries, x-mcp-headerMcp-Param-* mirroring | Typed clap flags from JSON Schema; progress token attached automatically | | Resources | resources/read, resources/subscribe/unsubscribe | resources/read (MRTR-capable), subscriptions/listen | get <URI> for concrete reads; subscribe verifies the era-appropriate subscription | | Prompts | prompts/get | prompts/get (MRTR-capable) | Each prompt becomes a command with typed argument flags | | Completions | completion/complete with ref.context | same | complete command with ref context (resource or prompt) | | Logging | logging/setLevel, notifications/message | per-request _meta["…/logLevel"] | log <LEVEL> works in both; the level persists and is injected per-request on modern servers | | Progress | notifications/progress + _meta.progressToken | same (request-scoped stream) | Progress tokens auto-attached; ticks rendered to stderr or event sinks | | Cancellation | notifications/cancelled (bidirectional) | notifications/cancelled (stdio) / closing the response stream (HTTP) | Ctrl+C cancels the in-flight request | | Server input (elicitation/sampling/roots) | server-initiated JSON-RPC requests | MRTR: resultType: "input_required" + retry with inputResponses | Same interactive terminal prompts in both revisions | | Tasks | experimental core (_meta.task, tasks/get/result/cancel) | official io.modelcontextprotocol/tasks extension (resultType: "task", polled tasks/get, tasks/update) | --background creates a task; jobs show/wait/cancel/watch tracks it; unsolicited modern tasks are polled transparently |

Operations

  • Authenticationauth login/logout/status with file-backed token persistence
  • Event system — 5 sink types: stderr, HTTP webhook, Unix socket, SSE server, command exec
  • Output formats--json, --output json|ndjson|human — every command supports structured output
  • Request timeouts — global default + per-command --timeout override
  • Daemon mode — keep MCP connections warm between invocations (Unix socket IPC)
  • Doctor & Inspect — runtime health diagnostics, full capability dump

Multi-Server Workflow

Each alias routes to a different MCP server. Each feels like its own standalone application.

# Set up multiple servers
mcp2cli config init --name dev --transport stdio --stdio-command ./dev-server
mcp2cli config init --name staging --transport streamable_http --endpoint https://staging.api/mcp
mcp2cli config init --name prod --transport streamable_http --endpoint https://prod.api/mcp

# Create aliases
mcp2cli link create --name dev
mcp2cli link create --name staging
mcp2cli link create --name prod

# Each alias is its own CLI
dev ls                          # Local dev server
staging deploy --version 1.2.3  # Staging HTTP server
prod doctor                     # Production health check

JSON Output for Scripts & Agents

Every command supports structured JSON output:

# JSON envelope
email --json ls | jq '.data.items[].id'

# Tool result
email --json send --to user@example.com --subject "Hi" --body "Hello" | jq '.data.content[0].text'

# Health check data
email --json doctor | jq '.data.server'

# Machine-readable discovery
email --json ls --tools | jq '[.data.items[] | {id, kind, summary}]'

Consistent envelope format:

{
  "app_id": "email",
  "command": "invoke",
  "summary": "called send",
  "lines": ["..."],
  "data": { "content": [...] }
}

Profile Overlays

Customize the CLI surface per-server — no server changes needed:

profile:
  display_name: "Email CLI"
  aliases:
    long-running-operation: lro     # Rename commands
    echo: ping
  hide:
    - debug-tool                    # Hide from help/ls
  groups:
    mail:                           # Custom grouping
      - send
      - reply
      - draft-create
  flags:
    echo:
      message: msg                  # Rename flags
  resource_verb: fetch              # "fetch" instead of "get"

Config Model

Each named config is a YAML file. Minimal example:

schema_version: 1
server:
  transport: streamable_http
  endpoint: http://localhost:3001/mcp

Full example with all options:

schema_version: 1

app:
  profile: bridge

server:
  display_name: My MCP Server
  transport: stdio                       # or streamable_http
  endpoint: null                         # required for streamable_http
  protocol_version: auto                 # auto | 2026-07-28 | 2025-11-25
  stdio:
    command: npx
    args: ['@modelcontextprotocol/server-everything']
  roots:
    - uri: "file:///home/user/project"
      name: "Project Root"

defaults:
  output: human                          # human | json | ndjson
  timeout_seconds: 120                   # 0 = no timeout

logging:
  level: warn
  format: pretty
  outputs:
    - kind: stderr

auth:
  browser_open_command: null

events:
  enable_stdio_events: true
  # http_endpoint: "http://127.0.0.1:9090/events"
  # local_socket_path: "/tmp/mcp2cli-events.sock"
  # sse_endpoint: "127.0.0.1:9091"
  # command: "logger -t mcp2cli '${MCP_EVENT_MESSAGE}'"

prof

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars10
CategoryDevelopment
Updated1mo ago
Forks1

Languages

Rust

Security Score

92/100

Audited on Jul 23, 2026

1 low1 info