Convert OpenAPI specifications into MCP tool definitions with automatic parameter conflict resolution
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: stringThe 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.
- 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, areadOnlyOnlysafety switch, andx-mcpextension flags with root < path < operation precedence - Smart Parameter Handling -- Automatic conflict detection and resolution across path, query, header, cookie, and body;
allOfbodies flatten, union and binary bodies map cleanly (wholeBody,binarymarkers) - Complete Schemas -- Input schema combines all parameters; output schema from responses (with oneOf unions); clean JSON Schema 2020-12 output (
nullableunions, normalizedexamples) - MCP-Native Tools --
titleand toolannotations(readOnly/destructive/idempotent hints) inferred from HTTP semantics, overridable via thex-mcpextension 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
$refresolution; one-flagsecureDefaultsposture for untrusted specs - Multiple Input Sources -- Load from URL, file, YAML string, or JSON object
- Rich Metadata -- Authentication, servers, tags, deprecation, external docs,
x-frontmcpextension - Production Ready -- Full TypeScript support, validation, structured errors, 100% test coverage (enforced)
- Runtime Agnostic -- Works on Node and V8 isolates (Cloudflare Workers) alike
npm install mcp-from-openapi
# or
yarn add mcp-from-openapi
# or
pnpm add mcp-from-openapiimport { 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.
});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.
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() }] };
});
}| 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 |
- Node.js >= 20.0.0
- TypeScript >= 5.0 (for TypeScript users)
- Peer dependency:
zod@^4.0.0
Contributions are welcome! Start with the contributing guide; this project follows the Contributor Covenant. Bug reports and feature requests go through the issue templates.
Report vulnerabilities privately — see the
security policy.
When loading untrusted specs, use secureDefaults: true.