docs: add code fences to Example: docstring blocks (#2104)

This commit is contained in:
Jonathan Hefner
2026-02-19 14:06:11 -06:00
committed by GitHub
parent c0328540c9
commit cb07adeca3
18 changed files with 85 additions and 20 deletions
@@ -187,11 +187,13 @@ class ExperimentalTaskHandlers:
WARNING: These APIs are experimental and may change without notice.
Example:
```python
handlers = ExperimentalTaskHandlers(
get_task=my_get_task_handler,
list_tasks=my_list_tasks_handler,
)
session = ClientSession(..., experimental_task_handlers=handlers)
```
"""
# Pure task request handlers
+6
View File
@@ -5,6 +5,7 @@ This module provides client methods for interacting with MCP tasks.
WARNING: These APIs are experimental and may change without notice.
Example:
```python
# Call a tool as a task
result = await session.experimental.call_tool_as_task("tool_name", {"arg": "value"})
task_id = result.task.task_id
@@ -21,6 +22,7 @@ Example:
# Cancel a task
await session.experimental.cancel_task(task_id)
```
"""
from collections.abc import AsyncIterator
@@ -72,6 +74,7 @@ class ExperimentalClientFeatures:
CreateTaskResult containing the task reference
Example:
```python
# Create task
result = await session.experimental.call_tool_as_task(
"long_running_tool", {"input": "data"}
@@ -87,6 +90,7 @@ class ExperimentalClientFeatures:
# Get result
final = await session.experimental.get_task_result(task_id, CallToolResult)
```
"""
return await self._session.send_request(
types.CallToolRequest(
@@ -189,6 +193,7 @@ class ExperimentalClientFeatures:
GetTaskResult for each poll
Example:
```python
async for status in session.experimental.poll_task(task_id):
print(f"Status: {status.status}")
if status.status == "input_required":
@@ -197,6 +202,7 @@ class ExperimentalClientFeatures:
# Task is now terminal, get the result
result = await session.experimental.get_task_result(task_id, CallToolResult)
```
"""
async for status in poll_until_terminal(self.get_task, task_id):
yield status
+2
View File
@@ -206,8 +206,10 @@ class ClientSession(
These APIs are experimental and may change without notice.
Example:
```python
status = await session.experimental.get_task(task_id)
result = await session.experimental.get_task_result(task_id, CallToolResult)
```
"""
if self._experimental_features is None:
self._experimental_features = ExperimentalClientFeatures(self)
+3 -2
View File
@@ -91,13 +91,14 @@ class ClientSessionGroup:
For auxiliary handlers, such as resource subscription, this is delegated to
the client and can be accessed via the session.
Example Usage:
Example:
```python
name_fn = lambda name, server_info: f"{(server_info.name)}_{name}"
async with ClientSessionGroup(component_name_hook=name_fn) as group:
for server_param in server_params:
await group.connect_to_server(server_param)
...
```
"""
class _ComponentNames(BaseModel):
@@ -160,6 +160,7 @@ class Experimental:
RuntimeError: If task support is not enabled or task_metadata is missing
Example:
```python
async def handle_tool(ctx: RequestContext, params: CallToolRequestParams) -> CallToolResult:
async def work(task: ServerTaskContext) -> CallToolResult:
result = await task.elicit(
@@ -170,6 +171,7 @@ class Experimental:
return CallToolResult(content=[TextContent(text="Done" if confirmed else "Cancelled")])
return await ctx.experimental.run_task(work)
```
WARNING: This API is experimental and may change without notice.
"""
@@ -56,6 +56,7 @@ class ServerTaskContext:
- Status notifications via the session
Example:
```python
async def my_task_work(task: ServerTaskContext) -> CallToolResult:
await task.update_status("Starting...")
@@ -68,6 +69,7 @@ class ServerTaskContext:
return CallToolResult(content=[TextContent(text="Done!")])
else:
return CallToolResult(content=[TextContent(text="Cancelled")])
```
"""
def __init__(
+9 -3
View File
@@ -31,14 +31,20 @@ class TaskSupport:
- Manages a task group for background task execution
Example:
# Simple in-memory setup
server.experimental.enable_tasks()
Simple in-memory setup:
# Custom store/queue for distributed systems
```python
server.experimental.enable_tasks()
```
Custom store/queue for distributed systems:
```python
server.experimental.enable_tasks(
store=RedisTaskStore(redis_url),
queue=RedisTaskMessageQueue(redis_url),
)
```
"""
store: TaskStore
+9 -3
View File
@@ -118,14 +118,20 @@ class ExperimentalHandlers(Generic[LifespanResultT]):
The TaskSupport configuration object
Example:
# Simple in-memory setup
server.experimental.enable_tasks()
Simple in-memory setup:
# Custom store/queue for distributed systems
```python
server.experimental.enable_tasks()
```
Custom store/queue for distributed systems:
```python
server.experimental.enable_tasks(
store=RedisTaskStore(redis_url),
queue=RedisTaskMessageQueue(redis_url),
)
```
WARNING: This API is experimental and may change without notice.
"""
+14
View File
@@ -535,19 +535,25 @@ class MCPServer(Generic[LifespanResultT]):
- If False, unconditionally creates an unstructured tool
Example:
```python
@server.tool()
def my_tool(x: int) -> str:
return str(x)
```
```python
@server.tool()
async def tool_with_context(x: int, ctx: Context) -> str:
await ctx.info(f"Processing {x}")
return str(x)
```
```python
@server.tool()
async def async_tool(x: int, context: Context) -> str:
await context.report_progress(50, 100)
return str(x)
```
"""
# Check if user passed function directly instead of calling decorator
if callable(name):
@@ -579,12 +585,14 @@ class MCPServer(Generic[LifespanResultT]):
- context: Optional CompletionContext with previously resolved arguments
Example:
```python
@mcp.completion()
async def handle_completion(ref, argument, context):
if isinstance(ref, ResourceTemplateReference):
# Return completions based on ref, argument, and context
return Completion(values=["option1", "option2"])
return None
```
"""
def decorator(func: _CallableT) -> _CallableT:
@@ -647,6 +655,7 @@ class MCPServer(Generic[LifespanResultT]):
meta: Optional metadata dictionary for the resource
Example:
```python
@server.resource("resource://my-resource")
def get_data() -> str:
return "Hello, world!"
@@ -664,6 +673,7 @@ class MCPServer(Generic[LifespanResultT]):
async def get_weather(city: str) -> str:
data = await fetch_weather(city)
return f"Weather for {city}: {data}"
```
"""
# Check if user passed function directly instead of calling decorator
if callable(uri):
@@ -747,6 +757,7 @@ class MCPServer(Generic[LifespanResultT]):
icons: Optional list of icons for the prompt
Example:
```python
@server.prompt()
def analyze_table(table_name: str) -> list[Message]:
schema = read_table_schema(table_name)
@@ -772,6 +783,7 @@ class MCPServer(Generic[LifespanResultT]):
}
}
]
```
"""
# Check if user passed function directly instead of calling decorator
if callable(name):
@@ -813,9 +825,11 @@ class MCPServer(Generic[LifespanResultT]):
include_in_schema: Whether to include in OpenAPI schema, defaults to True
Example:
```python
@server.custom_route("/health", methods=["GET"])
async def health_check(request: Request) -> Response:
return JSONResponse({"status": "ok"})
```
"""
def decorator( # pragma: no cover
+3 -3
View File
@@ -2,8 +2,8 @@
This module implements a Server-Sent Events (SSE) transport layer for MCP servers.
Example usage:
```
Example:
```python
# Create an SSE transport at an endpoint
sse = SseServerTransport("/messages/")
@@ -27,7 +27,7 @@ Example usage:
# Create and run Starlette app
starlette_app = Starlette(routes=routes)
uvicorn.run(starlette_app, host="127.0.0.1", port=port)
```
```
Note: The handle_sse function must return a Response to avoid a
"TypeError: 'NoneType' object is not callable" error when client disconnects. The example above returns
+3 -3
View File
@@ -4,8 +4,8 @@ This module provides functionality for creating an stdio-based transport layer
that can be used to communicate with an MCP client through standard input/output
streams.
Example usage:
```
Example:
```python
async def run_server():
async with stdio_server() as (read_stream, write_stream):
# read_stream contains incoming JSONRPCMessages from stdin
@@ -14,7 +14,7 @@ Example usage:
await server.run(read_stream, write_stream, init_options)
anyio.run(run_server)
```
```
"""
import sys
+17 -5
View File
@@ -44,26 +44,38 @@ def create_mcp_http_client(
The returned AsyncClient must be used as a context manager to ensure
proper cleanup of connections.
Examples:
# Basic usage with MCP defaults
Example:
Basic usage with MCP defaults:
```python
async with create_mcp_http_client() as client:
response = await client.get("https://api.example.com")
```
# With custom headers
With custom headers:
```python
headers = {"Authorization": "Bearer token"}
async with create_mcp_http_client(headers) as client:
response = await client.get("/endpoint")
```
# With both custom headers and timeout
With both custom headers and timeout:
```python
timeout = httpx.Timeout(60.0, read=300.0)
async with create_mcp_http_client(headers, timeout) as client:
response = await client.get("/long-request")
```
# With authentication
With authentication:
```python
from httpx import BasicAuth
auth = BasicAuth(username="user", password="pass")
async with create_mcp_http_client(headers, timeout, auth) as client:
response = await client.get("/protected-endpoint")
```
"""
# Set MCP defaults
kwargs: dict[str, Any] = {"follow_redirects": True}
+2
View File
@@ -65,6 +65,7 @@ class UrlElicitationRequiredError(MCPError):
must complete one or more URL elicitations before the request can be processed.
Example:
```python
raise UrlElicitationRequiredError([
ElicitRequestURLParams(
message="Authorization required for your files",
@@ -72,6 +73,7 @@ class UrlElicitationRequiredError(MCPError):
elicitation_id="auth-001"
)
])
```
"""
def __init__(self, elicitations: list[ElicitRequestURLParams], message: str | None = None):
@@ -72,8 +72,10 @@ async def cancel_task(
- Task is already in a terminal state (completed, failed, cancelled)
Example:
```python
async def handle_cancel(ctx, params: CancelTaskRequestParams) -> CancelTaskResult:
return await cancel_task(store, params.task_id)
```
"""
task = await store.get_task(task_id)
if task is None:
+2
View File
@@ -18,11 +18,13 @@ def get_display_name(obj: Tool | Resource | Prompt | ResourceTemplate | Implemen
For other objects: title > name
Example:
```python
# In a client displaying available tools
tools = await session.list_tools()
for tool in tools.tools:
display_name = get_display_name(tool)
print(f"Available tool: {display_name}")
```
Args:
obj: An MCP object with name and optional title fields
+2
View File
@@ -25,6 +25,7 @@ class ResponseRouter(Protocol):
and deliver the response/error to the appropriate handler.
Example:
```python
class TaskResultHandler(ResponseRouter):
def route_response(self, request_id, response):
resolver = self._pending_requests.pop(request_id, None)
@@ -32,6 +33,7 @@ class ResponseRouter(Protocol):
resolver.set_result(response)
return True
return False
```
"""
def route_response(self, request_id: RequestId, response: dict[str, Any]) -> bool:
+2
View File
@@ -60,8 +60,10 @@ class RequestResponder(Generic[ReceiveRequestT, SendResultT]):
cancellation handling:
Example:
```python
with request_responder as resp:
await resp.respond(result)
```
The context manager ensures:
1. Proper cancellation scope setup and cleanup
+3 -1
View File
@@ -77,7 +77,8 @@ class StreamSpyCollection:
def stream_spy() -> Generator[Callable[[], StreamSpyCollection], None, None]:
"""Fixture that provides spies for both client and server write streams.
Example usage:
Example:
```python
async def test_something(stream_spy):
# ... set up server and client ...
@@ -92,6 +93,7 @@ def stream_spy() -> Generator[Callable[[], StreamSpyCollection], None, None]:
# Clear for the next operation
spies.clear()
```
"""
client_spy = None
server_spy = None