Hello World MCP Server
A simple FastMCP-based server implementing a Hello World example with tools, resources, and prompts.
Overview
This is a minimal but fully representative MCP (Machine Conversation Protocol) server built using the fastmcp framework in Python. It serves as a demonstration of core MCP concepts and functionality.
The server includes:
-
Tools: Functions that can be called by agents
say_hello: Greets a user by name and logs the interactionget_greeting_log: Returns a list of previously greeted namesclear_log: Clears the greeting history
-
Resources: Shared state components
greetings://log: Resource URI that provides access to the greeting log
-
Prompts: Natural language instructions for agents
greet_user: Template for creating a prompt to greet someone
Uvicorn Integration
This project showcases a production-ready setup using Uvicorn as the ASGI server. Uvicorn offers several advantages:
- Performance: Uvicorn is built on uvloop (an asyncio event loop) and httptools for high performance
- Concurrency: Better handling of concurrent requests
- Production-ready: Suitable for production deployments with features like TLS support and process management
- Scaling: Can be placed behind a reverse proxy like Nginx for horizontal scaling
The integration works by:
- Creating an ASGI application from FastMCP using
mcp.sse_app() - Exposing this application to Uvicorn at
main:app - Running Uvicorn programmatically with appropriate settings
Setup
-
Create and activate a virtual environment
python -m venv .venv source .venv/bin/activate # On Windows: .venv\\Scripts\\activate -
Install dependencies
pip install -r requirements.txt -
Run the server
./setup_and_run.shThe server will start on port 4242 with the MCP endpoint available at
/sse.
Running Options
The setup script supports several options:
./setup_and_run.sh [options]
Available options:
--no-uvicorn: Use the built-in FastMCP transport instead of Uvicorn--foreground: Run the server in the foreground (useful for debugging)--port=PORT: Specify a custom port (default: 4242)--host=HOST: Specify a custom host (default: 0.0.0.0)--help: Show all available options
Examples:
# Run in foreground mode for debugging
./setup_and_run.sh --foreground
# Run on a different port
./setup_and_run.sh --port=8000
# Run without Uvicorn (using built-in transport)
./setup_and_run.sh --no-uvicorn
Server Modes
The server can run in two distinct modes:
-
Uvicorn Mode (Default)
./setup_and_run.shThis mode uses Uvicorn as the ASGI server. You'll see log messages like:
INFO: Started server process [1234] INFO: Uvicorn running on http://0.0.0.0:4242 -
Built-in Transport Mode
./setup_and_run.sh --no-uvicornThis mode uses FastMCP's built-in transport. You'll see log messages like:
[04/23/25 hh:mm:ss] INFO Starting server "Hello World MCP Server"...
Testing
You can quickly test the server with:
./test_server.sh
This will start the server, run the test client, and then (optionally) shut down the server when testing is complete.
Using the Test Client
We provide a test client that demonstrates how to interact with the MCP server:
python test_client.py
This will:
- Test available endpoints
- Connect to the SSE endpoint
- List available tools, resources, and prompts
- Execute each tool to demonstrate functionality
Expected Output
When you run the test client, you'll see output similar to this:
Testing raw endpoints:
/: 404
/tools: 404
/mcp: 404
/mcp/tools: 404
/mcp/message: 404
/sse: 200 OK
/api: 404
Created client for server at http://localhost:4242/sse
Client message path: http://localhost:4242/sse
Testing MCP Client...
1. Listing available tools:
- name='say_hello' description='Greet a person by name.' inputSchema={...}
- name='get_greeting_log' description='Get a list of all greeted names.' inputSchema={...}
- name='clear_log' description='Clear the greeting history.' inputSchema={...}
2. Testing say_hello tool:
Result: [TextContent(type='text', text='{"message": "Hello, Alice!"}', annotations=None)]
3. Testing get_greeting_log tool:
Result: [TextContent(type='text', text='{"names": ["Alice"]}', annotations=None)]
4. Testing greeting log resource:
Resource: [TextResourceContents(uri=AnyUrl('greetings://log'), mimeType='text/plain', text='{"greeted_names": ["Alice"]}')]
5. Testing clear_log tool:
Result: [TextContent(type='text', text='{"status": "cleared"}', annotations=None)]
6. Verifying log is cleared:
Result: [TextContent(type='text', text='{"names": []}', annotations=None)]
7. Listing available prompts:
- name='greet_user' description='Create a prompt for greeting someone.' arguments=[...]
8. Testing greet_user prompt:
Prompt: [PromptMessage(role='user', content=TextContent(type='text', text='\\n Use the `say_hello` tool to greet Bob...')]
Key observations:
- Only the
/sseendpoint returns a 200 status code - this is normal and expected - Tool results come back as
TextContentobjects with JSON payloads - Resources are returned as
TextResourceContentsobjects with URIs and content - The greeting log stores and clears names correctly
- The prompt template generates a user message with instructions
The test client source (test_client.py) is commented and can be used as a reference for building your own MCP clients.
Using the Python MCP Client
import asyncio
from fastmcp import Client
async def main():
async with Client("http://localhost:4242/sse") as client:
# List available tools
tools = await client.list_tools()
print(tools)
# Call a tool
result = await client.call_tool("say_hello", {"name": "Alice"})
print(result)
asyncio.run(main())
Using curl
Direct HTTP REST API calls are not supported. FastMCP uses a WebSocket-based protocol for client-server communication through Server-Sent Events (SSE).
Implementation Details
This server demonstrates:
- Decorator-based API: Using decorators for tools, resources, and prompts
- Shared State: Maintaining state between requests using the GreetingLog
- SSE Transport: Using FastMCP's SSE transport for client communication
- Uvicorn Integration: Running as a production-ready ASGI server with Uvicorn
The server can run in two modes:
- Uvicorn mode (default): Uses Uvicorn's ASGI server for better performance and production readiness
- Built-in mode: Uses FastMCP's built-in server for simplicity
Architecture
Main Components
This project follows a modular architecture:
-
main.py: The core server definition with:
- FastMCP setup and configuration
- Tool, resource, and prompt definitions
- ASGI app initialization for Uvicorn
- Flexible runner that supports both Uvicorn and built-in modes
-
setup_and_run.sh: Deployment script with:
- Environment setup
- Port conflict detection
- Configurable runtime options
- Background/foreground process management
-
test_client.py: Client implementation that demonstrates:
- Endpoint discovery
- MCP client connection
- Tool and resource interaction
Uvicorn Integration Code
The key to the Uvicorn integration is in main.py:
# Create the ASGI app for Uvicorn to use
app = mcp.sse_app()
def run_server(use_uvicorn=True, host="0.0.0.0", port=4242):
"""Run the server using either Uvicorn or built-in transport."""
if use_uvicorn:
print(f"Starting server with Uvicorn on {host}:{port}")
uvicorn.run(
"main:app",
host=host,
port=port,
log_level="info"
)
else:
print(f"Starting server with built-in transport on port {port}")
mcp.run(transport="sse", host=host, port=port)
Debugging Tips
- Server logs are saved to
server.log - Run in foreground mode for immediate feedback:
./setup_and_run.sh --foreground - The FastMCP client connects to the
/sseendpoint, not directly to tool paths - Data is exchanged via a message-based protocol, not standard REST
- You can identify which mode the server is running in by checking the logs:
- Uvicorn mode: "INFO: Uvicorn running on http://0.0.0.0:PORT"
- Built-in mode: "INFO: Starting server 'Hello World MCP Server'..."
Here's an updated section that includes both configuration options:
Claude Desktop Integration
To configure Claude Desktop to use this MCP server, add one of the following configurations to your Claude Desktop configuration file:
- Windows:
%AppData%\\Claude\\claude_desktop_config.json - Mac:
~/Library/Application Support/Claude/claude_desktop_config.json
Option 1: Let Claude Desktop start the server
{
"mcpServers": {
"hello-world": {
"command": "python",
"args": [
"-m",
"main",
"--uvicorn"
],
"env": {},
"cwd": "/path/to/your/hello-world-mcp-server"
}
}
}
Option 2: Connect to an already running server
If you've already started the server manually using ./setup_and_run.sh:
{
"mcpServers": {
"hello-world": {
"url": "http://localhost:4242/sse"
}
}
}
After saving the configuration, restart Claude Desktop. You should see the hammer icon indicating MCP server availability. Click it to access the Hello World MCP tools.
Learn More
For more information about MCP, see:
Recommend MCP Servers 💡
@mzxrai/mcp-webresearch
A Model Context Protocol (MCP) server for web research. Bring real-time info into Claude and easily research any topic.
anoncam/linear-mcp
A Model Context Protocol (MCP) server for Linear, providing AI assistants with access to Linear's project management capabilities, including resources, tools, and prompt templates.
@alanse/fish-audio-mcp-server
MCP server integrating Fish Audio's TTS API with LLMs for natural language-driven speech synthesis.
kagimcp
The Official Model Context Protocol (MCP) server for Kagi search & other tools.
mcp-server-indexnow
An MCP server that bridges MCP clients with the IndexNow protocol for submitting URLs to search engines.
rootly-mcp-server
Rootly MCP server