Show HN: Mcpgen – Turn OpenAPI/Postman Specs into Python MCP Servers Mcpgen, a new open-source CLI tool, generates a complete Python MCP server from an OpenAPI spec or Postman collection, producing source code users own with no runtime dependency on mcpgen. The tool, installable via pip install mcpgen-cli, outputs a self-contained directory with server.py and requirements.txt that can be run immediately, and it supports OpenAPI 3.x JSON/YAML, Postman Collection v2.1, and auto-detects auth schemes like Bearer token, API Key, and Basic Auth. 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. pip install mcpgen-cli 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. 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: bash /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. 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 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. | 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 https://petstore3.swagger.io/api/v3/openapi.json — 19 endpoints → 19 tools- GitHub REST API subset - Stripe API subset - Any valid OpenAPI 3.x spec 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. 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 - 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 /JnanaSrota/mcpgen/blob/main/CONTRIBUTING.md . 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. MIT — the generated code is yours to do whatever you want with.