
MCP Server Template
A comprehensive template for building Model Context Protocol servers with FastMCP framework, featuring modular architecture, auto-discovery registry, and support for multiple transport methods. Includes example arithmetic and weather tools to help developers quickly create custom MCP servers.
README
MCP Server Template
A comprehensive, modular template for building Model Context Protocol (MCP) servers using FastMCP with professional architecture, auto-discovery, and flexible deployment options.
🚀 Project Overview
This template provides a robust foundation for creating MCP servers with:
- FastMCP Framework: Built on FastMCP 2.11.3+ for rapid MCP server development
- Modular Architecture: Clean separation of tools, resources, prompts, and configuration
- Auto-Discovery Registry: Automatic component registration using registry pattern
- Multiple Entry Points: Backward compatibility with flexible deployment options
- Transport Flexibility: Supports streamable HTTP and Server-Sent Events (SSE) transports
- Comprehensive Testing: Unit and integration test suite structure
- Development Template: Docker support, structured logging, and configuration management
- Type Safety: Pydantic models and type hints throughout
- Extensible Design: Easy to add new tools, resources, and prompts
Version: 0.1.0
🏃 Quick Start Guide
Prerequisites
- Python 3.13+
- uv (recommended package manager)
1. Clone and Setup
git clone <your-repo>
cd mcp-server-template
uv venv
source .venv/bin/activate
uv install
2. Run the Server
Choose your preferred method:
New Modular Way (Recommended):
source .venv/bin/activate && uv run python -m mcp_server
Backward Compatible:
source .venv/bin/activate && uv run python main.py
With Custom Transport:
# Streamable HTTP transport
export MCP_TRANSPORT=streamable-http
export MCP_PORT=8080
source .venv/bin/activate && uv run python -m mcp_server
# Server-Sent Events transport
export MCP_TRANSPORT=sse
export MCP_PORT=8081
source .venv/bin/activate && uv run python -m mcp_server
3. Test Connection
# Run diagnostic test
source .venv/bin/activate && uv run python diagnosis_test.py
# Run verification test
source .venv/bin/activate && uv run python verification_test.py
📦 Installation Instructions
Development Installation
# Clone the repository
git clone <your-repo-url>
cd mcp-server-template
# Create and activate virtual environment
uv venv
source .venv/bin/activate
# Install dependencies
uv install
# Install development dependencies
uv install --group dev
Production Installation
# Install from source
uv install git+<your-repo-url>
# Or from local directory
uv install .
🔧 Available Tools
Arithmetic Tools
- add: Add two integers together
- subtract: Subtract two integers
Weather Tools
- get_current_weather: Get current weather information for a location
Note: Weather tool uses OpenWeatherMap API. Set WEATHER_API_KEY
environment variable for real data, or it will use mock data for development.
🔧 Usage Examples
1. Default Mode
# Standard streamable HTTP mode
source .venv/bin/activate && uv run python -m mcp_server
2. Streamable HTTP Server Mode
# Run as streamable HTTP server
export MCP_TRANSPORT=streamable-http
export MCP_HOST=0.0.0.0
export MCP_PORT=8080
source .venv/bin/activate && uv run python -m mcp_server
3. Server-Sent Events (SSE) Mode
# Run as SSE server
export MCP_TRANSPORT=sse
export MCP_HOST=0.0.0.0
export MCP_PORT=8081
source .venv/bin/activate && uv run python -m mcp_server
4. Development Mode with Debug Logging
# Enable debug logging
export MCP_LOG_LEVEL=DEBUG
export MCP_ENVIRONMENT=development
source .venv/bin/activate && uv run python -m mcp_server
5. Docker Deployment
# Build image
docker build -t mcp-server .
# Run container (default mode)
docker run -it mcp-server
# Run container (Streamable HTTP mode)
docker run -e MCP_TRANSPORT=streamable-http -e MCP_PORT=8080 -p 8080:8080 mcp-server
# With custom configuration
docker run -e MCP_LOG_LEVEL=DEBUG -e MCP_ENVIRONMENT=production -it mcp-server
6. Integration with Claude Desktop
Add to your Claude Desktop MCP configuration:
Default Mode (Recommended):
{
"mcpServers": {
"mcp-server-template": {
"command": "uv",
"args": ["run", "python", "-m", "mcp_server"],
"cwd": "/path/to/your/mcp-server-template"
}
}
}
Streamable HTTP Mode:
{
"mcpServers": {
"mcp-server-template": {
"url": "http://localhost:8080/mcp",
"transport": "streamable-http"
}
}
}
🏗️ Architecture Overview
Directory Structure
mcp-server-template/
├── src/mcp_server/ # Main package (v0.1.0)
│ ├── __init__.py # Package initialization & lazy imports
│ ├── __main__.py # Module entry point
│ ├── server.py # Core FastMCP server implementation
│ ├── config/ # Configuration management
│ │ ├── __init__.py
│ │ ├── settings.py # Pydantic settings with environment support
│ │ └── logging.py # Structured logging configuration
│ ├── tools/ # MCP tools
│ │ ├── __init__.py
│ │ ├── base.py # Base tool class
│ │ ├── arithmetic.py # Arithmetic tools (add, subtract)
│ │ ├── weather.py # Weather tools (get_current_weather)
│ │ └── registry.py # Tool auto-discovery registry
│ ├── resources/ # MCP resources
│ │ ├── __init__.py
│ │ ├── base.py # Base resource class
│ │ ├── system.py # System information resources
│ │ └── registry.py # Resource auto-discovery registry
│ └── prompts/ # MCP prompts
│ ├── __init__.py
│ ├── base.py # Base prompt class
│ ├── text_processing.py # Text processing prompts
│ └── registry.py # Prompt auto-discovery registry
├── tests/ # Test suite
│ ├── conftest.py # Shared test fixtures
│ ├── unit/ # Unit tests
│ │ └── test_tools.py
│ └── integration/ # Integration tests
│ └── test_client_interactions.py
├── main.py # Backward compatibility entry
├── Dockerfile # Container deployment
├── diagnosis_test.py # Server diagnostic tool
├── verification_test.py # Server verification tool
└── pyproject.toml # Project configuration
Key Components
1. Server Factory Pattern
Clean server creation with comprehensive configuration:
# Server creation with auto-discovery
from mcp_server import create_server
server = create_server() # Automatically discovers and registers all components
2. Registry Pattern with Auto-Discovery
All components are automatically discovered and registered:
# Components are automatically found and registered
from mcp_server.tools.registry import register_all_tools
from mcp_server.resources.registry import register_all_resources
from mcp_server.prompts.registry import register_all_prompts
# Registration happens automatically in create_server()
register_all_tools(mcp)
register_all_resources(mcp)
register_all_prompts(mcp)
3. Transport-Agnostic Design
Supports multiple transport methods:
# Flexible transport configuration
await mcp.run_async(
transport=settings.transport, # streamable-http or sse
host=settings.host, # configurable host
port=settings.port # configurable port
)
4. Comprehensive Configuration
Environment-based configuration with validation:
from mcp_server.config.settings import get_settings
settings = get_settings() # Loads from environment with defaults
# Supports: transport, host, port, log_level, environment, etc.
🔨 Extension Guide
Adding New Tools
- Create a new tool file in
src/mcp_server/tools/
:
# src/mcp_server/tools/my_tool.py
from typing import Any
from fastmcp import FastMCP
from .base import BaseTool
class MyTool(BaseTool):
"""Example tool that processes text input."""
def __init__(self):
super().__init__(name="my_tool")
def register_with_mcp(self, mcp: FastMCP) -> None:
"""Register tools with FastMCP instance."""
@mcp.tool()
async def process_text(text: str) -> str:
"""Process text input and return formatted result.
Args:
text: Input text to process
Returns:
Processed text in uppercase
"""
self._log_tool_call("process_text", text=text)
return f"Processed: {text.upper()}"
self.logger.info("Registered my_tool: process_text")
# The tool is automatically discovered by the registry!
-
The tool is automatically registered - no manual registration needed!
-
Advanced tool with validation:
from typing import Dict, Any
from fastmcp import FastMCP
from .base import BaseTool
class ValidatedTool(BaseTool):
"""Example tool with validation using FastMCP decorators"""
def __init__(self):
super().__init__(name="validated")
def register_with_mcp(self, mcp: FastMCP) -> None:
@mcp.tool()
async def process_data(value: int, name: str) -> Dict[str, Any]:
"""Process data with validation.
Args:
value: Integer value to process
name: Name to include in result
Returns:
Processed data dictionary
"""
if not (0 <= value <= 100):
raise ValueError("Value must be between 0-100")
if not name or not name.strip():
raise ValueError("Name cannot be empty")
return {"value": value, "name": name.strip(), "processed": True}
self.logger.info("Registered validated tool: process_data")
Adding New Resources
- Create a resource file in
src/mcp_server/resources/
:
# src/mcp_server/resources/my_resource.py
import json
from typing import Any
from .base import BaseResource
class MyResource(BaseResource):
"""Example resource that provides data."""
uri_template = "my://data/{category}"
name = "My Data Resource"
description = "Provides categorized data"
mime_type = "application/json"
async def read(self, category: str = "default") -> str:
"""Read resource data for the given category."""
data = {
"category": category,
"items": [f"item-{i}" for i in range(1, 6)],
"timestamp": "2024-01-01T00:00:00Z"
}
return json.dumps(data, indent=2)
# Automatically discovered by the registry!
Adding New Prompts
- Create a prompt file in
src/mcp_server/prompts/
:
# src/mcp_server/prompts/my_prompt.py
from typing import Any, List
from fastmcp import FastMCP
from .base import BasePrompt
class MyPrompt(BasePrompt):
"""Example prompt for content generation."""
def __init__(self):
super().__init__(name="my_prompt")
def register_with_mcp(self, mcp: FastMCP) -> None:
"""Register prompts with FastMCP instance."""
@mcp.prompt()
async def generate_content(topic: str, format: str = "markdown") -> str:
"""Generate structured content about a topic.
Args:
topic: The topic to generate content about
format: Output format (markdown, text, etc.)
Returns:
Generated content in the specified format
"""
self._log_prompt_call("generate_content", topic=topic, format=format)
if format == "markdown":
return f"""# {topic}
## Overview
This is an overview of {topic}.
## Key Points
- Point 1 about {topic}
- Point 2 about {topic}
- Point 3 about {topic}
## Conclusion
Summary of {topic}.
"""
else:
return f"Content about {topic} in {format} format"
self.logger.info("Registered my_prompt: generate_content")
# Automatically discovered by the registry!
🧪 Testing
Running Tests
# All tests
source .venv/bin/activate && uv run pytest
# Unit tests only
source .venv/bin/activate && uv run pytest tests/unit/ -v
# Integration tests only
source .venv/bin/activate && uv run pytest tests/integration/ -v
# Specific test file
source .venv/bin/activate && uv run pytest tests/unit/test_tools.py -v
# With coverage
source .venv/bin/activate && uv run pytest --cov=src/mcp_server --cov-report=html
# Parallel execution
source .venv/bin/activate && uv run pytest -n auto
Test Structure
tests/
├── conftest.py # Shared test fixtures
├── unit/ # Unit tests
│ └── test_tools.py # Tool testing
└── integration/ # Integration tests
└── test_client_interactions.py # End-to-end tests
Writing Tests
Example unit test for tools:
import pytest
from mcp_server.tools.arithmetic import ArithmeticTools
@pytest.mark.asyncio
async def test_arithmetic_tools():
tools = ArithmeticTools()
# Test direct methods
assert tools.add_numbers(5, 3) == 8
assert tools.subtract_numbers(10, 4) == 6
@pytest.mark.asyncio
async def test_weather_tools():
from mcp_server.tools.weather import WeatherTools
tools = WeatherTools()
# Weather tool would require proper MCP setup for full testing
# This is a simplified example
assert tools._use_mock_data() == True # Default is mock data
Example integration test:
import pytest
from mcp_server import create_server
@pytest.mark.asyncio
async def test_server_creation():
server = create_server()
assert server is not None
# Test component registration
# This would require proper async setup in real tests
assert server is not None
# Verify tools are available (actual implementation would vary)
# The server would have add, subtract, get_current_weather tools
⚙️ Configuration
Environment Variables
Variable | Default | Description |
---|---|---|
MCP_TRANSPORT |
streamable-http |
Transport method (streamable-http, sse) |
MCP_HOST |
0.0.0.0 |
Server host for network transports |
MCP_PORT |
8080 |
Server port for network transports |
MCP_LOG_LEVEL |
INFO |
Logging level (DEBUG, INFO, WARNING, ERROR) |
MCP_LOG_FORMAT |
[%(levelname)s]: %(message)s |
Log format string |
MCP_ENVIRONMENT |
development |
Environment (development, production, testing) |
MCP_SERVER_NAME |
MCP Server Template |
Server identification name |
MCP_VERSION |
0.1.0 |
Server version |
PORT |
- | Cloud Run compatible port override |
Configuration Examples
Development Configuration:
export MCP_ENVIRONMENT=development
export MCP_LOG_LEVEL=DEBUG
export MCP_TRANSPORT=streamable-http
Streamable HTTP Server Configuration:
export MCP_TRANSPORT=streamable-http
export MCP_HOST=0.0.0.0
export MCP_PORT=8080
export MCP_ENVIRONMENT=production
export MCP_LOG_LEVEL=INFO
Server-Sent Events Configuration:
export MCP_TRANSPORT=sse
export MCP_HOST=0.0.0.0
export MCP_PORT=8081
export MCP_ENVIRONMENT=production
Advanced Configuration
The settings system supports complex configuration scenarios:
# src/mcp_server/config/settings.py
from pydantic import BaseModel, Field
from typing import Literal
class Settings(BaseModel):
# Server Configuration
server_name: str = "MCP Server Template"
host: str = "0.0.0.0"
port: int = 8080
transport: Literal["streamable-http", "sse"] = "streamable-http"
# Logging Configuration
log_level: str = "INFO"
log_format: str = "[%(levelname)s]: %(message)s"
# Environment Configuration
environment: Literal["development", "production", "testing"] = "development"
version: str = "0.1.0"
model_config = {
"env_prefix": "MCP_",
"case_sensitive": False,
"env_file": ".env",
"env_file_encoding": "utf-8"
}
🚀 Deployment
Docker Deployment
- Build the image:
docker build -t my-mcp-server .
- Run with different transports:
# Default mode
docker run -it my-mcp-server
# Streamable HTTP mode
docker run -e MCP_TRANSPORT=streamable-http -e MCP_HOST=0.0.0.0 -e MCP_PORT=8080 -p 8080:8080 my-mcp-server
# Server-Sent Events mode
docker run -e MCP_TRANSPORT=sse -e MCP_HOST=0.0.0.0 -e MCP_PORT=8081 -p 8081:8081 my-mcp-server
# With custom environment
docker run -e MCP_LOG_LEVEL=DEBUG -e MCP_ENVIRONMENT=production -it my-mcp-server
- Docker Compose:
version: '3.8'
services:
mcp-server-default:
build: .
environment:
- MCP_TRANSPORT=streamable-http
- MCP_LOG_LEVEL=INFO
stdin_open: true
tty: true
mcp-server-http:
build: .
environment:
- MCP_TRANSPORT=streamable-http
- MCP_HOST=0.0.0.0
- MCP_PORT=8080
- MCP_LOG_LEVEL=INFO
ports:
- "8080:8080"
mcp-server-sse:
build: .
environment:
- MCP_TRANSPORT=sse
- MCP_HOST=0.0.0.0
- MCP_PORT=8081
- MCP_LOG_LEVEL=INFO
ports:
- "8081:8081"
Production Deployment
- System Service (systemd example):
# /etc/systemd/system/mcp-server.service
[Unit]
Description=MCP Server
After=network.target
[Service]
Type=simple
User=mcp
WorkingDirectory=/opt/mcp-server
Environment=MCP_TRANSPORT=streamable-http
Environment=MCP_HOST=0.0.0.0
Environment=MCP_PORT=8080
Environment=MCP_LOG_LEVEL=INFO
Environment=MCP_ENVIRONMENT=production
ExecStart=/opt/mcp-server/.venv/bin/python -m mcp_server
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
- Process Manager (PM2 example):
{
"name": "mcp-server",
"script": "python",
"args": ["-m", "mcp_server"],
"cwd": "/opt/mcp-server",
"interpreter": "/opt/mcp-server/.venv/bin/python",
"env": {
"MCP_TRANSPORT": "streamable-http",
"MCP_HOST": "0.0.0.0",
"MCP_PORT": "8080",
"MCP_LOG_LEVEL": "INFO",
"MCP_ENVIRONMENT": "production"
}
}
- Kubernetes Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mcp-server
spec:
replicas: 3
selector:
matchLabels:
app: mcp-server
template:
metadata:
labels:
app: mcp-server
spec:
containers:
- name: mcp-server
image: my-mcp-server:latest
env:
- name: MCP_TRANSPORT
value: "streamable-http"
- name: MCP_HOST
value: "0.0.0.0"
- name: MCP_PORT
value: "8080"
- name: MCP_ENVIRONMENT
value: "production"
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: mcp-server-service
spec:
selector:
app: mcp-server
ports:
- port: 80
targetPort: 8080
type: LoadBalancer
👥 Development
Development Setup
# Clone and setup
git clone <repo-url>
cd mcp-server-template
uv venv
source .venv/bin/activate
uv install --group dev
# Set development environment
export MCP_ENVIRONMENT=development
export MCP_LOG_LEVEL=DEBUG
Code Quality
# Format and lint code
source .venv/bin/activate && uv run ruff check src tests --fix
source .venv/bin/activate && uv run ruff format src tests
# Type checking (mypy not included in current dependencies)
# Add mypy to dev dependencies if type checking is needed
# Run all quality checks
source .venv/bin/activate && uv run pytest && uv run ruff check src tests
Contributing Guidelines
- Fork and clone the repository
- Create a feature branch:
git checkout -b feature/my-feature
- Set development environment:
export MCP_ENVIRONMENT=development
- Write tests for new functionality
- Ensure all tests pass:
source .venv/bin/activate && uv run pytest
- Run linting:
source .venv/bin/activate && uv run ruff check src tests --fix
- Test different transports: Test streamable-http and sse modes
- Commit changes: Follow conventional commits
- Submit a pull request
Development Workflows
Testing Different Transports:
# Test default streamable HTTP mode
export MCP_TRANSPORT=streamable-http && source .venv/bin/activate && uv run python -m mcp_server
# Test SSE mode
export MCP_TRANSPORT=sse && export MCP_PORT=8081 && source .venv/bin/activate && uv run python -m mcp_server
Component Development:
# Verify tool registration
source .venv/bin/activate && uv run python -c "
from mcp_server.tools.registry import get_all_tools
print([tool.__class__.__name__ for tool in get_all_tools()])
"
# Test new components
source .venv/bin/activate && uv run python diagnosis_test.py
🐛 Troubleshooting
Common Issues
-
Server not starting:
# Check Python version python --version # Should be 3.13+ # Check dependencies source .venv/bin/activate && uv pip list # Check with debug logging export MCP_LOG_LEVEL=DEBUG source .venv/bin/activate && uv run python -m mcp_server
-
Transport-specific issues:
# Streamable HTTP transport issues export MCP_TRANSPORT=streamable-http export MCP_HOST=localhost export MCP_PORT=8080 curl http://localhost:8080/health # Test endpoint # SSE transport issues export MCP_TRANSPORT=sse export MCP_PORT=8081 # Test with SSE client
-
Components not registered:
# Verify component discovery source .venv/bin/activate && uv run python -c "
from mcp_server import create_server server = create_server() print('Server created successfully with all components') "
4. **Docker issues**:
```bash
# Check container logs
docker logs <container-id>
# Interactive debugging
docker run -it --entrypoint /bin/bash my-mcp-server
# Test different transports
docker run -e MCP_TRANSPORT=streamable-http -e MCP_PORT=8080 -p 8080:8080 my-mcp-server
Debug Mode
Enable comprehensive debugging:
export MCP_LOG_LEVEL=DEBUG
export MCP_ENVIRONMENT=development
source .venv/bin/activate && uv run python -m mcp_server
Health Checks
Use the provided diagnostic tools:
# Basic functionality test
source .venv/bin/activate && uv run python diagnosis_test.py
# Full verification test
source .venv/bin/activate && uv run python verification_test.py
# Test specific transport
export MCP_TRANSPORT=streamable-http && source .venv/bin/activate && uv run python verification_test.py
🔧 FastMCP Features
This template leverages FastMCP's powerful capabilities:
Multi-Transport Support
# Automatic transport detection and configuration
await mcp.run_async(
transport="streamable-http", # Streamable HTTP server mode
transport="sse" # Server-Sent Events mode
)
Automatic Type Validation
from fastmcp import tool
@tool
async def validated_function(count: int, name: str) -> dict:
"""FastMCP handles automatic type conversion and validation."""
return {"count": count, "name": name}
Built-in Error Handling
# FastMCP provides comprehensive error handling
try:
result = await tool.execute(params)
except ValidationError as e:
logger.error(f"Validation error: {e}")
except Exception as e:
logger.error(f"Execution error: {e}")
Lazy Loading for Performance
# The template uses lazy imports for optimal startup
def create_server():
from .server import create_server as _create_server
return _create_server()
📄 Dependencies
Core Dependencies
- fastmcp (>=2.11.3): FastMCP framework for rapid MCP server development
- httpx (>=0.28.1): HTTP client for external API integration
- pydantic (>=2.0.0): Data validation and settings management
Development Dependencies
- pytest (>=8.4.1): Testing framework with async support
- pytest-asyncio (>=0.23.0): Async testing support for pytest
- ruff (>=0.12.10): Fast Python linter and formatter
- ipykernel (>=6.30.1): Jupyter kernel for interactive development
🆕 What's New in v0.1.0
- Multi-Transport Support: Streamable HTTP and Server-Sent Events transport options
- Environment-Based Configuration: Comprehensive settings management with MCP_ prefixes
- Registry Pattern: Automatic component discovery and registration
- Structured Logging: Configurable logging formats with proper levels
- Development Template: Docker support with Python 3.13, structured for extension
- FastMCP Integration: Built on the latest FastMCP framework
- Lazy Loading: Optimized startup performance with lazy imports
- Flexible Deployment: Multiple deployment options and configurations
📄 License
[Your License Here]
🤝 Support
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: This README and inline code documentation
- FastMCP Docs: FastMCP Documentation
- MCP Specification: Model Context Protocol
Happy building with MCP and FastMCP! 🚀
推荐服务器

Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。