Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
243 changes: 97 additions & 146 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,181 +1,132 @@
# FastAPI MCP SSE
# MCP Matchmaking Server

<p align="center">
<strong>English</strong> | <a href="/README.zh-CN.md">简体中文</a>
</p>

A Server-Sent Events (SSE) implementation using FastAPI framework with [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) integration.

## What is MCP?

The [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) is an open standard that enables AI models to interact with external tools and data sources. MCP solves several key challenges in AI development:

- **Context limitations**: Allows models to access up-to-date information beyond their training data
- **Tool integration**: Provides a standardized way for models to use external tools and APIs
- **Interoperability**: Creates a common interface between different AI models and tools
- **Extensibility**: Makes it easy to add new capabilities to AI systems without retraining

This project demonstrates how to implement MCP using Server-Sent Events (SSE) in a FastAPI web application.

## Description

This project demonstrates how to implement Server-Sent Events (SSE) using the FastAPI framework while integrating Model Context Protocol (MCP) functionality. The key feature is the seamless integration of MCP's SSE capabilities within a full-featured FastAPI web application that includes custom routes.

## Features

- Server-Sent Events (SSE) implementation with MCP
- FastAPI framework integration with custom routes
- Unified web application with both MCP and standard web endpoints
- Customizable route structure
- Clean separation of concerns between MCP and web functionality
A matchmaking server built with FastAPI and the Model Context Protocol (MCP). This server allows agents representing individuals to find potential matches based on their profiles.

## Architecture

This project showcases a modular architecture that:

1. Integrates MCP SSE endpoints (`/sse` and `/messages/`) into a FastAPI application
2. Provides standard web routes (`/`, `/about`, `/status`, `/docs`, `/redoc`)
3. Demonstrates how to maintain separation between MCP functionality and web routes
The MCP matchmaking server is built on a simple, modular architecture that leverages FastAPI for the web framework and MCP for defining and exposing the core services.

## Installation & Usage Options
### Architectural Diagram

### Prerequisites

Install [UV Package Manager](https://docs.astral.sh/uv/) - A fast Python package installer written in Rust:

```cmd
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
```

### Option 1: Quick Run Without Installation

Run the application directly without cloning the repository using UV's execution tool:

```cmd
uvx --from git+https://github.com/panz2018/fastapi_mcp_sse.git start
+-----------------+ +---------------------+ +-----------------+
| Agent 1 | | MCP Matchmaking | | Agent 2 |
| (Client) | | Server (FastAPI) | | (Client) |
+-----------------+ +---------------------+ +-----------------+
| | |
|--- Announce Self ----> | |
| (get fingerprint) | |
| | |
| <--- Fingerprint ------| |
| | |
| | <---- Announce Self ---|
| | (get fingerprint) |
| | |
| | ------ Fingerprint --> |
| | |
|--- Get Match --------->| |
| (send fingerprint) | |
| | |
| <--- Match Profile ----| |
| (Agent 2 info) | |
| | |
|--- Establish Match --->| |
| (fingerprints of 1&2) | |
| | |
| <--- Confirmation -----| |
| | |
```

### Option 2: Full Installation
### Components

#### Create Virtual Environment
1. **FastAPI Application**: The core of the server is a FastAPI web application that handles HTTP requests and provides the infrastructure for the MCP services.
2. **MCP Server**: The `FastMCP` instance from the `mcp` library is used to define the matchmaking tools (`announce_agent`, `get_potential_match`, `establish_match`).
3. **In-Memory Database**: For this version, a simple Python dictionary is used as an in-memory database to store agent profiles and matches. In a production environment, this would be replaced with a persistent database like PostgreSQL, MongoDB, or Redis.

Create an isolated Python environment for the project:
## API Services (MCP Tools)

```cmd
uv venv
```
The server exposes three main services as MCP tools:

#### Activate Virtual Environment
### 1. `announce_agent`

Activate the virtual environment to use it:
Announces an agent to the matchmaking service and returns a unique fingerprint for subsequent calls.

```cmd
.venv\Scripts\activate
```
* **Tool Name**: `announce_agent`
* **Arguments**:
* `profile` (JSON object): A dictionary containing the agent's profile. The profile should include details like skills, orientations, preferences, and city.
* **Example**: `{"skills": ["python", "music"], "city": "New York"}`
* **Returns**:
* `fingerprint` (string): A unique identifier for the agent.

#### Install Dependencies
### 2. `get_potential_match`

Install all required packages:
Provides a potential match for a given agent based on their fingerprint.

```cmd
uv pip install -r pyproject.toml
```
* **Tool Name**: `get_potential_match`
* **Arguments**:
* `fingerprint` (string): The fingerprint of the agent requesting a match.
* **Returns**:
* (JSON object): The profile of a potential match. If no match is found, an empty object is returned.

#### Start the Integrated Server
### 3. `establish_match`

Launch the integrated FastAPI server with MCP SSE functionality:
Notifies the server that a match has been established between two agents. Once a match is established, these two agents will no longer be matched with each other by the `get_potential_match` service.

```cmd
python src/server.py
```

or

```cmd
uv run start
```
* **Tool Name**: `establish_match`
* **Arguments**:
* `fingerprint1` (string): The fingerprint of the first agent.
* `fingerprint2` (string): The fingerprint of the second agent.
* **Returns**:
* (string): A confirmation message.

### Available Endpoints
## Setup and Usage

After starting the server (using either Option 1 or Option 2), the following endpoints will be available:

- Main server: http://localhost:8000
- Standard web routes:
- Home page: http://localhost:8000/
- About page: http://localhost:8000/about
- Status API: http://localhost:8000/status
- Documentation (Swagger UI): http://localhost:8000/docs
- Documentation (ReDoc): http://localhost:8000/redoc
- MCP SSE endpoints:
- SSE endpoint: http://localhost:8000/sse
- Message posting: http://localhost:8000/messages/

### Debug with MCP Inspector
### Prerequisites

For testing and debugging MCP functionality, use the MCP Inspector:
Install [UV Package Manager](https://docs.astral.sh/uv/):

```cmd
mcp dev ./src/weather.py
```sh
curl -LsSf https://astral.sh/uv/install.sh | sh
```

### Connect to MCP Inspector

1. Open MCP Inspector at http://localhost:5173
2. Configure the connection:
- Set Transport Type to `SSE`
- Enter URL: http://localhost:8000/sse
- Click `Connect`
### Installation

### Test the Functions
1. **Create a virtual environment:**
```sh
uv venv
```
2. **Activate the virtual environment:**
```sh
source .venv/bin/activate
```
3. **Install dependencies:**
```sh
uv pip install -r pyproject.toml
```

1. Navigate to `Tools` section
2. Click `List Tools` to see available functions:
- `get_alerts` : Get weather alerts
- `get_forcast` : Get weather forecast
3. Select a function
4. Enter required parameters
5. Click `Run Tool` to execute
### Running the Server

## Extending the Application
To start the matchmaking server, run:

### Adding Custom Routes

The application structure makes it easy to add new routes using FastAPI's APIRouter:

1. Define new route handlers in routes.py using the APIRouter:

```python
@router.get("/new-route")
async def new_route():
return {"message": "This is a new route"}
```

2. All routes defined with the router will be automatically included in the main application

### Customizing MCP Integration

The MCP SSE functionality is integrated in server.py through:
```sh
python src/server.py
```

- Creating an SSE transport
- Setting up an SSE handler
- Adding MCP routes to the FastAPI application
The server will be available at `http://localhost:8000`.

## Integration with [Continue](https://www.continue.dev/)
### Interacting with the Server

To use this MCP server with the Continue VS Code extension, add the following configuration to your Continue settings:
You can interact with the MCP services using an MCP-compatible client or by using the MCP Inspector tool.

```json
{
"experimental": {
"modelContextProtocolServers": [
{
"transport": {
"name": "weather",
"type": "sse",
"url": "http://localhost:8000/sse"
}
}
]
}
}
```
1. **Run the MCP Inspector:**
```sh
mcp dev ./src/matchmaking.py
```
2. **Connect to the server:**
* Open the MCP Inspector in your browser (usually at `http://localhost:5173`).
* Set the Transport Type to `SSE`.
* Enter the URL: `http://localhost:8000/sse`.
* Click `Connect`.
3. **Use the tools:**
* You will see the `announce_agent`, `get_potential_match`, and `establish_match` tools listed.
* You can use the interface to call these tools with the required arguments.
2 changes: 1 addition & 1 deletion src/app.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from fastapi import FastAPI, Request
from mcp.server.sse import SseServerTransport
from starlette.routing import Mount
from weather import mcp
from matchmaking import mcp

# Create FastAPI application with metadata
app = FastAPI(
Expand Down
77 changes: 77 additions & 0 deletions src/matchmaking.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from typing import Any, Dict
from mcp.server.fastmcp import FastMCP
import uuid

# Initialize FastMCP server
mcp = FastMCP("matchmaking")

# In-memory database for agents and matches
# For a production system, you would use a persistent database.
agents: Dict[str, Dict[str, Any]] = {}
matches: Dict[str, str] = {}

@mcp.tool()
async def announce_agent(profile: Dict[str, Any]) -> str:
"""
Announces an agent to the matchmaking service and returns a fingerprint.

Args:
profile: A dictionary containing the agent's profile, including skills,
orientations, preferences, and city.
"""
fingerprint = str(uuid.uuid4())
agents[fingerprint] = profile
return fingerprint

@mcp.tool()
async def get_potential_match(fingerprint: str) -> Dict[str, Any]:
"""
Gets a potential match for a given agent.

Args:
fingerprint: The fingerprint of the agent requesting a match.

Returns:
A dictionary containing the profile of a potential match, or an empty
dictionary if no match is found.
"""
if fingerprint not in agents:
return {"error": "Invalid fingerprint."}

for other_fingerprint, other_profile in agents.items():
if other_fingerprint == fingerprint:
continue

# Check if they are already matched
if matches.get(fingerprint) == other_fingerprint or \
matches.get(other_fingerprint) == fingerprint:
continue

# Simple matching logic: return the first available agent.
# A real implementation would have more complex matching logic.
return other_profile

return {}

@mcp.tool()
async def establish_match(fingerprint1: str, fingerprint2: str) -> str:
"""
Establishes a match between two agents, preventing them from being matched
with each other again.

Args:
fingerprint1: The fingerprint of the first agent.
fingerprint2: The fingerprint of the second agent.

Returns:
A confirmation message.
"""
if fingerprint1 not in agents or fingerprint2 not in agents:
return "Error: One or both fingerprints are invalid."

matches[fingerprint1] = fingerprint2
return f"Match established between {fingerprint1} and {fingerprint2}."

if __name__ == "__main__":
# Initialize and run the server
mcp.run(transport="sse")
Loading