akitana-airtanker/mcp-python-streamable-e2e-test-template
If you are the rightful owner of mcp-python-streamable-e2e-test-template and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
This is a template project for developing Python-based Model Context Protocol (MCP) servers using FastMCP and Docker.
Python MCP Server Template (FastMCP + Docker/Devcontainer)
This is a template project for efficiently developing Python-based Model Context Protocol (MCP) servers using FastMCP and Docker (Devcontainer).
It provides samples for basic MCP server functionalities (e.g., an add tool and a greeting resource), utilizes type hints, includes Ruff for static analysis and formatting, a test environment, and supports a ready-to-use development environment setup.
This repository is a Streamable-ready End-to-End (E2E) test template for MCP written in Python and comes with a Docker/Devcontainer setup out of the box.
Detailed explanatory articles have been published!
- English (dev.to): Python MCP Remote Server: The Dawn of the Streamable HTTP Era, with a Minimalist Template
- Japanese (Qiita): ใชใขใผใใตใผใใผใงๅใใ Python MCP Server โ Streamable HTTP ๆไปฃใฎๅงใพใ ~ uv / Docker / pytest ใๅใใใใใใซใใณใใฌใผใไปใ ~
Table of Contents
- Features
- Prerequisites
- Setup (Local Environment)
- Running the Server (Local Environment)
- Running the Client (Local Environment)
- Development with Devcontainer (Recommended)
- Running with Docker
- Running Tests (pytest)
- Connecting with MCP Inspector
- Current Features
- License
Features
- MCP Python SDK: Built upon the official Model Context Protocol Python SDK.
- FastMCP Based: Uses FastMCP (part of the SDK), a lightweight and fast MCP server library for Python.
- Docker & Devcontainer: Provides containerization with Docker and a consistent development environment with VS Code Dev Containers.
- The container runs as a non-root user (
appuser) for enhanced security.
- The container runs as a non-root user (
- Package Management with
uv: Employsuv, a fast Python package installer and resolver. - Static Analysis and Formatting: Linting and formatting with
Ruffare pre-configured. - Test Environment: Sample asynchronous tests using
pytestandpytest-asynciowith an execution environment. - Type Hints: Actively uses type hints throughout the project to improve code robustness and readability.
- Configurable Logging: Log output can be controlled via the
LOG_LEVELenvironment variable (e.g.,DEBUG,INFO,WARNING).
Prerequisites
- Python (3.10 or higher, see
pyproject.toml. Dockerfile uses 3.13-slim) uv(Python package management tool)- Docker (for container execution)
- (Optional) VS Code and Dev Containers extension (for Devcontainer usage)
Setup (Local Environment)
-
Create a new repository from this template or clone the repository. Use the "Use this template" button on GitHub or clone as follows:
git clone https://github.com/akitana-airtanker/mcp-python-streamable-e2e-test-template.git <your-project-name> cd <your-project-name>Replace
<your-project-name>with your project's name. -
Create a virtual environment and install dependencies. Run the following commands in the project's root directory:
uv venv uv pip install -e ".[test,dev]" # Install test and dev dependencies as wellThis creates a virtual environment in the
.venvdirectory and installs the necessary packages (including those for testing and development) based onpyproject.toml.
Using Ruff (Linter/Formatter) Locally
This template uses Ruff. To use it locally:
# Install Ruff (should already be installed with dev dependencies, but can be installed individually)
# uv pip install ruff
# Check code
ruff check .
# Format code
ruff format .
It's recommended to set up pre-commit hooks to automate this:
pre-commit install
Running the Server (Local Environment)
-
Activate the virtual environment (if not already activated).
source .venv/bin/activate -
Start the server.
mcp-server-demoThe server will start at
http://0.0.0.0:8000and listen for MCP requests. You can change the log verbosity by setting theLOG_LEVELenvironment variable (e.g.,LOG_LEVEL=DEBUG mcp-server-demo).
Running the Client (Local Environment)
- Ensure the server is running.
- Open another terminal and activate the virtual environment.
cd <your-project-name> # Navigate to the project root directory source .venv/bin/activate - Run the client.
The client will connect to the server, call the
mcp-client-demoaddtool, and print the result (Result of add(10, 5): 15) to the console. You can control the client's output verbosity using the--quietor--verboseflags:Themcp-client-demo --quiet # Suppresses print statements, logs WARNING and above mcp-client-demo --verbose # Enables DEBUG logging and print statementsLOG_LEVELenvironment variable can also be used to set the logging level, with CLI flags taking precedence if specified.
Development with Devcontainer (Recommended)
Using VS Code Dev Containers allows for an easy setup of a consistent development environment with all necessary tools and configurations.
-
Prerequisites:
- Visual Studio Code
- Docker Desktop
- VS Code's Dev Containers extension (recommended, though VS Code may automatically suggest installing it)
-
Open the Development Container:
- Open this project folder in VS Code.
- VS Code will detect the
.devcontainer/devcontainer.jsonfile and show a notification "Reopen in Container" in the bottom right. Click this notification. - Alternatively, open the Command Palette (Ctrl+Shift+P or Cmd+Shift+P), type "Dev Containers: Reopen in Container", and execute it.
-
Working inside the Container:
- Once the container is built and started, VS Code will automatically connect to the project inside the container.
- Opening a terminal will open a terminal inside the container.
mcp-server-demoandmcp-client-democan be run directly in this container terminal.# Start the server (in the container terminal) mcp-server-demo # Run the client (in another container terminal) mcp-client-demo- Dependencies (including
testanddevextras) are installed via the Dockerfile andpostCreateCommandindevcontainer.json, so all necessary packages are available when the container starts. Pre-commit hooks are also installed. - Linting and formatting with
Ruffwill be performed automatically due to VS Code settings. - The container runs as a non-root user (
appuser). - Port 8000 is automatically forwarded, so you can access
http://localhost:8000/mcp(for MCP Inspector) from your host machine's browser.
Running with Docker
-
Build the Docker image. Run the following command in the project's root directory:
docker build -t mcp-server . -
Run the Docker container.
docker run -p 8000:8000 -e LOG_LEVEL=DEBUG mcp-serverThis starts the MCP server inside the container and maps it to port 8000 on the host. You can control the server's log level in the container by passing environment variables like
-e LOG_LEVEL=DEBUG. The container runs as a non-root user (appuser).
Running Tests (pytest)
This repository includes a minimal test setup located in the tests/ directory (e.g., tests/test_client.py).
The tests start the FastMCP server on a dedicated port 8001 (configured in tests/conftest.py) and verify that tool calls work correctly.
Mechanism
- The
tests/conftest.pyfixture passesMCP_SERVER_PORT=8001as an environment variable to the child process when starting the server process. - In
src/mcp_python_streamable_e2e_test_template/server.py, theConfigclass readsMCP_SERVER_PORTandFASTMCP_PORT. IfMCP_SERVER_PORTis set andFASTMCP_PORTis not,FASTMCP_PORT(used by FastMCP) defaults to the value ofMCP_SERVER_PORT.This ensures that normal startup (# src/mcp_python_streamable_e2e_test_template/server.py # ... from .config import Config cfg = Config() if cfg.mcp_server_port and not cfg.fastmcp_port: os.environ.setdefault("FASTMCP_PORT", cfg.mcp_server_port) # ...mcp-server-demo) defaults to port 8000 (or the value ofFASTMCP_PORT/MCP_SERVER_PORTif set), while pytest execution uses port 8001 for the server.
Execution
# Assuming the virtual environment is activated
pytest
If the tests pass, you will see output similar to this:
collected 1 item
test_client.py . [100%]
============================= 1 passed in X.XXs =============================
Connecting with MCP Inspector
With the server running locally or in Docker, you can connect to it using MCP Inspector to verify its behavior.
-
Start MCP Inspector. Run the following command in a new terminal:
npx --yes @modelcontextprotocol/inspector -
Connect to MCP Inspector. Once MCP Inspector opens in your browser, connect with the following settings:
- Transport Type:
Streamable HTTP - URL:
http://localhost:8000/mcp
- Transport Type:
Current Features
addTool: Adds two numbers.- Example Input:
{"a": 10, "b": 5} - Example Output:
15(as TextContent)
- Example Input:
greetingResource: Returns a greeting for a specified name.- Example URI:
greeting://World - Example Output:
"Hello, World!"
- Example URI:
License
This project is licensed under the MIT License. See the file for details.