Skip to main content
Glama

MCP Template

README.md10.8 kB
# 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 ```bash # 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 ```bash # Initialize default configuration mcp-template init # This creates: # - config/config.yaml (server configuration) # - .env (environment variables) ``` ### Run the Server ```bash # 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: ```yaml 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: ```bash # 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: ```bash # 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/`: ```python # 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"] } ) ``` 2. Register it in `src/mcp_template/app.py`: ```python 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, ) ``` 3. Enable it in `config/config.yaml`: ```yaml tools: enabled: - "my_tool" ``` ### Adding a New Resource Similar pattern - create handler and schema, register in `app.py`, enable in config. ```python # 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 ```python # 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: ```python 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: ```python from mcp_template.registry.manager import RegistryManager registry_manager = RegistryManager(settings, client=MyRegistryClient()) ``` ## Development ### Setup Development Environment ```bash # Install with development dependencies pip install -e ".[dev]" # Or using make make install ``` ### Running Tests ```bash # 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 ```bash # Format code make format # Lint code make lint # Type check make typecheck # Run all checks make check ``` ### Pre-commit Hooks ```bash # Install pre-commit hooks pre-commit install # Run manually pre-commit run --all-files ``` ## Deployment ### Docker Create a `Dockerfile`: ```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: ```bash 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: ```bash config/ ├── config.yaml # Default ├── config.dev.yaml # Development ├── config.staging.yaml # Staging └── config.prod.yaml # Production ``` Run with specific config: ```bash mcp-template run --config config/config.prod.yaml ``` ## Monitoring and Observability ### Structured Logging All logs are structured (JSON format by default) for easy parsing: ```json { "timestamp": "2024-01-01T12:00:00.000Z", "level": "info", "event": "Server started", "server": "my-server", "version": "0.1.0" } ``` ### Health Checks ```bash # 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** ```bash # Initialize configuration mcp-template init # Or specify path mcp-template run --config path/to/config.yaml ``` **Registry connection failed** ```bash # Check registry health mcp-template health # Disable registry temporarily # In config.yaml: registry: enabled: false ``` **Import errors** ```bash # 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 - [MCP Documentation](https://modelcontextprotocol.io/) - [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) - [Pydantic Documentation](https://docs.pydantic.dev/) - [Structlog Documentation](https://www.structlog.org/) ## Support For issues, questions, or contributions, please open an issue on GitHub.

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