Skip to content

Commit 392bb35

Browse files
committed
docs: consolidate pytest-examples into single test and add skip tags
Consolidate the separate README.v2.md and docs/ pytest-examples tests into a single unified test using `find_examples("README.v2.md", "docs/")`. Add skip tags to pre-existing code blocks that aren't self-contained: - migration.md: all blocks (before/after migration patterns) - experimental/*.md: all blocks (experimental API patterns) - testing.md: test blocks (reference local server module) - README.v2.md: 4 context-dependent snippets
1 parent d18a2fd commit 392bb35

File tree

8 files changed

+83
-88
lines changed

8 files changed

+83
-88
lines changed

README.v2.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ _Full example: [examples/snippets/servers/basic_prompt.py](https://github.com/mo
595595

596596
MCP servers can provide icons for UI display. Icons can be added to the server implementation, tools, resources, and prompts:
597597

598-
```python
598+
```python skip-run="true"
599599
from mcp.server.mcpserver import MCPServer, Icon
600600

601601
# Create an icon from a file path or URL
@@ -1079,7 +1079,7 @@ The MCPServer server instance accessible via `ctx.mcp_server` provides access to
10791079
- `stateless_http` - Whether the server operates in stateless mode
10801080
- And other configuration options
10811081

1082-
```python
1082+
```python skip-run="true"
10831083
@mcp.tool()
10841084
def server_info(ctx: Context) -> dict:
10851085
"""Get information about the current server."""
@@ -1106,7 +1106,7 @@ The session object accessible via `ctx.session` provides advanced control over c
11061106
- `await ctx.session.send_tool_list_changed()` - Notify clients that the tool list changed
11071107
- `await ctx.session.send_prompt_list_changed()` - Notify clients that the prompt list changed
11081108

1109-
```python
1109+
```python skip-run="true"
11101110
@mcp.tool()
11111111
async def notify_data_update(resource_uri: str, ctx: Context) -> str:
11121112
"""Update data and notify clients of the change."""
@@ -1134,7 +1134,7 @@ The request context accessible via `ctx.request_context` contains request-specif
11341134
- `ctx.request_context.request` - The original MCP request object for advanced processing
11351135
- `ctx.request_context.request_id` - Unique identifier for this request
11361136

1137-
```python
1137+
```python skip-run="true"
11381138
# Example with typed lifespan context
11391139
@dataclass
11401140
class AppContext:

docs/experimental/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Tasks are useful for:
2626

2727
Experimental features are accessed via the `.experimental` property:
2828

29-
```python
29+
```python skip="true"
3030
# Server-side
3131
@server.experimental.get_task()
3232
async def handle_get_task(request: GetTaskRequest) -> GetTaskResult:

docs/experimental/tasks-client.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ This guide covers calling task-augmented tools from clients, handling the `input
1010

1111
Call a tool as a task and poll for the result:
1212

13-
```python
13+
```python skip="true"
1414
from mcp.client.session import ClientSession
1515
from mcp.types import CallToolResult
1616

@@ -38,7 +38,7 @@ async with ClientSession(read, write) as session:
3838

3939
Use `call_tool_as_task()` to invoke a tool with task augmentation:
4040

41-
```python
41+
```python skip="true"
4242
result = await session.experimental.call_tool_as_task(
4343
"my_tool", # Tool name
4444
{"arg": "value"}, # Arguments
@@ -62,7 +62,7 @@ The response is a `CreateTaskResult` containing:
6262

6363
The `poll_task()` async iterator polls until the task reaches a terminal state:
6464

65-
```python
65+
```python skip="true"
6666
async for status in session.experimental.poll_task(task_id):
6767
print(f"Status: {status.status}")
6868
if status.statusMessage:
@@ -79,7 +79,7 @@ It automatically:
7979

8080
When a task needs user input (elicitation), it transitions to `input_required`. You must call `get_task_result()` to receive and respond to the elicitation:
8181

82-
```python
82+
```python skip="true"
8383
async for status in session.experimental.poll_task(task_id):
8484
print(f"Status: {status.status}")
8585

@@ -95,7 +95,7 @@ The elicitation callback (set during session creation) handles the actual user i
9595

9696
To handle elicitation requests from the server, provide a callback when creating the session:
9797

98-
```python
98+
```python skip="true"
9999
from mcp.types import ElicitRequestParams, ElicitResult
100100

101101
async def handle_elicitation(context, params: ElicitRequestParams) -> ElicitResult:
@@ -124,7 +124,7 @@ async with ClientSession(
124124

125125
Similarly, handle sampling requests with a callback:
126126

127-
```python
127+
```python skip="true"
128128
from mcp.types import CreateMessageRequestParams, CreateMessageResult, TextContent
129129

130130
async def handle_sampling(context, params: CreateMessageRequestParams) -> CreateMessageResult:
@@ -150,7 +150,7 @@ async with ClientSession(
150150

151151
Once a task completes, retrieve the result:
152152

153-
```python
153+
```python skip="true"
154154
if status.status == "completed":
155155
result = await session.experimental.get_task_result(task_id, CallToolResult)
156156
for content in result.content:
@@ -174,7 +174,7 @@ The result type matches the original request:
174174

175175
Cancel a running task:
176176

177-
```python
177+
```python skip="true"
178178
cancel_result = await session.experimental.cancel_task(task_id)
179179
print(f"Cancelled, status: {cancel_result.status}")
180180
```
@@ -185,7 +185,7 @@ Note: Cancellation is cooperative—the server must check for and handle cancell
185185

186186
View all tasks on the server:
187187

188-
```python
188+
```python skip="true"
189189
result = await session.experimental.list_tasks()
190190
for task in result.tasks:
191191
print(f"{task.taskId}: {task.status}")
@@ -205,7 +205,7 @@ Servers can send task-augmented requests to clients. This is useful when the ser
205205

206206
Register task handlers to declare what task-augmented requests your client accepts:
207207

208-
```python
208+
```python skip="true"
209209
from mcp.client.experimental.task_handlers import ExperimentalTaskHandlers
210210
from mcp.types import (
211211
CreateTaskResult, GetTaskResult, GetTaskPayloadResult,
@@ -279,7 +279,7 @@ This enables flows where:
279279

280280
A client that handles all task scenarios:
281281

282-
```python
282+
```python skip="true"
283283
import anyio
284284
from mcp.client.session import ClientSession
285285
from mcp.client.stdio import stdio_client
@@ -336,7 +336,7 @@ if __name__ == "__main__":
336336

337337
Handle task errors gracefully:
338338

339-
```python
339+
```python skip="true"
340340
from mcp.shared.exceptions import MCPError
341341

342342
try:

docs/experimental/tasks-server.md

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ This guide covers implementing task support in MCP servers, from basic setup to
1010

1111
The simplest way to add task support:
1212

13-
```python
13+
```python skip="true"
1414
from mcp.server import Server
1515
from mcp.server.experimental.task_context import ServerTaskContext
1616
from mcp.types import CallToolResult, CreateTaskResult, TextContent, Tool, ToolExecution, TASK_REQUIRED
@@ -57,7 +57,7 @@ That's it. `enable_tasks()` automatically:
5757

5858
Tools declare task support via the `execution.taskSupport` field:
5959

60-
```python
60+
```python skip="true"
6161
from mcp.types import Tool, ToolExecution, TASK_REQUIRED, TASK_OPTIONAL, TASK_FORBIDDEN
6262

6363
Tool(
@@ -75,7 +75,7 @@ Tool(
7575

7676
Validate the request matches your tool's requirements:
7777

78-
```python
78+
```python skip="true"
7979
@server.call_tool()
8080
async def handle_tool(name: str, arguments: dict):
8181
ctx = server.request_context
@@ -95,7 +95,7 @@ async def handle_tool(name: str, arguments: dict):
9595

9696
`run_task()` is the recommended way to execute task work:
9797

98-
```python
98+
```python skip="true"
9999
async def handle_my_tool(arguments: dict) -> CreateTaskResult:
100100
ctx = server.request_context
101101
ctx.experimental.validate_task_mode(TASK_REQUIRED)
@@ -127,7 +127,7 @@ async def handle_my_tool(arguments: dict) -> CreateTaskResult:
127127

128128
Keep clients informed of progress:
129129

130-
```python
130+
```python skip="true"
131131
async def work(task: ServerTaskContext) -> CallToolResult:
132132
await task.update_status("Starting...")
133133

@@ -149,7 +149,7 @@ Tasks can request user input via elicitation. This transitions the task to `inpu
149149

150150
Collect structured data from the user:
151151

152-
```python
152+
```python skip="true"
153153
async def work(task: ServerTaskContext) -> CallToolResult:
154154
await task.update_status("Waiting for confirmation...")
155155

@@ -177,7 +177,7 @@ async def work(task: ServerTaskContext) -> CallToolResult:
177177

178178
Direct users to external URLs for OAuth, payments, or other out-of-band flows:
179179

180-
```python
180+
```python skip="true"
181181
async def work(task: ServerTaskContext) -> CallToolResult:
182182
await task.update_status("Waiting for OAuth...")
183183

@@ -198,7 +198,7 @@ async def work(task: ServerTaskContext) -> CallToolResult:
198198

199199
Tasks can request LLM completions from the client:
200200

201-
```python
201+
```python skip="true"
202202
from mcp.types import SamplingMessage, TextContent
203203

204204
async def work(task: ServerTaskContext) -> CallToolResult:
@@ -220,7 +220,7 @@ async def work(task: ServerTaskContext) -> CallToolResult:
220220

221221
Sampling supports additional parameters:
222222

223-
```python
223+
```python skip="true"
224224
result = await task.create_message(
225225
messages=[...],
226226
max_tokens=500,
@@ -235,7 +235,7 @@ result = await task.create_message(
235235

236236
Check for cancellation in long-running work:
237237

238-
```python
238+
```python skip="true"
239239
async def work(task: ServerTaskContext) -> CallToolResult:
240240
for i in range(1000):
241241
if task.is_cancelled:
@@ -254,7 +254,7 @@ The SDK's default cancel handler updates the task status. Your work function sho
254254

255255
For production, implement `TaskStore` with persistent storage:
256256

257-
```python
257+
```python skip="true"
258258
from mcp.shared.experimental.tasks.store import TaskStore
259259
from mcp.types import Task, TaskMetadata, Result
260260

@@ -287,7 +287,7 @@ class RedisTaskStore(TaskStore):
287287

288288
Use your custom store:
289289

290-
```python
290+
```python skip="true"
291291
store = RedisTaskStore(redis_client)
292292
server.experimental.enable_tasks(store=store)
293293
```
@@ -296,7 +296,7 @@ server.experimental.enable_tasks(store=store)
296296

297297
A server with multiple task-supporting tools:
298298

299-
```python
299+
```python skip="true"
300300
from mcp.server import Server
301301
from mcp.server.experimental.task_context import ServerTaskContext
302302
from mcp.types import (
@@ -382,7 +382,7 @@ async def handle_tool(name: str, arguments: dict) -> CallToolResult | CreateTask
382382

383383
Tasks handle errors automatically, but you can also fail explicitly:
384384

385-
```python
385+
```python skip="true"
386386
async def work(task: ServerTaskContext) -> CallToolResult:
387387
try:
388388
result = await risky_operation()
@@ -407,7 +407,7 @@ For custom error messages, call `task.fail()` before raising.
407407

408408
For web applications, use the Streamable HTTP transport:
409409

410-
```python
410+
```python skip="true"
411411
from collections.abc import AsyncIterator
412412
from contextlib import asynccontextmanager
413413

@@ -484,7 +484,7 @@ if __name__ == "__main__":
484484

485485
Test task functionality with the SDK's testing utilities:
486486

487-
```python
487+
```python skip="true"
488488
import pytest
489489
import anyio
490490
from mcp.client.session import ClientSession
@@ -530,7 +530,7 @@ async def test_task_tool():
530530

531531
### Keep Work Functions Focused
532532

533-
```python
533+
```python skip="true"
534534
# Good: focused work function
535535
async def work(task: ServerTaskContext) -> CallToolResult:
536536
await task.update_status("Validating...")
@@ -544,7 +544,7 @@ async def work(task: ServerTaskContext) -> CallToolResult:
544544

545545
### Check Cancellation in Loops
546546

547-
```python
547+
```python skip="true"
548548
async def work(task: ServerTaskContext) -> CallToolResult:
549549
results = []
550550
for item in large_dataset:
@@ -558,7 +558,7 @@ async def work(task: ServerTaskContext) -> CallToolResult:
558558

559559
### Use Meaningful Status Messages
560560

561-
```python
561+
```python skip="true"
562562
async def work(task: ServerTaskContext) -> CallToolResult:
563563
await task.update_status("Connecting to database...")
564564
db = await connect()
@@ -575,7 +575,7 @@ async def work(task: ServerTaskContext) -> CallToolResult:
575575

576576
### Handle Elicitation Responses
577577

578-
```python
578+
```python skip="true"
579579
async def work(task: ServerTaskContext) -> CallToolResult:
580580
result = await task.elicit(message="Continue?", requestedSchema={...})
581581

docs/experimental/tasks.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ Server Client
101101

102102
When augmenting a request with task execution, include `TaskMetadata`:
103103

104-
```python
104+
```python skip="true"
105105
from mcp.types import TaskMetadata
106106

107107
task = TaskMetadata(ttl=60000) # TTL in milliseconds
@@ -113,7 +113,7 @@ The `ttl` (time-to-live) specifies how long the task and result are retained aft
113113

114114
Servers persist task state in a `TaskStore`. The SDK provides `InMemoryTaskStore` for development:
115115

116-
```python
116+
```python skip="true"
117117
from mcp.shared.experimental.tasks import InMemoryTaskStore
118118

119119
store = InMemoryTaskStore()
@@ -140,7 +140,7 @@ The SDK manages these automatically when you enable task support.
140140

141141
**Server** (simplified API):
142142

143-
```python
143+
```python skip="true"
144144
from mcp.server import Server
145145
from mcp.server.experimental.task_context import ServerTaskContext
146146
from mcp.types import CallToolResult, TextContent, TASK_REQUIRED
@@ -163,7 +163,7 @@ async def handle_tool(name: str, arguments: dict):
163163

164164
**Client:**
165165

166-
```python
166+
```python skip="true"
167167
from mcp.client.session import ClientSession
168168
from mcp.types import CallToolResult
169169

0 commit comments

Comments
 (0)