Turn any MCP server, OpenAPI spec, or GraphQL endpoint into a CLI. Use this skill when the user wants to interact with an MCP server, OpenAPI/REST API, or GraphQL API via command line, discover available tools/endpoints, call API operations, or generate a new skill from an API. Triggers include "mcp2cli", "call this MCP server", "use this API", "list tools from", "create a skill for this API", "graphql", or any task involving MCP tool invocation, OpenAPI endpoint calls, or GraphQL queries without writing code.
Turn any MCP server, OpenAPI spec, or GraphQL endpoint into a CLI at runtime. No codegen.
# Run directly (no install needed)
uvx mcp2cli --help
# Or install
pip install mcp2cli
--list (or filter with --search)<command> --help# MCP over HTTP
mcp2cli --mcp https://mcp.example.com/sse --list
mcp2cli --mcp https://mcp.example.com/sse create-task --help
mcp2cli --mcp https://mcp.example.com/sse create-task --title "Fix bug"
# MCP over stdio
mcp2cli --mcp-stdio "npx @modelcontextprotocol/server-filesystem /tmp" --list
mcp2cli --mcp-stdio "npx @modelcontextprotocol/server-filesystem /tmp" read-file --path /tmp/hello.txt
# OpenAPI spec (remote or local, JSON or YAML)
mcp2cli --spec https://petstore3.swagger.io/api/v3/openapi.json --list
mcp2cli --spec ./openapi.json --base-url https://api.example.com list-pets --status available
# GraphQL endpoint
mcp2cli --graphql https://api.example.com/graphql --list
mcp2cli --graphql https://api.example.com/graphql users --limit 10
mcp2cli --graphql https://api.example.com/graphql create-user --name "Alice"
mcp2cli [global options] <subcommand> [command options]
Source (mutually exclusive, one required):
--spec URL|FILE OpenAPI spec (JSON or YAML, local or remote)
--mcp URL MCP server URL (HTTP/SSE)
--mcp-stdio CMD MCP server command (stdio transport)
--graphql URL GraphQL endpoint URL
Options:
--auth-header K:V HTTP header (repeatable, value supports env:/file: prefixes)
--base-url URL Override base URL from spec
--transport TYPE MCP HTTP transport: auto|sse|streamable (default: auto)
--env KEY=VALUE Env var for stdio server process (repeatable)
--oauth Enable OAuth (authorization code + PKCE flow)
--oauth-client-id ID OAuth client ID (supports env:/file: prefixes)
--oauth-client-secret S OAuth client secret (supports env:/file: prefixes)
--oauth-scope SCOPE OAuth scope(s) to request
--cache-key KEY Custom cache key
--cache-ttl SECONDS Cache TTL (default: 3600)
--refresh Bypass cache
--list List available subcommands
--search PATTERN Search tools by name or description (implies --list)
--fields FIELDS Override GraphQL selection set (e.g. "id name email")
--pretty Pretty-print JSON output
--raw Print raw response body
--toon Encode output as TOON (token-efficient for LLMs)
--jq EXPR Filter JSON output through jq expression
--head N Limit output to first N records (arrays)
--version Show version
Bake mode:
bake create NAME [opts] Save connection settings as a named tool
bake list List all baked tools
bake show NAME Show config (secrets masked)
bake update NAME [opts] Update a baked tool
bake remove NAME Delete a baked tool
bake install NAME Create ~/.local/bin wrapper script
@NAME [args] Run a baked tool (e.g. mcp2cli @petstore --list)
Subcommands and flags are generated dynamically from the source.
# API key header (literal value)
mcp2cli --spec ./spec.json --auth-header "Authorization:Bearer tok_..." list-items
# Secret from environment variable (avoids exposing in process list)
mcp2cli --mcp https://mcp.example.com/sse \
--auth-header "Authorization:env:API_TOKEN" \
search --query "test"
# Secret from file
mcp2cli --mcp https://mcp.example.com/sse \
--auth-header "x-api-key:file:/run/secrets/api_key" \
search --query "test"
# Authorization code + PKCE (opens browser)
mcp2cli --mcp https://mcp.example.com/sse --oauth --list
# Client credentials (machine-to-machine)
mcp2cli --mcp https://mcp.example.com/sse \
--oauth-client-id "my-id" --oauth-client-secret "my-secret" \
search --query "test"
# With scopes
mcp2cli --mcp https://mcp.example.com/sse --oauth --oauth-scope "read write" --list
Tokens are cached in ~/.cache/mcp2cli/oauth/ and refreshed automatically.
# Default: tries streamable HTTP, falls back to SSE
mcp2cli --mcp https://mcp.example.com/sse --list
# Force SSE transport (skip streamable HTTP attempt)
mcp2cli --mcp https://mcp.example.com/sse --transport sse --list
# Force streamable HTTP (no SSE fallback)
mcp2cli --mcp https://mcp.example.com/sse --transport streamable --list
# Discover queries and mutations
mcp2cli --graphql https://api.example.com/graphql --list
# Run a query
mcp2cli --graphql https://api.example.com/graphql users --limit 10
# Run a mutation
mcp2cli --graphql https://api.example.com/graphql create-user --name "Alice" --email "[email protected]"
# Override auto-generated selection set
mcp2cli --graphql https://api.example.com/graphql users --fields "id name email"
# With auth
mcp2cli --graphql https://api.example.com/graphql --auth-header "Authorization:Bearer tok_..." users
# Filter tools by name or description (case-insensitive)
mcp2cli --mcp https://mcp.example.com/sse --search "task"
mcp2cli --spec ./openapi.json --search "create"
mcp2cli --graphql https://api.example.com/graphql --search "user"
--search implies --list — shows only matching tools.
echo '{"name": "Fido", "tag": "dog"}' | mcp2cli --spec ./spec.json create-pet --stdin
mcp2cli --mcp-stdio "node server.js" --env API_KEY=sk-... --env DEBUG=1 search --query "test"
Save connection settings as named configurations to avoid repeating flags:
# Create a baked tool
mcp2cli bake create petstore --spec https://api.example.com/spec.json \
--exclude "delete-*,update-*" --methods GET,POST --cache-ttl 7200
mcp2cli bake create mygit --mcp-stdio "npx @mcp/github" \
--include "search-*,list-*" --exclude "delete-*"
# Use with @ prefix
mcp2cli @petstore --list
mcp2cli @petstore list-pets --limit 10
# Manage
mcp2cli bake list
mcp2cli bake show petstore
mcp2cli bake update petstore --cache-ttl 3600
mcp2cli bake remove petstore
mcp2cli bake install petstore # creates ~/.local/bin/petstore wrapper
Filter options: --include (glob whitelist), --exclude (glob blacklist), --methods (HTTP methods, OpenAPI only).
Configs stored in ~/.config/mcp2cli/baked.json (override with MCP2CLI_CONFIG_DIR).
Specs and MCP tool lists are cached in ~/.cache/mcp2cli/ (1h TTL). Local files are never cached.
mcp2cli --spec https://api.example.com/spec.json --refresh --list # Force refresh
mcp2cli --spec https://api.example.com/spec.json --cache-ttl 86400 --list # 24h TTL
mcp2cli --mcp https://mcp.example.com/sse --toon list-tags
Best for large uniform arrays — 40-60% fewer tokens than JSON.
Prefer --jq over Python scripts for JSON processing — it uses fewer tokens and avoids script overhead.
# Extract specific fields
mcp2cli --spec ./spec.json list-pets --jq '.[].name'
# Count results
mcp2cli --mcp https://example.com/sse list-items --jq 'length'
# Complex filtering
mcp2cli --spec ./spec.json list-pets --jq '[.[] | select(.status == "available")] | length'
# Preview large datasets (--head truncates before --jq processes)
mcp2cli --spec ./spec.json list-records --head 3 --jq '.'
# Preview first 3 records from a potentially huge dataset
mcp2cli --spec ./spec.json list-records --head 3 --pretty
# Combine with --jq for targeted inspection
mcp2cli --spec ./spec.json list-records --head 1 --jq 'keys'
--head N slices JSON arrays to the first N elements. Useful for datasets with oversized fields (e.g. geo_shape polygons at ~200KB per record).
When the user asks to create a skill from an MCP server, OpenAPI spec, or GraphQL endpoint, follow this workflow:
Discover all available commands:
uvx mcp2cli --mcp https://target.example.com/sse --list
Inspect each command to understand parameters:
uvx mcp2cli --mcp https://target.example.com/sse <command> --help
Test key commands and probe for edge cases:
uvx mcp2cli --mcp https://target.example.com/sse <command> --param value
Specifically test for:
--head 3 to preview — do any fields produce oversized output (e.g. geo_shape, embedded blobs)?date'2022'?)--offset/--limit?Bake the connection settings so the skill doesn't need to repeat flags:
uvx mcp2cli bake create myapi \
--mcp https://target.example.com/sse \
--auth-header "Authorization:Bearer env:MYAPI_TOKEN" \
--exclude "delete-*" --methods GET,POST
Install the wrapper into the skill's scripts directory:
uvx mcp2cli bake install myapi --dir .claude/skills/myapi/scripts/
Create a SKILL.md in .claude/skills/myapi/ that teaches another AI agent how to use this API. The SKILL.md must go beyond --help output — focus on knowledge that can only be learned through testing and reading documentation.
The generated skill uses mcp2cli as its execution layer — the baked wrapper script handles all connection details so the SKILL.md stays clean and portable.
Frontmatter:
---
name: myapi
description: Interact with the MyAPI service
allowed-tools: Bash(bash *)
---
Core Workflow (discovery + execution):
# List available commands
bash ${CLAUDE_SKILL_DIR}/scripts/myapi --list
# Get help for a command
bash ${CLAUDE_SKILL_DIR}/scripts/myapi <command> --help
# Run a command
bash ${CLAUDE_SKILL_DIR}/scripts/myapi <command> --param value --pretty
Before Querying checklist — include a decision framework:
--offset, --limit)?--head)?Anti-Patterns & Gotchas — document every surprise found during testing:
date'2022' vs "2022")--head or --jq to exclude)Output Processing — recommend --jq over Python for JSON filtering:
# Extract specific fields
bash ${CLAUDE_SKILL_DIR}/scripts/myapi list-records --jq '.[].name'
# Count results
bash ${CLAUDE_SKILL_DIR}/scripts/myapi list-records --jq 'length'
# Filter by condition
bash ${CLAUDE_SKILL_DIR}/scripts/myapi list-records --jq '[.[] | select(.status == "active")]'
Prefer --jq over piping to Python for JSON processing — it is more token-efficient and avoids unnecessary script complexity.
Export Formats (if the API supports multiple output types):
bash ${CLAUDE_SKILL_DIR}/scripts/myapi export --format xlsx --raw > output.xlsxKnowledge Delta Principle: Do not duplicate parameter listings from --help. Instead, document which parameters actually matter for common tasks, default behaviors that are surprising, combinations that don't work, and rate limits or response size limits.