How to Turn Any Python CLI
into an MCP Server
MCP (Model Context Protocol) is how AI coding agents talk to tools. Claude Code, Cursor, Codex, Cline — they all use it. But if your team already has Python CLI tools built with Click or typer, you'd normally need to write a separate MCP server for each one.
That means duplicate code, duplicate maintenance, and a new server for every tool. Not sustainable.
Here's how to skip all of that and turn your existing Python CLI into an MCP server with zero code changes.
The Three Ways to Make an MCP Server
| Approach | Effort | Best For |
|---|---|---|
| Write from scratch (FastMCP) | Medium | New tools, greenfield |
| Manual wrapper per CLI | High | 1-2 CLIs with custom logic |
| Auto-wrap with click-to-mcp | Low | Existing Click/typer CLIs |
If you're building something new, FastMCP is great. But most teams have existing tools. That's where click-to-mcp shines — it introspects your CLI at runtime and serves it as an MCP server automatically.
Step 1: Install click-to-mcp
pip install git+https://github.com/Coding-Dev-Tools/click-to-mcp.git
If you want HTTP+SSE transport (for web-based clients like Cursor), install with the http extra:
pip install "click-to-mcp[http] @ git+https://github.com/Coding-Dev-Tools/click-to-mcp.git"
Step 2: Discover Your CLIs
$ click-to-mcp discover
Scanning environment for Click/typer CLIs...
Found 3 CLIs:
• my-database-tool (6 commands)
• my-api-validator (4 commands)
• my-deploy-helper (3 commands)
click-to-mcp scans your Python environment and finds every installed Click or typer CLI. No configuration needed — it detects them automatically.
Step 3: Serve as MCP Server
$ click-to-mcp serve my-database-tool
MCP server starting on stdio...
Tool: db_query (2 params)
Tool: db_migrate (1 param)
Tool: db_seed (1 param)
Tool: db_dump (1 param)
Tool: db_stats (0 params)
Tool: db_reset (0 params)
Ready — 6 tools exposed
Every command in your CLI becomes an MCP tool. Arguments become required input properties. Options become optional properties with defaults. click.Choice becomes a JSON Schema enum. Nested groups become prefixed tools.
How Click Maps to MCP
| Click Concept | MCP Mapping |
|---|---|
@click.command() | MCP tool |
@click.argument() | Required input property |
@click.option() | Optional input with default |
click.Choice | JSON Schema enum |
click.INT / click.FLOAT | integer / number |
click.BOOL / is_flag | boolean |
Nested click.Group | Prefixed tools (e.g. config_show) |
The mapping is automatic because Click's type system already carries everything MCP needs. No annotations. No decorators. No boilerplate.
Step 4: Connect to Your AI Agent
Claude Code
Add to .claude/settings.json:
{
"mcpServers": {
"my-database-tool": {
"command": "click-to-mcp",
"args": ["serve", "my-database-tool"]
}
}
}
Cursor
Add to .cursor/mcp.json:
{
"mcpServers": {
"my-database-tool": {
"command": "click-to-mcp",
"args": ["serve", "my-database-tool"]
}
}
}
Cline / VS Code
Add to .vscode/mcp.json:
{
"servers": {
"my-database-tool": {
"command": "click-to-mcp",
"args": ["serve", "my-database-tool"]
}
}
}
Step 5: Use It
Now when you ask your AI agent a question about your tool, it will automatically invoke the MCP tool:
You: What tables are in my database?
Claude Code: *calls db_stats tool*
→ Database: production_db
→ 23 tables, 1.2M rows total
→ Largest: orders (450K rows), users (180K rows)
No manual command invocation. The AI agent picks the right tool and arguments automatically.
stdio vs HTTP+SSE: Which Transport?
| Transport | Command | Use With |
|---|---|---|
| stdio (default) | click-to-mcp serve my-cli | Claude Code, Cline, terminal agents |
| HTTP+SSE | click-to-mcp serve-http my-cli --port 8000 | Cursor, web clients, remote agents |
Most local development uses stdio. If your AI tool connects over HTTP (like Cursor does for some configurations), use the HTTP+SSE transport.
Multiple CLIs at Once
The real power is exposing your entire toolkit:
{
"mcpServers": {
"database-tool": {
"command": "click-to-mcp",
"args": ["serve", "my-database-tool"]
},
"api-validator": {
"command": "click-to-mcp",
"args": ["serve", "my-api-validator"]
},
"deploy-helper": {
"command": "click-to-mcp",
"args": ["serve", "my-deploy-helper"]
}
}
}
Now your AI agent has access to all three tools — database operations, API validation, and deployment commands — in a single conversation.
What click-to-mcp Is NOT
- Not a replacement for FastMCP. Building a new MCP server from scratch? Use FastMCP. click-to-mcp is for existing CLIs.
- Not limited to our tools. Any Click/typer CLI works — your internal tools, open-source packages, anything pip-installable.
- Not a runtime proxy. It introspects at startup, then serves directly. Zero per-request overhead.
- Not a code generator. Your CLI code stays untouched. click-to-mcp reads the Click registry at runtime.
Who Should Use This
- Teams with multiple Python CLIs — wrap them all as MCP servers in minutes, not days
- DevOps teams — expose deployment, monitoring, and infrastructure CLIs to AI agents
- API developers — let AI agents validate specs, run checks, and diff contracts
- Anyone using AI coding agents — give your agent access to your actual tools, not just file editing
Try it now — your CLI becomes an MCP server in 10 seconds
Star on GitHub →Further Reading
- From CLI to MCP in One Command — the original click-to-mcp announcement
- Model Context Protocol spec — official MCP documentation
- FastMCP on PyPI — for building new MCP servers from scratch
- click-to-mcp vs FastMCP comparison