GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||||||||||||||||||||
GeezerVison is showing coding-dev-tools.github.io — How to Turn Any Python CLI into an MCP Server for AI Agents | DevForge
MCP Python AI Agents
How to Turn Any Python CLI
|
| 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.
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"
$ 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.
$ 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.
| 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.
Add to .claude/settings.json:
{
"mcpServers": {
"my-database-tool": {
"command": "click-to-mcp",
"args": ["serve", "my-database-tool"]
}
}
}
Add to .cursor/mcp.json:
{
"mcpServers": {
"my-database-tool": {
"command": "click-to-mcp",
"args": ["serve", "my-database-tool"]
}
}
}
Add to .vscode/mcp.json:
{
"servers": {
"my-database-tool": {
"command": "click-to-mcp",
"args": ["serve", "my-database-tool"]
}
}
}
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.
| 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.
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.
Try it now — your CLI becomes an MCP server in 10 seconds
Star on GitHub →