Skip to content

OpenAPI to MCP generators compared (2026): 6 open-source tools tested on the same specs

Six open-source OpenAPI-to-MCP tools run against the same two specs and a recording mock API: schema fidelity, request correctness, auth and protocol.

By Updated

Short answer: for Python teams, FastMCP's from_openapi sent the most requests correctly among runtime tools. If you want a TypeScript project you own or a Cloudflare Worker, openapi-mcp-generator 5.0.1 passed every schema check and every request check except multipart uploads. If you never want generated code, @ivotoby/openapi-mcp-server is the Node runtime option, over stdio.

Last verified: 24 October 2026. Disclosure: I maintain openapi-mcp-generator, one of the tools tested. The harness, both specs and every raw request log are public so you can check the results or rerun them.

TL;DR: which tool to use when#

Pick by how you want to own the server, then check the specific features your API uses against the tables below.

If you... Use Why, from this benchmark
work in Python, or already use FastMCP FastMCP from_openapi 4.1.3 Correct query arrays (both styles), cookies, multipart uploads, typed bodies and outputSchema. Weak spots: readOnly fields shown as inputs, 3.0 exclusiveMinimum left as a boolean, no argument validation for types or bounds.
never want generated code and run Node @ivotoby/openapi-mcp-server 1.16.1 Runtime proxy, multipart works, a dynamic meta-tool mode for large APIs. Weak spots: no input validation, no cookies, comma-joined arrays, and its streamable HTTP tools/call failed with the official Python client.
want a TypeScript project you own, or a Cloudflare Worker openapi-mcp-generator 5.0.1 18/18 schema checks, 19 of 20 request checks, input validation before any request, fail-closed credentials, per-operation security and servers, OAuth2 client credentials. Multipart uploads still fail, and you regenerate when the spec changes.
run on AWS and use Cognito AWS Labs openapi-mcp-server 1.1.6 An SSRF guard on spec URLs, Cognito support, correct query arrays, cookies and multipart. It is stdio only, takes one auth type per server, and on our edge-case spec a successful getItem came back as an error. Petstore passed cleanly.
want a managed or hosted product Speakeasy, Stainless or Zuplo Not benchmarked here. See commercial options.

Two tools are hard to recommend today: @tyk-technologies/api-to-mcp 0.1.1 (last release 27 June 2025) exposes JSON request bodies as an untyped string, and mcp-openapi 0.3.0 dropped the path part of the base URL, so every call in both specs went to the wrong URL.

How we tested#

Every tool got the same two OpenAPI files, the same local mock API and the same MCP client. Every number below comes from that run; nothing is estimated.

  • Specs. Spec A is the real Swagger Petstore 3 description (version 1.0.27, OpenAPI 3.0.4, 19 operations), unchanged. Spec B is a small purpose-built "fidelity" spec (OpenAPI 3.0.3, 12 operations) that packs in the features converters most often get wrong: oneOf/anyOf/allOf, nullable, readOnly/writeOnly, the 3.0 boolean exclusiveMinimum, header and cookie parameters, query arrays with explode true and false, multipart upload, a per-operation servers override, apiKey, bearer and OAuth2 client-credentials security, an operation without operationId and an 85-character operationId.
  • Mock upstream. A local HTTP server implements both specs and writes every request it receives (method, path, query, headers, cookies, body, parsed multipart parts) to a log before answering. That log is the ground truth for whether a request was right. No public API was called.
  • Client. The official MCP Python SDK (mcp 2.3.0) over stdio, offering protocol version 2025-11-25. Tool calls were sent without client-side output validation, so we saw what servers actually returned; SDK validation was then run separately as its own check.
  • Defaults only. Each tool ran with its documented quickstart. The only configuration was the base URL of the mock and credentials through each tool's documented mechanism. openapi-mcp-generator ran without --output-schema or filters.
  • Runs. Each tool and spec ran twice end to end. No check changed result between the two runs.
  • Versions. openapi-mcp-generator 5.0.0 was tested earlier the same day. It failed the explode=true query array and cookie checks; 5.0.1, published later that day, fixes both, and the full benchmark was rerun on it. No other check result changed for any tool. Multipart still fails in 5.0.1.

The harness is a single command (make bench) in the benchmark repository, with the method, fairness rules and limitations in its README. Full per-check evidence is in its results/summary.md.

Results#

Setup and startup#

Every tool installs in seconds; the bigger differences are the extra build step for codegen and Python startup time.

Tool Version Kind Installed packages Install size Launch to first tools/list, median of 3 (Petstore / Fidelity) Tools (Petstore / Fidelity)
openapi-mcp-generator 5.0.1 codegen, TypeScript 17 (CLI); generated project: 31 production 5 MB CLI; 46 MB project node_modules incl. TypeScript 0.34 s / 0.32 s 19 / 12
FastMCP from_openapi 4.1.3 Python framework 68 59 MB 1.73 s / 1.81 s 19 / 12
AWS Labs openapi-mcp-server 1.1.6 Python runtime proxy 87 88 MB 2.21 s / 1.98 s 19 / 12
@ivotoby/openapi-mcp-server 1.16.1 Node runtime proxy 126 22 MB 0.32 s / 0.31 s 19 / 12
@tyk-technologies/api-to-mcp 0.1.1 Node runtime proxy 180 25 MB 0.42 s / 0.43 s 19 / 11
mcp-openapi (Docat0209) 0.3.0 Node runtime proxy 112 43 MB 0.31 s / 0.30 s 19 / 12

openapi-mcp-generator adds a one-time step before first launch: generate (0.2 s), npm install (2.2 s) and npm run build (2.5 s) on our machine, producing one src/index.ts of 1,160 non-blank lines for Petstore and 1,059 for the Fidelity spec. Install times were measured with warm package caches, so they are indicative only. Tyk lists 11 tools for 12 operations because it skipped the operation without an operationId.

Schema fidelity (Fidelity spec)#

This table checks the inputSchema each server advertises, which is what a model sees and fills in.

Check openapi-mcp-generator FastMCP AWS Labs ivotoby Tyk mcp-openapi
integer type kept pass pass pass pass pass pass
enum kept pass pass pass pass FAIL pass
minimum/maximum kept pass pass pass pass FAIL FAIL
oneOf preserved pass partial (became anyOf) partial (became anyOf) pass FAIL FAIL
anyOf preserved pass pass pass pass FAIL FAIL
allOf handled pass pass pass pass FAIL pass
nullable allows null pass pass pass partial (nullable left as-is) FAIL FAIL
readOnly excluded from inputs pass FAIL FAIL FAIL n/a FAIL
writeOnly kept pass pass pass pass FAIL pass
3.0 exclusiveMinimum converted to a number pass FAIL FAIL FAIL FAIL FAIL
$ref resolved pass pass pass pass pass pass
nested $ref object expanded pass pass pass pass FAIL pass
array item types kept pass pass pass pass FAIL pass
required propagated pass pass pass pass FAIL pass
header parameter exposed pass pass pass pass pass pass
cookie parameter exposed pass pass pass pass pass FAIL
default kept pass pass pass pass FAIL pass
format kept (uuid, date-time) pass pass pass pass FAIL pass
Total 18 / 0 / 0 15 / 1 / 2 15 / 1 / 2 15 / 1 / 2 4 / 0 / 13 11 / 0 / 7

Totals are pass / partial / fail. Tyk's readOnly result is n/a because it exposes the whole JSON body as a single untyped string, so there is nothing to exclude.

Two results matter beyond the table. The boolean exclusiveMinimum: true that FastMCP, AWS Labs and ivotoby pass through is valid OpenAPI 3.0 but invalid JSON Schema 2020-12, and it broke real calls: the MCP Python SDK refused FastMCP's getItem result because the tool's outputSchema failed schema validation, and AWS Labs returned isError for a successful 200 response because its own output validation hit the same keyword. On Petstore, which has no such keyword, both worked.

Execution (Fidelity spec)#

This table checks what each server actually sent to the API, read from the mock's request log.

Check openapi-mcp-generator FastMCP AWS Labs ivotoby Tyk mcp-openapi
path parameter substituted pass pass pass pass pass pass
query array, explode=true (tag=a&tag=b) pass pass pass FAIL FAIL FAIL
query array, explode=false (ids=1,2) pass pass pass pass FAIL pass
header parameter sent pass pass pass pass pass pass
cookie parameter sent pass pass pass FAIL FAIL FAIL
JSON body sent as given pass partial (null dropped) partial (null dropped) pass pass pass
multipart/form-data upload FAIL pass pass pass FAIL FAIL
per-operation servers override used pass FAIL FAIL FAIL FAIL FAIL
base URL path kept pass pass pass pass pass FAIL
API key from config pass pass FAIL (one auth type) pass pass pass
bearer token from config pass pass pass pass pass pass
OAuth2 client credentials fetched and used pass FAIL FAIL FAIL FAIL pass
credentials sent only where the operation requires them pass FAIL FAIL FAIL pass FAIL
invalid arguments rejected before any request (3 cases) pass partial (1 of 3) FAIL FAIL partial (2 of 3) FAIL
200 response returned as a non-error result pass pass FAIL pass pass FAIL
upstream 404 and 500 returned as isError with status pass pass pass pass pass pass
structuredContent returned pass pass FAIL FAIL FAIL FAIL
empty 204 response handled pass pass pass pass pass FAIL
operation without operationId callable pass pass pass pass FAIL pass
85-char operationId gives a name of 64 chars or less pass pass pass pass FAIL pass
Total 19 / 0 / 1 15 / 2 / 4 12 / 1 / 8 13 / 0 / 7 10 / 1 / 9 10 / 0 / 10

A separate row, "result passes MCP Python SDK output validation", failed for FastMCP and AWS Labs and was n/a for the others (they declare no outputSchema by default). mcp-openapi's 200, 204 and base-path failures share one cause, described in its section; request checks compare paths relative to the base URL so that one bug does not fail everything. AWS Labs accepts one auth type per server, so it received the spec's global bearer token and no API key.

Execution (Swagger Petstore)#

On a typical spec most tools did the basics right; the differences were in result shape.

Check openapi-mcp-generator FastMCP AWS Labs ivotoby Tyk mcp-openapi
getPetById: path and api_key header pass pass pass pass pass pass
findPetsByStatus: query enum pass pass pass pass pass pass
addPet: JSON body sent as given pass pass pass pass pass pass
200 returned as a non-error result pass pass pass pass pass FAIL
base URL path kept (/api/v3) pass pass pass pass pass FAIL
structuredContent returned pass pass pass FAIL FAIL FAIL

Protocol, transports and credentials#

All six negotiated 2025-11-25 with the official client. Only two answered the newer 2026-07-28 server/discover probe.

Tool Server instructions Unknown tool server/discover (2026-07-28) Transports (docs) Streamable HTTP test No credentials configured
openapi-mcp-generator yes (from info.description) JSON-RPC error -32602 yes stdio, HTTP+SSE, streamable HTTP, Cloudflare Worker pass fails closed, names the missing variable, sends nothing
FastMCP no isError result yes stdio, streamable HTTP, SSE pass sends the request without credentials, surfaces the 401
AWS Labs yes (generic text) isError result no stdio only in 1.1.6 not applicable sends without credentials, surfaces the 401
ivotoby no JSON-RPC error -32603 no stdio, streamable HTTP FAIL: tools/call answered 202 Accepted with an empty body sends without credentials, surfaces the 401
Tyk no isError result no stdio not applicable sends without credentials, surfaces the 401
mcp-openapi no isError result no stdio, SSE not tested sends without credentials

The streamable HTTP test ran initialize, list and one call. For ivotoby, initialize and tools/list returned 200 with JSON; tools/call returned 202 Accepted and no body, which the streamable HTTP transport reserves for notifications and responses, so the Python SDK client rejected it. Missing-credential behavior is a design choice, so it is reported rather than scored.

Maintenance signals#

Checked 24 October 2026. Stars and downloads describe popularity, not quality.

Tool Tested version released GitHub stars License Weekly downloads
openapi-mcp-generator 2026-10-24 640 MIT 6,248 (npm)
FastMCP 2026-10-20 28,193 Apache-2.0 14,357,639 (PyPI, whole framework)
AWS Labs openapi-mcp-server 2026-09-08 9,828 (awslabs/mcp monorepo) Apache-2.0 1,793 (PyPI)
@ivotoby/openapi-mcp-server 2026-06-15 301 MIT 4,780 (npm)
@tyk-technologies/api-to-mcp 2025-06-27 51 MIT 62 (npm)
mcp-openapi 2026-03-21 3 MIT 327 (npm)

FastMCP is a general MCP framework, so its downloads and stars are not a measure of from_openapi use. The AWS Labs star count is for the whole awslabs/mcp repository.

The tools, one by one#

FastMCP from_openapi (4.1.3)#

FastMCP is the most widely used Python MCP framework, and FastMCP.from_openapi(spec, client=httpx2.AsyncClient(...)) turns a spec into tools at startup. It was the most correct runtime option at the HTTP layer.

  • Strengths: serialized both query array styles correctly, sent cookies, sent real multipart uploads, kept oneOf semantics close (as anyOf), declared outputSchema for 10 of 12 Fidelity operations and returned structuredContent. Streamable HTTP worked and it answered the 2026-07-28 probe.
  • Limitations: readOnly properties (id, createdAt) appear as inputs; the 3.0 boolean exclusiveMinimum is passed through, which made the SDK reject a result; a string for an integer field and a value below minimum both reached the API (a missing required path parameter was rejected); explicit null body values were dropped; per-operation servers were ignored; credentials are client headers sent on every request, and OAuth2 client credentials are not built in (you would configure an auth flow on the HTTP client yourself). No server instructions by default; titles are derived from the tool name (Getitem), not the summary.
  • Best for: Python teams who want a runtime server they can extend with hand-written tools. FastMCP's own docs recommend curated servers over raw conversion for production. Feature by feature: openapi-mcp-generator vs FastMCP.

openapi-mcp-generator (5.0.1)#

It generates a TypeScript MCP server project you own and build. It was the only tool to pass every schema check, and it failed one request check, multipart upload. Version 5.0.0, tested earlier the same day, also failed the explode=true array and cookie checks; 5.0.1 fixes both.

  • Strengths: 18/18 schema fidelity; all three invalid-argument cases rejected before any request; credentials scoped per operation, fail closed when missing; per-operation servers; OAuth2 client credentials fetched automatically; titles and annotations on every tool; server instructions from info.description; structuredContent; streamable HTTP and the 2026-07-28 probe both passed; Cloudflare Worker output.
  • Limitations, measured: multipart bodies are exposed as a single string and sent as that text with a bare Content-Type: multipart/form-data header and no boundary, so a real server would reject the upload. In 5.0.0, explode=true query arrays were also sent comma-joined (tag=red%2Cblue instead of tag=red&tag=blue) and the cookie parameter was never sent; in 5.0.1 both reached the mock correctly (tag=red&tag=blue, Cookie: session_id=sess-123).
  • Limitations, by design: you regenerate when the spec changes, and --force overwrites edits; one tool per operation with no dynamic or code-execution mode yet; no outputSchema unless you pass --output-schema; upstream OAuth2 authorization code and implicit flows need a pre-acquired token (5.0.1 also fetches password-grant tokens, which this benchmark did not test).
  • Best for: teams who want a reviewable TypeScript project, strict input validation or a Cloudflare Worker. Not yet for APIs that depend on file uploads.

AWS Labs openapi-mcp-server (1.1.6)#

A Python runtime proxy from AWS Labs, built on FastMCP 3.4.11, configured with environment variables and run with uvx.

  • Strengths: an SSRF guard on spec URLs (with API_SPEC_URL=http://127.0.0.1/... it refused to start: "URL scheme 'http' not allowed"; a local spec file and an http:// base URL work with defaults); Cognito authentication; correct query arrays, cookies and multipart, like FastMCP; Petstore passed every check.
  • Limitations: on the Fidelity spec, getItem received a 200 from the API but returned isError with "True is not of type 'number'", because response validation hit the boolean exclusiveMinimum; no argument validation (with itemId missing it requested /v1/items/%7BitemId%7D, a literal template); one auth type per server; per-operation servers ignored; stdio only in this version.
  • Best for: AWS shops on stdio, especially with Cognito. Test with your own spec first, and consider converting 3.0 specs to 3.1. Feature by feature: openapi-mcp-generator vs AWS Labs OpenAPI MCP Server.

@ivotoby/openapi-mcp-server (1.16.1)#

A Node runtime proxy configured by environment variables or flags, with a dynamic mode that exposes three meta-tools (list, get schema, invoke) instead of one tool per operation.

  • Strengths: multipart uploads and JSON bodies sent correctly; abbreviated tool names kept to 64 characters; fast startup (about 0.3 s); optional dynamic mode for large APIs (not benchmarked).
  • Limitations: explode=true arrays comma-joined; cookies not sent; no input validation (all three invalid cases reached the API, including a literal {itemId} path); nullable left as an OpenAPI keyword; readOnly fields as inputs; static headers sent on every request; no OAuth2 client credentials from the CLI; no structuredContent; and the streamable HTTP tools/call issue above. Tool names are abbreviated (lst-items), so none matched the operationId.
  • Best for: Node users who want a no-codegen proxy over stdio, or the dynamic mode for very large APIs.

@tyk-technologies/api-to-mcp (0.1.1)#

A Node runtime proxy from Tyk with overlays and allow/deny lists. Its latest release is from 27 June 2025.

  • Strengths: per-scheme credentials (SECURITY_CREDENTIALS), so it was one of two tools that sent each credential only where required; JSON bodies arrive intact when passed as a JSON string.
  • Limitations: request bodies are exposed as one untyped requestBody string, so models get no field schema; parameter enums, bounds, defaults and formats are dropped; query arrays sent as tag[]=red&tag[]=blue; no cookies; multipart sent as JSON; the operation without an operationId was skipped; the 85-character operationId became an 85-character tool name; no tool descriptions; no structuredContent.
  • Best for: existing Tyk users with simple, flat APIs. Not recommended for new projects.

mcp-openapi by Docat0209 (0.3.0, optional extra)#

A small Node runtime proxy with flattened parameters, retries and optional paid "Pro" features.

  • Strengths: OAuth2 client credentials (as a global auth mode) fetched and used a token; explode=false arrays and JSON bodies correct; fast startup.
  • Limitations: it builds URLs with new URL(path, baseUrl) and a leading-slash path, so --base-url http://host/v1 sent /items/42 instead of /v1/items/42 on both specs; oneOf and anyOf collapsed to their first variant; nullable, minimum and maximum dropped; cookie parameters not exposed.
  • Best for: APIs whose base URL has no path, once you have tested it.

Not benchmarked, and why#

janwilmake/openapi-mcp-server now explores specs rather than serving an API's operations as tools, which is a different job. Higress openapi-to-mcpserver emits gateway configuration rather than running a server, a different category.

Commercial options (not benchmarked)#

These products were not run. Descriptions come from each vendor's own documentation, checked on 24 October 2026.

  • Speakeasy. Generates a standalone TypeScript MCP server from OpenAPI with speakeasy quickstart --mcp, with optional Cloudflare Worker config and MCPB/desktop extension packages (docs). Its product page lists code mode by default, JQ response filters and managed OAuth 2.1 (product). Separately, its hosted platform formerly called Gram, now the "AI control plane", creates an MCP server from an uploaded OpenAPI document and recommends OpenAPI 3.1 (docs, rename note).
  • Stainless. Generates an MCP server as a subpackage of a Stainless TypeScript SDK. Its docs mark MCP generation as experimental, describe a two-tool design (a TypeScript code execution tool plus docs search) rather than one tool per operation, and mark Stainless-hosted code execution as deprecated in favor of --code-execution-mode=local (docs).
  • Zuplo. Its gateway's MCP Server handler turns routes described in OpenAPI into MCP tools and re-invokes each route inside the gateway, so the route's authentication, rate limiting and other policies still apply (handler docs, overview). It fits APIs already behind Zuplo.

Pricing was not verified for this article; check each vendor's pricing page.

Codegen vs runtime proxy#

A code generator writes a server project you build and own; a runtime proxy reads the spec every time it starts. That is the main decision, before any feature table.

  • Codegen (openapi-mcp-generator, Speakeasy): you can read, review, test and edit the code, deploy it like any service (including Workers), and pin its behavior. The cost is regeneration when the spec changes and a build step.
  • Runtime proxy (FastMCP from_openapi, AWS Labs, ivotoby, Tyk, mcp-openapi): point it at a spec and go; spec changes need only a restart. The cost is less control over generated behavior, and fixes depend on the proxy's release cycle.
  • Gateway or platform (Zuplo, Speakeasy's AI control plane): conversion runs inside infrastructure you may already operate, with its policies and analytics, at the cost of vendor dependence.

In this benchmark the split did not predict correctness. A generator had the best schema and request totals, a runtime framework sent the most requests correctly among runtime tools, and only runtime tools sent a valid multipart upload.

FAQ#

What is the best OpenAPI to MCP generator? There is no single winner. In this benchmark FastMCP sent requests most correctly among runtime tools and openapi-mcp-generator kept schemas most faithful and validated inputs. Choose by language and ownership model, then check your spec's features against the tables.

Can I convert an OpenAPI spec to an MCP server without writing code? Yes. FastMCP needs about ten lines of Python; AWS Labs, ivotoby, Tyk and mcp-openapi run from one command with environment variables; openapi-mcp-generator generates the code for you and needs only npm install and a build.

Do these tools support OpenAPI 3.0 and 3.1? All six accepted our 3.0.3 and 3.0.4 files. 3.0-specific keywords are where they differ: only openapi-mcp-generator converted nullable and boolean exclusiveMinimum into valid JSON Schema in every case; FastMCP and AWS Labs converted nullable but not exclusiveMinimum.

Which tools validate tool arguments before calling the API? Only openapi-mcp-generator rejected all three invalid cases (wrong type, missing required, below minimum) without sending a request. FastMCP rejected only the missing path parameter, Tyk rejected two of three, and the others sent all three.

Which tools handle file uploads (multipart/form-data)? FastMCP, AWS Labs and ivotoby sent valid multipart requests. openapi-mcp-generator (5.0.0 and 5.0.1), Tyk and mcp-openapi did not.

How do these tools handle authentication to the upstream API? openapi-mcp-generator reads per-scheme environment variables and fetches OAuth2 client-credentials tokens; Tyk maps credentials per scheme; mcp-openapi supports one global auth mode, including client credentials; FastMCP and ivotoby send static headers on every request; AWS Labs takes one auth type per server, including Cognito.

Should I use codegen or a runtime proxy? Use codegen if you want code you can review, edit and deploy anywhere. Use a runtime proxy if you want spec changes to apply on restart without regenerating.

Methodology and limitations#

The benchmark measures tool behavior against two specs, not how well models use the tools. Read the results with these limits in mind.

  • One author wrote Spec B, and that author maintains one of the tools. Spec B covers OpenAPI 3.0 features, but choosing which features to test is still a choice. Spec A is unmodified.
  • One machine, warm package caches. Install and startup times are indicative.
  • One client, the MCP Python SDK. Other clients differ in name limits, schema handling and validation.
  • No model in the loop, so tool-selection quality and description usefulness are not measured.
  • OAuth2 tested only for client credentials. Large-API modes (dynamic tools, code execution) were not compared.
  • Results apply to the exact versions listed. Rerun the harness before quoting them for later releases.

Sources#

All checked 24 October 2026.