May 17, 2026 · 10 min read
How to Use click-to-mcp with Claude Desktop, Cursor, and Any MCP Client
click-to-mcp auto-wraps any Click or Typer CLI as an MCP server with zero code changes. But once you have it installed, how do you actually connect it to Claude Desktop, Cursor, or your IDE of choice?
This guide walks through every major MCP client configuration, with real config files, troubleshooting tips, and best practices. Whether you're a VS Code user trying Cursor for the first time or a Claude Desktop power user, you'll be up and running in minutes.
Try it now
pip install git+https://github.com/Coding-Dev-Tools/click-to-mcp.git · Apache 2.0 · Free forever
View on GitHub →Quick Refresher: What Is click-to-mcp?
Before we dive into configurations, here's the one-minute summary. click-to-mcp is a Python library and CLI tool that introspects your existing Click or Typer command definitions and exposes them as MCP tools over stdio. Every @click.command(), @click.option(), and @click.argument() decorator is mapped to the equivalent JSON Schema tool definition that MCP clients understand.
The core workflow is:
# 1. Install
pip install click-to-mcp
# 2. Scan for CLI tools in your environment
click-to-mcp discover
# 3. Serve one as an MCP server
click-to-mcp serve your-cli-name
That serve command starts a stdio-based MCP server. Any MCP client that can launch a subprocess and communicate over stdin/stdout can use it. The rest of this guide shows you exactly how to wire that into each client.
Configuration Overview
Every MCP client uses a slightly different configuration format, but they all need the same information:
- Command: the executable to run (usually
click-to-mcp) - Arguments: typically
serve your-cli-name - Environment variables: sometimes
PYTHONUNBUFFERED=1for reliable stdio streaming
Here's how that translates across the major clients.
1. Claude Desktop
Claude Desktop (the macOS and Windows native app by Anthropic) supports MCP servers via a JSON configuration file located at ~/Library/Application Support/Claude/claude_desktop_config.json on macOS or %APPDATA%\Claude\claude_desktop_config.json on Windows.
Basic Configuration
{
"mcpServers": {
"my-cli": {
"command": "click-to-mcp",
"args": ["serve", "my-cli-name"],
"env": {
"PYTHONUNBUFFERED": "1"
}
}
}
}
Replace my-cli-name with the name shown by click-to-mcp discover. For example, if you have the DevForge suite installed:
{
"mcpServers": {
"api-contract-guardian": {
"command": "click-to-mcp",
"args": ["serve", "api-contract-guardian"],
"env": { "PYTHONUNBUFFERED": "1" }
},
"json2sql": {
"command": "click-to-mcp",
"args": ["serve", "json2sql"],
"env": { "PYTHONUNBUFFERED": "1" }
},
"configdrift": {
"command": "click-to-mcp",
"args": ["serve", "configdrift"],
"env": { "PYTHONUNBUFFERED": "1" }
}
}
}
Using pipx (Recommended for Isolation)
If you installed click-to-mcp via pipx (which keeps it in its own isolated environment), the command path changes slightly. Find the pipx bin directory:
# Find the pipx-managed click-to-mcp binary
which click-to-mcp
# Usually: ~/.local/bin/click-to-mcp (macOS/Linux) or ~/.local/bin/click-to-mcp.exe (Windows Git Bash)
Then reference the full path in your config:
{
"mcpServers": {
"deadcode": {
"command": "/Users/you/.local/bin/click-to-mcp",
"args": ["serve", "deadcode"],
"env": { "PYTHONUNBUFFERED": "1" }
}
}
}
Using a Virtual Environment
If your target CLI lives in a specific virtualenv, point the command to the Python executable inside that environment and use click-to-mcp as a library entry point:
{
"mcpServers": {
"my-project-cli": {
"command": "/path/to/venv/bin/python",
"args": ["-m", "click_to_mcp", "serve", "my-cli"],
"env": { "PYTHONUNBUFFERED": "1" }
}
}
}
Troubleshooting Claude Desktop
- No hammer icon? Check Claude's MCP logs: View → Toggle Developer Tools → Console tab. Look for "Failed to spawn" or "Connection refused" errors.
- "Command not found"? Use the absolute path to click-to-mcp (via
which click-to-mcp) instead of the short name. - Tools not showing up? Run
click-to-mcp discoverstandalone first to confirm the CLI name is correct. - Python environment mismatch? Ensure click-to-mcp and your target CLI are installed in the same Python environment, or use the venv approach above.
2. Cursor IDE
Cursor (the AI-first VS Code fork) supports MCP servers through its .cursor/mcp.json file, placed at your project root. Unlike Claude Desktop which uses a global config, Cursor's config is per-project. This is actually a feature — you can expose different CLIs for different projects.
Project-Level Configuration
Create .cursor/mcp.json in your project root:
{
"mcpServers": {
"schemaforge": {
"command": "click-to-mcp",
"args": ["serve", "schemaforge"],
"env": { "PYTHONUNBUFFERED": "1" }
}
}
}
That's it. Open the project in Cursor, and the tools automatically appear in Cursor's Composer and chat interfaces. Cursor auto-discovers .cursor/mcp.json on project load — no restart needed.
Using with a Monorepo
If you have multiple CLIs relevant to different parts of your monorepo, create separate .cursor/mcp.json files in each subdirectory, or combine them all in a root-level config:
{
"mcpServers": {
"api-contract-guardian": {
"command": "click-to-mcp",
"args": ["serve", "api-contract-guardian"],
"env": { "PYTHONUNBUFFERED": "1" }
},
"deploydiff": {
"command": "click-to-mcp",
"args": ["serve", "deploydiff"],
"env": { "PYTHONUNBUFFERED": "1" }
},
"json2sql": {
"command": "click-to-mcp",
"args": ["serve", "json2sql"],
"env": { "PYTHONUNBUFFERED": "1" }
}
}
}
Verifying in Cursor
Once the config is in place, open Cursor's command palette (Cmd+Shift+P) and search for "MCP". You should see your server listed. Open the chat panel (Cmd+I) and ask Cursor to use one of your tools — it will discover available tools automatically through the MCP protocol.
.cursor/mcp.json, reload the Cursor window (Cmd+Shift+P → "Developer: Reload Window") to pick up the changes.
Cursor-Specific Considerations
- Windows users: Use forward slashes or escaped backslashes in paths. Cursor runs MCP servers as subprocesses and handles MSYS paths properly if you use Git Bash.
- Multiple projects: Each project gets its own MCP tool set. This is great for keeping context small and relevant.
- Cursor vs Claude Code: Cursor uses the same MCP spec, so any server that works with one works with the other. The config format differs only in file location.
3. Claude Code CLI
Claude Code (Anthropic's CLI agent, installable via npm) uses a global MCP configuration file at ~/.claude/settings.json (macOS/Linux) or %USERPROFILE%\.claude\settings.json on Windows.
Configuration
{
"mcpServers": {
"envault": {
"command": "click-to-mcp",
"args": ["serve", "envault"],
"env": { "PYTHONUNBUFFERED": "1" }
}
}
}
After saving the file, Claude Code auto-discovers the new server on the next invocation. You can test it by running:
# Start Claude Code in the directory
claude
# Then ask it to use your tool
# "List the available MCP tools"
# Claude will call tools/list and show your wrapped CLI commands
Real Example: Wrapping api-contract-guardian
Here's a concrete workflow. You have api-contract-guardian installed, which provides api-contract-guardian diff and api-contract-guardian check commands for OpenAPI schema validation. You configure it in Claude Code:
{
"mcpServers": {
"api-contract-guardian": {
"command": "click-to-mcp",
"args": ["serve", "api-contract-guardian"],
"env": { "PYTHONUNBUFFERED": "1" }
}
}
}
Now during a PR review, you can tell Claude Code: "Check the OpenAPI diff between main and this branch" — and Claude Code will call api-contract-guardian diff --base-branch main --head-branch feature-branch through the MCP bridge, parse the output, and summarize the breaking changes.
4. Any MCP Client (Generic)
The MCP ecosystem is growing fast. Tools like Continue.dev (VS Code/Cursor extension), MCP Inspector (debugging UI), mcp-cli (command-line MCP client), and custom scripts all follow the same pattern: they spawn a subprocess running an MCP server and communicate over stdio.
Generic stdio Configuration
Every MCP client needs three things from you:
# The server process to spawn:
command: click-to-mcp
args: ["serve", "your-cli-name"]
env: { "PYTHONUNBUFFERED": "1" }
# Or using Python module mode:
command: python
args: ["-m", "click_to_mcp", "serve", "your-cli-name"]
MCP Inspector
MCP Inspector is a web-based debugging tool that lets you test your MCP server outside any client. It's invaluable for development:
# Install and run MCP Inspector
npx @modelcontextprotocol/inspector click-to-mcp serve your-cli-name
# Opens a browser at http://localhost:5173
# Click "Connect" to see your tools listed
# Test individual tool calls with custom parameters
This is the fastest way to verify your server works before wiring it into a client.
mcp-cli (Command Line)
For quick testing from the terminal:
# Install mcp-cli
npm install -g @modelcontextprotocol/cli
# Test your server
mcp-cli --server "click-to-mcp serve your-cli-name"
# List available tools
mcp-cli --server "click-to-mcp serve your-cli-name" tools list
Continue.dev
Continue (the open-source AI code assistant) supports MCP via its ~/.continue/config.json:
{
"experimental": {
"mcpServers": {
"deadcode": {
"command": "click-to-mcp",
"args": ["serve", "deadcode"],
"env": { "PYTHONUNBUFFERED": "1" }
}
}
}
}
Custom Script Integration
You can also drive click-to-mcp programmatically from your own MCP client or script:
import subprocess
import json
# Start the MCP server process
proc = subprocess.Popen(
["click-to-mcp", "serve", "your-cli-name"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env={"PYTHONUNBUFFERED": "1"}
)
# List available tools
list_request = json.dumps({
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}) + "\n"
proc.stdin.write(list_request.encode())
proc.stdin.flush()
response = proc.stdout.readline().decode()
tools = json.loads(response)
print(json.dumps(tools, indent=2))
# Call a tool
call_request = json.dumps({
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "your_tool_name",
"arguments": {"param1": "value1"}
}
}) + "\n"
proc.stdin.write(call_request.encode())
proc.stdin.flush()
result = proc.stdout.readline().decode()
print(result)
This is useful for CI pipelines, automated workflows, or building your own MCP-aware tooling.
5. Using the Library API Directly
Instead of using the click-to-mcp serve CLI, you can embed MCP server functionality directly into your application using the Python API. This is useful when you need to run multiple MCP servers from the same process or integrate with a custom server manager.
from click_to_mcp import serve_stdio
import click
@click.group()
def cli():
pass
@cli.command()
@click.option("--name", default="world")
def hello(name):
"""Say hello to someone."""
click.echo(f"Hello, {name}!")
# Serve as MCP — no subprocess needed
serve_stdio(cli, name="my-app", description="My app's CLI tools")
# Blocks and serves over stdin/stdout
Pair this with any MCP client config that launches python my_script.py and you have full control over the server lifecycle.
Configuration Cheat Sheet
| Client | Config File Location | Format | Restart Needed? |
|---|---|---|---|
| Claude Desktop | ~/Library/Application Support/Claude/claude_desktop_config.json |
mcpServers object |
Yes (full restart) |
| Cursor IDE | .cursor/mcp.json (project root) |
mcpServers object |
Reload window |
| Claude Code CLI | ~/.claude/settings.json |
mcpServers object |
Auto-detects |
| Continue.dev | ~/.continue/config.json |
experimental.mcpServers |
Reload VS Code |
| MCP Inspector | CLI args | Command + args | Refresh page |
| mcp-cli | CLI args | --server flag |
N/A |
Best Practices
Always Set PYTHONUNBUFFERED=1
MCP communicates over stdio using newline-delimited JSON. If Python buffers stdout, your MCP server may appear unresponsive — tool calls won't return until the buffer flushes. Setting PYTHONUNBUFFERED=1 forces line-buffered output, ensuring the MCP client receives each response immediately.
Use pipx for Click/Typer CLIs
If your target CLI is installed via pip (not pipx), and you also install click-to-mcp via pip, they'll share the same Python environment. This is the simplest setup. However, if you use pipx for isolation, remember to use the full path to the pipx-managed binary in your MCP client config.
Test with MCP Inspector First
Before wiring into any client, run MCP Inspector. It gives you a clean UI to verify that every tool is exposed with the correct parameters. If a tool doesn't appear in MCP Inspector, it won't appear in any client — and the Inspector's error messages are much clearer than a client's silent failure.
Name Your Tools Clearly
click-to-mcp uses your CLI command names as tool names. If you have subcommands (Click groups), they become prefixed tool names like config_set and config_get. This is clear for developers, but consider adding good help text (help="..." in Click) so the AI agent understands when to call each tool.
Keep Your CLI's --help Text Updated
MCP clients read tool descriptions from your CLI's help text. The quality of your AI agent's tool usage is directly proportional to the quality of your --help output. Write clear, detailed descriptions for every command and parameter — the agent reads them.
Ready to Get Started?
Install click-to-mcp, run discover, and pick your client config from the table above. You're minutes away from having your CLI tools available in every AI agent.
What's Next
Once you've connected click-to-mcp to your client of choice, here are some next steps:
- Add more CLIs — run
click-to-mcp discoverperiodically to find new tools you've installed - Combine with the library API — embed
serve_stdio()directly in your own CLI for a built-in MCP endpoint - Try it in CI — use the custom script pattern above to let AI agents invoke your tools in automated pipelines
- Share your config — commit your
.cursor/mcp.jsonorclaude_desktop_config.jsonto your team's dotfiles repo - Explore the DevForge suite — all our CLI tools work with click-to-mcp out of the box
Get DevForge Updates
New tools, deep dives, and AI agent dev stories — delivered to your inbox.
Star us on GitHub · Introducing click-to-mcp → · View Pricing → · Documentation →