---
title: OpenAPI Integration
sidebarTitle: OpenAPI
description: Generate MCP servers from OpenAPI specs
icon: code-branch
---
import { VersionBadge } from '/snippets/version-badge.mdx'

<VersionBadge version="2.0.0" />

FastMCP can automatically generate an MCP server from an OpenAPI specification. Users only need to provide an OpenAPI specification (3.0 or 3.1) and an API client.

```python
import httpx
from fastmcp import FastMCP

# Create a client for your API
api_client = httpx.AsyncClient(base_url="https://api.example.com")

# Load your OpenAPI spec
spec = {...} 

# Create an MCP server from your OpenAPI spec
mcp = FastMCP.from_openapi(openapi_spec=spec, client=api_client)

if __name__ == "__main__":
    mcp.run()
```

## Configuration Options

### Timeout

You can set a timeout for all requests by providing a `timeout` parameter (in seconds):

```python
mcp = FastMCP.from_openapi(
    openapi_spec=spec, 
    client=api_client,
    timeout=30.0  # 30 second timeout
)
```

### Component Naming

<VersionBadge version="2.5.0" />

You can customize how FastMCP names the components generated from your OpenAPI spec:

```python
# Custom naming function
def my_component_namer(route, mcp_type, default_name):
    # Create custom names based on the route and component type
    if route.operation_id:
        return route.operation_id
    
    # For example, prefix with component type
    prefix = {
        MCPType.TOOL: "tool_",
        MCPType.RESOURCE: "resource_",
        MCPType.RESOURCE_TEMPLATE: "template_",
    }.get(mcp_type, "")
    
    path_name = route.path.replace("/", "_").strip("_")
    return f"{prefix}{path_name}"

mcp = FastMCP.from_openapi(
    openapi_spec=spec,
    client=api_client,
    component_namer=my_component_namer
)
```

By default, FastMCP generates component names as follows:

- If the route has an `operationId` in the OpenAPI spec, that is used
- Otherwise, the name is generated from the route path:
  - For `GET` routes mapped to resources: Just the resource name (e.g., `/users` → `users`)
  - For routes with path parameters mapped to templates: The path with parameter names (e.g., `/users/{id}` → `users_id`)
  - For other methods mapped to tools: Method + resource name (e.g., `POST /users` → `post_users`)

#### Handling Name Collisions

When multiple routes would generate the same component name, FastMCP automatically appends a number suffix to ensure uniqueness (e.g., `users`, `users_2`, `users_3`). You'll see these numbered suffixes in the component names returned by `get_tools()`, `get_resources()`, etc.

If you need more control over naming, you can provide a custom `component_namer` function that handles potential collisions in your own way.

### Route Mapping

By default, OpenAPI routes are mapped to MCP components based on these rules:

| OpenAPI Route | Example |MCP Component | Notes |
|- | - | - | - |
| `GET` without path params | `GET /stats` | Resource | Simple resources for fetching data |
| `GET` with path params | `GET /users/{id}` | Resource Template | Path parameters become template parameters |
| `POST`, `PUT`, `PATCH`, `DELETE`, etc. | `POST /users` | Tool | Operations that modify data |

Internally, FastMCP uses a priority-ordered set of `RouteMap` objects to determine the component type. Route maps indicate that a specific HTTP method (or methods) and path pattern should be treated as a specific component type. This is the default set of route maps:

```python
# Simplified version of the actual mapping rules
DEFAULT_ROUTE_MAPPINGS = [
    # GET with path parameters -> ResourceTemplate
    RouteMap(
        methods=["GET"], 
        pattern=r".*\{.*\}.*", 
        mcp_type=MCPType.RESOURCE_TEMPLATE,
    ),
    
    # GET without path parameters -> Resource
    RouteMap(
        methods=["GET"], 
        pattern=r".*", 
        mcp_type=MCPType.RESOURCE,
    ),
    
    # All other methods -> Tool
    ALL_TOOLS(),
]
```

#### Custom Route Maps

Users can add custom route maps to override the default mapping behavior. User-supplied route maps are always applied first, before the default route maps.

```python
from fastmcp.server.openapi import RouteMap, MCPType

# Custom mapping rules
custom_maps = [
    # Force all analytics endpoints to be Tools
    RouteMap(methods=["GET"], 
             pattern=r"^/analytics/.*", 
             mcp_type=MCPType.TOOL)
]

# Apply custom mappings
mcp = FastMCP.from_openapi(
    openapi_spec=spec,
    client=api_client,
    route_maps=custom_maps
)
```

<Info>
For backward compatibility, FastMCP still supports the `route_type` parameter and `RouteType` enum, but they are deprecated and will be removed in a future version. You will see deprecation warnings if you use them.
</Info>

#### All Routes as Tools

When building AI agent backends, it's often useful to treat all routes as callable tools regardless of their HTTP method. You can use the `ALL_TOOLS()` shortcut or create a custom route map:

```python
# Make all endpoints tools using the shortcut
mcp = FastMCP.from_openapi(
    openapi_spec=spec,
    client=api_client,
    route_maps=[ALL_TOOLS()]
)

# Same effect using a custom route map
mcp = FastMCP.from_openapi(
    openapi_spec=spec,
    client=api_client,
    route_maps=[
        RouteMap(methods="*", pattern=r".*", mcp_type=MCPType.TOOL)
    ]
)
```

#### Excluding Routes

If you want to exclude certain routes from being converted to MCP components, you can map them to `MCPType.EXCLUDE`. This is useful for endpoints that should not be accessible to the agent.

```python
from fastmcp.server.openapi import RouteMap, MCPType

# Custom mapping rules to exclude specific routes
custom_maps = [
    # Exclude all admin endpoints
    RouteMap(
        methods="*", 
        pattern=r"^/admin/.*", 
        mcp_type=MCPType.EXCLUDE
    ),
    # Exclude analytics GET endpoints
    RouteMap(
        methods=["GET"], 
        pattern=r"^/analytics/.*", 
        mcp_type=MCPType.EXCLUDE
    )
]

# Apply custom mappings
mcp = FastMCP.from_openapi(
    openapi_spec=spec,
    client=api_client,
    route_maps=custom_maps
)
```

When a route is mapped to `MCPType.EXCLUDE`, FastMCP will log its presence but won't create any MCP component for it, effectively making it invisible to clients and agents using the MCP server.

You can customize this behavior by providing a list of `RouteMap` objects:

```python
from fastmcp.server.openapi import FastMCPOpenAPI, RouteMap, MCPType

# Custom route mappings
custom_mappings = [
    # Convert all user-related routes to tools
    RouteMap(
        methods=["GET", "POST", "PUT", "DELETE"],
        pattern=r"^/users.*",
        mcp_type=MCPType.TOOL
    ),
    # Exclude analytics routes
    RouteMap(
        methods=["*"],  # All methods
        pattern=r"^/analytics.*",
        mcp_type=MCPType.EXCLUDE
    ),
]

# Create server with custom mappings
mcp = FastMCPOpenAPI(
    openapi_spec=spec,
    client=httpx.AsyncClient(),
    route_maps=custom_mappings,
)
```

#### Route Map Shortcuts

<VersionBadge version="2.5.0" />

FastMCP provides several shortcut functions to create common route maps more easily:

```python
from fastmcp.server.openapi import (
    ALL_TOOLS,
    EXCLUDE_ALL,
    EXCLUDE_PATTERN,
    PATTERN_AS_TOOLS,
)

# Create an MCP server with custom route maps using shortcuts
mcp = FastMCP.from_openapi(
    openapi_spec=spec,
    client=api_client,
    route_maps=[
        # First exclude all admin endpoints
        EXCLUDE_PATTERN(r"^/admin/.*"),
        
        # Make all /api/v1 endpoints tools
        PATTERN_AS_TOOLS(r"^/api/v1/.*"),
        
        # Make all remaining routes tools
        ALL_TOOLS(),
    ]
)
```

Available shortcuts:

| Shortcut Function | Description |
|------------------|-------------|
| `ALL_TOOLS()` | Converts all matching routes to tools |
| `EXCLUDE_ALL()` | Excludes all matching routes from being converted to any component |
| `PATTERN_AS_TOOLS(pattern)` | Converts routes matching a specific pattern to tools |
| `EXCLUDE_PATTERN(pattern)` | Excludes routes matching a specific pattern |

These shortcuts are particularly useful for:

1. Converting all remaining unmatched routes to tools (use `ALL_TOOLS()`)
2. Excluding whole sections of your API (use `EXCLUDE_PATTERN("/path/.*")`)
3. Converting routes matching specific patterns to tools (use `PATTERN_AS_TOOLS("/path/.*")`)

<Tip>
You can use `EXCLUDE_ALL()` as the last entry in your custom route maps to completely ignore the default route maps. Since custom route maps are applied first and default maps are appended afterward, having `EXCLUDE_ALL()` at the end of your custom maps will match any routes that your earlier custom rules didn't match, preventing the default maps from having any effect.

```python
# Create server that only uses custom route maps, ignoring defaults
mcp = FastMCP.from_openapi(
    openapi_spec=spec,
    client=api_client,
    route_maps=[
        # Routes to keep as tools
        PATTERN_AS_TOOLS(r"^/api/v1/.*"),
        
        # Exclude everything else (ignores default route maps)
        EXCLUDE_ALL(),
    ]
)
```
</Tip>

## How It Works

1. FastMCP parses your OpenAPI spec to extract routes and schemas
2. It applies mapping rules to categorize each route
3. When an MCP client calls a tool or accesses a resource:
   - FastMCP constructs an HTTP request based on the OpenAPI definition
   - It sends the request through the provided httpx client
   - It translates the HTTP response to the appropriate MCP format

### Request Parameter Handling

FastMCP carefully handles different types of parameters in OpenAPI requests:

#### Query Parameters

By default, FastMCP will only include query parameters that have non-empty values. Parameters with `None` values or empty strings (`""`) are automatically filtered out of requests. This ensures that API servers don't receive unnecessary empty parameters that might cause issues.

For example, if you call a tool with these parameters:
```python
await client.call_tool("search_products", {
    "category": "electronics",  # Will be included
    "min_price": 100,           # Will be included
    "max_price": None,          # Will be excluded
    "brand": "",                # Will be excluded
})
```

The resulting HTTP request will only include `category=electronics&min_price=100`.

#### Path Parameters

For path parameters, which are typically required by REST APIs, FastMCP filters out `None` values and checks that all required path parameters are provided. If a required path parameter is missing or `None`, an error will be raised.

```python
# This will work
await client.call_tool("get_product", {"product_id": 123})

# This will raise ValueError: "Missing required path parameters: {'product_id'}"
await client.call_tool("get_product", {"product_id": None})
```

## Example: Custom Authentication

If your API requires authentication, you can set headers on the client:

```python
import httpx
from fastmcp import FastMCP

# Create a client with authentication
api_client = httpx.AsyncClient(
    base_url="https://api.example.com",
    headers={"Authorization": "Bearer YOUR_TOKEN"}
)

# Create an MCP server from your OpenAPI spec
mcp = FastMCP.from_openapi(openapi_spec=spec, client=api_client)
```
