mcp-from-openapi converts OpenAPI 3.0/3.1 specifications into MCP (Model Context Protocol) tool definitions. It handles parameter resolution, schema conversion, security configuration, SSRF-safe $ref dereferencing, and format-to-schema enrichment.
OpenAPI Spec (JSON/YAML/URL/File)
|
v
OpenAPIToolGenerator (src/generator.ts)
|-- initialize(): dereference $refs, then validate
|-- generateTools(): iterate paths/operations
|-- generateTool(): build a single McpOpenAPITool
|
|-- ParameterResolver (src/parameter-resolver.ts)
| resolves params + requestBody into inputSchema + mapper
|
|-- ResponseBuilder (src/response-builder.ts)
| builds outputSchema from responses
|
|-- Format Resolution (src/format-resolver.ts)
| enriches schemas with format constraints (optional)
|
v
McpOpenAPITool { name, description, inputSchema, outputSchema, mapper, metadata }
| File | Purpose |
|---|---|
src/generator.ts |
Main entry point. Factory methods (fromJSON, fromYAML, fromURL, fromFile), tool generation, SSRF protection, $ref dereferencing |
src/types.ts |
All type definitions, toJsonSchema() conversion, isReferenceObject() guard |
src/parameter-resolver.ts |
Resolves OpenAPI parameters + requestBody into flat inputSchema with conflict resolution |
src/response-builder.ts |
Builds outputSchema from OpenAPI responses with content-type and status code preferences |
src/format-resolver.ts |
Format-to-schema resolution. Built-in resolvers for uuid, date-time, email, int32, etc. |
src/schema-builder.ts |
Static utilities: merge, union, clone, flatten, simplify, withFormat, etc. |
src/security-resolver.ts |
Resolves security schemes (Bearer, Basic, Digest, API Key, OAuth2, OpenID Connect) |
src/validator.ts |
Validates OpenAPI document structure |
src/errors.ts |
Error class hierarchy: LoadError, ParseError, ValidationError, GenerationError, SchemaError |
src/index.ts |
Barrel file for public exports |
yarn test # Run all tests (unit + integration)
yarn test:unit # Run unit tests only
yarn test:integration # Run integration tests only
yarn test:coverage # Run tests with coverage report
yarn build # Build CJS + ESM + type declarations
yarn build:cjs # Build CommonJS output only
yarn build:esm # Build ESM output only
yarn build:types # Emit TypeScript declarations only
yarn clean # Remove dist/ and coverage/- Bundler: esbuild (separate CJS and ESM builds)
- Type declarations: tsc with
tsconfig.lib.json - Packages: external (not bundled into output) via
--packages=external - CJS output:
dist/index.js - ESM output:
dist/esm/index.mjs - Types:
dist/index.d.ts
- Framework: Jest 29 with SWC transformer (
@swc/jest) - Coverage provider: V8 (
coverageProvider: 'v8'in jest.config.js) - Coverage target: 100% statements, branches, functions, lines
- Unit tests:
src/__tests__/*.spec.ts(one per module) - Integration tests:
src/__tests__/integration.spec.ts(full pipeline, imports from entrypoint only) - Coverage exclusion:
src/index.ts(barrel file)
- Inline specs: Tests create OpenAPI spec objects directly (no fixture files)
- Mock fetch: URL loading tests mock
global.fetchwithjest.fn() - Temp files: File loading tests create temp files in
os.tmpdir(), clean up infinally - Spy on dereference: SSRF tests spy on
$RefParser.dereferenceto inspect options without making network calls c8 ignore next: Used for defensive branches unreachable through normal code paths (V8 coverage ignores)transformIgnorePatterns:@apidevtools/json-schema-ref-parseris ESM-only and must be transformed by SWC
@apidevtools/json-schema-ref-parser v15 is ESM-only. The project uses dynamic import() in generator.ts so it works from both CJS and ESM contexts. Jest transforms the package via transformIgnorePatterns in jest.config.js.
LoadOptions (factory methods)
-> constructor (normalizes defaults)
-> initialize()
-> $RefParser.dereference() [if dereference: true]
-> Validator.validate() [if validate: true]
GenerateOptions (generateTools/generateTool)
-> ParameterResolver(namingStrategy)
.resolve(operation, pathParams, security, includeSecurityInInput)
-> ResponseBuilder(preferredStatusCodes, includeAllResponses)
.build(responses)
-> resolveSchemaFormats(schema, resolvers) [if resolveFormats/formatResolvers set]
toJsonSchema()converts OpenAPI SchemaObject to JSON Schema (handles exclusiveMin/Max boolean-to-numeric conversion)- Schemas pass through
toJsonSchema()in both ParameterResolver and ResponseBuilder - Metadata is attached via
x-prefixed properties (x-parameter-location,x-status-code,x-content-type) - The
mapperarray maps inputSchema keys to their HTTP locations (path/query/header/body/cookie) - Security info lives on mapper entries (not on inputSchema unless
includeSecurityInInput: true) - Format resolution is a post-processing step applied to final inputSchema/outputSchema
- All docs live in
docs/folder docs/FORMAT_RESOLUTION.md— Format resolution feature docs (built-in resolvers, custom resolvers, standalone usage)
All links in README.md must use absolute GitHub URLs (not relative paths) because npm renders README on its own domain and relative links break. Use the format:
https://github.com/agentfront/mcp-from-openapi/blob/main/docs/<file>.md
When adding new docs or links to README, always use absolute URLs pointing to the main branch.