carlosfuentesdev

πŸ”Œ openapi-to-mcp

Community carlosfuentesdev
Updated

Turn any OpenAPI 3.x spec into a live Model Context Protocol (MCP) server: every endpoint becomes a validated tool your AI agent can call.

πŸ”Œ openapi-to-mcp

Turn any OpenAPI 3.x spec into a live MCP server.Point it at a spec (file or URL) and every endpoint becomes a validated tool yourAI agent can call β€” no glue code, no per-API server to write.

CInpmtestsnodelicense

Quick start Β· How it maps Β· Config Β· Secure it Β· Limits Β· EspaΓ±ol

  OpenAPI 3.x spec                         your AI client
 (JSON / YAML, file or URL)               (Claude, Cursor)
          β”‚                                      β”‚
          β–Ό                                      β”‚  MCP / JSON-RPC (stdio)
 [ openapi-to-mcp ]  β—€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚  GET /pets/{id} β†’ tool "get_pet_by_id"
          β–Ό  HTTP + your auth header
   the underlying REST API

Why

MCP lets an agent call tools, but someone has to write those tools. If thecapability you want already exists as a REST API with an OpenAPI spec, writing abespoke MCP server for it is busywork.

openapi-to-mcp reads the spec and does the mapping for you: each METHOD /pathbecomes a tool, each parameter and request body becomes a Zod-validated input,and every call is turned into an HTTP request with your auth header attached. Theresponse comes back trimmed for an LLM context window.

Quick start

No install needed β€” run it straight from npm:

npx @karlangas12/openapi-to-mcp --spec https://api.example.com/openapi.json \
  --auth-header "Authorization: Bearer YOUR_TOKEN"

See what tools a spec produces without starting a server:

npx @karlangas12/openapi-to-mcp --spec ./openapi.yaml --list

Claude Desktop β€” claude_desktop_config.json

{
  "mcpServers": {
    "petstore": {
      "command": "npx",
      "args": [
        "-y", "@karlangas12/openapi-to-mcp",
        "--spec", "https://petstore3.swagger.io/api/v3/openapi.json",
        "--auth-header", "Authorization: Bearer YOUR_TOKEN"
      ]
    }
  }
}

Cursor β€” .cursor/mcp.json

{
  "mcpServers": {
    "my-api": {
      "command": "npx",
      "args": [
        "-y", "@karlangas12/openapi-to-mcp",
        "--spec", "./openapi.yaml",
        "--base-url", "https://api.internal.company.com"
      ]
    }
  }
}

That's the whole integration. Restart the client and the API's endpoints show upas tools.

How it maps

OpenAPI Becomes
operationId, or METHOD /path if absent Tool name (get_pets_by_pet_id)
summary / description Tool description
Path, query and header parameters Tool input properties (path params are required)
requestBody (application/json) A body input property
Every input schema A Zod validator + a JSON Schema for tools/list
Local $ref (#/components/...) Resolved inline
enum, minimum/maximum, required, nullable, oneOf/anyOf/allOf Enforced on input

When the agent calls a tool, arguments are validated before any HTTP requestgoes out. Path params are substituted into the URL, query params are appended,header params and your static --auth-header values are sent, and a JSON body isserialized. A 4xx/5xx response comes back as an error result the model canread and react to β€” not a silent failure.

Configuration

openapi-to-mcp --spec <path|url> [options]

  -s, --spec <path|url>    OpenAPI 3.x spec (JSON or YAML, local or remote)
      --base-url <url>     API base URL (when the spec declares no "servers")
  -H, --auth-header <h>    Header to forward, "Name: value" (repeatable)
      --format <mode>      Response format: markdown (default) or json
  -n, --name <name>        MCP server name
      --list               Print the generated tools and exit
  -h, --help / -v, --version

Multiple headers:

npx @karlangas12/openapi-to-mcp --spec ./api.yaml \
  --auth-header "Authorization: Bearer XYZ" \
  --auth-header "X-Api-Version: 2024-01"

Export a standalone server (codegen)

npx @karlangas12/openapi-to-mcp codegen --spec ./api.yaml -o server.ts

Writes a single self-contained TypeScript file that embeds the spec and boots theserver via this package β€” handy for committing a pinned server to a repo.

Pairing with mcp-shield-proxy

openapi-to-mcp talks to a third-party API on your behalf, with yourcredentials. If you want a policy, credential masking and an audit trail aroundthat, wrap it with mcp-shield-proxyβ€” they compose with one extra line:

{
  "mcpServers": {
    "petstore": {
      "command": "npx",
      "args": [
        "-y", "mcp-shield-proxy", "--",          // ← inspect, mask, audit
        "npx", "-y", "@karlangas12/openapi-to-mcp",
        "--spec", "https://api.example.com/openapi.json",
        "--auth-header", "Authorization: Bearer YOUR_TOKEN"
      ]
    }
  }
}

Now every generated tool call is policy-checked, credentials in the traffic aremasked, and the whole session lands in a verifiable audit log.

Use as a library

import { loadSpec, buildTools, createMcpServer, startStdioServer } from '@karlangas12/openapi-to-mcp';

const doc = await loadSpec('./openapi.yaml');
const { tools, baseUrl } = buildTools(doc);

const server = createMcpServer({
  tools,
  baseUrl: baseUrl ?? 'https://api.example.com',
  headers: { Authorization: 'Bearer YOUR_TOKEN' },
  fetchFn: (url, init) => fetch(url, init as RequestInit),
});

startStdioServer(server);

The parser, the schema→Zod converter and the tool builder are all exportedindependently.

Honest limitations

  • stdio transport only. The MCP server speaks stdio, which covers ClaudeDesktop, Cursor and Claude Code. Native HTTP/SSE serving isn't implemented yet.
  • Local $ref only. References inside the document (#/components/...) areresolved. External refs (other files or URLs) are not β€” they raise a clearerror rather than failing quietly.
  • application/json bodies. Request bodies are mapped for JSON content.multipart/form-data and application/x-www-form-urlencoded aren't mapped yet.
  • It's a mapper, not a gateway. It doesn't add retries, caching or ratelimiting. Pair it with a proxy if you need those.

Performance

The spec is parsed once at startup; after that, each tool call is a schemavalidation plus one HTTP request. Parsing and tool generation for a typical specis sub-millisecond β€” the latency you feel is the underlying API's, not this.

Testing

npm test          # 32 tests
npm run typecheck # strict TypeScript

Coverage includes JSON and YAML parsing, endpoint→tool conversion with Zodschemas, and a full tools/call round trip over JSON-RPC against a mocked HTTPbackend (asserting the URL, method, headers and body that reach it).

License

MIT

MCP Server Β· Populars

MCP Server Β· New