File size: 7,671 Bytes
0332908
 
 
 
 
 
 
 
 
9d6fa16
 
0332908
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
---
title: OpenAPI Integration
sidebarTitle: OpenAPI
description: Automatically create FastMCP servers from existing OpenAPI specifications.
icon: code-branch
---

If you have existing REST APIs documented with the OpenAPI Specification (OAS), FastMCP can automatically generate MCP tools, resources, and resource templates directly from that specification. This provides a quick way to make your existing HTTP APIs accessible to MCP clients and LLMs.

FastMCP supports both OpenAPI 3.0 and 3.1 specifications for maximum compatibility with existing API definitions.

## The Goal: API -> MCP Server

The core idea is to map OpenAPI paths and operations (like `GET /users/{id}` or `POST /orders`) to their corresponding MCP components:

-   `GET` requests often map to MCP **Resources** (for fetching single items) or **Resource Templates** (if the path has parameters).
-   `POST`, `PUT`, `PATCH`, `DELETE` requests typically map to MCP **Tools** (for actions that create or modify data).

FastMCP automates this mapping process.

## Creating from OpenAPI Spec

Use the `FastMCP.from_openapi()` class method. You need:

1.  The OpenAPI specification as a Python dictionary.
2.  An `httpx.AsyncClient` configured to make requests to the actual API backend.

<CodeGroup>

```python server.py
import asyncio
import httpx
from fastmcp import FastMCP

# load the OpenAPI specification from the openapi_spec.py file
petstore_spec = PETSTORE_SPEC

# Client to communicate with the actual Pet Store API backend
# The base_url should match the server URL in the OpenAPI spec
http_client = httpx.AsyncClient(base_url="http://petstore.example.com/api")

# Create the FastMCP server from the spec
# This is an async class method
async def create_openapi_server():
    mcp_server = await FastMCP.from_openapi(
        openapi_spec=petstore_spec,
        client=http_client,
        name="PetStoreMCP" # Optional name for the MCP server
    )
    return mcp_server

async def run_server():
    server = await create_openapi_server()
    print(f"Starting OpenAPI-based server '{server.name}'...")

    # List discovered components
    tools = await server.list_tools()
    resources = await server.list_resources()
    templates = await server.list_resource_templates()
    print("Discovered Tools:", [t.name for t in tools])
    print("Discovered Resources:", [r.uri for r in resources]) # Should be empty if no parameterless GETs
    print("Discovered Templates:", [t.uriTemplate for t in templates])

    # Run the server (e.g., via stdio)
    # server.run()

if __name__ == "__main__":
    # Example: Create the server and print discovered components
    # Requires httpx: uv pip install httpx
    asyncio.run(run_server())

# Expected Output might include:
# Discovered Tools: ['listPets', 'createPet']
# Discovered Resources: []
# Discovered Templates: ['resource://openapi/showPetById/{petId}']
```

```python openapi_spec.py
# Example OpenAPI Specification (simplified Pet Store)
PETSTORE_SPEC = {
    "openapi": "3.1.0",
    "info": {"title": "Simple Pet Store", "version": "1.0.0"},
    "servers": [{"url": "http://petstore.example.com/api"}], # Base URL for API calls
    "paths": {
        "/pets": {
            "get": {
                "summary": "List all pets",
                "operationId": "listPets",
                "tags": ["pets"],
                "parameters": [{ # Query parameter -> Tool argument
                    "name": "limit", "in": "query", "schema": {"type": "integer"}
                }],
                "responses": {"200": {"description": "A list of pets."}},
            },
            "post": { # POST -> Tool
                "summary": "Create a pet",
                "operationId": "createPet",
                "tags": ["pets"],
                "requestBody": { # Request body -> Tool arguments
                    "required": True,
                    "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PetInput"}}}
                },
                "responses": {"201": {"description": "Pet created."}},
            },
        },
        "/pets/{petId}": { # Path parameter -> Resource Template
            "get": { # GET with path param -> Resource Template / FunctionResource
                "summary": "Info for a specific pet",
                "operationId": "showPetById",
                "tags": ["pets"],
                "parameters": [{ # Path parameter -> Template function argument
                    "name": "petId", "in": "path", "required": True, "schema": {"type": "string"}
                }],
                "responses": {"200": {"description": "Information about the pet."}},
            },
        },
    },
    "components": {
        "schemas": {
            "PetInput": {"type": "object", "properties": {"name": {"type": "string"}, "tag": {"type": "string"}}},
        }
    }
}
``` 

</CodeGroup>

### How it Works Internally

1.  **Parsing**: `from_openapi` parses the spec using utilities that leverage `openapi-pydantic`. It extracts paths, operations, parameters, request bodies, and responses.
2.  **Mapping**: It applies mapping rules (see below) to decide whether each OpenAPI operation (`GET /pets`, `POST /pets`, `GET /pets/{petId}`) becomes an MCP `Tool`, `Resource`, or `ResourceTemplate`.
3.  **Component Creation**: It creates specialized internal components (`OpenAPITool`, `OpenAPIResource`, `OpenAPIResourceTemplate`).
4.  **HTTP Execution**: When an MCP client calls a tool or reads a resource from this server:
    *   The corresponding OpenAPI component constructs an HTTP request based on the OpenAPI definition and the arguments provided by the MCP client.
    *   It uses the provided `httpx.AsyncClient` to send the request to the backend API.
    *   It processes the HTTP response and returns it to the MCP client in the appropriate MCP format.
5.  **Schema Generation**: The schemas for MCP tools are derived by combining OpenAPI parameters (path, query, header) and request body schemas. Resource template function arguments are derived from path parameters.
6.  **Descriptions**: Tool/Resource descriptions are enhanced with information from OpenAPI responses to give the LLM more context about potential outcomes.

### Default Mapping Rules

FastMCP uses the following default rules to map OpenAPI operations:

-   `GET` operation with path parameters (e.g., `/users/{id}`) -> **`ResourceTemplate`**
-   `GET` operation without path parameters (e.g., `/users`) -> **`Resource`**
-   `POST`, `PUT`, `PATCH`, `DELETE`, `OPTIONS`, `HEAD` -> **`Tool`**

### Customize Route Mapping

You can customize the mapping rules by providing a list of `RouteMap` objects directly to `FastMCP.from_openapi()` using the `route_maps` parameter:

```python
from fastmcp.server.openapi import RouteMap, RouteType
from fastmcp import FastMCP

# Custom mapping: Treat GET /admin/stats as a Tool, not a Resource
custom_maps = [
    RouteMap(methods=["GET"], pattern=r"^/admin/stats$", route_type=RouteType.TOOL)
]

async def create_server_with_custom_mapping():
    mcp_server = await FastMCP.from_openapi(
        openapi_spec=petstore_spec,
        client=http_client,
        name="PetStoreMCP",
        route_maps=custom_maps  # Pass custom mapping rules
    )
    return mcp_server
```

Each `RouteMap` maps one or more HTTP methods and a regular expression pattern for the route path to an MCP `RouteType`. Route maps are processed in order, and the first match wins.

All parameters passed to `FastMCP.from_openapi()` will be forwarded to the underlying `FastMCPOpenAPI` constructor, so you can customize any aspect of the OpenAPI integration directly through this method call.