MCP servers are great for universal compatibility with agents, but for every coding agent you use, you have to re-connect to each server. Also, if your coding agent doesn't have a good harness for tool search, your MCP servers can unnecessarily eat up a ton of context.
mcp-to-cli fixes this. It's a fully local command-line client that saves named connections to remote MCP servers in one place (~/.mcp-to-cli/). Connect once, use everywhere — any tool that can shell out to a CLI can call MCP tools through it.
Run directly with npx:
npx mcp-to-cli@latestOr install as a skill:
npx skills add smithery-ai/mcp-to-cli
claude "use /mcp-cli to connect to https://mcp.deepwiki.com/mcp and tell me about browserbase/stagehand"# Install globally
npm i -g mcp-to-cli
# Connect to a server
# (opens browser for OAuth, or ngrok URL for remote setups like OpenClaw)
mcp connect https://mcp.deepwiki.com/mcp --name deepwiki --ngrok
# List what tools are available
mcp deepwiki tools list
# Call a tool (args are validated locally with Zod before sending)
mcp deepwiki tools call ask_question --args '{"repoName":"browserbase/stagehand", "question": "What does this do?"}'- Connects to remote MCP servers over Streamable HTTP, with SSE fallback.
- Stores named connections locally so you can address a server by name.
- Supports OAuth browser authorization flows for protected servers.
- Lists tool, resource, and prompt capabilities exposed by a server.
- Validates tool arguments locally against each tool's input schema before sending the call.
- Calls tools interactively or with JSON arguments from the command line.
- MCP URLs can be safely guessed via run.tools shortcuts (requires a Smithery account), i.e.
mcp connect notion->mcp connect https://notion.run.tools
- Bun 1.3+
- A reachable MCP server URL
NGROK_AUTHTOKENin your environment when using--ngrok
bun installbun startWatch mode:
bun devThe repository uses Oxc tooling for linting and formatting:
bun fmtformats the codebase withoxfmtand applies autofixableoxlintchanges.bun checkverifies formatting, fails on lint warnings, and runs TypeScript type-checking.
Useful individual commands:
bun run lint
bun run fmt:check
bun run typecheckThis repo now uses release-please to infer version bumps and changelog entries from Conventional Commit messages.
Use release-worthy commit prefixes on changes that should ship:
fix:for patch releasesfeat:for minor releasesfeat!:orfix!:for major releases
On every push to main, GitHub Actions runs release-please and either:
- open or update a release pull request that bumps versions and regenerates
CHANGELOG.md - create a GitHub release and publish to npm after that release pull request is merged
If you need to force a specific version, release-please also supports a Release-As: x.y.z footer in the commit body.
To dry-run the publish locally:
bun install
npm run release:dry-runTo publish manually from an authenticated machine:
npm run releaseRepository setup required:
- add the
NPM_TOKENGitHub Actions secret - use Conventional Commit messages on merge commits or squash commit titles
Top-level help:
bun start --helpmcp connect https://example.com/mcp --name exampleYou can also pass a bare service name instead of a full URL. The CLI resolves it to https://<name>.run.tools (Smithery):
mcp connect linear # → https://linear.run.tools
mcp connect notion # → https://notion.run.toolsPrint the OAuth URL instead of opening a browser:
mcp connect https://example.com/mcp --name example --no-openUse ngrok for OAuth callbacks (useful for OpenClaw/remote setups):
mcp connect https://example.com/mcp --name example --ngrokEquivalent command:
mcp connections add https://example.com/mcp --name example [--no-open]If --name is omitted, the CLI derives a name from the server hostname.
mcp connections listmcp connections remove exampleProfiles let you maintain separate sets of connections and credentials. For example, keep work and personal MCP servers isolated, or split staging from production.
mcp profile create work
mcp profile create acme/staging
mcp profile create acme/prodProfiles can be nested — acme/staging and acme/prod are children of acme.
Either pass --profile (or -p) to any command:
mcp --profile work connect https://linear.run.tools
mcp --profile work connections list
mcp -p work linear tools listOr set the MCP_CLI_PROFILE environment variable:
export MCP_CLI_PROFILE=work
mcp connect https://linear.run.tools
mcp connections listResolution order: --profile flag > MCP_CLI_PROFILE env > "default".
mcp profile listmcp profile remove work
mcp profile rm acme --recursiveRemoving a profile deletes its saved connections and auth for that profile. If the profile has child profiles, pass --recursive to remove the whole subtree.
Child profiles inherit connections and auth from their parents. For profile acme/staging, the lookup chain is:
default → acme → acme/staging
Connections are merged (child overrides parent for the same name). Auth is resolved from most specific to least specific — if acme/staging doesn't have auth for a connection, it checks acme, then default.
Writes (adding connections, saving auth) always target the current profile only.
After a server is saved, address it by connection name:
mcp <connection> <category> <command>Supported categories:
toolsresourcesprompts
List available tools:
mcp example tools listPaginate and show full descriptions:
mcp example tools list --offset 0 --limit 10 --full-descriptionInspect a tool schema:
mcp example tools get search_docsCall a tool interactively:
mcp example tools call search_docsCall a tool with JSON arguments:
mcp example tools call search_docs --args '{"query":"oauth"}'Return raw JSON output:
mcp example tools call search_docs --args '{"query":"oauth"}' --jsonList resources:
mcp example resources listRead a resource:
mcp example resources get file:///docs/intro.mdList prompts:
mcp example prompts listRender a prompt:
mcp example prompts get summarize_releaseFor servers that require OAuth:
- The CLI opens the system browser (or prints the URL if
--no-openwas used). - It listens on a shared local callback server at
http://localhost:8912/<connection>/callback. - If the connection was created with
--ngrok, the redirect URI uses the ngrok URL for that same callback path instead of localhost. - After approval, tokens are stored for the saved connection and reused on future requests.
- Both
--ngrokand--no-openpreferences are saved with the connection and applied automatically on future requests.
Saved connection metadata and auth state are stored under:
~/.mcp-to-cli/
profiles/
default/
connections.json
auth-<name>.json
work/
connections.json
auth-<name>.json
acme/
staging/
connections.json
auth-<name>.json
Each profile has its own directory containing:
connections.jsonfor saved serversauth-<name>.jsonfor per-connection OAuth state
src/cli.ts Command parsing and user-facing CLI flows
src/client.ts MCP client creation, transport fallback, auth retry logic
src/auth.ts OAuth provider and local callback server
src/config.ts Local storage for saved connections and auth state
index.ts Re-exports for library-style imports
GitHub Actions runs the same checks used locally on pushes and pull requests to main:
- formatting check
- lint with warnings treated as failures
- TypeScript type-checking
