mcp-from-openapi 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,34 +1,31 @@
1
1
  # mcp-from-openapi
2
2
 
3
- > Production-ready TypeScript library for converting OpenAPI specifications into MCP (Model Context Protocol) tool
4
- > definitions
3
+ > Convert OpenAPI specifications into MCP tool definitions with automatic parameter conflict resolution
5
4
 
6
5
  [![npm version](https://badge.fury.io/js/mcp-from-openapi.svg)](https://www.npmjs.com/package/mcp-from-openapi)
7
6
  [![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-yellow.svg)](https://opensource.org/license/apache-2-0)
8
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.3-blue.svg)](https://www.typescriptlang.org/)
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
8
+ [![Node.js](https://img.shields.io/badge/Node.js-20+-green.svg)](https://nodejs.org/)
9
9
 
10
10
  ## What This Solves
11
11
 
12
- When converting OpenAPI specs to MCP tools, you encounter **parameter conflicts** - the same parameter name appears in
13
- different locations (path, query, body). This library automatically resolves these conflicts and provides an **explicit
14
- mapper** that tells you exactly how to construct HTTP requests.
12
+ 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.
15
13
 
16
14
  **The Problem:**
17
15
 
18
16
  ```yaml
19
- # OpenAPI spec
20
17
  paths:
21
18
  /users/{id}:
22
19
  post:
23
20
  parameters:
24
- - name: id # id in PATH
21
+ - name: id # path
25
22
  in: path
26
23
  requestBody:
27
24
  content:
28
25
  application/json:
29
26
  schema:
30
27
  properties:
31
- id: # id in BODY - CONFLICT!
28
+ id: # body -- CONFLICT!
32
29
  type: string
33
30
  ```
34
31
 
@@ -38,8 +35,8 @@ paths:
38
35
  {
39
36
  inputSchema: {
40
37
  properties: {
41
- pathId: { type: "string" }, // Automatically renamed!
42
- bodyId: { type: "string" } // Automatically renamed!
38
+ pathId: { type: "string" }, // Automatically renamed
39
+ bodyId: { type: "string" } // Automatically renamed
43
40
  }
44
41
  },
45
42
  mapper: [
@@ -49,17 +46,18 @@ paths:
49
46
  }
50
47
  ```
51
48
 
52
- Now you know **exactly** how to build the HTTP request!
49
+ Now you know exactly how to build the HTTP request.
53
50
 
54
51
  ## Features
55
52
 
56
- - 🎯 **Smart Parameter Handling** - Automatic conflict detection and resolution
57
- - 📦 **Complete Schemas** - Input schema combines all parameters, output schema from responses
58
- - 🔐 **Rich Metadata** - Authentication, servers, tags, deprecation status
59
- - 🔧 **Multiple Input Sources** - Load from URL, file, YAML string, or JSON object
60
- - ✅ **Production Ready** - Full TypeScript, validation, error handling, 80%+ test coverage
61
- - 🧩 **Zod Compatible** - Schemas ready for json-schema-to-zod conversion
62
- - 🚀 **MCP Native** - Designed specifically for Model Context Protocol integration
53
+ - **Smart Parameter Handling** -- Automatic conflict detection and resolution across path, query, header, cookie, and body
54
+ - **Complete Schemas** -- Input schema combines all parameters; output schema from responses (with oneOf unions)
55
+ - **Security Resolution** -- Framework-agnostic auth for Bearer, Basic, Digest, API Key, OAuth2, OpenID, mTLS, HMAC, AWS Sig V4
56
+ - **SSRF Prevention** -- Blocks internal IPs, localhost, and cloud metadata endpoints by default during `$ref` resolution
57
+ - **Multiple Input Sources** -- Load from URL, file, YAML string, or JSON object
58
+ - **Rich Metadata** -- Authentication, servers, tags, deprecation, external docs, `x-frontmcp` extension
59
+ - **Production Ready** -- Full TypeScript support, validation, structured errors, 80%+ test coverage
60
+ - **MCP Native** -- Designed specifically for Model Context Protocol integration
63
61
 
64
62
  ## Installation
65
63
 
@@ -73,594 +71,103 @@ pnpm add mcp-from-openapi
73
71
 
74
72
  ## Quick Start
75
73
 
76
- ### Basic Usage
77
-
78
74
  ```typescript
79
75
  import { OpenAPIToolGenerator } from 'mcp-from-openapi';
80
76
 
81
- // 1. Load OpenAPI spec
77
+ // Load an OpenAPI spec
82
78
  const generator = await OpenAPIToolGenerator.fromURL('https://api.example.com/openapi.json');
83
79
 
84
- // 2. Generate tools
80
+ // Generate MCP tools
85
81
  const tools = await generator.generateTools();
86
82
 
87
- // 3. Each tool has everything you need:
83
+ // Each tool has everything you need
88
84
  tools.forEach((tool) => {
89
- console.log(tool.name); // "createUser"
90
- console.log(tool.inputSchema); // Combined schema for all params
91
- console.log(tool.outputSchema); // Response schema
92
- console.log(tool.mapper); // How to build the HTTP request
93
- console.log(tool.metadata); // Auth, servers, tags, etc.
85
+ console.log(tool.name); // "createUser"
86
+ console.log(tool.inputSchema); // Combined schema for all params
87
+ console.log(tool.outputSchema); // Response schema
88
+ console.log(tool.mapper); // How to build the HTTP request
89
+ console.log(tool.metadata); // Auth, servers, tags, etc.
94
90
  });
95
91
  ```
96
92
 
97
- ### Loading from Different Sources
98
-
99
- ```typescript
100
- // From URL
101
- const generator = await OpenAPIToolGenerator.fromURL('https://api.example.com/openapi.json');
102
-
103
- // From file
104
- const generator = await OpenAPIToolGenerator.fromFile('./openapi.yaml');
105
-
106
- // From YAML string
107
- const yamlString = `
108
- openapi: 3.0.0
109
- info:
110
- title: My API
111
- version: 1.0.0
112
- paths:
113
- /users:
114
- get:
115
- responses:
116
- '200':
117
- description: Success
118
- `;
119
- const generator = await OpenAPIToolGenerator.fromYAML(yamlString);
120
-
121
- // From JSON object
122
- const openApiSpec = { openapi: '3.0.0' /* ... */ };
123
- const generator = await OpenAPIToolGenerator.fromJSON(openApiSpec);
124
- ```
125
-
126
- ### Understanding the Output
127
-
128
- Each generated tool includes:
129
-
130
- ```typescript
131
- interface McpOpenAPITool {
132
- name: string; // Operation ID or generated name
133
- description: string; // From operation summary/description
134
- inputSchema: JSONSchema7; // Combined input schema (all params)
135
- outputSchema?: JSONSchema7; // Response schema (can be union)
136
- mapper: ParameterMapper[]; // Input → Request mapping
137
- metadata: ToolMetadata; // Auth, servers, etc.
138
- }
139
- ```
140
-
141
- ### Using the Mapper
93
+ ## Using the Mapper
142
94
 
143
- The mapper tells you how to convert tool input into an HTTP request:
95
+ The mapper tells you how to convert tool inputs into an HTTP request:
144
96
 
145
97
  ```typescript
146
- function buildRequest(tool: McpOpenAPITool, input: any) {
98
+ function buildRequest(tool: McpOpenAPITool, input: Record<string, any>) {
147
99
  let path = tool.metadata.path;
148
100
  const query = new URLSearchParams();
149
101
  const headers: Record<string, string> = {};
150
- let body: any;
102
+ let body: Record<string, any> | undefined;
151
103
 
152
- tool.mapper.forEach((m) => {
104
+ for (const m of tool.mapper) {
153
105
  const value = input[m.inputKey];
154
- if (!value) return;
106
+ if (value === undefined) continue;
155
107
 
156
108
  switch (m.type) {
157
109
  case 'path':
158
110
  path = path.replace(`{${m.key}}`, encodeURIComponent(value));
159
111
  break;
160
112
  case 'query':
161
- query.set(m.key, value);
113
+ query.set(m.key, String(value));
162
114
  break;
163
115
  case 'header':
164
- headers[m.key] = value;
116
+ headers[m.key] = String(value);
165
117
  break;
166
118
  case 'body':
167
119
  if (!body) body = {};
168
120
  body[m.key] = value;
169
121
  break;
170
122
  }
171
- });
123
+ }
124
+
125
+ const baseUrl = tool.metadata.servers?.[0]?.url ?? '';
126
+ const qs = query.toString();
172
127
 
173
128
  return {
174
- url: `${tool.metadata.servers[0].url}${path}?${query}`,
175
- method: tool.metadata.method,
129
+ url: `${baseUrl}${path}${qs ? '?' + qs : ''}`,
130
+ method: tool.metadata.method.toUpperCase(),
176
131
  headers,
177
132
  body: body ? JSON.stringify(body) : undefined,
178
133
  };
179
134
  }
180
-
181
- // Example usage
182
- const request = buildRequest(tool, {
183
- pathId: 'user-123',
184
- bodyName: 'John Doe',
185
- bodyEmail: 'john@example.com',
186
- });
187
-
188
- const response = await fetch(request.url, {
189
- method: request.method,
190
- headers: request.headers,
191
- body: request.body,
192
- });
193
- ```
194
-
195
- ### Handling Parameter Conflicts
196
-
197
- When the same parameter name appears in different locations, the library automatically renames them:
198
-
199
- ```typescript
200
- // OpenAPI with conflicts:
201
- // - id in path
202
- // - id in query
203
- // - id in body
204
-
205
- const tool = await generator.generateTool('/users/{id}', 'post');
206
-
207
- // Generated input schema:
208
- {
209
- properties: {
210
- pathId: { type: "string" }, // Renamed!
211
- queryId: { type: "string" }, // Renamed!
212
- bodyId: { type: "string" } // Renamed!
213
- }
214
- }
215
-
216
- // Your input should use the renamed keys:
217
- const input = {
218
- pathId: "user-123", // Not "id"
219
- queryId: "track-456",
220
- bodyId: "internal-789"
221
- };
222
- ```
223
-
224
- ## Common Use Cases
225
-
226
- ### 1. Build an MCP Server
227
-
228
- ```typescript
229
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
230
- import { OpenAPIToolGenerator } from 'mcp-from-openapi';
231
-
232
- const server = new Server(/* ... */);
233
-
234
- // Load tools from OpenAPI
235
- const generator = await OpenAPIToolGenerator.fromURL('https://api.example.com/openapi.json');
236
- const tools = await generator.generateTools();
237
-
238
- // Register each tool
239
- tools.forEach((tool) => {
240
- server.setRequestHandler(tool.name, async (request) => {
241
- const httpRequest = buildRequest(tool, request.params);
242
- const response = await fetch(httpRequest.url, httpRequest);
243
- return response.json();
244
- });
245
- });
246
- ```
247
-
248
- ### 2. Filter Operations
249
-
250
- ```typescript
251
- // Only GET operations
252
- const tools = await generator.generateTools({
253
- filterFn: (op) => op.method === 'get', // op has path and method properties
254
- });
255
-
256
- // Specific operations by ID
257
- const tools = await generator.generateTools({
258
- includeOperations: ['getUser', 'createUser'],
259
- });
260
-
261
- // Exclude deprecated
262
- const tools = await generator.generateTools({
263
- includeDeprecated: false,
264
- });
265
- ```
266
-
267
- ### 3. Handle Multiple Response Codes
268
-
269
- ```typescript
270
- // Include all response status codes
271
- const tools = await generator.generateTools({
272
- includeAllResponses: true, // Creates oneOf union
273
- });
274
-
275
- // Or prefer specific codes only
276
- const tools = await generator.generateTools({
277
- preferredStatusCodes: [200, 201],
278
- includeAllResponses: false,
279
- });
280
- ```
281
-
282
- ### 4. Custom Base URL
283
-
284
- ```typescript
285
- const generator = await OpenAPIToolGenerator.fromURL(url, {
286
- baseUrl: 'https://staging.api.example.com',
287
- });
288
- ```
289
-
290
- ### 5. Validate Before Generating
291
-
292
- ```typescript
293
- const generator = await OpenAPIToolGenerator.fromFile('./openapi.yaml');
294
-
295
- const validation = await generator.validate();
296
- if (!validation.valid) {
297
- console.error('Validation errors:', validation.errors);
298
- throw new Error('Invalid OpenAPI spec');
299
- }
300
-
301
- const tools = await generator.generateTools();
302
- ```
303
-
304
- ### 6. Custom Naming Strategy
305
-
306
- ```typescript
307
- const tool = await generator.generateTool('/users/{id}', 'post', {
308
- namingStrategy: {
309
- conflictResolver: (paramName, location, index) => {
310
- // Custom naming logic
311
- return `${location.toUpperCase()}_${paramName}`;
312
- },
313
- },
314
- });
315
- ```
316
-
317
- ### 7. Integration with Zod
318
-
319
- ```typescript
320
- import { zodSchema } from 'json-schema-to-zod';
321
-
322
- const tools = await generator.generateTools();
323
-
324
- const validatedTools = tools.map((tool) => ({
325
- ...tool,
326
- validateInput: zodSchema(tool.inputSchema),
327
- validateOutput: tool.outputSchema ? zodSchema(tool.outputSchema) : null,
328
- }));
329
-
330
- // Use validators
331
- const validatedInput = validatedTools[0].validateInput.parse(userInput);
332
- ```
333
-
334
- ## API Reference
335
-
336
- ### OpenAPIToolGenerator
337
-
338
- #### Static Factory Methods
339
-
340
- ```typescript
341
- // Load from URL
342
- static async fromURL(url: string, options?: LoadOptions): Promise<OpenAPIToolGenerator>
343
-
344
- // Load from file path
345
- static async fromFile(filePath: string, options?: LoadOptions): Promise<OpenAPIToolGenerator>
346
-
347
- // Load from YAML string
348
- static async fromYAML(yaml: string, options?: LoadOptions): Promise<OpenAPIToolGenerator>
349
-
350
- // Load from JSON object
351
- static async fromJSON(json: object, options?: LoadOptions): Promise<OpenAPIToolGenerator>
352
- ```
353
-
354
- #### Instance Methods
355
-
356
- ```typescript
357
- // Generate all tools
358
- async generateTools(options?: GenerateOptions): Promise<McpOpenAPITool[]>
359
-
360
- // Generate a specific tool
361
- async generateTool(path: string, method: string, options?: GenerateOptions): Promise<McpOpenAPITool>
362
-
363
- // Get OpenAPI document
364
- getDocument(): OpenAPIDocument
365
-
366
- // Validate OpenAPI document
367
- async validate(): Promise<ValidationResult>
368
- ```
369
-
370
- ### Configuration Options
371
-
372
- #### LoadOptions
373
-
374
- ```typescript
375
- interface LoadOptions {
376
- dereference?: boolean; // Resolve $refs (default: true)
377
- baseUrl?: string; // Override base URL
378
- headers?: Record<string, string>; // Custom headers for URL loading
379
- timeout?: number; // Request timeout (default: 30000ms)
380
- validate?: boolean; // Validate document (default: true)
381
- followRedirects?: boolean; // Follow redirects (default: true)
382
- }
383
- ```
384
-
385
- #### GenerateOptions
386
-
387
- ```typescript
388
- interface GenerateOptions {
389
- includeOperations?: string[]; // Include only these operation IDs
390
- excludeOperations?: string[]; // Exclude these operation IDs
391
- filterFn?: (op: OperationWithContext) => boolean; // Custom filter (op has path and method)
392
- namingStrategy?: NamingStrategy; // Custom naming for conflicts
393
- preferredStatusCodes?: number[]; // Preferred response codes
394
- includeDeprecated?: boolean; // Include deprecated ops (default: false)
395
- includeAllResponses?: boolean; // Include all status codes (default: true)
396
- maxSchemaDepth?: number; // Max depth for schemas (default: 10)
397
- }
398
-
399
- // OperationWithContext extends OperationObject with:
400
- interface OperationWithContext extends OperationObject {
401
- path: string; // The API path
402
- method: string; // The HTTP method (get, post, etc.)
403
- }
404
- }
405
- ```
406
-
407
- #### NamingStrategy
408
-
409
- ```typescript
410
- interface NamingStrategy {
411
- conflictResolver: (paramName: string, location: ParameterLocation, index: number) => string;
412
-
413
- toolNameGenerator?: (path: string, method: HTTPMethod, operationId?: string) => string;
414
- }
415
- ```
416
-
417
- ### Types
418
-
419
- #### McpOpenAPITool
420
-
421
- ```typescript
422
- interface McpOpenAPITool {
423
- name: string;
424
- description: string;
425
- inputSchema: JSONSchema7;
426
- outputSchema?: JSONSchema7;
427
- mapper: ParameterMapper[];
428
- metadata: ToolMetadata;
429
- }
430
- ```
431
-
432
- #### ParameterMapper
433
-
434
- ```typescript
435
- interface ParameterMapper {
436
- inputKey: string; // Property name in input schema
437
- type: ParameterLocation; // 'path' | 'query' | 'header' | 'cookie' | 'body'
438
- key: string; // Original parameter name
439
- required?: boolean;
440
- style?: string;
441
- explode?: boolean;
442
- serialization?: SerializationInfo;
443
- }
444
- ```
445
-
446
- #### ToolMetadata
447
-
448
- ```typescript
449
- interface ToolMetadata {
450
- path: string;
451
- method: HTTPMethod;
452
- operationId?: string;
453
- tags?: string[];
454
- deprecated?: boolean;
455
- security?: SecurityRequirement[];
456
- servers?: ServerInfo[];
457
- responseStatusCodes?: number[];
458
- externalDocs?: ExternalDocumentation;
459
- }
460
- ```
461
-
462
- ## Error Handling
463
-
464
- ```typescript
465
- import { LoadError, ParseError, ValidationError, GenerationError } from 'mcp-from-openapi';
466
-
467
- try {
468
- const generator = await OpenAPIToolGenerator.fromURL(url);
469
- const tools = await generator.generateTools();
470
- } catch (error) {
471
- if (error instanceof LoadError) {
472
- console.error('Failed to load:', error.message);
473
- } else if (error instanceof ParseError) {
474
- console.error('Failed to parse:', error.message);
475
- } else if (error instanceof ValidationError) {
476
- console.error('Invalid spec:', error.errors);
477
- } else if (error instanceof GenerationError) {
478
- console.error('Generation failed:', error.message);
479
- }
480
- }
481
- ```
482
-
483
- ## Architecture
484
-
485
- ### System Overview
486
-
487
- The library follows a modular architecture with clear separation of concerns:
488
-
489
- ```
490
- OpenAPIToolGenerator (Main Entry Point)
491
- ├── Validator → OpenAPI document validation
492
- ├── ParameterResolver → Parameter conflict resolution & mapping
493
- ├── ResponseBuilder → Output schema generation
494
- └── SchemaBuilder → Schema manipulation utilities
495
- ```
496
-
497
- ### Data Flow
498
-
499
- ```
500
- User Input (URL/File/String/Object)
501
- ↓
502
- Load & Parse
503
- ↓
504
- OpenAPI Document
505
- ↓
506
- Validate (optional)
507
- ↓
508
- Dereference $refs (optional)
509
- ↓
510
- For Each Operation:
511
- ├── ParameterResolver → inputSchema + mapper
512
- ├── ResponseBuilder → outputSchema
513
- └── Metadata Extractor → metadata
514
- ↓
515
- McpOpenAPITool[]
516
- ```
517
-
518
- ### Core Components
519
-
520
- #### 1. OpenAPIToolGenerator
521
-
522
- - **Responsibility**: Entry point, orchestration, document management
523
- - **Key Methods**: Factory methods, generateTools(), validate()
524
-
525
- #### 2. ParameterResolver
526
-
527
- - **Responsibility**: Collect parameters, detect conflicts, generate mapper
528
- - **Algorithm**:
529
- 1. Collect all parameters by name from all sources
530
- 2. Detect naming conflicts
531
- 3. Apply naming strategy to resolve conflicts
532
- 4. Build combined input schema
533
- 5. Create mapper entries
534
-
535
- #### 3. ResponseBuilder
536
-
537
- - **Responsibility**: Extract response schemas, handle multiple status codes
538
- - **Features**:
539
- - Prefer specific status codes
540
- - Generate union types (oneOf) for multiple responses
541
- - Add metadata (status code, content type)
542
-
543
- #### 4. Validator
544
-
545
- - **Responsibility**: Validate OpenAPI document structure
546
- - **Checks**:
547
- - OpenAPI version (3.0.x or 3.1.x)
548
- - Required fields (info, paths, etc.)
549
- - Path parameters defined
550
- - Operation structure
551
-
552
- ### Design Patterns
553
-
554
- 1. **Factory Pattern** - For creating generator instances
555
- 2. **Strategy Pattern** - For parameter naming customization
556
- 3. **Builder Pattern** - For schema construction
557
- 4. **Template Method** - For tool generation workflow
558
-
559
- ### Extension Points
560
-
561
- 1. **Custom Naming Strategies** - Implement `NamingStrategy` interface
562
- 2. **Custom Filters** - Use `filterFn` in `GenerateOptions`
563
- 3. **Custom Validators** - Extend `Validator` class
564
- 4. **Schema Transformations** - Use `SchemaBuilder` utilities
565
-
566
- ## Best Practices
567
-
568
- ### 1. Always Dereference in Production
569
-
570
- ```typescript
571
- const generator = await OpenAPIToolGenerator.fromURL(url, {
572
- dereference: true, // Resolve all $refs for easier consumption
573
- });
574
- ```
575
-
576
- ### 2. Validate Before Generating
577
-
578
- ```typescript
579
- const validation = await generator.validate();
580
- if (!validation.valid) {
581
- throw new Error('Invalid OpenAPI spec');
582
- }
583
135
  ```
584
136
 
585
- ### 3. Cache Generated Tools
586
-
587
- ```typescript
588
- class ToolCache {
589
- private cache = new Map<string, McpOpenAPITool[]>();
137
+ ## Documentation
590
138
 
591
- async getTools(apiUrl: string): Promise<McpOpenAPITool[]> {
592
- if (this.cache has(apiUrl)) {
593
- return this.cache.get(apiUrl)!;
594
- }
595
-
596
- const generator = await OpenAPIToolGenerator.fromURL(apiUrl);
597
- const tools = await generator.generateTools();
598
- this.cache.set(apiUrl, tools);
599
-
600
- return tools;
601
- }
602
- }
603
- ```
604
-
605
- ### 4. Use TypeScript
606
-
607
- ```typescript
608
- import type { McpOpenAPITool, LoadOptions } from 'mcp-from-openapi';
609
-
610
- const options: LoadOptions = {
611
- dereference: true,
612
- validate: true,
613
- };
614
- ```
615
-
616
- ### 5. Handle Errors Properly
617
-
618
- ```typescript
619
- try {
620
- const tools = await generator.generateTools();
621
- } catch (error) {
622
- if (error instanceof ValidationError) {
623
- console.error('Validation errors:', error.errors);
624
- }
625
- // Handle appropriately
626
- }
627
- ```
628
-
629
- ## Examples
630
-
631
- Check the `examples/` directory for comprehensive examples including:
632
-
633
- 1. Basic usage
634
- 2. Parameter conflict resolution
635
- 3. Custom naming strategies
636
- 4. Multiple response handling
637
- 5. Authentication handling
638
- 6. Operation filtering
639
- 7. Zod integration
640
- 8. Request mapping
139
+ | Document | Description |
140
+ |----------|-------------|
141
+ | [Getting Started](https://github.com/agentfront/mcp-from-openapi/blob/main/docs/getting-started.md) | Loading specs, generating tools, building requests |
142
+ | [Configuration](https://github.com/agentfront/mcp-from-openapi/blob/main/docs/configuration.md) | LoadOptions, GenerateOptions, RefResolutionOptions |
143
+ | [Parameter Conflicts](https://github.com/agentfront/mcp-from-openapi/blob/main/docs/parameter-conflicts.md) | How conflict detection and resolution works |
144
+ | [Response Schemas](https://github.com/agentfront/mcp-from-openapi/blob/main/docs/response-schemas.md) | Output schemas, status codes, oneOf unions |
145
+ | [Security](https://github.com/agentfront/mcp-from-openapi/blob/main/docs/security.md) | SecurityResolver, all auth types, custom resolvers |
146
+ | [SSRF Prevention](https://github.com/agentfront/mcp-from-openapi/blob/main/docs/ssrf-prevention.md) | Ref resolution security, blocked IPs and hosts |
147
+ | [Format Resolution](https://github.com/agentfront/mcp-from-openapi/blob/main/docs/FORMAT_RESOLUTION.md) | Format-to-schema enrichment (uuid, date-time, email, int32, etc.) |
148
+ | [Naming Strategies](https://github.com/agentfront/mcp-from-openapi/blob/main/docs/naming-strategies.md) | Custom tool naming and conflict resolvers |
149
+ | [SchemaBuilder](https://github.com/agentfront/mcp-from-openapi/blob/main/docs/schema-builder.md) | JSON Schema utility methods |
150
+ | [Error Handling](https://github.com/agentfront/mcp-from-openapi/blob/main/docs/error-handling.md) | Error classes, context, and patterns |
151
+ | [x-frontmcp Extension](https://github.com/agentfront/mcp-from-openapi/blob/main/docs/x-frontmcp.md) | Custom OpenAPI extension for MCP annotations |
152
+ | [API Reference](https://github.com/agentfront/mcp-from-openapi/blob/main/docs/api-reference.md) | Complete types, interfaces, and exports |
153
+ | [Examples](https://github.com/agentfront/mcp-from-openapi/blob/main/docs/examples.md) | MCP server, Zod, filtering, security, and more |
154
+ | [Architecture](https://github.com/agentfront/mcp-from-openapi/blob/main/docs/architecture.md) | System overview, data flow, design patterns |
641
155
 
642
156
  ## Requirements
643
157
 
644
- - Node.js >= 18.0.0
158
+ - Node.js >= 20.0.0
645
159
  - TypeScript >= 5.0 (for TypeScript users)
646
-
647
- ## Dependencies
648
-
649
- - `@apidevtools/json-schema-ref-parser` - $ref dereferencing
650
- - `yaml` - YAML parsing
651
- - `undici` - Modern HTTP client
652
- - `json-schema` - Type definitions
160
+ - Peer dependency: `zod@^4.0.0`
653
161
 
654
162
  ## Contributing
655
163
 
656
- Contributions are welcome! Please see our contributing guidelines.
164
+ Contributions are welcome! Please see our [issues page](https://github.com/agentfront/mcp-from-openapi/issues).
657
165
 
658
166
  ## Related Projects
659
167
 
660
168
  - [Model Context Protocol](https://modelcontextprotocol.io/)
661
169
  - [OpenAPI Specification](https://www.openapis.org/)
662
- - [JSON Schema](https://json-schema.org/)
663
170
 
664
- ---
171
+ ## License
665
172
 
666
- **Made with ❤️ for the MCP community**
173
+ [Apache 2.0](https://github.com/agentfront/mcp-from-openapi/blob/main/LICENSE)