---
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.

## 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.

