Skip to content

Its a template that can be extended to write MCP servers following Enterprise best practices around Security and Deployment on Kubernetes

License

Notifications You must be signed in to change notification settings

redhat-data-and-ai/template-mcp-server

Repository files navigation

Template MCP Server

Python 3.12+ Tests Coverage License: Apache 2.0

Description

A production-ready template for developing Model Context Protocol (MCP) servers using Python and FastMCP. This server provides a foundation for creating MCP-compliant servers with comprehensive examples of tools, structured logging, configuration management, and containerized deployment.

The template includes three example MCP tools: a multiply calculator, a code review prompt generator, and a Red Hat logo resource handler. It demonstrates best practices for MCP server development including proper error handling, health checks, multiple transport protocols (HTTP, SSE, streamable-HTTP), SSL support, and comprehensive development tooling.

Architecture

System Architecture

graph TB
    subgraph "External Clients"
        A[Claude Code/LLM Client]
        B[Custom MCP Client]
        C[Development Tools]
    end

    subgraph "Network Layer"
        D[Load Balancer/Proxy]
        E[SSL Termination]
    end

    subgraph "Template MCP Server"
        subgraph "Application Layer"
            F[FastAPI Application<br/>api.py]
            G[Health Check Endpoint<br/>/health]
            H[MCP Protocol Handler<br/>/mcp]
        end

        subgraph "MCP Core"
            I[TemplateMCPServer<br/>mcp.py]
            J[FastMCP Instance<br/>Protocol Implementation]
            K[Tool Registry<br/>Dynamic Registration]
        end

        subgraph "Tool Layer"
            L[Mathematical Tools<br/>multiply_numbers]
            M[Resource Tools<br/>redhat_logo]
            N[Prompt Tools<br/>code_review_prompt]
            O[Custom Tools<br/>Extensible]
        end

        subgraph "Infrastructure Layer"
            P[Configuration Management<br/>settings.py]
            Q[Structured Logging<br/>pylogger.py]
            R[Error Handling<br/>Exception Management]
            S[Asset Management<br/>Static Resources]
        end

        subgraph "Transport Layer"
            T[HTTP Transport]
            U[SSE Transport]
            V[Streamable HTTP Transport]
        end
    end

    subgraph "External Dependencies"
        W[Environment Variables<br/>.env]
        X[SSL Certificates<br/>TLS/HTTPS]
        Y[Static Assets<br/>Images/Files]
        Z[Container Runtime<br/>Docker/Podman]
    end

    A --> D
    B --> D
    C --> D
    D --> E
    E --> F
    F --> G
    F --> H
    H --> I
    I --> J
    J --> K
    K --> L
    K --> M
    K --> N
    K --> O
    I --> P
    I --> Q
    I --> R
    M --> S
    F --> T
    F --> U
    F --> V
    P --> W
    E --> X
    S --> Y
    Z --> F

    classDef client fill:#e3f2fd
    classDef network fill:#f3e5f5
    classDef application fill:#e8f5e8
    classDef core fill:#fff3e0
    classDef tools fill:#fce4ec
    classDef infrastructure fill:#f1f8e9
    classDef transport fill:#fef7e0
    classDef external fill:#f5f5f5

    class A,B,C client
    class D,E network
    class F,G,H application
    class I,J,K core
    class L,M,N,O tools
    class P,Q,R,S infrastructure
    class T,U,V transport
    class W,X,Y,Z external
Loading

Control Flow

flowchart TD
    A[MCP Client Request] --> B{Transport Protocol?}

    B -->|HTTP/Streamable-HTTP| C[FastAPI App<br/>api.py]
    B -->|SSE| D[SSE App<br/>create_sse_app]

    C --> E[Health Check?]
    D --> E

    E -->|/health| F[Health Endpoint<br/>Return Status]
    E -->|/mcp| G[MCP Request Handler<br/>FastMCP Instance]

    G --> H{MCP Method Type?}

    H -->|tools/list| I[List Available Tools<br/>Return tool definitions]
    H -->|tools/call| J[Tool Execution Router<br/>mcp.py]

    J --> K{Which Tool?}

    K -->|multiply_numbers| L[Multiply Tool<br/>multiply_tool.py]
    K -->|read_redhat_logo_content| M[Logo Resource Tool<br/>redhat_logo.py]
    K -->|get_code_review_prompt| N[Code Review Prompt<br/>code_review_prompt_tool.py]

    L --> O[Validate Input<br/>Check numeric types]
    M --> P[Read Asset File<br/>Base64 encode PNG]
    N --> Q[Generate Prompt<br/>Format code review template]

    O --> R[Perform Calculation<br/>a * b]
    P --> S[Return Image Data<br/>MIME type + base64]
    Q --> T[Return Prompt Array<br/>Structured messages]

    R --> U[Log Result<br/>Structured logging]
    S --> U
    T --> U

    U --> V[Return Success Response<br/>JSON format]

    V --> W[Send to MCP Client<br/>Complete request cycle]

    F --> W
    I --> W

    X[Configuration Loading<br/>settings.py] --> Y[Environment Variables<br/>.env file]
    Y --> Z[Pydantic Validation<br/>Type checking & defaults]
    Z --> AA[Server Startup<br/>main.py]
    AA --> C
    AA --> D

    BB[Error Handling] --> CC[Structured Logging<br/>pylogger.py]
    CC --> DD[JSON Output<br/>Timestamp + Context]

    O --> BB
    P --> BB
    Q --> BB

    classDef request fill:#e3f2fd
    classDef routing fill:#f3e5f5
    classDef tools fill:#e8f5e8
    classDef config fill:#fff3e0
    classDef logging fill:#fce4ec

    class A,B,E,H,K request
    class C,D,G,J routing
    class L,M,N,O,P,Q,R,S,T tools
    class X,Y,Z,AA config
    class BB,CC,DD logging
Loading

Code Structure

template-mcp-server/
├── template_mcp_server/           # Main package directory
│   ├── __init__.py
│   ├── src/                       # Core source code
│   │   ├── __init__.py
│   │   ├── main.py               # Application entry point & startup logic
│   │   ├── api.py                # FastAPI application & transport setup
│   │   ├── mcp.py                # MCP server implementation & tool registration
│   │   ├── settings.py           # Pydantic-based configuration management
│   │   └── tools/                # MCP tool implementations
│   │       ├── __init__.py
│   │       ├── multiply_tool.py  # Mathematical operations tool
│   │       ├── code_review_prompt_tool.py  # Code review prompt generator
│   │       ├── redhat_logo.py    # Base64 image resource handler
│   │       └── assets/           # Static resource files
│   │           └── redhat.png    # Example image asset
│   └── utils/                    # Shared utilities
│       ├── __init__.py
│       └── pylogger.py          # Structured logging with structlog
├── tests/                        # Comprehensive test suite (81+ tests)
│   ├── __init__.py              # Test package initialization
│   ├── conftest.py              # Pytest fixtures and configuration
│   ├── test_multiply_tool.py    # Unit tests for multiply tool (12 tests)
│   ├── test_redhat_logo.py      # Unit tests for logo tool (10 tests)
│   ├── test_code_review_prompt.py  # Unit tests for prompt tool (14 tests)
│   ├── test_settings.py         # Unit tests for configuration (20 tests)
│   ├── test_mcp_server.py       # Unit tests for MCP server (15 tests)
│   └── test_integration.py      # Integration tests (10 tests)
├── pyproject.toml               # Project metadata & dependencies
├── Containerfile               # Red Hat UBI-based container build
├── compose.yaml                # Docker Compose orchestration
├── .env.example                # Environment configuration template
├── .gitignore                  # Version control exclusions
├── .pre-commit-config.yaml     # Code quality automation
└── README.md                   # Project documentation

Key Components

  • main.py: Application entry point with configuration validation, error handling, and uvicorn server startup
  • api.py: FastAPI application setup with transport protocol selection (HTTP/SSE/streamable-HTTP) and health endpoints
  • mcp.py: Core MCP server class that registers tools using FastMCP decorators
  • settings.py: Environment-based configuration using Pydantic BaseSettings with validation
  • tools/: MCP tool implementations demonstrating arithmetic, prompts, and resource access patterns
  • utils/pylogger.py: Structured JSON logging using structlog with comprehensive processors

Current MCP Tools

  1. multiply_numbers: Demonstrates basic arithmetic operations with error handling
  2. read_redhat_logo_content: Shows resource access patterns with base64 encoding
  3. get_code_review_prompt: Illustrates prompt generation for code analysis

How to Run the Code Locally

Prerequisites

  • Python 3.12 or higher
  • uv (fast Python package installer and resolver)

Setup

  1. Install uv (if not already installed):

    # On macOS/Linux:
    curl -LsSf https://astral.sh/uv/install.sh | sh
    
    # On MacOS using brew
    brew install uv
    
    # On Windows:
    powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
    
    # Or with pip:
    pip install uv
  2. Clone the repository:

    git clone https://github.com/redhat-data-and-ai/template-mcp-server
    cd template-mcp-server
  3. Create and activate a virtual environment with uv:

    uv venv
    
    # Activate the virtual environment:
    # On macOS/Linux:
    source .venv/bin/activate
    
    # On Windows:
    .venv\Scripts\activate
  4. Install the package and dependencies:

    # Install in editable mode with all dependencies
    uv pip install -e .
  5. Configure environment variables:

    cp .env.example .env
    # Edit .env file with your configuration
  6. Run the server:

    # Using the installed console script
    template-mcp-server
    
    # Or directly with Python module
    python -m template_mcp_server.src.main
    
    # Or using uv to run directly
    uv run python -m template_mcp_server.src.main

Configuration Options

The server configuration is managed through environment variables:

Variable Default Description
MCP_HOST 0.0.0.0 Server bind address
MCP_PORT 3000 Server port (1024-65535)
MCP_TRANSPORT_PROTOCOL streamable-http Transport protocol (http, sse, streamable-http)
MCP_SSL_KEYFILE None SSL private key file path
MCP_SSL_CERTFILE None SSL certificate file path
PYTHON_LOG_LEVEL INFO Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)

Using Podman

  1. Build and run with Podman Compose:

    podman-compose up --build
  2. Or build manually:

    podman build -t template-mcp-server .
    podman run -p 3000:3000 --env-file .env template-mcp-server

Deploying to OpenShift

See the OpenShift Deployment Guide for complete instructions.

Quick start:

# Deploy to OpenShift namespace
make deploy openshift NAMESPACE=your-project-name

# Remove deployment
make undeploy openshift

Deploying to Managed Platform (MPP)

Deploy to Red Hat Managed Platform with tenant configuration:

# Deploy to MPP with tenant
make deploy mpp TENANT=ask-data

# Remove MPP deployment
make undeploy mpp TENANT=ask-data

Verify Installation

  1. Health check:

    curl http://localhost:3000/health
  2. Test MCP tools:

    # Test multiply tool via MCP endpoint
    curl -X POST "http://localhost:3000/mcp" \
         -H "Content-Type: application/json" \
         -d '{"method": "tools/call", "params": {"name": "multiply_numbers", "arguments": {"a": 5, "b": 3}}}'

How to Test the Code Locally

Development Environment Setup

  1. Install development dependencies:

    uv pip install -e ".[dev]"
  2. Install pre-commit hooks:

    pre-commit install

Running Tests

The project includes a comprehensive test suite with 81+ tests covering unit tests, integration tests, and various edge cases.

  1. Run all tests:

    pytest
  2. Run tests with coverage reporting:

    pytest --cov=template_mcp_server --cov-report=html --cov-report=term
  3. Run tests by category:

    # Unit tests only
    pytest -m unit
    
    # Integration tests only
    pytest -m integration
    
    # Slow running tests
    pytest -m slow
    
    # Tests requiring network access
    pytest -m network
  4. Run specific test modules:

    # Test individual components
    pytest tests/test_multiply_tool.py -v
    pytest tests/test_redhat_logo.py -v
    pytest tests/test_code_review_prompt.py -v
    pytest tests/test_settings.py -v
    pytest tests/test_mcp_server.py -v
    
    # Run integration tests
    pytest tests/test_integration.py -v
  5. Run tests with different output formats:

    # Verbose output with detailed test names
    pytest -v
    
    # Short traceback format
    pytest --tb=short
    
    # Quiet output (minimal)
    pytest -q

Code Quality Checks

  1. Linting and formatting with Ruff:

    # Check for issues
    ruff check .
    
    # Auto-fix issues
    ruff check . --fix
    
    # Format code
    ruff format .
  2. Type checking with MyPy:

    mypy template_mcp_server/
  3. Docstring validation:

    pydocstyle template_mcp_server/ --convention=google
  4. Run all pre-commit checks:

    pre-commit run --all-files

Test Suite Overview

The project includes a comprehensive test suite with the following structure:

Test Category Count Description
Unit Tests 71 Individual component testing with mocking
Integration Tests 10 End-to-end workflow testing
Total Tests 81+ Complete test coverage

Test Files:

  • test_multiply_tool.py - 12 tests covering arithmetic operations, edge cases, error handling
  • test_redhat_logo.py - 10 tests covering async file operations, base64 encoding, error scenarios
  • test_code_review_prompt.py - 14 tests covering prompt generation, multiple languages, formatting
  • test_settings.py - 20 tests covering configuration, environment variables, validation
  • test_mcp_server.py - 15 tests covering server initialization, tool registration, error handling
  • test_integration.py - 10 tests covering complete workflows and system integration

Test Features:

  • ✅ Comprehensive error handling validation
  • ✅ Async function testing support
  • ✅ Mock external dependencies
  • ✅ Environment isolation with fixtures
  • ✅ Performance testing for large data
  • ✅ Concurrent usage simulation
  • ✅ Configuration validation testing

Manual Testing

  1. Container testing:

    docker-compose up -d
    curl -f http://localhost:3000/health
    docker-compose down
  2. SSL testing (if configured):

    curl -k https://localhost:3000/health

Continuous Integration & Deployment

This project uses GitHub Actions for automated CI/CD workflows to ensure code quality, security, and reliability.

CI/CD Workflows

Workflow Trigger Purpose
CI Push to main, PRs Run tests, linting, type checking, security scans
Dependency Updates Weekly schedule Automated dependency updates and security audits

CI Pipeline Features

✅ Code Quality Assurance:

  • Multi-Python version testing (3.12, 3.13)
  • Comprehensive test suite execution (81+ tests)
  • Code coverage reporting (80%+ requirement)
  • Ruff linting and formatting validation
  • MyPy type checking
  • Docstring validation with pydocstyle

✅ Security & Compliance:

  • Bandit security linting
  • Safety dependency vulnerability scanning

✅ Automation & Maintenance:

  • Dependabot configuration for automated dependency updates
  • Pre-commit hook automation
  • Weekly security audits
  • Automated PR creation for dependency updates

Running CI Checks Locally

Before pushing code, run the same checks that CI runs:

# Install development dependencies
uv pip install -e ".[dev]"

# Run all pre-commit checks
pre-commit run --all-files

# Run tests with coverage
pytest --cov=template_mcp_server --cov-fail-under=80

# Run security checks
bandit -r template_mcp_server/
safety check

# Build and test container
docker build -t template-mcp-server .
docker run --rm template-mcp-server python -c "import template_mcp_server; print('OK')"

Branch Protection

The main branch is protected with the following requirements:

  • All CI checks must pass
  • Pull request reviews required
  • Up-to-date branches required
  • No direct pushes to main

How to Contribute

Development Workflow

  1. Fork and clone:

    git fork <repository-url>
    git clone <your-fork-url>
    cd template-mcp-server
  2. Create feature branch:

    git checkout -b feature/your-feature-name
  3. Set up development environment:

    uv venv
    source .venv/bin/activate  # On Windows: .venv\Scripts\activate
    uv pip install -e ".[dev]"
    pre-commit install
  4. Make changes following our standards

  5. Run comprehensive testing:

    # Code quality
    ruff check . --fix
    ruff format .
    mypy template_mcp_server/
    
    # Tests
    pytest --cov=template_mcp_server
    
    # Pre-commit validation
    pre-commit run --all-files
  6. Commit and push:

    git add .
    git commit -m "feat: descriptive commit message"
    git push origin feature/your-feature-name
  7. Create Pull Request

Coding Standards

  • Python Style: Follow PEP 8 (enforced by Ruff)
  • Type Annotations: Required for all public functions and methods
  • Documentation: Google-style docstrings for all public APIs
  • Testing: Write tests for new functionality with pytest
  • Commits: Use conventional commit format (feat:, fix:, docs:, etc.)
  • Error Handling: Use structured logging and proper exception handling

Adding New MCP Tools

  1. Create tool module:

    # template_mcp_server/src/tools/your_tool.py
    async def your_tool_function(param: str) -> dict:
        """Your tool description.
    
        Args:
            param: Parameter description.
    
        Returns:
            dict: Result dictionary.
        """
        # Implementation here
        return {"result": "success"}
  2. Register in MCP server:

    # In template_mcp_server/src/mcp.py
    from template_mcp_server.src.tools.your_tool import your_tool_function
    
    def _register_mcp_tools(self) -> None:
        self.mcp.tool()(your_tool_function)  # Add this line
  3. Add tests:

    # tests/test_your_tool.py
    import pytest
    from template_mcp_server.src.tools.your_tool import your_tool_function
    
    @pytest.mark.asyncio
    async def test_your_tool():
        result = await your_tool_function("test_param")
        assert result["result"] == "success"
  4. Update documentation

Adding New Resources

  1. Place assets in: template_mcp_server/src/tools/assets/
  2. Create resource handler in: template_mcp_server/src/tools/
  3. Register in: template_mcp_server/src/mcp.py
  4. Add tests and documentation

Code Review Guidelines

  • All changes require pull request review
  • Automated checks must pass (tests, linting, type checking)
  • Documentation should be updated for user-facing changes
  • Breaking changes require discussion and versioning consideration

Getting Help

  • Issues: Open GitHub issues for bugs or feature requests
  • Discussions: Use GitHub Discussions for questions
  • Documentation: Check existing docs and code examples
  • Testing: Provide minimal reproduction cases for bugs

About

Its a template that can be extended to write MCP servers following Enterprise best practices around Security and Deployment on Kubernetes

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 8