api2mcp
Turn any OpenAPI spec into a working MCP server. One command.
api2mcp https://petstore3.swagger.io/api/v3/openapi.json
That's it. You now have a runnable MCP server exposing every endpoint in that API as a tool an LLM agent can call — typed arguments, docstrings, auth wiring, all generated.
The problem
Want Claude (or any MCP-compatible agent) to use Stripe, GitHub, your internal REST API, whatever? Right now that means hand-writing an MCP server: read the docs, define a tool per endpoint, map params, wire up auth, keep it in sync when the API changes.
Almost every API already publishes an OpenAPI/Swagger spec describing exactly that shape. api2mcp reads it and generates the server for you.
Install
pip install spec2mcp
(The PyPI package is named spec2mcp — api2mcp was already taken. The CLI command and import name are still api2mcp.)
Usage
api2mcp <spec-url-or-file> [-o output-dir]
Works with a spec URL, a local .json file, or a local .yaml/.yml file.
Example
$ api2mcp https://petstore3.swagger.io/api/v3/openapi.json -o ./petstore-mcp
Fetching spec from https://petstore3.swagger.io/api/v3/openapi.json ...
Generated 19 tools for 'Swagger Petstore - OpenAPI 3.0'
-> petstore-mcp/server.py
-> petstore-mcp/README.md
Run it:
cd petstore-mcp && pip install "mcp[cli]" requests && python server.py
Run the generated server, then point any MCP client at it — Claude Desktop, Claude Code, or your own agent — and every endpoint (findPetsByStatus, addPet, deletePet, …) is now a callable tool.
Point Claude Desktop / Claude Code at it
Add to your MCP client config (e.g. claude_desktop_config.json):
{
"mcpServers": {
"petstore": {
"command": "python",
"args": ["/absolute/path/to/petstore-mcp/server.py"],
"env": {
"API_BASE_URL": "https://petstore3.swagger.io/api/v3",
"API_KEY": "your-key-if-needed"
}
}
}
}
Auth
Set env vars before running the generated server:
API_BASE_URL— overrides the base URL detected from the specAPI_KEY— sent asAuthorization: Bearer <API_KEY>on every request
Use it as a library instead of the CLI
from api2mcp import parse_spec, write_server
spec = parse_spec("https://petstore3.swagger.io/api/v3/openapi.json")
write_server(spec, "./out")
What gets generated
For every operation in the spec, one @mcp.tool()-decorated function:
@mcp.tool()
def findpetsbystatus(status: str = "") -> dict:
"""Finds Pets by status."""
...
resp = requests.request("GET", url, params=params, json=json_body, headers=_headers(), timeout=30)
resp.raise_for_status()
return resp.json()
- Path, query, and JSON body params become typed Python arguments (required params ordered before optional ones, so it's always valid Python)
- The
summary/descriptionfrom the spec becomes the tool's docstring — that's what the LLM sees when deciding whether to call it - A
README.mdlisting every generated tool ships alongsideserver.py
The output is plain, readable code — not a black box. Generate it, read it, edit it by hand if you need something custom.
How it works
flowchart LR
A["OpenAPI spec\n(URL or file)"] --> B["parser.py\nflatten paths → Operations"]
B --> C["generator.py\nJinja2 template"]
C --> D["server.py\none @mcp.tool()\nper endpoint"]
D --> E["MCP client\n(Claude Desktop / Claude Code)"]
E -->|calls tool| F["your API"]
F -->|response| E
- Parse (
api2mcp/parser.py) — loads the spec (JSON or YAML, URL or file), walkspaths, flattens each operation's parameters and request body into a simple typedOperationmodel. - Generate (
api2mcp/generator.py+templates/server.py.j2) — renders a Jinja2 template into a single-file MCP server using the officialmcpPython SDK. - Run — the generated server is a normal Python script;
mcp.run()speaks the MCP protocol over stdio.
No LLM calls involved in generation — it's pure codegen from the spec's structure, so it's fast, free, and deterministic.
Development
git clone https://github.com/azamoviich/api2mcp
cd api2mcp
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev,serve]"
pytest
Limitations (v1)
- No OAuth2 flows — only static bearer token auth via
API_KEY $refresolution for request bodies is shallow (one level)- No pagination helpers — generated tools return raw responses as-is
Contributions welcome for any of the above.
License
MIT — see LICENSE.
Metadata
Release files for spec2mcp 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| spec2mcp-0.2.0.tar.gz | 262.5 kB | Without provenance | Details for spec2mcp-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| spec2mcp-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for spec2mcp-0.2.0-py3-none-any.whl |
Total release size: 272.5 kB
Release files / spec2mcp-0.2.0.tar.gz
| Download URL | spec2mcp-0.2.0.tar.gz |
|---|---|
| Size | 262.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7866da6007a2ca8a06cd99fd6f8d93350a6a6914f8627fe4d7e7c5599cb0275d
|
|
BLAKE2b-256 checksum How to use checksums |
f25263479b6310f21d0f19f5810c402b5777047163fbd9e6b8831cac3a25f6fb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Release files / spec2mcp-0.2.0-py3-none-any.whl
| Download URL | spec2mcp-0.2.0-py3-none-any.whl |
|---|---|
| Size | 9.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b82733b6611a515e784999575271756fe78b7960e76b3417a9a64a0e67638f92
|
|
BLAKE2b-256 checksum How to use checksums |
cf83504fdc4ed04075fad1dd0853de7e93e90386b0e3872751c40d893455b4af
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Security for spec2mcp 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.