ScavioScavio
Pricing
Tools
Sign InsGet Startedg
  1. Home
  2. Tutorials
  3. How to Generate an MCP Server from an OpenAPI Spec
Tutorial

How to Generate an MCP Server from an OpenAPI Spec

Auto-generate an MCP server from any OpenAPI spec. Give AI agents typed tool access to REST APIs in minutes, not days. With Python and JavaScript code.

Get Free API KeyAPI Docs

Generating an MCP server from an OpenAPI spec converts any documented REST API into a set of typed tools that AI agents can call directly, eliminating manual tool definition. Instead of writing MCP tool handlers by hand for each endpoint, you parse the OpenAPI JSON/YAML, extract operations, parameters, and response schemas, and generate a standards-compliant MCP server that Claude Code, Cursor, or any MCP client can consume. This tutorial builds a generator in Python that takes an OpenAPI 3.x spec and outputs a working MCP server.

Prerequisites

  • Python 3.10+
  • fastmcp library installed (pip install fastmcp)
  • An OpenAPI 3.x spec (JSON or YAML)
  • Scavio API key for testing with a real spec

Walkthrough

Step 1: Parse the OpenAPI spec

Load and parse an OpenAPI 3.x spec file, extracting all operations with their paths, methods, parameters, and request bodies.

Python
import json, yaml
from pathlib import Path

def parse_openapi(spec_path):
    content = Path(spec_path).read_text()
    spec = yaml.safe_load(content) if spec_path.endswith(('.yml', '.yaml')) else json.loads(content)
    operations = []
    for path, methods in spec.get('paths', {}).items():
        for method, details in methods.items():
            if method in ('get', 'post', 'put', 'patch', 'delete'):
                op = {
                    'operation_id': details.get('operationId', f'{method}_{path}'.replace('/', '_')),
                    'summary': details.get('summary', ''),
                    'method': method.upper(),
                    'path': path,
                    'parameters': details.get('parameters', []),
                    'request_body': details.get('requestBody', {}),
                }
                operations.append(op)
    print(f'Parsed {len(operations)} operations from {spec_path}')
    return spec, operations

spec, ops = parse_openapi('openapi.json')

Step 2: Generate MCP tool definitions

Convert each OpenAPI operation into an MCP tool with typed parameters and descriptions.

Python
def openapi_type_to_python(schema):
    type_map = {'string': 'str', 'integer': 'int', 'number': 'float',
                'boolean': 'bool', 'array': 'list', 'object': 'dict'}
    return type_map.get(schema.get('type', 'string'), 'str')

def generate_tool_code(op, base_url):
    params = []
    for p in op['parameters']:
        ptype = openapi_type_to_python(p.get('schema', {}))
        default = f' = None' if not p.get('required') else ''
        params.append(f"{p['name']}: {ptype}{default}")

    body_params = []
    if op['request_body']:
        content = op['request_body'].get('content', {})
        json_schema = content.get('application/json', {}).get('schema', {})
        for prop, schema in json_schema.get('properties', {}).items():
            ptype = openapi_type_to_python(schema)
            required = prop in json_schema.get('required', [])
            default = '' if required else ' = None'
            body_params.append(f"{prop}: {ptype}{default}")

    all_params = ', '.join(params + body_params)
    name = op['operation_id'].replace('-', '_').replace('.', '_')
    return name, all_params, op['summary']

Step 3: Build the MCP server file

Generate a complete MCP server Python file that registers all tools and handles HTTP requests to the underlying API.

Python
def generate_mcp_server(spec, operations, base_url, output_path='generated_mcp.py'):
    lines = [
        'import httpx',
        'from fastmcp import FastMCP',
        '',
        f'mcp = FastMCP("Generated API")',
        f'BASE_URL = "{base_url}"',
        '',
    ]
    for op in operations:
        name, params, summary = generate_tool_code(op, base_url)
        lines.append(f'@mcp.tool(description="{summary}")')
        lines.append(f'async def {name}({params}) -> dict:')
        lines.append(f'    async with httpx.AsyncClient() as client:')
        if op['method'] == 'GET':
            lines.append(f'        resp = await client.get(f"{{BASE_URL}}{op["path"]}")')
        else:
            lines.append(f'        resp = await client.{op["method"].lower()}(f"{{BASE_URL}}{op["path"]}", json=locals())')
        lines.append(f'        return resp.json()')
        lines.append('')

    Path(output_path).write_text('\n'.join(lines))
    print(f'Generated MCP server with {len(operations)} tools at {output_path}')

generate_mcp_server(spec, ops, 'https://api.example.com')

Step 4: Test with the Scavio OpenAPI spec

Fetch the Scavio API spec using search and generate an MCP server from it as a working example.

Python
import requests, os

# Use Scavio search to find OpenAPI specs for testing
H = {'Authorization': 'Bearer ' + os.environ['SCAVIO_API_KEY'], 'Content-Type': 'application/json'}
data = requests.post('https://api.scavio.dev/api/v2/google',
    headers=H, json={'query': 'petstore openapi 3.0 json spec', 'gl': 'us'}).json()

print('Found specs to test with:')
for r in data.get('organic_results', [])[:3]:
    print(f"  {r.get('title', '')}: {r.get('link', '')}")

# Example: generate from the classic Petstore spec
# spec, ops = parse_openapi('petstore.json')
# generate_mcp_server(spec, ops, 'https://petstore3.swagger.io/api/v3')

Python Example

Python
import json, yaml, httpx, os, requests
from pathlib import Path

def parse_openapi(spec_path):
    content = Path(spec_path).read_text()
    spec = yaml.safe_load(content) if spec_path.endswith(('.yml', '.yaml')) else json.loads(content)
    ops = []
    for path, methods in spec.get('paths', {}).items():
        for method, details in methods.items():
            if method in ('get', 'post', 'put', 'patch', 'delete'):
                ops.append({
                    'id': details.get('operationId', f'{method}_{path}'.replace('/', '_')),
                    'summary': details.get('summary', ''),
                    'method': method.upper(), 'path': path,
                    'parameters': details.get('parameters', []),
                    'body': details.get('requestBody', {}),
                })
    return spec, ops

def generate_server(spec, ops, base_url, out='generated_mcp.py'):
    type_map = {'string': 'str', 'integer': 'int', 'number': 'float', 'boolean': 'bool'}
    lines = ['import httpx', 'from fastmcp import FastMCP', '',
             'mcp = FastMCP("Generated API")', f'BASE = "{base_url}"', '']
    for op in ops:
        name = op['id'].replace('-', '_').replace('.', '_')
        params = []
        for p in op['parameters']:
            pt = type_map.get(p.get('schema', {}).get('type', 'string'), 'str')
            params.append(f"{p['name']}: {pt}")
        sig = ', '.join(params)
        lines.extend([
            f'@mcp.tool(description="{op["summary"]}")',
            f'async def {name}({sig}) -> dict:',
            f'    async with httpx.AsyncClient() as c:',
            f'        r = await c.request("{op["method"]}", f"{{BASE}}{op["path"]}")',
            f'        return r.json()', ''
        ])
    Path(out).write_text('\n'.join(lines))
    print(f'Generated {len(ops)} MCP tools to {out}')

# Example usage
# spec, ops = parse_openapi('openapi.json')
# generate_server(spec, ops, 'https://api.example.com')
print('MCP generator ready. Pass any OpenAPI 3.x spec.')

JavaScript Example

JavaScript
const fs = require('fs');

function parseOpenAPI(specPath) {
  const spec = JSON.parse(fs.readFileSync(specPath, 'utf-8'));
  const ops = [];
  for (const [path, methods] of Object.entries(spec.paths || {})) {
    for (const [method, details] of Object.entries(methods)) {
      if (['get', 'post', 'put', 'patch', 'delete'].includes(method)) {
        ops.push({
          id: details.operationId || `${method}_${path.replace(/\//g, '_')}`,
          summary: details.summary || '',
          method: method.toUpperCase(), path,
          parameters: details.parameters || [],
        });
      }
    }
  }
  return {spec, ops};
}

function generateServer(spec, ops, baseUrl, out = 'generated_mcp.mjs') {
  let code = `import {FastMCP} from 'fastmcp';\nconst mcp = new FastMCP('Generated API');\nconst BASE = '${baseUrl}';\n\n`;
  for (const op of ops) {
    const name = op.id.replace(/[-. ]/g, '_');
    const params = op.parameters.map(p => `${p.name}: {type: 'string'}`).join(', ');
    code += `mcp.addTool({name: '${name}', description: '${op.summary}',\n  parameters: {${params}},\n  execute: async (args) => {\n    const r = await fetch(\`\${BASE}${op.path}\`, {method: '${op.method}'});\n    return JSON.stringify(await r.json());\n  }\n});\n\n`;
  }
  fs.writeFileSync(out, code);
  console.log(`Generated ${ops.length} MCP tools to ${out}`);
}

// const {spec, ops} = parseOpenAPI('openapi.json');
// generateServer(spec, ops, 'https://api.example.com');
console.log('MCP generator ready');

Expected Output

JSON
Parsed 12 operations from openapi.json
Generated MCP server with 12 tools at generated_mcp.py
Tools: get_users, post_users, get_users_by_id, put_users_by_id, ...

Related Tutorials

    Frequently Asked Questions

    Most developers complete this tutorial in 15 to 30 minutes. You will need a Scavio API key (free tier works) and a working Python or JavaScript environment.

    Python 3.10+. fastmcp library installed (pip install fastmcp). An OpenAPI 3.x spec (JSON or YAML). Scavio API key for testing with a real spec. A Scavio API key gives you 50 free credits on signup.

    Yes. The free tier includes 50 credits on signup, which is more than enough to complete this tutorial and prototype a working solution.

    Scavio has a native LangChain package (langchain-scavio), an MCP server, and a plain REST API that works with any HTTP client. This tutorial uses the raw REST API, but you can adapt to your framework of choice.

    Related Resources

    Best Of

    Best Financial Data MCP Servers in May 2026

    Read more
    Comparison

    MCP Search Integration vs Direct API Integration

    Read more
    Best Of

    Best MCP Search Server in 2026

    Read more
    Comparison

    Tavily vs Scavio

    Read more
    Glossary

    Subscription vs Pay-as-You-Go API Model

    Read more
    Glossary

    TikTok Unofficial API

    Read more

    Start Building

    Auto-generate an MCP server from any OpenAPI spec. Give AI agents typed tool access to REST APIs in minutes, not days. With Python and JavaScript code.

    Get Free API KeyRead the Docs
    ScavioScavio

    One scraper API for every social, search, e-commerce and real estate platform. Built for AI agents.

    Product

    • Features
    • Pricing
    • Dashboard
    • Affiliates

    Developers

    • Documentation
    • API Reference
    • Quickstart
    • MCP Integration
    • Python SDK

    Alternatives

    • Tavily Alternative
    • SerpAPI Alternative
    • Firecrawl Alternative
    • Exa Alternative
    • Serper Alternative
    • Tavily vs Scavio
    • SerpAPI vs Scavio
    • All alternatives
    • Compare Scavio vs alternatives

    Search APIs

    • Google Search API
    • Amazon Product API
    • YouTube API
    • Reddit API
    • Walmart Product API
    • TikTok API
    • Instagram API

    Tools

    • All Tools

    © 2026 Scavio. All rights reserved.

    Featured on TAAFT
    Terms of ServicePrivacy Policy