openapi-mcp
Provides tools for interacting with the Swagger Petstore v3 API, enabling MCP clients to call its operations with generated schemas, annotations, and security guardrails.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@openapi-mcpcall getPetById with petId 1 and show me the result"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
OpenAPI → MCP Generator
Published on npm as @beernathan87/openapi-mcp-generator (the unscoped name was already taken); the command name stays openapi-mcp.
Turn an existing REST/OpenAPI application into an MCP server - security-first: nothing is exposed until you opt it in, destructive operations need an explicit second flag, auth never comes from the model, and every call is confined to one base URL with timeouts, size caps and a rate limit.
npx openapi-mcp init https://api.example.com/openapi.json # -> openapi-mcp.config.json, all tools disabled
# edit: "enabled": true on the operations you want; destructive ones also need "confirmDestructive": true
npx openapi-mcp list # what would be exposed
npx openapi-mcp console # local test page: call tools through the real executor
npx openapi-mcp serve # stdio MCP server for your clientMCP client config (Claude Desktop / Claude Code / Cursor):
{ "mcpServers": { "petstore": { "command": "npx", "args": ["openapi-mcp", "serve", "--config", "/abs/path/openapi-mcp.config.json"], "env": { "API_TOKEN": "..." } } } }What it generates
For every operation in the spec (OpenAPI 3.x, JSON or YAML, local $refs resolved):
a tool name (
operationId, ormethod_path), a description with method, path and a[WRITE]/[DESTRUCTIVE]taga JSON Schema input built from path/query/header parameters plus the request body (
bodyargument), withrequiredandadditionalProperties: falseMCP annotations derived from the method and wording:
readOnlyHint(GET/HEAD),destructiveHint(DELETE, or "delete/remove/destroy/purge/reset/revoke" in the summary),idempotentHint,openWorldHint: falsea risk class
read | write | destructiveshown inlistand the console
Related MCP server: safe-oas2mcp
Guardrails (executor)
Only the config's
baseUrlorigin is ever contacted; path parameters are URL-encoded; dot segments, slash/backslash and percent escapes are rejected, including in route templates. Review the base URL before enabling anything.Auth is injected from an environment variable (
auth.type:bearer|header|basic;auth.env, defaultAPI_TOKEN). Tool arguments cannot setAuthorization,Cookie,Hostor other transport headers.Timeout (
limits.timeoutMs, 15 s), response cap (limits.maxResponseBytes, 256 KiB - truncated and flagged), per-process rate limit (limits.maxCallsPerMinute, 60), no redirect following.Disabled tools are not merely refused - they are not listed. Enabled destructive tools without
confirmDestructive: trueare blocked, and the config fails validation so you notice.refreshre-reads the spec after an API update, keeps enabled flags for matching method/path pairs, and reports operations added/removed - new endpoints stay disabled.
Test console
openapi-mcp console serves a page on 127.0.0.1 only: it lists all operations (greyed out when disabled), shows the generated schema and annotations, lets you edit JSON arguments and calls the tool through the same executor the MCP server uses, showing the exact request URL and the response.
Limits (v1)
OpenAPI 3.x only (no Swagger 2.0); external $refs are not fetched; oneOf/anyOf bodies are passed through as-is; multipart/file uploads are not supported; responses are returned as text/JSON up to the cap; no OAuth flows (bring a token). Single-process rate limiting.
Development
npm install
npm test # includes an in-memory MCP client <-> server round trip with a fake upstream APIMIT.
Production notes
Verified 2026-09-13 from the packed tarball on Windows 11 and Linux (node:22 container) against two real APIs: httpbin.org through a rich spec (component
$refs,allOf, three auth styles, optional/array/object/header parameters, path templates, error responses, a deprecated operation) and Swagger Petstore v3 from its public URL. Through a real MCP stdio session: tools listed with correct annotations; path traversal in a path parameter rejected;Authorization/Hostsupplied as tool arguments ignored (auth comes only from the environment); upstream 404/500/503 and a 4 s timeout returned as tool errors while the session stayed protocol-clean and exited 0; disabled and undeclared-parameter operations fail closed.refreshafter a spec change disabled an operation whose method changed to DELETE, kept a confirmed destructive tool enabled, left a new operation disabled and reported the removed one.Exit codes:
serveexits 1 on an invalid config (including enabled-but-unconfirmed destructive tools) before speaking MCP; stdout is protocol-only, diagnostics go to stderr.Auth: the token env var must be present at
servetime or every call fails closed (auth requires environment variable …). Put it in the MCP client'senvblock, never in the config file.Update:
npm install -g @beernathan87/openapi-mcp-generator@latest, thenopenapi-mcp refreshper config; review the added/removed list. Configs are plain JSON you own - back them up with your project.
Troubleshooting
Symptom | Cause / fix |
| the spec's |
| the spec does not declare a parameter its path template uses; declare it in the spec and |
a tool is listed by | the client cached |
| export the variable (or the one named by |
Credits
Created by Nathan Beer. Developed by Nathan Beer with AI-assisted engineering using Claude and ChatGPT. Third-party licenses: THIRD_PARTY_NOTICES.md. Not affiliated with or endorsed by Anthropic, OpenAI, SmartBear/Swagger or the Model Context Protocol project.
Security review contract (v0.1)
The config is trusted local policy. The spec, model arguments and upstream response are untrusted. Review destinations and operation semantics before enabling tools: method-derived risk hints cannot prove that an API is read-only. confirmDestructive is a persistent operator opt-in, not per-call user consent. A newly destructive operation is disabled on refresh; descriptions, schemas, names and annotations are regenerated, replacing manual overrides. New routes remain disabled even when an operation ID is reused. Deprecated enabled operations warn on serve stderr.
Relative or templated server URLs are rejected; provide an absolute HTTP(S) URL without credentials, query or fragment. Imports are limited to 4 MiB, 512 operations, 64 KiB per input schema, depth 40 100,000 expansion nodes and 8 MiB expanded string data; remote imports time out after 15 seconds. External refs are not fetched and recursive refs become placeholders. Review these incomplete schemas before use. Descriptions/titles have control and format characters removed and are capped at 1,000 characters. This does not neutralize prompt injection: run mcp-scan against the generated server before deployment and after refresh, and treat response text as untrusted data.
Only declared top-level parameters are serialized; unknown top-level arguments are dropped. Request bodies remain API payloads, without runtime JSON Schema validation or recursive filtering. Object/array path, query and header parameters use JSON strings; OpenAPI style/explode is not implemented. GET/HEAD bodies are omitted. Basic auth uses one environment variable containing user:pass. Custom auth headers cannot be overridden by model arguments. API-specific query credentials and semantic routing headers are not inferred: do not enable parameters that act as credentials, proxy destinations or routing overrides.
Responses are streamed up to the byte cap and cancelled when exceeded; redirects are unsuccessful results. Non-JSON content stays text (binary is decoded as UTF-8). Text plus structuredContent duplicates the bounded response; JSON escaping can increase wire size by a constant factor. Peer exception details are withheld. Exact raw and Basic-base64 credential echoes are redacted from response bodies/content types; transformed, split, or encoded secrets cannot reliably be recognized. The upstream necessarily receives configured auth: only use a trusted destination, and treat console/results as sensitive.
The console binds to loopback, checks Host and exact Origin when present, and limits call bodies to 256 KiB. It is not an authentication boundary against local processes. Rate limits use a rolling 60-second process-local window, including invalid attempts. serve reserves stdout for MCP; diagnostics go to stderr; CLI failures exit 1.
This server cannot be deployed
Maintenance
Related MCP Connectors
Governed MCP gateway: one endpoint for your tools, with credential custody and audit log.
Zero-setup MCP gateway securely connecting AI to your tools with authentication and workflows
Security & DLP proxy for MCP: tool-poisoning scans, PII redaction on tool args/results. Beta.
Zero-secret MCP gateway for AI agents: risk-scored, audited calls with human-in-the-loop approval.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA safe gateway to convert OpenAPI specs into MCP tools with secure defaults, risk inspection, and confirmation gates.-
- FlicenseNot gradedqualityDmaintenanceTurns OpenAPI specs into MCP tools with secure defaults, risk inspection, confirmation gates, response limits, audit logging, and secret redaction.-
- AlicenseNot gradedqualityCmaintenanceConvert any OpenAPI spec into a secure MCP server with scoped auth, per-tool allow/deny policies, rate limiting, and a redacted audit trail.10 npmMIT
- FlicenseNot gradedqualityBmaintenanceEnables turning existing REST APIs into governed, agent-callable MCP servers by analyzing OpenAPI schemas, generating tool definitions, and gating releases behind automated evals.-