FastAPI MCP Streamable HTTP Starter
README.md
# FastAPI MCP Streamable HTTP Starter ๐
[](https://modelcontextprotocol.io)
[](https://python.org)
[](https://fastapi.tiangolo.com)
[](LICENSE)
A minimal, production-ready starter template for building **Model Context Protocol (MCP)** servers in Python with **FastAPI** over **Streamable HTTP**.
Implements the official MCP Specification version `2025-11-25`, handling standard JSON-RPC 2.0 requests:
- `initialize` (protocol handshake and capability negotiation)
- `tools/list` (dynamic tool discovery)
- `tools/call` (tool execution)
---
## โก Quickstart
### 1. Clone the repository
```bash
git clone https://github.com/kshitijkumrawat20/fastapi-mcp-streamable-http-starter.git
cd fastapi-mcp-streamable-http-starter
```
### 2. Install dependencies
Using `uv`:
```bash
uv pip install -r requirements.txt
```
Or standard `pip`:
```bash
pip install -r requirements.txt
```
### 3. Run the MCP server
```bash
uvicorn main:app --host 127.0.0.1 --port 8000 --reload
```
---
## ๐งช Testing with cURL
### 1. Protocol Handshake (`initialize`)
```bash
curl -X POST http://127.0.0.1:8000/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-11-25",
"capabilities": {},
"clientInfo": {"name": "curl-client", "version": "1.0.0"}
}
}'
```
### 2. Discover Tools (`tools/list`)
```bash
curl -X POST http://127.0.0.1:8000/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}'
```
### 3. Execute a Tool (`tools/call`)
```bash
curl -X POST http://127.0.0.1:8000/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "echo",
"arguments": {
"message": "Hello from MCP Streamable HTTP!"
}
}
}'
```
---
## ๐ Adding Custom Tools
Subclass `MCPTool` and register it in `mcp_server.py`:
```python
from mcp_server import MCPTool
class WeatherTool(MCPTool):
@property
def name(self) -> str:
return "get_weather"
@property
def description(self) -> str:
return "Returns current weather for a city."
@property
def input_schema(self) -> dict:
return {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name"}
},
"required": ["city"]
}
async def execute(self, arguments: dict) -> dict:
city = arguments["city"]
return {"city": city, "temperature": "72ยฐF", "condition": "Sunny"}
# Register in ToolRegistry:
server.registry.register(WeatherTool())
```
---
## ๐ License
MIT License. Feel free to use this template for your hackathons and production MCP servers!
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues