Skip to content

mcp-from-openapi

Convert OpenAPI specifications into MCP tool definitions with automatic parameter conflict resolution

npm version License: Apache 2.0 TypeScript Node.js CodeQL

What This Solves

When converting OpenAPI specs to MCP tools, you hit parameter conflicts -- the same name appears in different locations (path, query, body). This library resolves them automatically and gives you an explicit mapper for building HTTP requests.

The Problem:

paths:
  /users/{id}:
    post:
      parameters:
        - name: id # path
          in: path
      requestBody:
        content:
          application/json:
            schema:
              properties:
                id: # body -- CONFLICT!
                  type: string

The Solution:

{
  inputSchema: {
    properties: {
      pathId: { type: "string" },    // Automatically renamed
      bodyId: { type: "string" }     // Automatically renamed
    }
  },
  mapper: [
    { inputKey: "pathId", type: "path", key: "id" },
    { inputKey: "bodyId", type: "body", key: "id" }
  ]
}

Now you know exactly how to build the HTTP request.

Features

  • Built-in Request Builder -- buildHttpRequest() applies the full OpenAPI serialization table (form/deepObject/pipeDelimited queries, label/matrix paths, multipart, binary, wholeBody) so you never hand-write request assembly
  • Client Compatibility Targets -- target: 'claude' | 'openai' | 'gemini' | 'strict' emits schemas each client actually accepts (inlined refs, closed objects, collapsed unions, demoted formats)
  • Context-Budget Reports -- analyzeToolSet() estimates the token bill per tool and warns at the thresholds where agent accuracy degrades
  • Overlays & Lint -- apply OpenAPI Overlay curation files at load time; lint() flags the spec gaps that hurt tool-calling accuracy
  • Curation-Grade Filtering -- Filter by tag, method, path glob (/admin/**), operationId, a readOnlyOnly safety switch, and x-mcp extension flags with root < path < operation precedence
  • Smart Parameter Handling -- Automatic conflict detection and resolution across path, query, header, cookie, and body; allOf bodies flatten, union and binary bodies map cleanly (wholeBody, binary markers)
  • Complete Schemas -- Input schema combines all parameters; output schema from responses (with oneOf unions); clean JSON Schema 2020-12 output (nullable unions, normalized examples)
  • MCP-Native Tools -- title and tool annotations (readOnly/destructive/idempotent hints) inferred from HTTP semantics, overridable via the x-mcp extension family; spec-compliant tool names (64-char cap, stable hash truncation, collision dedup); deterministic tool ordering for prompt-cache friendliness; toSdkTool() for one-line SDK registration
  • Security Resolution -- Framework-agnostic auth for Bearer, Basic, Digest, API Key, OAuth2, OpenID, mTLS, HMAC, AWS Sig V4; per-scheme includeSecurityInInput
  • SSRF Prevention -- Blocks internal IPs, localhost, and cloud metadata endpoints by default during $ref resolution; one-flag secureDefaults posture for untrusted specs
  • Multiple Input Sources -- Load from URL, file, YAML string, or JSON object
  • Rich Metadata -- Authentication, servers, tags, deprecation, external docs, x-frontmcp extension
  • Production Ready -- Full TypeScript support, validation, structured errors, 100% test coverage (enforced)
  • Runtime Agnostic -- Works on Node and V8 isolates (Cloudflare Workers) alike

Installation

npm install mcp-from-openapi
# or
yarn add mcp-from-openapi
# or
pnpm add mcp-from-openapi

Quick Start

import { OpenAPIToolGenerator } from "mcp-from-openapi";

// Load an OpenAPI spec
const generator = await OpenAPIToolGenerator.fromURL(
  "https://api.example.com/openapi.json",
);

// Generate MCP tools
const tools = await generator.generateTools();

// Each tool has everything you need
tools.forEach((tool) => {
  console.log(tool.name); // "createUser"
  console.log(tool.title); // "Create a user" (from summary/extensions)
  console.log(tool.annotations); // { readOnlyHint: false, destructiveHint: true, ... }
  console.log(tool.inputSchema); // Combined schema for all params
  console.log(tool.outputSchema); // Response schema
  console.log(tool.mapper); // How to build the HTTP request
  console.log(tool.metadata); // Auth, servers, tags, etc.
});

Building Requests

buildHttpRequest() turns a tool plus input values into a ready-to-send request — style/explode serialization, deepObject queries, multipart, binary, and wholeBody handled correctly:

import { buildHttpRequest } from "mcp-from-openapi";

const request = buildHttpRequest(tool, { id: "42", filter: { tag: "news" } });
// { url: 'https://api.example.com/users/42?filter[tag]=news',
//   method: 'GET', headers: {...}, body: undefined, ... }

await fetch(request.url, {
  method: request.method,
  headers: request.headers,
  body: request.body as BodyInit,
});

The mapper array stays public for anyone who needs custom request assembly — see Request Builder and Parameter Conflicts for its contract.

Serving with the Official MCP SDK

import { toSdkTool, buildHttpRequest } from "mcp-from-openapi";
import { fromJsonSchema } from "@modelcontextprotocol/server"; // SDK v2

for (const tool of await generator.generateTools({ target: "claude" })) {
  server.registerTool(...toSdkTool(tool, { fromJsonSchema }), async (input) => {
    const request = buildHttpRequest(tool, input);
    const response = await fetch(request.url, {
      method: request.method,
      headers: request.headers,
      body: request.body as BodyInit,
    });
    return { content: [{ type: "text", text: await response.text() }] };
  });
}

Documentation

Document Description
Getting Started Loading specs, generating tools, building requests
Configuration LoadOptions, GenerateOptions, RefResolutionOptions
Parameter Conflicts How conflict detection and resolution works
Request Builder buildHttpRequest — full OpenAPI parameter serialization
Client Targets Per-client schema dialects (Claude, OpenAI, Gemini)
Curation Token budgets, overlays, lint, trimming, response hints
Response Schemas Output schemas, status codes, oneOf unions
Annotations & Extensions Tool title, annotation inference, x-mcp extension family
Security SecurityResolver, all auth types, custom resolvers
SSRF Prevention Ref resolution security, blocked IPs and hosts
Format Resolution Format-to-schema enrichment (uuid, date-time, email, int32, etc.)
Naming Strategies Custom tool naming and conflict resolvers
SchemaBuilder JSON Schema utility methods
Error Handling Error classes, context, and patterns
x-frontmcp Extension Custom OpenAPI extension for MCP annotations
API Reference Complete types, interfaces, and exports
Examples MCP server, Zod, filtering, security, and more
Architecture System overview, data flow, design patterns

Requirements

  • Node.js >= 20.0.0
  • TypeScript >= 5.0 (for TypeScript users)
  • Peer dependency: zod@^4.0.0

Contributing

Contributions are welcome! Start with the contributing guide; this project follows the Contributor Covenant. Bug reports and feature requests go through the issue templates.

Security

Report vulnerabilities privately — see the security policy. When loading untrusted specs, use secureDefaults: true.

Related Projects

License

Apache 2.0

About

Production-ready TypeScript library for converting OpenAPI specifications into MCP (Model Context Protocol) tool

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages