Skip to main content
Glama

MCP Template

MCP Template

Production-ready MCP (Model Context Protocol) server template in Python with registry integration, comprehensive configuration management, and extensibility patterns.

Features

  • Production-Ready: Enterprise-grade error handling, structured logging, and graceful shutdown

  • Registry Integration: Automatic server registration, heartbeats, and deregistration

  • Configuration Management: YAML-based config with environment variable overrides and Pydantic validation

  • Extensible Architecture: Easy-to-extend base classes for tools, resources, and prompts

  • Type Safety: Full type hints throughout the codebase

  • Developer Experience: Comprehensive CLI, extensive documentation, and example implementations

  • Testing: Unit and integration test examples with pytest

Quick Start

Installation

# Clone or copy this template cd mcp-template # Create virtual environment python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate # Install dependencies pip install -e ".[dev]" # Or using requirements.txt pip install -r requirements-dev.txt

Initialize Configuration

# Initialize default configuration mcp-template init # This creates: # - config/config.yaml (server configuration) # - .env (environment variables)

Run the Server

# Run with default configuration mcp-template run # Run with custom config mcp-template run --config path/to/config.yaml # Run in debug mode mcp-template run --debug # Validate configuration mcp-template validate # Check health mcp-template health

Project Structure

mcp-template/ ├── src/mcp_template/ │ ├── core/ # Core server components │ │ ├── server.py # Base MCP server implementation │ │ ├── settings.py # Pydantic settings models │ │ ├── config_loader.py # Configuration loader │ │ └── logger.py # Structured logging setup │ ├── registry/ # Registry integration │ │ ├── base.py # Registry client interface │ │ ├── http_client.py # HTTP registry implementation │ │ └── manager.py # Registry lifecycle manager │ ├── tools/ # MCP tools │ │ ├── calculator.py # Example calculator tool │ │ └── search.py # Example search tool │ ├── resources/ # MCP resources │ │ ├── config.py # Configuration resource │ │ └── status.py # Status resource │ ├── prompts/ # MCP prompts │ │ └── example.py # Example prompt │ ├── app.py # Main application │ └── cli.py # Command-line interface ├── config/ │ └── config.yaml # Server configuration ├── tests/ │ ├── unit/ # Unit tests │ └── integration/ # Integration tests ├── pyproject.toml # Project metadata and dependencies ├── requirements.txt # Production dependencies ├── requirements-dev.txt # Development dependencies ├── Makefile # Development commands └── README.md # This file

Configuration

Configuration File (config/config.yaml)

The main configuration file supports:

  • Server settings: Name, version, description, debug mode

  • Logging: Level, format (JSON/text), file output

  • Registry: URL, authentication, heartbeat settings, metadata

  • Tools/Resources/Prompts: Enable/disable specific components

Example:

server: name: "my-mcp-server" version: "0.1.0" description: "My custom MCP server" logging: level: "INFO" format: "json" registry: enabled: true url: "https://registry.example.com/api/v1" auth: type: "api_key" api_key: "${REGISTRY_API_KEY}" heartbeat: enabled: true interval: 60 tools: enabled: - "example_calculator" - "example_search"

Environment Variables

Override configuration using environment variables with double underscore as separator:

# Override server name export SERVER__NAME="production-server" # Override registry URL export REGISTRY__URL="https://prod-registry.example.com" # Set API key export REGISTRY__AUTH__API_KEY="your-api-key" # Override logging level export LOGGING__LEVEL="DEBUG"

Environment Variables File (.env)

Create a .env file for local development:

# Registry REGISTRY_API_KEY=your-api-key-here # Server overrides SERVER__DEBUG=false # Logging LOGGING__LEVEL=INFO

Adding Custom Components

Adding a New Tool

  1. Create a new file in src/mcp_template/tools/:

# src/mcp_template/tools/my_tool.py import mcp.types as types async def my_tool_handler(arguments: dict) -> str: """Handle the tool call.""" # Your implementation here return "Result" MY_TOOL_SCHEMA = types.Tool( name="my_tool", description="Description of what the tool does", inputSchema={ "type": "object", "properties": { "param1": { "type": "string", "description": "Parameter description" } }, "required": ["param1"] } )
  1. Register it in src/mcp_template/app.py:

from .tools.my_tool import my_tool_handler, MY_TOOL_SCHEMA # In MCPTemplateApp._register_components(): self.server.register_tool( "my_tool", my_tool_handler, MY_TOOL_SCHEMA, )
  1. Enable it in config/config.yaml:

tools: enabled: - "my_tool"

Adding a New Resource

Similar pattern - create handler and schema, register in app.py, enable in config.

# src/mcp_template/resources/my_resource.py import mcp.types as types async def my_resource_handler(uri: str) -> str: """Handle resource read.""" return "Resource data" MY_RESOURCE_SCHEMA = types.Resource( uri="myresource://example", name="My Resource", description="Resource description", mimeType="application/json" )

Adding a New Prompt

# src/mcp_template/prompts/my_prompt.py import mcp.types as types async def my_prompt_handler(arguments: dict) -> types.GetPromptResult: """Handle prompt request.""" return types.GetPromptResult( description="Prompt description", messages=[ types.PromptMessage( role="user", content=types.TextContent( type="text", text="Prompt text" ) ) ] ) MY_PROMPT_SCHEMA = types.Prompt( name="my_prompt", description="Prompt description", arguments=[ types.PromptArgument( name="arg1", description="Argument description", required=True ) ] )

Registry Integration

The template includes a pluggable registry system for server discovery and management.

How It Works

  1. Registration: On startup, server registers with the registry

  2. Heartbeat: Periodic heartbeats maintain the registration

  3. Deregistration: Graceful shutdown deregisters the server

Custom Registry Backend

Implement the RegistryClient interface for custom backends:

from mcp_template.registry.base import RegistryClient class MyRegistryClient(RegistryClient): async def register(self, server_info: dict) -> dict: # Your implementation pass async def deregister(self, server_id: str) -> bool: # Your implementation pass # Implement other methods...

Then use it in your application:

from mcp_template.registry.manager import RegistryManager registry_manager = RegistryManager(settings, client=MyRegistryClient())

Development

Setup Development Environment

# Install with development dependencies pip install -e ".[dev]" # Or using make make install

Running Tests

# Run all tests pytest # Run with coverage pytest --cov # Run only unit tests pytest tests/unit # Run only integration tests pytest tests/integration -m integration # Using make make test

Code Quality

# Format code make format # Lint code make lint # Type check make typecheck # Run all checks make check

Pre-commit Hooks

# Install pre-commit hooks pre-commit install # Run manually pre-commit run --all-files

Deployment

Docker

Create a Dockerfile:

FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY src/ src/ COPY config/ config/ RUN pip install -e . CMD ["mcp-template", "run"]

Build and run:

docker build -t mcp-template . docker run -e REGISTRY_API_KEY=your-key mcp-template

Environment-Specific Configuration

Create different config files for each environment:

config/ ├── config.yaml # Default ├── config.dev.yaml # Development ├── config.staging.yaml # Staging └── config.prod.yaml # Production

Run with specific config:

mcp-template run --config config/config.prod.yaml

Monitoring and Observability

Structured Logging

All logs are structured (JSON format by default) for easy parsing:

{ "timestamp": "2024-01-01T12:00:00.000Z", "level": "info", "event": "Server started", "server": "my-server", "version": "0.1.0" }

Health Checks

# CLI health check mcp-template health # Programmatic health check from mcp_template.app import create_app app = create_app() health = await app.server.health_check()

Troubleshooting

Common Issues

Configuration file not found

# Initialize configuration mcp-template init # Or specify path mcp-template run --config path/to/config.yaml

Registry connection failed

# Check registry health mcp-template health # Disable registry temporarily # In config.yaml: registry: enabled: false

Import errors

# Reinstall in editable mode pip install -e .

Contributing

  1. Fork the repository

  2. Create a feature branch

  3. Make your changes

  4. Add tests

  5. Run code quality checks: make check

  6. Submit a pull request

License

MIT License - see LICENSE file for details

Resources

Support

For issues, questions, or contributions, please open an issue on GitHub.

-
security - not tested
A
license - permissive license
-
quality - not tested

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/riteshsonawala/mcp-template'

If you have feedback or need assistance with the MCP directory API, please join our Discord server