MCP Server Template
Supports containerized deployment with comprehensive Docker configuration examples and multi-transport server modes
Provides deployment manifests and configuration for running the MCP server in Kubernetes clusters with load balancing and scaling support
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MCP Server Templateadd 15 and 27"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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
Related MCP server: Bootstrap MCP Server
🏃 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 install2. Run the Server
Choose your preferred method:
New Modular Way (Recommended):
source .venv/bin/activate && uv run python -m mcp_serverBackward Compatible:
source .venv/bin/activate && uv run python main.pyWith 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_server3. 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 devProduction 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_server2. 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_server3. 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_server4. 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_server5. 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-server6. 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 configurationKey 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 components2. 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 autoTest 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 testsWriting 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 dataExample 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 |
|
| Transport method (streamable-http, sse) |
|
| Server host for network transports |
|
| Server port for network transports |
|
| Logging level (DEBUG, INFO, WARNING, ERROR) |
|
| Log format string |
|
| Environment (development, production, testing) |
|
| Server identification name |
|
| Server version |
| - | Cloud Run compatible port override |
Configuration Examples
Development Configuration:
export MCP_ENVIRONMENT=development
export MCP_LOG_LEVEL=DEBUG
export MCP_TRANSPORT=streamable-httpStreamable 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=INFOServer-Sent Events Configuration:
export MCP_TRANSPORT=sse
export MCP_HOST=0.0.0.0
export MCP_PORT=8081
export MCP_ENVIRONMENT=productionAdvanced 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-serverDocker 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.targetProcess 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=DEBUGCode 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 testsContributing Guidelines
Fork and clone the repository
Create a feature branch:
git checkout -b feature/my-featureSet development environment:
export MCP_ENVIRONMENT=developmentWrite tests for new functionality
Ensure all tests pass:
source .venv/bin/activate && uv run pytestRun linting:
source .venv/bin/activate && uv run ruff check src tests --fixTest 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_serverComponent 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_serverTransport-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 clientComponents 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-serverDebug Mode
Enable comprehensive debugging:
export MCP_LOG_LEVEL=DEBUG
export MCP_ENVIRONMENT=development
source .venv/bin/activate && uv run python -m mcp_serverHealth 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! 🚀
This server cannot be installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/rwxproject/mcp-server-template'
If you have feedback or need assistance with the MCP directory API, please join our Discord server