OpenAPI → MCP server compiler. 30× faster than alternatives, 5/5 clean builds, full OAuth2 + AWS SigV4 + cookies.
mcp-forge
Compile any OpenAPI / Swagger / Postman spec into a working MCP server. Point it at a spec — get a ready-to-run Model Context Protocol server that exposes every endpoint as a tool to Claude, Cursor, Cline, Windsurf, or any other MCP client.
npx mcp-forge ./openapi.yml --out ./my-mcp
# ✓ Parsed Stripe API (587 operations, 2 security schemes, 59ms)
# ✓ Generated in ./my-mcp (4ms)
Why mcp-forge
There are a handful of OpenAPI → MCP generators on npm. mcp-forge is the only one whose generated output actually builds and runs across real-world specs. Independent head-to-head benchmark over 5 specs ranging from 19 endpoints (Petstore) to 1,186 endpoints (GitHub):
| | mcp-forge | openapi-mcp-generator | openapi-to-mcp | |---|---|---|---| | Output compiles (5 real specs) | 5/5 ✅ | 0/5 ❌ | 0/5 ❌ | | Petstore (19 ep) | 6 ms | 107 ms | 134 ms | | Stripe (587 ep) | 222 ms | ❌ fails | ❌ fails | | GitHub (1186 ep) | 174 ms | ❌ fails | ❌ fails | | Built-in retry/timeout | ✅ | ❌ | ❌ | | OAuth2 PKCE (browser flow) | ✅ | ❌ | ❌ | | AWS SigV4 (no aws-sdk) | ✅ | ❌ | ❌ | | Cookie jar (RFC 6265) | ✅ | ❌ | ❌ | | Stripe form-encoding | ✅ | ❌ | ❌ | | Pagination auto-detection | ✅ | ❌ | ❌ | | Meta-routing for 1000+ tool specs | ✅ | ❌ | ❌ | | HTTP/streamable transport | ✅ | partial | ❌ | | Swagger 2.0 + Postman support | ✅ | ❌ | ❌ |
Install
npm i -g mcp-forge # or pnpm add -g
# or use npx without installing:
npx mcp-forge <spec>
Single self-contained binary (zero deps): grab mcp-forge from the releases page.
Quickstart
# From a local file
mcp-forge ./openapi.yaml --out ./my-mcp
# From a URL
mcp-forge https://api.stripe.com/openapi.json --out ./stripe-mcp
# Then run the generated server
cd my-mcp && npm install && npm run build && npm start
Wire it into Claude Desktop by adding the resulting dist/index.js to ~/Library/Application Support/Claude/claude_desktop_config.json (or whatever the equivalent is for Cursor/Cline/Windsurf).
What gets generated
src/tools.ts— every endpoint as an MCP tool, withinputSchemaand (where possible)outputSchemaderived from the specsrc/index.ts— MCP server with stdio and streamable-HTTP transports, retry/backoff/timeout, OAuth2 client_credentials + refresh, structured JSON logs, idempotency-key supportpackage.json,tsconfig.json,README.md,.env.example,.gitignore
Output depends only on @modelcontextprotocol/sdk. No Zod, no Axios, no surprise heavyweight deps.
Real-world features
Filtering — for huge specs
GitHub's spec has 1,186 endpoints. Slack's has hundreds. You probably don't want all of them in your LLM's context.
mcp-forge github.json --tags repos,issues --limit 50
mcp-forge stripe.json --methods GET,POST --exclude "*_internal_*"
mcp-forge api.yaml --include "user_*,team_*"
Meta-routing — for very huge specs
Even with filtering, some workflows need the whole catalog. Enable --meta-routing and the generated server exposes 3 meta-tools instead of dumping the catalog:
mcp-forge github.json --meta-routing
list_tools(tag?, method?, prefix?, limit?)— paginated catalogsearch_tools(query, limit?)— free-text search by name/description/pathcall_tool(name, arguments)— invoke any underlying tool
The LLM discovers tools instead of seeing 1,186 names up front. Closes a fundamental scalability problem with large API catalogs and MCP.
Pagination auto-detection
The parser inspects each operation for pagination patterns: Link header (RFC 5988), cursor params (cursor, starting_after, next_cursor, page_token), page + per_page, offset + limit, and since_id. When detected, pagination metadata is attached to the tool so downstream agents can iterate without you wiring up loops.
Reliability primitives in the generated server
Every emitted server gets:
MCP_TIMEOUT_MS=30000 # per-request timeout
MCP_MAX_RETRIES=3 # retries on 429/5xx and network errors
MCP_RETRY_BASE_MS=500 # exponential backoff base
MCP_IDEMPOTENT_RETRY=0 # set 1 to retry POSTs (auto Idempotency-Key)
MCP_LOG=1 # structured JSON logs to stderr
MCP_META_ROUTING=0 # toggle meta-routing at runtime
Retry-After headers are honored. POST retries are off by default for safety but can be enabled with auto-generated Idempotency-Key headers.
Auth — all of it
| Scheme | Support |
|---|---|
| API Key (header / query / cookie) | ✅ |
| HTTP Bearer | ✅ live-verified vs GitHub API |
| HTTP Basic | ✅ |
| OAuth2 client_credentials + refresh | ✅ live-verified vs Stripe API, in-flight dedup (no stampede) |
| OAuth2 PKCE authorization_code | ✅ emits auth-login.js, S256 verified |
| AWS Signature v4 | ✅ no aws-sdk dep, byte-matched vs AWS reference vector |
| Cookie jar (RFC 6265) | ✅ Expires/Max-Age/Domain/Path/Secure |
Configure via env:
API_<SCHEMEID>= # static bearer/api-key — takes priority
OAUTH_<SCHEMEID>_TOKEN_URL=
OAUTH_<SCHEMEID>_CLIENT_ID=
OAUTH_<SCHEMEID>_CLIENT_SECRET=
OAUTH_<SCHEMEID>_REFRESH_TOKEN= # optional
OAUTH_<SCHEMEID>_SCOPE= # optional
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_REGION=
HTTP transport (hosted-gateway-ready)
mcp-forge openapi.yaml --transport http --port 8080
The generated server speaks both stdio and MCP streamable-HTTP. Drop it behind nginx or Caddy and you have a hosted gateway.
Workflow
mcp-forge spec.yaml --watch # regenerate on spec change
mcp-forge old.yaml --diff new.yaml # show added/removed/changed tools
CLI reference
USAGE
mcp-forge <spec> [options]
ARGUMENTS
spec Path or URL to an OpenAPI/Swagger/Postman spec (JSON or YAML)
OPTIONS
-o, --out <dir> Output directory (default: ./mcp-server)
--base-url <url> Override the API base URL
--transport <t> stdio | http (default: stdio)
--port <n> Port for http transport (default: 3000)
FILTERING
--tags <a,b> Only tools tagged with one of these
--include <a,b> Only tools whose name matches one of these globs
--exclude <a,b> Drop tools matching one of these globs
--methods <a,b> Only these HTTP methods
--limit <n> Cap at the first N tools after filtering
--meta-routing Expose 3 meta-tools (list/search/call) instead of full catalog
WORKFLOW
--watch Regenerate on spec change
--diff <spec2> Diff against a second spec, then exit
EXTRAS
--docker Emit Dockerfile + .dockerignore
--claude-config Emit Claude Desktop config snippet
--test Emit per-tool smoke-test script
--mock Emit mock server (returns spec examples, no real API)
Supported input formats
- OpenAPI 3.1.0 (JSON and YAML)
- OpenAPI 3.0.0–3.0.4 (JSON and YAML)
- Swagger / OpenAPI 2.0 (auto-upgraded via
swagger2openapi) - Postman Collection v2.1 (auto-converted)
License
MIT.
Contributing
Issues and PRs welcome at https://github.com/Ojebx/mcp-forge.