mcpgen MCP Server
CLI tool that generates MCP servers from OpenAPI/Postman specs — pip install mcpgen-cli
Documentation
Point mcpgen at an OpenAPI spec or Postman collection. Get back a complete Python MCP server you own — no runtime dependency on mcpgen, no proxy, no lock-in. Read it. Modify it. Ship it.
Install
pip install mcpgen-cli
Quickstart
# From a URL
mcpgen https://petstore3.swagger.io/api/v3/openapi.json
# From a local OpenAPI file (JSON or YAML)
mcpgen stripe.yaml
# From a Postman collection
mcpgen postman_collection.json
# Preview without writing anything
mcpgen openapi.json --dry-run
# Custom output directory and server name
mcpgen openapi.json --output ~/my-mcp-servers --name "My API"
That's it. mcpgen reads your spec and writes a Python MCP server to disk.
What you get
A self-contained directory with source code you own:
stripe_api_mcp/
├── server.py ← the MCP server (read it, edit it, it's yours)
└── requirements.txt ← httpx, mcp
Run it immediately:
cd stripe_api_mcp
pip install -r requirements.txt
export STRIPE_API_TOKEN="sk_live_..."
python server.py
The generated server.py looks like this:
#!/usr/bin/env python3
"""
Stripe API MCP Server
Generated by mcpgen — https://github.com/JnanaSrota/mcpgen
This file is yours. Modify it freely.
"""
import os, asyncio, httpx
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp import types
BASE_URL = "https://api.stripe.com"
AUTH_TOKEN = os.environ.get("STRIPE_API_TOKEN", "")
app = Server("stripe-api")
@app.call_tool()
async def _handle_get_customers(name: str, arguments: dict):
if name != "get_customers":
raise ValueError(f"Unknown tool: {name}")
url = BASE_URL + "/v1/customers"
query_params = {}
if "limit" in arguments:
query_params["limit"] = arguments["limit"]
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.get(url, params=query_params,
headers={"Authorization": f"Bearer {AUTH_TOKEN}"})
response.raise_for_status()
return [types.TextContent(type="text", text=response.text)]
# ... one function per API endpoint
@app.list_tools()
async def list_tools(): ...
if __name__ == "__main__":
asyncio.run(stdio_server(app))
No black box. No dependencies at runtime. Just Python.
Add to Claude Desktop
mcpgen prints the exact config snippet to paste into your claude_desktop_config.json:
{
"mcpServers": {
"stripe-api-mcp": {
"command": "python",
"args": ["/path/to/stripe_api_mcp/server.py"],
"env": { "STRIPE_API_TOKEN": "your-key-here" }
}
}
}
Config file location:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
Why source code instead of a proxy?
Most API-to-MCP tools are runtime proxies — they sit between Claude and your API forever, and you depend on them to stay running.
mcpgen generates source code you own. The output is a plain Python file. You can:
- Read every line of what's happening
- Modify auth logic, add retries, adjust error handling
- Deploy it anywhere without any dependency on
mcpgen - Commit it to your own repo, version it, review it in PRs
mcpgen is a build tool. Needed once, at generation time. Never at runtime.
Supported inputs
| Format | Example |
|---|---|
| OpenAPI 3.x JSON | mcpgen openapi.json |
| OpenAPI 3.x YAML | mcpgen api.yaml |
| URL pointing to OpenAPI spec | mcpgen https://api.example.com/openapi.json |
| Postman Collection v2.1 | mcpgen collection.json |
Tested with:
- Petstore — 19 endpoints → 19 tools
- GitHub REST API (subset)
- Stripe API (subset)
- Any valid OpenAPI 3.x spec
Auth support
mcpgen auto-detects your API's auth scheme from the spec:
| Scheme | OpenAPI declaration | Generated env var |
|---|---|---|
| Bearer token | type: http, scheme: bearer | YOUR_API_TOKEN |
| API Key | type: apiKey | YOUR_API_API_KEY |
| Basic Auth | type: http, scheme: basic | YOUR_API_CREDENTIALS |
| None | No securitySchemes | — |
OAuth2 flows are approximated as bearer token — you supply the token manually.
CLI reference
Usage: mcpgen [OPTIONS] INPUT
Turn any API into an MCP server in 30 seconds.
Arguments:
INPUT OpenAPI JSON/YAML file, Postman collection, or URL [required]
Options:
-o, --output PATH Output directory (default: current directory)
-n, --name TEXT Override the generated server name
--dry-run Print generated code without writing files
--no-color Disable colored output
-v, --version Show version and exit
--help Show this message and exit
Roadmap
- TypeScript output (
--lang ts) using@modelcontextprotocol/sdk - Swagger 2.x support (auto-detected, separate parser)
- Auto-detect OpenAPI URL from base domain (
/.well-known/openapi.json,/api-docs, etc.) -
--update-claude-configflag to patchclaude_desktop_config.jsonautomatically - Recursive
$refresolution for deeply nested schemas
PRs welcome. See CONTRIBUTING.md.
Contributing
git clone https://github.com/JnanaSrota/mcpgen
cd mcpgen
pip install -e ".[dev]"
pytest tests/ -v
The codebase has three clean layers:
Input (file / URL)
↓
loader.py ← detects format, routes to correct parser
↓
openapi.py / postman.py ← parse to MCPSpec (internal IR)
↓
generator/python.py ← renders Jinja2 templates → server.py
To add a new input format: write a parser that returns MCPSpec. Nothing else changes.
To add a new output language: write a generator that consumes MCPSpec. Nothing else changes.
License
MIT — the generated code is yours to do whatever you want with.