Skip to main content

api2mcp

License: MIT Python 3.10+

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 spec2mcpapi2mcp 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 spec
  • API_KEY — sent as Authorization: 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/description from the spec becomes the tool's docstring — that's what the LLM sees when deciding whether to call it
  • A README.md listing every generated tool ships alongside server.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

  1. Parse (api2mcp/parser.py) — loads the spec (JSON or YAML, URL or file), walks paths, flattens each operation's parameters and request body into a simple typed Operation model.
  2. Generate (api2mcp/generator.py + templates/server.py.j2) — renders a Jinja2 template into a single-file MCP server using the official mcp Python SDK.
  3. 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
  • $ref resolution 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.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

spec2mcp-0.1.0.tar.gz (8.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

spec2mcp-0.1.0-py3-none-any.whl (9.1 kB view details)

Uploaded Python 3

File details

Details for the file spec2mcp-0.1.0.tar.gz.

File metadata

  • Download URL: spec2mcp-0.1.0.tar.gz
  • Upload date:
  • Size: 8.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for spec2mcp-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ef651bf19d9ac5e179842d297ae257f2425f941d05a6d9905238a18345424ac1
MD5 2479740eb801a93e752ec8264d8f9886
BLAKE2b-256 2613c57381677f3b5dcaa5c1de9fd5f96d7a34aec4be798553780813f1e8c038

See more details on using hashes here.

File details

Details for the file spec2mcp-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: spec2mcp-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 9.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for spec2mcp-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 583af45306bc146b5e21a2e7c1b239cf8d970a86160f5afabb9214efd0d69a36
MD5 cd4415af267445bc917e499fef4e78da
BLAKE2b-256 bb2befc1e4548f9179f16a21f093ac76e768739696c1682c7c11f03bbc18072c

See more details on using hashes here.

Release history Release notifications | RSS feed

0.2.0

2 files

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page