Convert OpenAPI/Swagger specifications into Model Context Protocol (MCP) tool definitions with automatic parameter conflict resolution and HTTP request mapping.
Converts OpenAPI specifications (v3.0.x or v3.1.x) into Model Context Protocol (MCP) tool definitions. This skill automatically resolves parameter naming conflicts, generates JSON schemas, and provides explicit HTTP request mappers for seamless API integration.
When building MCP servers from REST APIs, you need to convert OpenAPI specs into MCP tool definitions. This skill uses the `mcp-from-openapi` library to:
1. Load OpenAPI specifications from URLs, files, YAML, or JSON
2. Automatically detect and resolve parameter naming conflicts (e.g., `id` in path vs body)
3. Generate complete input schemas combining all parameters (path, query, header, body)
4. Extract output schemas from API responses
5. Create explicit parameter mappers showing how to construct HTTP requests
6. Include authentication, server, and metadata information
Before using this skill, install the required dependency:
```bash
npm install mcp-from-openapi
```
For TypeScript projects, ensure you have TypeScript 5.3+ installed.
Identify what the user needs:
Use the appropriate factory method based on the source:
**From URL:**
```typescript
import { OpenAPIToolGenerator } from 'mcp-from-openapi';
const generator = await OpenAPIToolGenerator.fromURL('https://api.example.com/openapi.json');
```
**From File:**
```typescript
const generator = await OpenAPIToolGenerator.fromFile('./openapi.yaml');
```
**From YAML String:**
```typescript
const yamlString = `openapi: 3.0.0...`;
const generator = await OpenAPIToolGenerator.fromYAML(yamlString);
```
**From JSON Object:**
```typescript
const spec = { openapi: '3.0.0', /* ... */ };
const generator = await OpenAPIToolGenerator.fromJSON(spec);
```
Before generating tools, validate the OpenAPI document:
```typescript
const validation = await generator.validate();
if (!validation.valid) {
console.error('Validation errors:', validation.errors);
throw new Error('Invalid OpenAPI specification');
}
```
Determine the appropriate options based on requirements:
```typescript
const options = {
// Filter specific operations
includeOperations: ['getUser', 'createUser'], // or excludeOperations
// Custom filter function
filterFn: (op) => op.method === 'get', // op has path and method
// Include/exclude deprecated operations
includeDeprecated: false,
// Response handling
includeAllResponses: true, // Creates oneOf union for multiple status codes
preferredStatusCodes: [200, 201],
// Schema depth limit
maxSchemaDepth: 10,
// Custom naming strategy for conflicts
namingStrategy: {
conflictResolver: (paramName, location, index) => {
return `${location}${paramName.charAt(0).toUpperCase()}${paramName.slice(1)}`;
}
}
};
```
Generate all tools or a specific tool:
**All Tools:**
```typescript
const tools = await generator.generateTools(options);
```
**Specific Tool:**
```typescript
const tool = await generator.generateTool('/users/{id}', 'post', options);
```
Each tool contains:
```typescript
interface McpOpenAPITool {
name: string; // Operation ID or generated name
description: string; // From operation summary/description
inputSchema: JSONSchema7; // Combined schema for all parameters
outputSchema?: JSONSchema7; // Response schema (may be union type)
mapper: ParameterMapper[]; // Maps input keys to HTTP request parts
metadata: ToolMetadata; // Auth, servers, tags, etc.
}
```
The library automatically resolves naming conflicts:
**Problem:** Same parameter name in different locations
```yaml
paths:
/users/{id}:
post:
parameters:
- name: id
in: path
- name: id
in: query
requestBody:
properties:
id: string
```
**Solution:** Automatically renamed in input schema
```typescript
{
inputSchema: {
properties: {
pathId: { type: "string" }, // Renamed from "id"
queryId: { type: "string" }, // Renamed from "id"
bodyId: { type: "string" } // Renamed from "id"
}
},
mapper: [
{ inputKey: "pathId", type: "path", key: "id" },
{ inputKey: "queryId", type: "query", key: "id" },
{ inputKey: "bodyId", type: "body", key: "id" }
]
}
```
Use the mapper to construct HTTP requests:
```typescript
function buildRequest(tool: McpOpenAPITool, input: any) {
let path = tool.metadata.path;
const query = new URLSearchParams();
const headers: Record<string, string> = {};
let body: any;
tool.mapper.forEach((m) => {
const value = input[m.inputKey];
if (!value) return;
switch (m.type) {
case 'path':
path = path.replace(`{${m.key}}`, encodeURIComponent(value));
break;
case 'query':
query.set(m.key, value);
break;
case 'header':
headers[m.key] = value;
break;
case 'body':
if (!body) body = {};
body[m.key] = value;
break;
}
});
return {
url: `${tool.metadata.servers[0].url}${path}?${query}`,
method: tool.metadata.method,
headers,
body: body ? JSON.stringify(body) : undefined,
};
}
```
Register tools with an MCP server:
```typescript
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
const server = new Server(/* config */);
tools.forEach((tool) => {
server.setRequestHandler(tool.name, async (request) => {
const httpRequest = buildRequest(tool, request.params);
const response = await fetch(httpRequest.url, {
method: httpRequest.method,
headers: httpRequest.headers,
body: httpRequest.body,
});
return response.json();
});
});
```
Implement proper error handling:
```typescript
import { LoadError, ParseError, ValidationError, GenerationError } from 'mcp-from-openapi';
try {
const generator = await OpenAPIToolGenerator.fromURL(url);
const tools = await generator.generateTools();
} catch (error) {
if (error instanceof LoadError) {
console.error('Failed to load OpenAPI spec:', error.message);
} else if (error instanceof ParseError) {
console.error('Failed to parse OpenAPI spec:', error.message);
} else if (error instanceof ValidationError) {
console.error('Invalid OpenAPI specification:', error.errors);
} else if (error instanceof GenerationError) {
console.error('Tool generation failed:', error.message);
} else {
console.error('Unexpected error:', error);
}
}
```
When a user provides an OpenAPI spec and wants a full MCP server:
1. Load the spec using the appropriate method
2. Validate the specification
3. Generate all tools with `includeDeprecated: false`
4. Create request handlers for each tool
5. Set up authentication using `tool.metadata.security`
When user wants only specific HTTP methods (e.g., read-only GET operations):
```typescript
const tools = await generator.generateTools({
filterFn: (op) => op.method === 'get'
});
```
When API returns different schemas for different status codes:
```typescript
const tools = await generator.generateTools({
includeAllResponses: true, // Creates oneOf union
preferredStatusCodes: [200, 201, 204]
});
```
When testing against staging or custom endpoints:
```typescript
const generator = await OpenAPIToolGenerator.fromURL(url, {
baseUrl: 'https://staging.api.example.com'
});
```
When user wants runtime validation:
```typescript
import { zodSchema } from 'json-schema-to-zod';
const validatedTools = tools.map(tool => ({
...tool,
validateInput: zodSchema(tool.inputSchema),
validateOutput: tool.outputSchema ? zodSchema(tool.outputSchema) : null
}));
```
1. **Always dereference in production** - Use `dereference: true` to resolve all `$ref` pointers
2. **Validate before generating** - Catch spec issues early with `validate()`
3. **Handle authentication properly** - Check `tool.metadata.security` for auth requirements
4. **Use renamed parameter keys** - When conflicts occur, use the keys from `inputSchema`, not original names
5. **Implement rate limiting** - Protect your MCP server from abuse
6. **Cache generated tools** - Don't regenerate on every request
7. **Test with actual API** - Verify generated tools work with real endpoints
8. **Document renamed parameters** - Make it clear to users when parameters were renamed
Present the generated tools to the user in a clear, structured format:
1. **Summary:** Number of tools generated, operations included
2. **Tool List:** For each tool:
- Name and description
- HTTP method and path
- Input parameters (highlight any renamed parameters)
- Output schema summary
- Authentication requirements
3. **Code Examples:** Show how to use the tools in their MCP server
4. **Next Steps:** Guide on implementing request handlers and authentication
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/convert-openapi-to-mcp-tools/raw