Skip to content

README - replace code snippets with examples #1136

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
360 changes: 195 additions & 165 deletions README.md

Large diffs are not rendered by default.

Empty file.
80 changes: 80 additions & 0 deletions examples/snippets/clients/completion_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"""MCP client example showing completion usage.

This example demonstrates how to use the completion feature in MCP clients.
cd to the `examples/snippets` directory and run:
uv run completion-client
"""

import asyncio
import os

from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from mcp.types import PromptReference, ResourceTemplateReference

# Create server parameters for stdio connection
server_params = StdioServerParameters(
command="uv", # Using uv to run the server
args=["run", "server", "completion", "stdio"], # Server with completion support
env={"UV_INDEX": os.environ.get("UV_INDEX", "")},
)


async def run():
"""Run the completion client example."""
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
# Initialize the connection
await session.initialize()

# List available resource templates
templates = await session.list_resource_templates()
print("Available resource templates:")
for template in templates.resourceTemplates:
print(f" - {template.uriTemplate}")

# List available prompts
prompts = await session.list_prompts()
print("\nAvailable prompts:")
for prompt in prompts.prompts:
print(f" - {prompt.name}")

# Complete resource template arguments
if templates.resourceTemplates:
template = templates.resourceTemplates[0]
print(f"\nCompleting arguments for resource template: {template.uriTemplate}")

# Complete without context
result = await session.complete(
ref=ResourceTemplateReference(type="ref/resource", uri=template.uriTemplate),
argument={"name": "owner", "value": "model"},
)
print(f"Completions for 'owner' starting with 'model': {result.completion.values}")

# Complete with context - repo suggestions based on owner
result = await session.complete(
ref=ResourceTemplateReference(type="ref/resource", uri=template.uriTemplate),
argument={"name": "repo", "value": ""},
context_arguments={"owner": "modelcontextprotocol"},
)
print(f"Completions for 'repo' with owner='modelcontextprotocol': {result.completion.values}")

# Complete prompt arguments
if prompts.prompts:
prompt_name = prompts.prompts[0].name
print(f"\nCompleting arguments for prompt: {prompt_name}")

result = await session.complete(
ref=PromptReference(type="ref/prompt", name=prompt_name),
argument={"name": "style", "value": ""},
)
print(f"Completions for 'style' argument: {result.completion.values}")


def main():
"""Entry point for the completion client."""
asyncio.run(run())


if __name__ == "__main__":
main()
85 changes: 85 additions & 0 deletions examples/snippets/clients/stdio_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
"""MCP client example using stdio transport.

This is a documentation example showing how to write an MCP client.
cd to the `examples/snippets/clients` directory and run:
uv run client
"""

import asyncio
import os

from pydantic import AnyUrl

from mcp import ClientSession, StdioServerParameters, types
from mcp.client.stdio import stdio_client
from mcp.shared.context import RequestContext

# Create server parameters for stdio connection
server_params = StdioServerParameters(
command="uv", # Using uv to run the server
args=["run", "server", "fastmcp_quickstart", "stdio"], # We're already in snippets dir
env={"UV_INDEX": os.environ.get("UV_INDEX", "")},
)


# Optional: create a sampling callback
async def handle_sampling_message(
context: RequestContext, params: types.CreateMessageRequestParams
) -> types.CreateMessageResult:
print(f"Sampling request: {params.messages}")
return types.CreateMessageResult(
role="assistant",
content=types.TextContent(
type="text",
text="Hello, world! from model",
),
model="gpt-3.5-turbo",
stopReason="endTurn",
)


async def run():
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write, sampling_callback=handle_sampling_message) as session:
# Initialize the connection
await session.initialize()

# List available prompts
prompts = await session.list_prompts()
print(f"Available prompts: {[p.name for p in prompts.prompts]}")

# Get a prompt (greet_user prompt from fastmcp_quickstart)
if prompts.prompts:
prompt = await session.get_prompt("greet_user", arguments={"name": "Alice", "style": "friendly"})
print(f"Prompt result: {prompt.messages[0].content}")

# List available resources
resources = await session.list_resources()
print(f"Available resources: {[r.uri for r in resources.resources]}")

# List available tools
tools = await session.list_tools()
print(f"Available tools: {[t.name for t in tools.tools]}")

# Read a resource (greeting resource from fastmcp_quickstart)
resource_content = await session.read_resource(AnyUrl("greeting://World"))
content_block = resource_content.contents[0]
if isinstance(content_block, types.TextContent):
print(f"Resource content: {content_block.text}")

# Call a tool (add tool from fastmcp_quickstart)
result = await session.call_tool("add", arguments={"a": 5, "b": 3})
result_unstructured = result.content[0]
if isinstance(result_unstructured, types.TextContent):
print(f"Tool result: {result_unstructured.text}")
result_structured = result.structuredContent
print(f"Structured tool result: {result_structured}")


def main():
"""Entry point for the client script."""
asyncio.run(run())


if __name__ == "__main__":
main()
6 changes: 4 additions & 2 deletions examples/snippets/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

[tool.setuptools]
packages = ["servers"]
packages = ["servers", "clients"]

[project.scripts]
server = "servers:run_server"
server = "servers:run_server"
client = "clients.stdio_client:main"
completion-client = "clients.completion_client:main"
3 changes: 2 additions & 1 deletion examples/snippets/servers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ def run_server():
if len(sys.argv) < 2:
print("Usage: server <server-name> [transport]")
print("Available servers: basic_tool, basic_resource, basic_prompt, tool_progress,")
print(" sampling, elicitation, completion, notifications")
print(" sampling, elicitation, completion, notifications,")
print(" fastmcp_quickstart, structured_output, images")
print("Available transports: stdio (default), sse, streamable-http")
sys.exit(1)

Expand Down
38 changes: 38 additions & 0 deletions examples/snippets/servers/fastmcp_quickstart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""
FastMCP quickstart example.

cd to the `examples/snippets/clients` directory and run:
uv run server fastmcp_quickstart stdio
"""

from mcp.server.fastmcp import FastMCP

# Create an MCP server
mcp = FastMCP("Demo")


# Add an addition tool
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b


# Add a dynamic greeting resource
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
"""Get a personalized greeting"""
return f"Hello, {name}!"


# Add a prompt
@mcp.prompt()
def greet_user(name: str, style: str = "friendly") -> str:
"""Generate a greeting prompt"""
styles = {
"friendly": "Please write a warm, friendly greeting",
"formal": "Please write a formal, professional greeting",
"casual": "Please write a casual, relaxed greeting",
}

return f"{styles.get(style, styles['friendly'])} for someone named {name}."
15 changes: 15 additions & 0 deletions examples/snippets/servers/images.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"""Example showing image handling with FastMCP."""

from PIL import Image as PILImage

from mcp.server.fastmcp import FastMCP, Image

mcp = FastMCP("Image Example")


@mcp.tool()
def create_thumbnail(image_path: str) -> Image:
"""Create a thumbnail from an image"""
img = PILImage.open(image_path)
img.thumbnail((100, 100))
return Image(data=img.tobytes(), format="png")
56 changes: 56 additions & 0 deletions examples/snippets/servers/lifespan_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""Example showing lifespan support for startup/shutdown with strong typing."""

from collections.abc import AsyncIterator
from contextlib import asynccontextmanager
from dataclasses import dataclass

from mcp.server.fastmcp import Context, FastMCP


# Mock database class for example
class Database:
"""Mock database class for example."""

@classmethod
async def connect(cls) -> "Database":
"""Connect to database."""
return cls()

async def disconnect(self) -> None:
"""Disconnect from database."""
pass

def query(self) -> str:
"""Execute a query."""
return "Query result"


@dataclass
class AppContext:
"""Application context with typed dependencies."""

db: Database


@asynccontextmanager
async def app_lifespan(server: FastMCP) -> AsyncIterator[AppContext]:
"""Manage application lifecycle with type-safe context."""
# Initialize on startup
db = await Database.connect()
try:
yield AppContext(db=db)
finally:
# Cleanup on shutdown
await db.disconnect()


# Pass lifespan to server
mcp = FastMCP("My App", lifespan=app_lifespan)


# Access type-safe lifespan context in tools
@mcp.tool()
def query_db(ctx: Context) -> str:
"""Tool that uses initialized resources."""
db = ctx.request_context.lifespan_context.db
return db.query()
29 changes: 29 additions & 0 deletions examples/snippets/servers/structured_output.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""Example showing structured output with tools."""

from pydantic import BaseModel, Field

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("Structured Output Example")


# Using Pydantic models for rich structured data
class WeatherData(BaseModel):
"""Weather information structure."""

temperature: float = Field(description="Temperature in Celsius")
humidity: float = Field(description="Humidity percentage")
condition: str
wind_speed: float


@mcp.tool()
def get_weather(city: str) -> WeatherData:
"""Get weather for a city - returns structured data."""
# Simulated weather data
return WeatherData(
temperature=72.5,
humidity=45.0,
condition="sunny",
wind_speed=5.2,
)
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ Issues = "https://github.com/modelcontextprotocol/python-sdk/issues"
packages = ["src/mcp"]

[tool.pyright]
include = ["src/mcp", "tests", "examples/servers"]
include = ["src/mcp", "tests", "examples/servers", "examples/snippets"]
venvPath = "."
venv = ".venv"
strict = ["src/mcp/**/*.py"]
Expand Down
Loading
Loading