chore: import upstream snapshot with attribution
Upgrade checks / Notify on failure (push) Has been cancelled
Upgrade checks / Close issue on success (push) Has been cancelled
Schema Crash Test / Real-world schema crash test (232K schemas) (push) Has been cancelled
Run static analysis / static_analysis (push) Has been cancelled
Tests / Tests: Python 3.10 on ubuntu-latest (push) Has been cancelled
Tests / Tests: Python 3.13 on ubuntu-latest (push) Has been cancelled
Tests / Tests: Python 3.10 on windows-latest (push) Has been cancelled
Tests / Tests with lowest-direct dependencies (push) Has been cancelled
Tests / MCP conformance tests (push) Has been cancelled
Tests / Integration tests (push) Has been cancelled
Tests / Package install smoke (push) Has been cancelled
Upgrade checks / Static analysis (push) Has been cancelled
Upgrade checks / Tests: Python 3.10 on ubuntu-latest (push) Has been cancelled
Upgrade checks / Tests: Python 3.13 on ubuntu-latest (push) Has been cancelled
Upgrade checks / Tests: Python 3.10 on windows-latest (push) Has been cancelled
Upgrade checks / Integration tests (push) Has been cancelled
Update MCPServerConfig Schema / update-config-schema (push) Has been cancelled
Update SDK Documentation / update-sdk-docs (push) Has been cancelled
Upgrade checks / Notify on failure (push) Has been cancelled
Upgrade checks / Close issue on success (push) Has been cancelled
Schema Crash Test / Real-world schema crash test (232K schemas) (push) Has been cancelled
Run static analysis / static_analysis (push) Has been cancelled
Tests / Tests: Python 3.10 on ubuntu-latest (push) Has been cancelled
Tests / Tests: Python 3.13 on ubuntu-latest (push) Has been cancelled
Tests / Tests: Python 3.10 on windows-latest (push) Has been cancelled
Tests / Tests with lowest-direct dependencies (push) Has been cancelled
Tests / MCP conformance tests (push) Has been cancelled
Tests / Integration tests (push) Has been cancelled
Tests / Package install smoke (push) Has been cancelled
Upgrade checks / Static analysis (push) Has been cancelled
Upgrade checks / Tests: Python 3.10 on ubuntu-latest (push) Has been cancelled
Upgrade checks / Tests: Python 3.13 on ubuntu-latest (push) Has been cancelled
Upgrade checks / Tests: Python 3.10 on windows-latest (push) Has been cancelled
Upgrade checks / Integration tests (push) Has been cancelled
Update MCPServerConfig Schema / update-config-schema (push) Has been cancelled
Update SDK Documentation / update-sdk-docs (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,198 @@
|
||||
---
|
||||
title: "How to Create an MCP Server in Python"
|
||||
sidebarTitle: "Creating an MCP Server"
|
||||
description: "A step-by-step guide to building a Model Context Protocol (MCP) server using Python and FastMCP, from basic tools to dynamic resources."
|
||||
icon: server
|
||||
---
|
||||
|
||||
So you want to build a Model Context Protocol (MCP) server in Python. The goal is to create a service that can provide tools and data to AI models like Claude, Gemini, or others that support the protocol. While the [MCP specification](https://modelcontextprotocol.io/specification/) is powerful, implementing it from scratch involves a lot of boilerplate: handling JSON-RPC, managing session state, and correctly formatting requests and responses.
|
||||
|
||||
This is where **FastMCP** comes in. It's a high-level framework that handles all the protocol complexities for you, letting you focus on what matters: writing the Python functions that power your server.
|
||||
|
||||
This guide will walk you through creating a fully-featured MCP server from scratch using FastMCP.
|
||||
|
||||
<Tip>
|
||||
Every code block in this tutorial is a complete, runnable example. You can copy and paste it into a file and run it, or paste it directly into a Python REPL like IPython to try it out.
|
||||
</Tip>
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Make sure you have FastMCP installed. If not, follow the [installation guide](/getting-started/installation).
|
||||
|
||||
```bash
|
||||
pip install fastmcp
|
||||
```
|
||||
|
||||
|
||||
## Step 1: Create the Basic Server
|
||||
|
||||
Every FastMCP application starts with an instance of the `FastMCP` class. This object acts as the container for all your tools and resources.
|
||||
|
||||
Create a new file called `my_mcp_server.py`:
|
||||
|
||||
```python my_mcp_server.py
|
||||
from fastmcp import FastMCP
|
||||
|
||||
# Create a server instance with a descriptive name
|
||||
mcp = FastMCP(name="My First MCP Server")
|
||||
```
|
||||
|
||||
That's it! You have a valid (though empty) MCP server. Now, let's add some functionality.
|
||||
|
||||
## Step 2: Add a Tool
|
||||
|
||||
Tools are functions that an LLM can execute. Let's create a simple tool that adds two numbers.
|
||||
|
||||
To do this, simply write a standard Python function and decorate it with `@mcp.tool`.
|
||||
|
||||
```python my_mcp_server.py {5-8}
|
||||
from fastmcp import FastMCP
|
||||
|
||||
mcp = FastMCP(name="My First MCP Server")
|
||||
|
||||
@mcp.tool
|
||||
def add(a: int, b: int) -> int:
|
||||
"""Adds two integer numbers together."""
|
||||
return a + b
|
||||
```
|
||||
|
||||
FastMCP automatically handles the rest:
|
||||
- **Tool Name:** It uses the function name (`add`) as the tool's name.
|
||||
- **Description:** It uses the function's docstring as the tool's description for the LLM.
|
||||
- **Schema:** It inspects the type hints (`a: int`, `b: int`) to generate a JSON schema for the inputs.
|
||||
|
||||
This is the core philosophy of FastMCP: **write Python, not protocol boilerplate.**
|
||||
|
||||
## Step 3: Expose Data with Resources
|
||||
|
||||
Resources provide read-only data to the LLM. You can define a resource by decorating a function with `@mcp.resource`, providing a unique URI.
|
||||
|
||||
Let's expose a simple configuration dictionary as a resource.
|
||||
|
||||
```python my_mcp_server.py {10-13}
|
||||
from fastmcp import FastMCP
|
||||
|
||||
mcp = FastMCP(name="My First MCP Server")
|
||||
|
||||
@mcp.tool
|
||||
def add(a: int, b: int) -> int:
|
||||
"""Adds two integer numbers together."""
|
||||
return a + b
|
||||
|
||||
@mcp.resource("resource://config")
|
||||
def get_config() -> dict:
|
||||
"""Provides the application's configuration."""
|
||||
return {"version": "1.0", "author": "MyTeam"}
|
||||
```
|
||||
|
||||
When a client requests the URI `resource://config`, FastMCP will execute the `get_config` function and return its output (serialized as JSON) to the client. The function is only called when the resource is requested, enabling lazy-loading of data.
|
||||
|
||||
## Step 4: Generate Dynamic Content with Resource Templates
|
||||
|
||||
Sometimes, you need to generate resources based on parameters. This is what **Resource Templates** are for. You define them using the same `@mcp.resource` decorator but with placeholders in the URI.
|
||||
|
||||
Let's create a template that provides a personalized greeting.
|
||||
|
||||
```python my_mcp_server.py {15-17}
|
||||
from fastmcp import FastMCP
|
||||
|
||||
mcp = FastMCP(name="My First MCP Server")
|
||||
|
||||
@mcp.tool
|
||||
def add(a: int, b: int) -> int:
|
||||
"""Adds two integer numbers together."""
|
||||
return a + b
|
||||
|
||||
@mcp.resource("resource://config")
|
||||
def get_config() -> dict:
|
||||
"""Provides the application's configuration."""
|
||||
return {"version": "1.0", "author": "MyTeam"}
|
||||
|
||||
@mcp.resource("greetings://{name}")
|
||||
def personalized_greeting(name: str) -> str:
|
||||
"""Generates a personalized greeting for the given name."""
|
||||
return f"Hello, {name}! Welcome to the MCP server."
|
||||
```
|
||||
|
||||
Now, clients can request dynamic URIs:
|
||||
- `greetings://Ford` will call `personalized_greeting(name="Ford")`.
|
||||
- `greetings://Marvin` will call `personalized_greeting(name="Marvin")`.
|
||||
|
||||
FastMCP automatically maps the `{name}` placeholder in the URI to the `name` parameter in your function.
|
||||
|
||||
## Step 5: Run the Server
|
||||
|
||||
To make your server executable, add a `__main__` block to your script that calls `mcp.run()`.
|
||||
|
||||
```python my_mcp_server.py {19-20}
|
||||
from fastmcp import FastMCP
|
||||
|
||||
mcp = FastMCP(name="My First MCP Server")
|
||||
|
||||
@mcp.tool
|
||||
def add(a: int, b: int) -> int:
|
||||
"""Adds two integer numbers together."""
|
||||
return a + b
|
||||
|
||||
@mcp.resource("resource://config")
|
||||
def get_config() -> dict:
|
||||
"""Provides the application's configuration."""
|
||||
return {"version": "1.0", "author": "MyTeam"}
|
||||
|
||||
@mcp.resource("greetings://{name}")
|
||||
def personalized_greeting(name: str) -> str:
|
||||
"""Generates a personalized greeting for the given name."""
|
||||
return f"Hello, {name}! Welcome to the MCP server."
|
||||
|
||||
if __name__ == "__main__":
|
||||
mcp.run()
|
||||
```
|
||||
|
||||
Now you can run your server from the command line:
|
||||
```bash
|
||||
python my_mcp_server.py
|
||||
```
|
||||
This starts the server using the default **STDIO transport**, which is how clients like Claude Desktop communicate with local servers. To learn about other transports, like HTTP, see the [Running Your Server](/deployment/running-server) guide.
|
||||
|
||||
## The Complete Server
|
||||
|
||||
Here is the full code for `my_mcp_server.py` (click to expand):
|
||||
|
||||
```python my_mcp_server.py [expandable]
|
||||
from fastmcp import FastMCP
|
||||
|
||||
# 1. Create the server
|
||||
mcp = FastMCP(name="My First MCP Server")
|
||||
|
||||
# 2. Add a tool
|
||||
@mcp.tool
|
||||
def add(a: int, b: int) -> int:
|
||||
"""Adds two integer numbers together."""
|
||||
return a + b
|
||||
|
||||
# 3. Add a static resource
|
||||
@mcp.resource("resource://config")
|
||||
def get_config() -> dict:
|
||||
"""Provides the application's configuration."""
|
||||
return {"version": "1.0", "author": "MyTeam"}
|
||||
|
||||
# 4. Add a resource template for dynamic content
|
||||
@mcp.resource("greetings://{name}")
|
||||
def personalized_greeting(name: str) -> str:
|
||||
"""Generates a personalized greeting for the given name."""
|
||||
return f"Hello, {name}! Welcome to the MCP server."
|
||||
|
||||
# 5. Make the server runnable
|
||||
if __name__ == "__main__":
|
||||
mcp.run()
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
You've successfully built an MCP server! From here, you can explore more advanced topics:
|
||||
|
||||
- [**Tools in Depth**](/servers/tools): Learn about asynchronous tools, error handling, and custom return types.
|
||||
- [**Resources & Templates**](/servers/resources): Discover different resource types, including files and HTTP endpoints.
|
||||
- [**Prompts**](/servers/prompts): Create reusable prompt templates for your LLM.
|
||||
- [**Running Your Server**](/deployment/running-server): Deploy your server with different transports like HTTP.
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
---
|
||||
title: "What is the Model Context Protocol (MCP)?"
|
||||
sidebarTitle: "What is MCP?"
|
||||
description: "An introduction to the core concepts of the Model Context Protocol (MCP), explaining what it is, why it's useful, and how it works."
|
||||
icon: "diagram-project"
|
||||
---
|
||||
|
||||
The Model Context Protocol (MCP) is an open standard designed to solve a fundamental problem in AI development: how can Large Language Models (LLMs) reliably and securely interact with external tools, data, and services?
|
||||
|
||||
It's the **bridge between the probabilistic, non-deterministic world of AI and the deterministic, reliable world of your code and data.**
|
||||
|
||||
While you could build a custom REST API for your LLM, MCP provides a specialized, standardized "port" for AI-native communication. Think of it as **USB-C for AI**: a single, well-defined interface for connecting any compliant LLM to any compliant tool or data source.
|
||||
|
||||
This guide provides a high-level overview of the protocol itself. We'll use **FastMCP**, the leading Python framework for MCP, to illustrate the concepts with simple code examples.
|
||||
|
||||
## Why Do We Need a Protocol?
|
||||
|
||||
With countless APIs already in existence, the most common question is: "Why do we need another one?"
|
||||
|
||||
The answer lies in **standardization**. The AI ecosystem is fragmented. Every model provider has its own way of defining and calling tools. MCP's goal is to create a common language that offers several key advantages:
|
||||
|
||||
1. **Interoperability:** Build one MCP server, and it can be used by any MCP-compliant client (Claude, Gemini, OpenAI, custom agents, etc.) without custom integration code. This is the protocol's most important promise.
|
||||
2. **Discoverability:** Clients can dynamically ask a server what it's capable of at runtime. They receive a structured, machine-readable "menu" of tools and resources.
|
||||
3. **Security & Safety:** MCP provides a clear, sandboxed boundary. An LLM can't execute arbitrary code on your server; it can only *request* to run the specific, typed, and validated functions you explicitly expose.
|
||||
4. **Composability:** You can build small, specialized MCP servers and combine them to create powerful, complex applications.
|
||||
|
||||
## Core MCP Components
|
||||
|
||||
An MCP server exposes its capabilities through three primary components: Tools, Resources, and Prompts.
|
||||
|
||||
### Tools: Executable Actions
|
||||
|
||||
Tools are functions that the LLM can ask the server to execute. They are the action-oriented part of MCP.
|
||||
|
||||
In the spirit of a REST API, you can think of **Tools as being like `POST` requests.** They are used to *perform an action*, *change state*, or *trigger a side effect*, like sending an email, adding a user to a database, or making a calculation.
|
||||
|
||||
With FastMCP, creating a tool is as simple as decorating a Python function.
|
||||
|
||||
```python
|
||||
from fastmcp import FastMCP
|
||||
|
||||
mcp = FastMCP()
|
||||
|
||||
# This function is now an MCP tool named "get_weather"
|
||||
@mcp.tool
|
||||
def get_weather(city: str) -> dict:
|
||||
"""Gets the current weather for a specific city."""
|
||||
# In a real app, this would call a weather API
|
||||
return {"city": city, "temperature": "72F", "forecast": "Sunny"}
|
||||
```
|
||||
|
||||
[**Learn more about Tools →**](/servers/tools)
|
||||
|
||||
### Resources: Read-Only Data
|
||||
|
||||
Resources are data sources that the LLM can read. They are used to load information into the LLM's context, providing it with knowledge it doesn't have from its training data.
|
||||
|
||||
Following the REST API analogy, **Resources are like `GET` requests.** Their purpose is to *retrieve information* idempotently, ideally without causing side effects. A resource can be anything from a static text file to a dynamic piece of data from a database. Each resource is identified by a unique URI.
|
||||
|
||||
```python
|
||||
from fastmcp import FastMCP
|
||||
|
||||
mcp = FastMCP()
|
||||
|
||||
# This function provides a resource at the URI "system://status"
|
||||
@mcp.resource("system://status")
|
||||
def get_system_status() -> dict:
|
||||
"""Returns the current operational status of the service."""
|
||||
return {"status": "all systems normal"}
|
||||
```
|
||||
|
||||
#### Resource Templates
|
||||
|
||||
You can also create **Resource Templates** for dynamic data. A client could request `users://42/profile` to get the profile for a specific user.
|
||||
|
||||
```python
|
||||
from fastmcp import FastMCP
|
||||
|
||||
mcp = FastMCP()
|
||||
|
||||
# This template provides user data for any given user ID
|
||||
@mcp.resource("users://{user_id}/profile")
|
||||
def get_user_profile(user_id: str) -> dict:
|
||||
"""Returns the profile for a specific user."""
|
||||
# Fetch user from a database...
|
||||
return {"id": user_id, "name": "Zaphod Beeblebrox"}
|
||||
```
|
||||
|
||||
[**Learn more about Resources & Templates →**](/servers/resources)
|
||||
|
||||
### Prompts: Reusable Instructions
|
||||
|
||||
Prompts are reusable, parameterized message templates. They provide a way to define consistent, structured instructions that a client can request to guide the LLM's behavior for a specific task.
|
||||
|
||||
```python
|
||||
from fastmcp import FastMCP
|
||||
|
||||
mcp = FastMCP()
|
||||
|
||||
@mcp.prompt
|
||||
def summarize_text(text_to_summarize: str) -> str:
|
||||
"""Creates a prompt asking the LLM to summarize a piece of text."""
|
||||
return f"""
|
||||
Please provide a concise, one-paragraph summary of the following text:
|
||||
|
||||
{text_to_summarize}
|
||||
"""
|
||||
```
|
||||
|
||||
[**Learn more about Prompts →**](/servers/prompts)
|
||||
|
||||
## Advanced Capabilities
|
||||
|
||||
Beyond the core components, MCP also supports more advanced interaction patterns, such as a server requesting that the *client's* LLM generate a completion (known as **sampling**), or a server sending asynchronous **notifications** to a client. These features enable more complex, bidirectional workflows and are fully supported by FastMCP.
|
||||
|
||||
## Next Steps
|
||||
|
||||
Now that you understand the core concepts of the Model Context Protocol, you're ready to start building. The best place to begin is our step-by-step tutorial.
|
||||
|
||||
[**Tutorial: How to Create an MCP Server in Python →**](/tutorials/create-mcp-server)
|
||||
@@ -0,0 +1,203 @@
|
||||
---
|
||||
title: "How to Connect an LLM to a REST API"
|
||||
sidebarTitle: "Connect LLMs to REST APIs"
|
||||
description: "A step-by-step guide to making any REST API with an OpenAPI spec available to LLMs using FastMCP."
|
||||
icon: "plug"
|
||||
---
|
||||
|
||||
You've built a powerful REST API, and now you want your LLM to be able to use it. Manually writing a wrapper function for every single endpoint is tedious, error-prone, and hard to maintain.
|
||||
|
||||
This is where **FastMCP** shines. If your API has an OpenAPI (or Swagger) specification, FastMCP can automatically convert your entire API into a fully-featured MCP server, making every endpoint available as a secure, typed tool for your AI model.
|
||||
|
||||
This guide will walk you through converting a public REST API into an MCP server in just a few lines of code.
|
||||
|
||||
<Tip>
|
||||
Every code block in this tutorial is a complete, runnable example. You can copy and paste it into a file and run it, or paste it directly into a Python REPL like IPython to try it out.
|
||||
</Tip>
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Make sure you have FastMCP installed. If not, follow the [installation guide](/getting-started/installation).
|
||||
|
||||
```bash
|
||||
pip install fastmcp
|
||||
```
|
||||
|
||||
## Step 1: Choose a Target API
|
||||
|
||||
For this tutorial, we'll use the [JSONPlaceholder API](https://jsonplaceholder.typicode.com/), a free, fake online REST API for testing and prototyping. It's perfect because it's simple and has a public OpenAPI specification.
|
||||
|
||||
- **API Base URL:** `https://jsonplaceholder.typicode.com`
|
||||
- **OpenAPI Spec URL:** We'll use a community-provided spec for it.
|
||||
|
||||
## Step 2: Create the MCP Server
|
||||
|
||||
Now for the magic. We'll use `FastMCP.from_openapi`. This method takes an `httpx.AsyncClient` configured for your API and its OpenAPI specification, and automatically converts **every endpoint** into a callable MCP `Tool`.
|
||||
|
||||
<Tip>
|
||||
Learn more about working with OpenAPI specs in the [OpenAPI integration docs](/integrations/openapi).
|
||||
</Tip>
|
||||
|
||||
<Note>
|
||||
For this tutorial, we'll use a simplified OpenAPI spec directly in the code. In a real project, you would typically load the spec from a URL or local file.
|
||||
</Note>
|
||||
|
||||
Create a file named `api_server.py`:
|
||||
|
||||
```python api_server.py {31-35}
|
||||
import httpx
|
||||
from fastmcp import FastMCP
|
||||
|
||||
# Create an HTTP client for the target API
|
||||
client = httpx.AsyncClient(base_url="https://jsonplaceholder.typicode.com")
|
||||
|
||||
# Define a simplified OpenAPI spec for JSONPlaceholder
|
||||
openapi_spec = {
|
||||
"openapi": "3.0.0",
|
||||
"info": {"title": "JSONPlaceholder API", "version": "1.0"},
|
||||
"paths": {
|
||||
"/users": {
|
||||
"get": {
|
||||
"summary": "Get all users",
|
||||
"operationId": "get_users",
|
||||
"responses": {"200": {"description": "A list of users."}}
|
||||
}
|
||||
},
|
||||
"/users/{id}": {
|
||||
"get": {
|
||||
"summary": "Get a user by ID",
|
||||
"operationId": "get_user_by_id",
|
||||
"parameters": [{"name": "id", "in": "path", "required": True, "schema": {"type": "integer"}}],
|
||||
"responses": {"200": {"description": "A single user."}}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Create the MCP server from the OpenAPI spec
|
||||
mcp = FastMCP.from_openapi(
|
||||
openapi_spec=openapi_spec,
|
||||
client=client,
|
||||
name="JSONPlaceholder MCP Server"
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
mcp.run(transport="http", port=8000)
|
||||
```
|
||||
|
||||
And that's it! With just a few lines of code, you've created an MCP server that exposes the entire JSONPlaceholder API as a collection of tools.
|
||||
|
||||
## Step 3: Test the Generated Server
|
||||
|
||||
Let's verify that our new MCP server works. We can use the `fastmcp.Client` to connect to it and inspect its tools.
|
||||
|
||||
<Tip>
|
||||
Learn more about the FastMCP client in the [client docs](/clients/client).
|
||||
</Tip>
|
||||
|
||||
Create a separate file, `api_client.py`:
|
||||
|
||||
```python api_client.py {2, 6, 9, 16}
|
||||
import asyncio
|
||||
from fastmcp import Client
|
||||
|
||||
async def main():
|
||||
# Connect to the MCP server we just created
|
||||
async with Client("http://127.0.0.1:8000/mcp") as client:
|
||||
|
||||
# List the tools that were automatically generated
|
||||
tools = await client.list_tools()
|
||||
print("Generated Tools:")
|
||||
for tool in tools:
|
||||
print(f"- {tool.name}")
|
||||
|
||||
# Call one of the generated tools
|
||||
print("\n\nCalling tool 'get_user_by_id'...")
|
||||
user = await client.call_tool("get_user_by_id", {"id": 1})
|
||||
print(f"Result:\n{user.data}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
First, run your server:
|
||||
```bash
|
||||
python api_server.py
|
||||
```
|
||||
|
||||
Then, in another terminal, run the client:
|
||||
```bash
|
||||
python api_client.py
|
||||
```
|
||||
|
||||
You should see a list of generated tools (`get_users`, `get_user_by_id`) and the result of calling the `get_user_by_id` tool, which fetches data from the live JSONPlaceholder API.
|
||||
|
||||

|
||||
|
||||
|
||||
## Step 4: Customizing Route Maps
|
||||
|
||||
By default, FastMCP converts every API endpoint into an MCP `Tool`. This ensures maximum compatibility with contemporary LLM clients, many of which **only support the `tools` part of the MCP specification.**
|
||||
|
||||
However, for clients that support the full MCP spec, representing `GET` requests as `Resources` can be more semantically correct and efficient.
|
||||
|
||||
FastMCP allows users to customize this behavior using the concept of "route maps". A `RouteMap` is a mapping of an API route to an MCP type. FastMCP checks each API route against your custom maps in order. If a route matches a map, it's converted to the specified `mcp_type`. Any route that doesn't match your custom maps will fall back to the default behavior (becoming a `Tool`).
|
||||
|
||||
<Tip>
|
||||
Learn more about route maps in the [OpenAPI integration docs](/integrations/openapi#route-mapping).
|
||||
</Tip>
|
||||
|
||||
Here’s how you can add custom route maps to turn `GET` requests into `Resources` and `ResourceTemplates` (if they have path parameters):
|
||||
|
||||
```python api_server_with_resources.py {3, 37-42}
|
||||
import httpx
|
||||
from fastmcp import FastMCP
|
||||
from fastmcp.server.providers.openapi import RouteMap, MCPType
|
||||
|
||||
|
||||
# Create an HTTP client for the target API
|
||||
client = httpx.AsyncClient(base_url="https://jsonplaceholder.typicode.com")
|
||||
|
||||
# Define a simplified OpenAPI spec for JSONPlaceholder
|
||||
openapi_spec = {
|
||||
"openapi": "3.0.0",
|
||||
"info": {"title": "JSONPlaceholder API", "version": "1.0"},
|
||||
"paths": {
|
||||
"/users": {
|
||||
"get": {
|
||||
"summary": "Get all users",
|
||||
"operationId": "get_users",
|
||||
"responses": {"200": {"description": "A list of users."}}
|
||||
}
|
||||
},
|
||||
"/users/{id}": {
|
||||
"get": {
|
||||
"summary": "Get a user by ID",
|
||||
"operationId": "get_user_by_id",
|
||||
"parameters": [{"name": "id", "in": "path", "required": True, "schema": {"type": "integer"}}],
|
||||
"responses": {"200": {"description": "A single user."}}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Create the MCP server with custom route mapping
|
||||
mcp = FastMCP.from_openapi(
|
||||
openapi_spec=openapi_spec,
|
||||
client=client,
|
||||
name="JSONPlaceholder MCP Server",
|
||||
route_maps=[
|
||||
# Map GET requests with path parameters (e.g., /users/{id}) to ResourceTemplate
|
||||
RouteMap(methods=["GET"], pattern=r".*\{.*\}.*", mcp_type=MCPType.RESOURCE_TEMPLATE),
|
||||
# Map all other GET requests to Resource
|
||||
RouteMap(methods=["GET"], mcp_type=MCPType.RESOURCE),
|
||||
]
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
mcp.run(transport="http", port=8000)
|
||||
```
|
||||
With this configuration:
|
||||
- `GET /users/{id}` becomes a `ResourceTemplate`.
|
||||
- `GET /users` becomes a `Resource`.
|
||||
- Any `POST`, `PUT`, etc. endpoints would still become `Tools` by default.
|
||||
Reference in New Issue
Block a user