Loading...
Loading...
Turn any MCP, OpenAPI, or GraphQL server into a CLI at runtime with zero codegen, saving 96-99% of tokens wasted on tool schemas
npx skill4agent add aradotso/mcp-skills mcp2cli-api-to-cliSkill by ara.so — MCP Skills collection.
# Run directly without installing
uvx mcp2cli --help
# Or install globally
uv tool install mcp2cli
# Install as a skill for AI agents
npx skills add knowsuchagency/mcp2cli --skill mcp2cli# List available tools
mcp2cli --mcp https://mcp.example.com/sse --list
# Call a tool
mcp2cli --mcp https://mcp.example.com/sse search --query "rust async"
# With authentication
mcp2cli --mcp https://mcp.example.com/sse \
--auth-header "x-api-key:env:MCP_API_KEY" \
query --sql "SELECT * FROM users LIMIT 10"
# Force specific transport (skip auto-negotiation)
mcp2cli --mcp https://mcp.example.com/sse --transport sse --list
# Search tools by name or description
mcp2cli --mcp https://mcp.example.com/sse --search "database"# List tools from filesystem MCP server
mcp2cli --mcp-stdio "npx @modelcontextprotocol/server-filesystem /tmp" --list
# Read a file
mcp2cli --mcp-stdio "npx @modelcontextprotocol/server-filesystem /tmp" \
read-file --path /tmp/data.json
# Pass environment variables to the server
mcp2cli --mcp-stdio "node ./custom-server.js" \
--env DATABASE_URL=env:DATABASE_URL \
--env DEBUG=1 \
search --query "test"# Remote spec
mcp2cli --spec https://petstore3.swagger.io/api/v3/openapi.json --list
# Local spec with base URL override
mcp2cli --spec ./openapi.yaml --base-url https://api.example.com --list
# Call an endpoint
mcp2cli --spec ./openapi.json --base-url https://api.example.com \
list-pets --status available --limit 20
# POST with JSON body from stdin
echo '{"name": "Fido", "species": "dog"}' | \
mcp2cli --spec ./openapi.json create-pet --stdin
# With authentication
mcp2cli --spec ./openapi.json \
--auth-header "Authorization:Bearer env:API_TOKEN" \
create-item --name "New Item"# List all queries and mutations
mcp2cli --graphql https://api.example.com/graphql --list
# Execute a query (auto-generates selection set)
mcp2cli --graphql https://api.example.com/graphql users --limit 10
# Execute a mutation
mcp2cli --graphql https://api.example.com/graphql \
create-user --name "Alice" --email "alice@example.com"
# Override selection set fields
mcp2cli --graphql https://api.example.com/graphql \
users --fields "id name email createdAt"
# With authentication
mcp2cli --graphql https://api.example.com/graphql \
--auth-header "Authorization:Bearer env:GRAPHQL_TOKEN" \
users# Authorization code + PKCE (opens browser)
mcp2cli --mcp https://mcp.example.com/sse --oauth --list
mcp2cli --spec https://api.example.com/openapi.json --oauth list-users
mcp2cli --graphql https://api.example.com/graphql --oauth users
# Client credentials (machine-to-machine)
mcp2cli --spec https://api.example.com/openapi.json \
--oauth-client-id "env:OAUTH_CLIENT_ID" \
--oauth-client-secret "env:OAUTH_CLIENT_SECRET" \
list-resources
# With specific scopes
mcp2cli --graphql https://api.example.com/graphql \
--oauth --oauth-scope "read:users write:users" \
users
# Local spec — provide base URL for OAuth discovery
mcp2cli --spec ./openapi.json \
--base-url https://api.example.com \
--oauth \
--list~/.cache/mcp2cli/oauth/# Read from environment variable
mcp2cli --mcp https://mcp.example.com/sse \
--auth-header "Authorization:env:MY_API_TOKEN" \
--list
# Read from file
mcp2cli --spec ./openapi.json \
--oauth-client-secret "file:/run/secrets/client_secret" \
--oauth-client-id "file:/run/secrets/client_id" \
--list
# Works with secret managers
vault kv get -field=token secret/api | \
MY_TOKEN=$(cat) mcp2cli --mcp https://mcp.example.com/sse \
--auth-header "Authorization:env:MY_TOKEN" \
search --query "data"# Create baked tool from OpenAPI spec
mcp2cli bake create petstore \
--spec https://api.example.com/openapi.json \
--auth-header "Authorization:Bearer env:PETSTORE_TOKEN" \
--exclude "delete-*,update-*" \
--methods GET,POST \
--cache-ttl 7200
# Create baked tool from MCP stdio server
mcp2cli bake create github \
--mcp-stdio "npx @modelcontextprotocol/server-github" \
--env GITHUB_TOKEN=env:GITHUB_TOKEN \
--include "search-*,list-*" \
--exclude "delete-*"
# Create baked tool from GraphQL endpoint
mcp2cli bake create hasura \
--graphql https://hasura.example.com/v1/graphql \
--auth-header "x-hasura-admin-secret:env:HASURA_SECRET"
# Use baked tool with @ prefix
mcp2cli @petstore --list
mcp2cli @petstore list-pets --limit 5
mcp2cli @github search-repos --query "mcp server"
mcp2cli @hasura users --limit 10
# Manage baked tools
mcp2cli bake list
mcp2cli bake show petstore
mcp2cli bake update petstore --cache-ttl 3600
mcp2cli bake remove petstore
# Install as standalone script
mcp2cli bake install petstore
# Creates ~/.local/bin/petstore wrapper
# Install to custom directory
mcp2cli bake install petstore --dir ./scripts/# Include only specific tool patterns
mcp2cli bake create myapi \
--spec ./openapi.json \
--include "list-*,get-*,search-*"
# Exclude dangerous operations
mcp2cli bake create myapi \
--spec ./openapi.json \
--exclude "delete-*,destroy-*"
# Limit to specific HTTP methods (OpenAPI only)
mcp2cli bake create myapi \
--spec ./openapi.json \
--methods GET,POST# Default list (sorted by usage frequency when available)
mcp2cli @myapi --list
# Top 10 most-used tools, compact output (~20 tokens)
mcp2cli @myapi --list --top 10 --compact
# Sort by most recently used
mcp2cli @myapi --list --sort recent
# Alphabetical sort
mcp2cli @myapi --list --sort alpha
# Show full descriptions
mcp2cli @myapi --list --verbose~/.cache/mcp2cli/usage.json# Pretty-print JSON (auto-enabled for TTY)
mcp2cli --spec ./openapi.json --pretty list-users
# Raw response body (no JSON parsing)
mcp2cli --spec ./openapi.json --raw get-binary-data
# Limit output to first N records
mcp2cli --spec ./openapi.json list-logs --head 20
# TOON output (40-60% fewer tokens for LLMs)
mcp2cli --mcp https://mcp.example.com/sse --toon list-large-dataset
# Pipe-friendly output
mcp2cli --spec ./openapi.json list-users | jq '.[] | .email'# Force refresh (bypass cache)
mcp2cli --spec https://api.example.com/openapi.json --refresh --list
# Custom TTL (7 days)
mcp2cli --spec https://api.example.com/openapi.json --cache-ttl 604800 --list
# Custom cache key
mcp2cli --spec https://api.example.com/openapi.json --cache-key prod-api --list
# Override cache directory
MCP2CLI_CACHE_DIR=/tmp/my-cache mcp2cli --spec ./openapi.json --list~/.cache/mcp2cli/# Generate a skill configuration for an OpenAPI service
mcp2cli --spec https://api.example.com/openapi.json --list
# Create baked tool for easier access
mcp2cli bake create myservice \
--spec https://api.example.com/openapi.json \
--auth-header "Authorization:Bearer env:MYSERVICE_TOKEN"
# Use in skill workflows
mcp2cli @myservice list-resources --format json | jq '.[] | select(.active == true)'# Development environment
mcp2cli bake create myapi-dev \
--spec https://dev-api.example.com/openapi.json \
--auth-header "Authorization:Bearer env:DEV_TOKEN"
# Production environment
mcp2cli bake create myapi-prod \
--spec https://api.example.com/openapi.json \
--auth-header "Authorization:Bearer env:PROD_TOKEN"
# Use environment-specific tools
mcp2cli @myapi-dev test-endpoint --data "test"
mcp2cli @myapi-prod get-metrics --period "24h"# Use filesystem MCP to read config, then call API
CONFIG=$(mcp2cli --mcp-stdio "npx @modelcontextprotocol/server-filesystem /etc" \
read-file --path /etc/myapp/config.json)
echo "$CONFIG" | jq -r '.api_endpoint' | \
xargs -I {} mcp2cli --spec {}/openapi.json --list# Search tools related to users
mcp2cli @myapi --search "user"
# List only creation operations
mcp2cli @myapi --list | grep "^create-"
# Get compact list of top tools for LLM context
mcp2cli @myapi --list --top 20 --compactfrom mcp2cli.openapi import load_spec
from mcp2cli.client import make_request
import asyncio
async def call_api():
# Load OpenAPI spec
spec = await load_spec("https://api.example.com/openapi.json")
# Make request
response = await make_request(
spec=spec,
operation_id="listPets",
params={"limit": 10},
auth_headers={"Authorization": "Bearer token"}
)
return response
result = asyncio.run(call_api())# Clear cached tokens
rm -rf ~/.cache/mcp2cli/oauth/
# Retry with verbose output
mcp2cli --spec ./openapi.json --oauth --list --verbose# Test transport explicitly
mcp2cli --mcp https://mcp.example.com/sse --transport sse --list
mcp2cli --mcp https://mcp.example.com/sse --transport streamable --list
# Check server logs if using stdio
mcp2cli --mcp-stdio "npx @modelcontextprotocol/server-filesystem /tmp" \
--env DEBUG=* \
--list# Force refresh
mcp2cli --spec ./openapi.json --refresh --list
# Clear all cache
rm -rf ~/.cache/mcp2cli/
# Use temporary cache location
MCP2CLI_CACHE_DIR=/tmp/test-cache mcp2cli --spec ./openapi.json --list# Check baked tool exists
mcp2cli bake list
# Verify configuration
mcp2cli bake show myapi
# Recreate with explicit filters
mcp2cli bake update myapi --include "*"# Use --head to limit records
mcp2cli @myapi list-all --head 100
# Use --raw to get full response
mcp2cli @myapi list-all --raw > output.json
# Use TOON for token efficiency
mcp2cli @myapi list-all --toon~/.config/mcp2cli/~/.cache/mcp2cli/MCP2CLI_CONFIG_DIRMCP2CLI_CACHE_DIR~/.config/mcp2cli/baked.json~/.cache/mcp2cli/usage.json~/.cache/mcp2cli/oauth/