Building & Deploying MCP Basics
8 examples to get you started with a minimal MCP server - 5 basic and 3 intermediate.
Search across all documentation pages
8 examples to get you started with a minimal MCP server - 5 basic and 3 intermediate.
You will install the Python MCP SDK, expose one tool over stdio, keep logs off stdout, list tools from a tiny client, and sketch the jump to HTTP.
uv or pip for installspython -m venv .venv && source .venv/bin/activate
pip install "mcp[cli]"
# or: uv add "mcp[cli]"Start with a named server and a single health tool.
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("hello-mcp")
@mcp.tool()
def echo(message: str) -> str:
"""Echo a short message back to the client."""
return message
if __name__ == "__main__":
mcp.run(transport="stdio")transport="stdio" is the local default for desktop hosts.server.py and keep the process free of accidental print() calls.Related: Anatomy of an MCP Server: Handlers, Schemas, and Transport
Hosts spawn your process; you can also run it by hand to confirm it starts.
python server.py
# Process waits on stdin for JSON-RPC lines; Ctrl+C to stop.Never write diagnostics to stdout when using stdio transport.
import logging
import sys
logging.basicConfig(stream=sys.stderr, level=logging.INFO)
log = logging.getLogger("hello-mcp")
@mcp.tool()
def echo(message: str) -> str:
"""Echo a short message back to the client."""
log.info("echo called, len=%s", len(message))
return messageprint(..., file=sys.stderr) is also safe.Point Claude Desktop (or similar) at an absolute command.
{
"mcpServers": {
"hello-mcp": {
"command": "python",
"args": ["/ABSOLUTE/PATH/TO/server.py"]
}
}
}python path if dependencies are not global.echo appears.Schemas get richer when parameters are constrained.
from typing import Literal
@mcp.tool()
def greet(name: str, style: Literal["short", "formal"] = "short") -> str:
"""Greet a person in a short or formal style."""
if style == "formal":
return f"Good day, {name}."
return f"Hi, {name}!"Validate the server without a full desktop host.
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def main() -> None:
params = StdioServerParameters(
command="python",
args=["/ABSOLUTE/PATH/TO/server.py"],
)
async with stdio_client(params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
print([t.name for t in tools.tools], file=__import__("sys").stderr)
asyncio.run(main())initialize must succeed before list/call.Related: Building Your First MCP Server in TypeScript or Python
Drive one happy-path invocation for CI.
result = await session.call_tool("echo", {"message": "pong"})
# result.content is a list of content blocks; text tools usually expose .text
for block in result.content:
if hasattr(block, "text"):
print(block.text, file=__import__("sys").stderr)isError flags as failures when your SDK exposes them.Same tools, different transport, once you need a shared service.
# Development sketch - verify host/path/API at build for your SDK version
if __name__ == "__main__":
import os
mode = os.environ.get("MCP_TRANSPORT", "stdio")
if mode == "stdio":
mcp.run(transport="stdio")
else:
# e.g. mcp.run(transport="streamable-http") with host/port settings
mcp.run(transport="streamable-http")Related: Anatomy of an MCP Server: Handlers, Schemas, and Transport
Related: Building Your First MCP Server in TypeScript or Python
Stack versions: Pins from the category manifest (verify at build): OpenRouter (~315+ models, July 2026 pricing/fees); LangGraph 1.0+; CrewAI 1.14+; Microsoft Agent Framework 1.0; Vercel AI SDK 6; Pydantic AI (latest); LlamaIndex (latest); OpenAI Agents SDK (latest + MCP); MCP (Linux Foundation governance); A2A (HTTP+SSE+JSON-RPC 2.0); Solana
@solana/web3.js+@solana/spl-token.
Reviewed by Chris St. John·Last updated Jul 16, 2026