mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-24 22:44:17 +02:00
312 lines
9.3 KiB
Text
312 lines
9.3 KiB
Text
---
|
|
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
|
|
)
|
|
```
|
|
|
|
## Route Mapping
|
|
|
|
<VersionBadge version="2.5.0" />
|
|
|
|
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
|
|
|
|
|
|
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)
|
|
```
|