JnanaSrota/mcpgen
Turn any OpenAPI spec or Postman collection into an ownable Python MCP server in 30 seconds - JnanaSrota/mcpgen
18 stars · 4 forks · Python Topics: python, api, cli, code-generator, mcp, openapi, postman, developer-tools, claude, llm, anthropic, model-context-protocol
README
mcpgen Turn any API into an MCP server in 30 seconds.
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.jsonFrom a local OpenAPI file (JSON or YAML)
mcpgen stripe.yamlFrom a Postman collection
mcpgen postman_collection.jsonPreview without writing anything
mcpgen openapi.json --dry-runCustom 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-config flag to patch claude_desktop_config.json automatically Recursive $ref resolution 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.
