ScavioScavio
ProductPricingDocs
Sign InGet Started
Blog
mcpopenapiswagger

Swagger to MCP Server: The Pattern Explained

Auto-generate MCP server tool definitions from OpenAPI specs. Each endpoint becomes a callable tool for your LLM.

May 14, 2026
8 min

Any API with an OpenAPI (Swagger) specification can be automatically converted into an MCP server. Each endpoint becomes a callable tool, path parameters become tool arguments, and response schemas define the output format. This pattern lets you expose any REST API to LLMs without writing tool definitions by hand.

How the pattern works

  1. Parse the OpenAPI spec (YAML or JSON)
  2. Extract each endpoint as a tool definition
  3. Map path/query parameters to tool input schema
  4. Generate the MCP server with HTTP call handlers
  5. Register authentication from environment variables

Step 1: Parse the OpenAPI spec

Python
import yaml, json

def load_spec(path):
    with open(path) as f:
        if path.endswith(".yaml") or path.endswith(".yml"):
            return yaml.safe_load(f)
        return json.load(f)

spec = load_spec("openapi.yaml")
base_url = spec.get("servers", [{}])[0].get("url", "http://localhost:8000")
paths = spec.get("paths", {})

Step 2: Generate tool definitions

Python
def spec_to_tools(spec):
    tools = []
    for path, methods in spec.get("paths", {}).items():
        for method, details in methods.items():
            if method not in ("get", "post", "put", "delete"):
                continue
            params = details.get("parameters", [])
            properties = {}
            required = []
            for p in params:
                properties[p["name"]] = {
                    "type": p.get("schema", {}).get("type", "string"),
                    "description": p.get("description", ""),
                }
                if p.get("required", False):
                    required.append(p["name"])

            # Handle request body for POST/PUT
            body = details.get("requestBody", {})
            if body:
                schema = body.get("content", {}).get(
                    "application/json", {}
                ).get("schema", {})
                for prop_name, prop_def in schema.get("properties", {}).items():
                    properties[prop_name] = prop_def
                required.extend(schema.get("required", []))

            tools.append({
                "name": details.get("operationId", f"{method}_{path}"),
                "description": details.get("summary", path),
                "method": method.upper(),
                "path": path,
                "input_schema": {
                    "type": "object",
                    "properties": properties,
                    "required": required,
                },
            })
    return tools

Step 3: Build the MCP server

Python
from mcp.server import Server
from mcp.types import TextContent
import requests, os

app = Server("openapi-bridge")

def make_handler(tool_def, base_url):
    async def handler(**kwargs):
        path = tool_def["path"]
        # Replace path parameters
        for key, value in kwargs.items():
            path = path.replace(" + key + ", str(value))

        url = f"{base_url}{path}"
        headers = {"Authorization": f"Bearer {os.environ.get('API_TOKEN', '')}"}

        if tool_def["method"] == "GET":
            resp = requests.get(url, headers=headers, params=kwargs)
        else:
            resp = requests.request(
                tool_def["method"], url, headers=headers, json=kwargs,
            )

        return [TextContent(type="text", text=resp.text)]
    return handler

# Register all tools from spec
spec = load_spec("openapi.yaml")
base_url = spec["servers"][0]["url"]
for tool_def in spec_to_tools(spec):
    handler = make_handler(tool_def, base_url)
    handler.__name__ = tool_def["name"]
    handler.__doc__ = tool_def["description"]
    app.tool()(handler)

Real-world example: search API

The Scavio search API has an OpenAPI spec. Converting it to MCP gives your LLM access to web search, TikTok search, and YouTube search as callable tools -- or you can skip the conversion and use the hosted MCP endpoint directly.

JSON
{
  "mcpServers": {
    "scavio": {
      "url": "https://mcp.scavio.dev/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}

Limitations of auto-generation

  • Complex authentication flows (OAuth2) need manual handling
  • Paginated endpoints need wrapper logic for multi-page fetching
  • Tool descriptions from Swagger summaries are often too terse for LLMs
  • Large APIs generate too many tools -- LLMs struggle with 50+ tools

Best practices

  • Filter to 5-15 most-used endpoints, not the entire API
  • Rewrite tool descriptions for LLM consumption (what it does, when to use it)
  • Group related endpoints into a single tool with an action parameter
  • Add error handling that returns human-readable messages

Continue reading

aeod2c

AEO Tracking for D2C Ecommerce Brands in 2026

6 min read
ai-agentscost-optimization

Agent Discovery vs Extraction: Why Cost Split Matters

6 min read
ScavioScavio

Real-time search API for AI agents. Search every platform, not just Google.

Product

  • Features
  • Pricing
  • Dashboard
  • Affiliates

Developers

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

Alternatives

  • Tavily Alternative
  • SerpAPI Alternative
  • Firecrawl Alternative
  • Exa Alternative

Tools

  • JSON Formatter
  • cURL to Code
  • Token Counter
  • All Tools

© 2026 Scavio. All rights reserved.

Featured on TAAFT
Terms of ServicePrivacy Policy