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
Ruff
are pre-configured. - Test Environment: Sample asynchronous tests using
pytest
andpytest-asyncio
with 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_LEVEL
environment 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 well
This creates a virtual environment in the
.venv
directory 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-demo
The server will start at
http://0.0.0.0:8000
and listen for MCP requests. You can change the log verbosity by setting theLOG_LEVEL
environment 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-demo
add
tool, and print the result (Result of add(10, 5): 15
) to the console. You can control the client's output verbosity using the--quiet
or--verbose
flags:Themcp-client-demo --quiet # Suppresses print statements, logs WARNING and above mcp-client-demo --verbose # Enables DEBUG logging and print statements
LOG_LEVEL
environment 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.json
file 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-demo
andmcp-client-demo
can 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
test
anddev
extras) are installed via the Dockerfile andpostCreateCommand
indevcontainer.json
, so all necessary packages are available when the container starts. Pre-commit hooks are also installed. - Linting and formatting with
Ruff
will 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-server
This 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.py
fixture passesMCP_SERVER_PORT=8001
as an environment variable to the child process when starting the server process. - In
src/mcp_python_streamable_e2e_test_template/server.py
, theConfig
class readsMCP_SERVER_PORT
andFASTMCP_PORT
. IfMCP_SERVER_PORT
is set andFASTMCP_PORT
is 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_PORT
if 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
add
Tool: Adds two numbers.- Example Input:
{"a": 10, "b": 5}
- Example Output:
15
(as TextContent)
- Example Input:
greeting
Resource: 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.