Embed code snippets for README from executable examples (#1055)
This commit is contained in:
parent
7bc190bae8
commit
adf327164a
13 changed files with 1139 additions and 1131 deletions
|
|
@ -20,6 +20,6 @@ def desktop() -> list[str]:
|
|||
|
||||
|
||||
@mcp.tool()
|
||||
def add(a: int, b: int) -> int:
|
||||
def sum(a: int, b: int) -> int:
|
||||
"""Add two numbers"""
|
||||
return a + b
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ mcp = FastMCP("Demo")
|
|||
|
||||
# Add an addition tool
|
||||
@mcp.tool()
|
||||
def add(a: int, b: int) -> int:
|
||||
def sum(a: int, b: int) -> int:
|
||||
"""Add two numbers"""
|
||||
return a + b
|
||||
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ def get_weather_alerts(region: str) -> list[WeatherAlert]:
|
|||
WeatherAlert(
|
||||
severity="high",
|
||||
title="Heat Wave Warning",
|
||||
description="Temperatures expected to exceed 40°C",
|
||||
description="Temperatures expected to exceed 40 degrees",
|
||||
affected_areas=["Los Angeles", "San Diego", "Riverside"],
|
||||
valid_until=datetime(2024, 7, 15, 18, 0),
|
||||
),
|
||||
|
|
|
|||
18
examples/snippets/pyproject.toml
Normal file
18
examples/snippets/pyproject.toml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
[project]
|
||||
name = "mcp-snippets"
|
||||
version = "0.1.0"
|
||||
description = "MCP Example Snippets"
|
||||
requires-python = ">=3.10"
|
||||
dependencies = [
|
||||
"mcp",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["setuptools", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[tool.setuptools]
|
||||
packages = ["servers"]
|
||||
|
||||
[project.scripts]
|
||||
server = "servers:run_server"
|
||||
36
examples/snippets/servers/__init__.py
Normal file
36
examples/snippets/servers/__init__.py
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
"""MCP Snippets.
|
||||
|
||||
This package contains simple examples of MCP server features.
|
||||
Each server demonstrates a single feature and can be run as a standalone server.
|
||||
|
||||
To run a server, use the command:
|
||||
uv run server basic_tool sse
|
||||
"""
|
||||
|
||||
import importlib
|
||||
import sys
|
||||
from typing import Literal, cast
|
||||
|
||||
|
||||
def run_server():
|
||||
"""Run a server by name with optional transport.
|
||||
|
||||
Usage: server <server-name> [transport]
|
||||
Example: server basic_tool sse
|
||||
"""
|
||||
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("Available transports: stdio (default), sse, streamable-http")
|
||||
sys.exit(1)
|
||||
|
||||
server_name = sys.argv[1]
|
||||
transport = sys.argv[2] if len(sys.argv) > 2 else "stdio"
|
||||
|
||||
try:
|
||||
module = importlib.import_module(f".{server_name}", package=__name__)
|
||||
module.mcp.run(cast(Literal["stdio", "sse", "streamable-http"], transport))
|
||||
except ImportError:
|
||||
print(f"Error: Server '{server_name}' not found")
|
||||
sys.exit(1)
|
||||
18
examples/snippets/servers/basic_prompt.py
Normal file
18
examples/snippets/servers/basic_prompt.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
from mcp.server.fastmcp import FastMCP
|
||||
from mcp.server.fastmcp.prompts import base
|
||||
|
||||
mcp = FastMCP(name="Prompt Example")
|
||||
|
||||
|
||||
@mcp.prompt(title="Code Review")
|
||||
def review_code(code: str) -> str:
|
||||
return f"Please review this code:\n\n{code}"
|
||||
|
||||
|
||||
@mcp.prompt(title="Debug Assistant")
|
||||
def debug_error(error: str) -> list[base.Message]:
|
||||
return [
|
||||
base.UserMessage("I'm seeing this error:"),
|
||||
base.UserMessage(error),
|
||||
base.AssistantMessage("I'll help debug that. What have you tried so far?"),
|
||||
]
|
||||
20
examples/snippets/servers/basic_resource.py
Normal file
20
examples/snippets/servers/basic_resource.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
mcp = FastMCP(name="Resource Example")
|
||||
|
||||
|
||||
@mcp.resource("file://documents/{name}")
|
||||
def read_document(name: str) -> str:
|
||||
"""Read a document by name."""
|
||||
# This would normally read from disk
|
||||
return f"Content of {name}"
|
||||
|
||||
|
||||
@mcp.resource("config://settings")
|
||||
def get_settings() -> str:
|
||||
"""Get application settings."""
|
||||
return """{
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"debug": false
|
||||
}"""
|
||||
16
examples/snippets/servers/basic_tool.py
Normal file
16
examples/snippets/servers/basic_tool.py
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
mcp = FastMCP(name="Tool Example")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def sum(a: int, b: int) -> int:
|
||||
"""Add two numbers together."""
|
||||
return a + b
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def get_weather(city: str, unit: str = "celsius") -> str:
|
||||
"""Get weather for a city."""
|
||||
# This would normally call a weather API
|
||||
return f"Weather in {city}: 22degrees{unit[0].upper()}"
|
||||
49
examples/snippets/servers/completion.py
Normal file
49
examples/snippets/servers/completion.py
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
from mcp.server.fastmcp import FastMCP
|
||||
from mcp.types import (
|
||||
Completion,
|
||||
CompletionArgument,
|
||||
CompletionContext,
|
||||
PromptReference,
|
||||
ResourceTemplateReference,
|
||||
)
|
||||
|
||||
mcp = FastMCP(name="Example")
|
||||
|
||||
|
||||
@mcp.resource("github://repos/{owner}/{repo}")
|
||||
def github_repo(owner: str, repo: str) -> str:
|
||||
"""GitHub repository resource."""
|
||||
return f"Repository: {owner}/{repo}"
|
||||
|
||||
|
||||
@mcp.prompt(description="Code review prompt")
|
||||
def review_code(language: str, code: str) -> str:
|
||||
"""Generate a code review."""
|
||||
return f"Review this {language} code:\n{code}"
|
||||
|
||||
|
||||
@mcp.completion()
|
||||
async def handle_completion(
|
||||
ref: PromptReference | ResourceTemplateReference,
|
||||
argument: CompletionArgument,
|
||||
context: CompletionContext | None,
|
||||
) -> Completion | None:
|
||||
"""Provide completions for prompts and resources."""
|
||||
|
||||
# Complete programming languages for the prompt
|
||||
if isinstance(ref, PromptReference):
|
||||
if ref.name == "review_code" and argument.name == "language":
|
||||
languages = ["python", "javascript", "typescript", "go", "rust"]
|
||||
return Completion(
|
||||
values=[lang for lang in languages if lang.startswith(argument.value)],
|
||||
hasMore=False,
|
||||
)
|
||||
|
||||
# Complete repository names for GitHub resources
|
||||
if isinstance(ref, ResourceTemplateReference):
|
||||
if ref.uri == "github://repos/{owner}/{repo}" and argument.name == "repo":
|
||||
if context and context.arguments and context.arguments.get("owner") == "modelcontextprotocol":
|
||||
repos = ["python-sdk", "typescript-sdk", "specification"]
|
||||
return Completion(values=repos, hasMore=False)
|
||||
|
||||
return None
|
||||
41
examples/snippets/servers/elicitation.py
Normal file
41
examples/snippets/servers/elicitation.py
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
from pydantic import BaseModel, Field
|
||||
|
||||
from mcp.server.fastmcp import Context, FastMCP
|
||||
|
||||
mcp = FastMCP(name="Elicitation Example")
|
||||
|
||||
|
||||
class BookingPreferences(BaseModel):
|
||||
"""Schema for collecting user preferences."""
|
||||
|
||||
checkAlternative: bool = Field(description="Would you like to check another date?")
|
||||
alternativeDate: str = Field(
|
||||
default="2024-12-26",
|
||||
description="Alternative date (YYYY-MM-DD)",
|
||||
)
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def book_table(
|
||||
date: str,
|
||||
time: str,
|
||||
party_size: int,
|
||||
ctx: Context,
|
||||
) -> str:
|
||||
"""Book a table with date availability check."""
|
||||
# Check if date is available
|
||||
if date == "2024-12-25":
|
||||
# Date unavailable - ask user for alternative
|
||||
result = await ctx.elicit(
|
||||
message=(f"No tables available for {party_size} on {date}. Would you like to try another date?"),
|
||||
schema=BookingPreferences,
|
||||
)
|
||||
|
||||
if result.action == "accept" and result.data:
|
||||
if result.data.checkAlternative:
|
||||
return f"[SUCCESS] Booked for {result.data.alternativeDate}"
|
||||
return "[CANCELLED] No booking made"
|
||||
return "[CANCELLED] Booking cancelled"
|
||||
|
||||
# Date available
|
||||
return f"[SUCCESS] Booked for {date} at {time}"
|
||||
18
examples/snippets/servers/notifications.py
Normal file
18
examples/snippets/servers/notifications.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
from mcp.server.fastmcp import Context, FastMCP
|
||||
|
||||
mcp = FastMCP(name="Notifications Example")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def process_data(data: str, ctx: Context) -> str:
|
||||
"""Process data with logging."""
|
||||
# Different log levels
|
||||
await ctx.debug(f"Debug: Processing '{data}'")
|
||||
await ctx.info("Info: Starting processing")
|
||||
await ctx.warning("Warning: This is experimental")
|
||||
await ctx.error("Error: (This is just a demo)")
|
||||
|
||||
# Notify about resource changes
|
||||
await ctx.session.send_resource_list_changed()
|
||||
|
||||
return f"Processed: {data}"
|
||||
24
examples/snippets/servers/sampling.py
Normal file
24
examples/snippets/servers/sampling.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
from mcp.server.fastmcp import Context, FastMCP
|
||||
from mcp.types import SamplingMessage, TextContent
|
||||
|
||||
mcp = FastMCP(name="Sampling Example")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def generate_poem(topic: str, ctx: Context) -> str:
|
||||
"""Generate a poem using LLM sampling."""
|
||||
prompt = f"Write a short poem about {topic}"
|
||||
|
||||
result = await ctx.session.create_message(
|
||||
messages=[
|
||||
SamplingMessage(
|
||||
role="user",
|
||||
content=TextContent(type="text", text=prompt),
|
||||
)
|
||||
],
|
||||
max_tokens=100,
|
||||
)
|
||||
|
||||
if result.content.type == "text":
|
||||
return result.content.text
|
||||
return str(result.content)
|
||||
20
examples/snippets/servers/tool_progress.py
Normal file
20
examples/snippets/servers/tool_progress.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
from mcp.server.fastmcp import Context, FastMCP
|
||||
|
||||
mcp = FastMCP(name="Progress Example")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def long_running_task(task_name: str, ctx: Context, steps: int = 5) -> str:
|
||||
"""Execute a task with progress updates."""
|
||||
await ctx.info(f"Starting: {task_name}")
|
||||
|
||||
for i in range(steps):
|
||||
progress = (i + 1) / steps
|
||||
await ctx.report_progress(
|
||||
progress=progress,
|
||||
total=1.0,
|
||||
message=f"Step {i + 1}/{steps}",
|
||||
)
|
||||
await ctx.debug(f"Completed step {i + 1}")
|
||||
|
||||
return f"Task '{task_name}' completed"
|
||||
Loading…
Reference in a new issue