This tutorial demonstrates how to use the Model Context Protocol (MCP) with different transport modes: stdio, SSE, and Streamable HTTP. The example MCP server implements a simple calculator with an add
tool that adds two integers. The tutorial covers both running the server using Python scripts and deploying it using Docker containers.
- Python 3.12
- Node.js and npm (for MCP Inspector 0.14.0)
- uv package manager
- MCP Python library: mcp[cli]==1.9.4
- httpx>=0.28.1
- Docker (for containerized deployment)
# Initialize uv
uv init
# Create virtual environment and activate it
uv venv
source .venv/bin/activate
# Install dependencies
uv add "mcp[cli]==1.9.4" "httpx>=0.28.1"
Install Node.js and npm on your local machine, then execute the command to launch the MCP inspector:
npx -y @modelcontextprotocol/inspector@0.14.0
Note: Ensure MCP inspector version is >= 0.12.0 to support streamable HTTP mode
MCP supports three different transport modes, each with its own characteristics and use cases:
- Definition: Uses standard input/output streams (stdin, stdout, stderr)
- Key Features:
- One-to-one coupling: Each client directly owns its server subprocess
- Auto-cleanup: Server process terminates automatically when client exits
- Optimal for local use: Ideal for desktop applications like Claude Desktop App, Cursor, etc.
- Definition: Uses Server-Sent Events with two endpoints:
- POST /messages (commands)
- GET /sse (streamed replies)
- Limitations:
- Stateful design by default
- Hard to scale beyond 2 replicas without sticky session management
- Being phased out in favor of Streamable HTTP
- Definition: Uses a single endpoint
/mcp
supporting both GET and POST methods - Advantages:
- Built-in session handling
- Resumable connections
- Simpler architecture
- Optional SSE streaming support
- Enables stateless server designs
- Better scalability and reliability
The stdio server should not be run directly as it requires a client connection due to its one-to-one coupling nature.
# List all the tools
uv run python client.py ./server_stdio.py
# The client will automatically start the server as a subprocess
uv run python client.py ./server_stdio.py add a=5 b=3
Configuration the connection:
- Transport Type: STDIO
- Command: uv
- Arguments: run python server_stdio.py
Testing the
add
tool in stdio mode. The client automatically starts the server as a subprocess.
# Start the SSE server
uv run python server_sse.py
# List all the tools
uv run python client.py http://127.0.0.1:8000/sse
# Connect to the SSE server and call the add tool
uv run python client.py http://127.0.0.1:8000/sse add a=10 b=20
Configuration the connection:
- Transport Type: SSE
- URL: http://127.0.1:8000/sse
Testing the
add
tool in SSE mode. The server runs independently and communicates via Server-Sent Events.
# Start the Streamable HTTP server
uv run python server_streamable_http.py
# List all the tools
uv run python client.py http://127.0.0.1:8000/mcp
# Connect to the Streamable HTTP server and call the add tool
uv run python client.py http://127.0.0.1:8000/mcp add a=100 b=200
Configuration the connection:
- Transport Type: Streamable HTTP
- URL: http://127.0.1:8000/mcp
Testing the
add
tool in Streamable HTTP mode. The server uses a single endpoint for both commands and responses.
# Build the Docker image for stdio mode
docker build -t simple-mcp-server-stdio -f Dockerfile.stdio .
You cannot test the client directly since the server is in the Docker container and is not set up by the client in this script. However, you can implement your own code to set up Docker as a process and connect the client with it.
Configuration the connection:
- Transport Type: STDIO
- Command: docker
- Arguments: run -i --rm simple-mcp-server-stdio
Testing the
add
tool in stdio mode using Docker. Note that stdio mode is primarily designed for local use.
# Build the Docker image for SSE mode
docker build -t simple-mcp-server-sse -f Dockerfile.sse .
# Run the SSE server container
docker run -p 8000:8000 simple-mcp-server-sse
# List all the tools
uv run python client.py http://127.0.0.1:8000/sse
# Connect to the SSE server and call the add tool
uv run python client.py http://127.0.0.1:8000/sse add a=10 b=20
Configuration the connection:
- Transport Type: SSE
- URL: http://127.0.1:8000/sse
Testing the
add
tool in SSE mode using Docker. The server runs in an isolated environment with all dependencies included.
# Build the Docker image for Streamable HTTP mode
docker build -t simple-mcp-server-http -f Dockerfile.http .
# Run the Streamable HTTP server container
docker run -p 8000:8000 simple-mcp-server-http
# List all the tools
uv run python client.py http://127.0.0.1:8000/mcp
# Connect to the Streamable HTTP server and call the add tool
uv run python client.py http://127.0.0.1:8000/mcp add a=100 b=200
Configuration the connection:
- Transport Type: Streamable HTTP
- URL: http://127.0.1:8000/mcp
Testing the
add
tool in Streamable HTTP mode using Docker. The server runs in an isolated environment with all dependencies included.
The repository includes a weather service example in weather_mcp.py
.
-
Follow the official guide at Testing Your Server with Claude Desktop
-
Use the provided
weather_mcp.py
script as your MCP server and make sure the MCP Configuration is:
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/",
"run",
"weather_mcp.py"
]
}
}
}
- Build the Docker image:
docker build -t weather-mcp-server-stdio -f Dockerfile.weather.stdio .
- Configure Claude Desktop App:
- Open Claude Desktop App settings
- Add the following MCP configuration:
{
"mcpServers": {
"weather": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"weather-mcp-server-stdio"
]
}
}
}
- Verify the setup:
To use MCP with the Cursor App, follow the Cursor integration guide for MCP.
You can use the same configuration as for Claude Desktop. Once configured, you can call the weather MCP and receive responses directly in Cursor, as shown below: