How to Dynamically Create MCP Servers with FastMCP

How to Dynamically Create MCP Servers with FastMCP

MCP has gained a huge amount of popularity. And for good reason, it's easy to use and can allow you to really harness the benefits of LLMs. So here's a quick MCP tip!

Dynamically create MCP servers with FastMCP by passing a REST API's OpenAPI schema to the from_openapi function.

The example below builds a NetBox MCP with full read/write access, DELETE endpoint exclusion, and schema caching:

# /// script
# requires-python = ">=3.10"
# dependencies = ["httpx", "python-dotenv", "fastmcp"]
# ///

import os
import json
from pathlib import Path

import httpx
from dotenv import load_dotenv
from fastmcp import FastMCP
from fastmcp.server.providers.openapi import RouteMap, MCPType

load_dotenv()

NETBOX_URL = os.environ["NETBOX_URL"]
NETBOX_TOKEN = os.environ["NETBOX_TOKEN"]
SCHEMA_CACHE = Path(__file__).parent / "netbox_schema.json"

auth_headers = {"Authorization": f"Token {NETBOX_TOKEN}"}

# Authenticated client for the NetBox API
client = httpx.AsyncClient(
    base_url=f"{NETBOX_URL}",
    headers=auth_headers,
    timeout=120,
)

# Load the OpenAPI schema from the cache file if it exists
if SCHEMA_CACHE.exists():
    openapi_spec = json.loads(SCHEMA_CACHE.read_text())
else:
    # Fetch the OpenAPI schema from NetBox and cache it
    openapi_spec = httpx.get(
        f"{NETBOX_URL}/api/schema/?format=json",
        headers=auth_headers,
        timeout=120,
    )
    openapi_spec.raise_for_status()
    SCHEMA_CACHE.write_text(json.dumps(openapi_spec.json()))


# Build the MCP server, excluding every DELETE endpoint
mcp = FastMCP.from_openapi(
    openapi_spec=openapi_spec,
    client=client,
    name="NetBox MCP",
    route_maps=[
        RouteMap(methods=["DELETE"], mcp_type=MCPType.EXCLUDE),
    ],
)

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

After saving the above as server.py and setting your NetBox URL and Token in .env, simply run:

uv run server.py

Subscribe to our newsletter and stay updated.

Don't miss anything. Get all the latest posts delivered straight to your inbox.
Great! Check your inbox and click the link to confirm your subscription.
Error! Please enter a valid email address!