|
| 1 | +# Story examples |
| 2 | + |
| 3 | +One feature per folder. Each story is a small, self-verifying program: a |
| 4 | +`server.py` (plus, where the wire contract is worth seeing by hand, a |
| 5 | +`server_lowlevel.py`) and a `client.py` whose `scenario(client)` makes |
| 6 | +assertions and exits non-zero on failure. The code you read here is the same |
| 7 | +code CI runs — there is no separate test double. |
| 8 | + |
| 9 | +## Running a story |
| 10 | + |
| 11 | +From the repository root: |
| 12 | + |
| 13 | +```bash |
| 14 | +# stdio (default — the client spawns the server as a subprocess) |
| 15 | +uv run python -m stories.tools.client |
| 16 | + |
| 17 | +# against a running HTTP server |
| 18 | +uv run python -m stories.tools.server --http --port 8000 & |
| 19 | +uv run python -m stories.tools.client --http http://127.0.0.1:8000/mcp |
| 20 | +``` |
| 21 | + |
| 22 | +The full matrix (every story × transport × era × server-variant) runs under |
| 23 | +pytest: |
| 24 | + |
| 25 | +```bash |
| 26 | +uv run --frozen pytest tests/examples/ # everything |
| 27 | +uv run --frozen pytest tests/examples/ -k tools # one story |
| 28 | +``` |
| 29 | + |
| 30 | +[`manifest.toml`](manifest.toml) declares each story's transports, era, and |
| 31 | +variants; `tests/examples/` expands it. |
| 32 | + |
| 33 | +## Layout |
| 34 | + |
| 35 | +`_harness.py` and `_hosting.py` are scaffolding that adapts a story's |
| 36 | +`build_server()` / `build_app()` to argv (stdio vs `--http`) and to the |
| 37 | +in-process test bridge. They isolate the parts of the SDK's hosting surface |
| 38 | +that are still moving — **don't copy them into your own project**; copy the |
| 39 | +`server.py` / `client.py` bodies instead. `_shared/` holds an in-process OAuth |
| 40 | +authorization server reused by the auth stories. |
| 41 | + |
| 42 | +## Stories |
| 43 | + |
| 44 | +| story | what it shows | status | |
| 45 | +|---|---|---| |
| 46 | +| **— start here —** | | | |
| 47 | +| [`tools`](tools/) | `@mcp.tool()`, schema inference, structured output, annotations | ready | |
| 48 | +| [`prompts`](prompts/) | `@mcp.prompt()`, list/get, argument completion | ready | |
| 49 | +| [`resources`](resources/) | `@mcp.resource()`, list/read, URI templates | ready | |
| 50 | +| [`lifespan`](lifespan/) | startup/shutdown lifespan, per-request state injection | ready | |
| 51 | +| [`dual_era`](dual_era/) | one server factory serving both protocol eras; era-neutral accessors | ready | |
| 52 | +| [`custom_version`](custom_version/) | restricting `supported_protocol_versions` | ready | |
| 53 | +| **— feature stories —** | | | |
| 54 | +| [`streaming`](streaming/) | progress notifications, in-flight logging, cancellation | ready | |
| 55 | +| [`elicitation`](elicitation/) | server pauses a tool to ask the user (form + url) | ready (legacy-era) | |
| 56 | +| [`sampling`](sampling/) | server asks the client's LLM mid-tool (push request) | ready (legacy-era) | |
| 57 | +| [`stickynotes`](stickynotes/) | capstone: tools mutate state → resources + `list_changed` + elicit guard | ready | |
| 58 | +| [`custom_methods`](custom_methods/) | vendor-prefixed JSON-RPC via `add_request_handler` / `send_request` | ready | |
| 59 | +| [`schema_validators`](schema_validators/) | tool input schema from pydantic / TypedDict / dataclass / dict | ready | |
| 60 | +| [`middleware`](middleware/) | server-side request/response middleware | ready | |
| 61 | +| [`parallel_calls`](parallel_calls/) | N×M concurrent calls; per-call notification attribution | ready | |
| 62 | +| [`roots`](roots/) | client-declared roots, server reads them via `ctx` | ready (legacy-era) | |
| 63 | +| [`pagination`](pagination/) | manual cursor loop over list endpoints | ready | |
| 64 | +| [`error_handling`](error_handling/) | `is_error` results vs `MCPError`; `ToolError` | ready | |
| 65 | +| [`client_session`](client_session/) | dropping to `client.session` / `ClientSession` mechanics | ready | |
| 66 | +| [`serve_one`](serve_one/) | building a `Connection` by hand and calling `serve_one` directly | ready | |
| 67 | +| **— HTTP hosting —** | | | |
| 68 | +| [`stateless_legacy`](stateless_legacy/) | `streamable_http_app()` default posture; the one-liner deploy | ready | |
| 69 | +| [`json_response`](json_response/) | `json_response=True` mode; raw 2026 POST envelope on the wire | ready | |
| 70 | +| [`legacy_routing`](legacy_routing/) | `is_legacy_request()` classifier in front of a sessionful 1.x deploy | ready | |
| 71 | +| [`starlette_mount`](starlette_mount/) | mounting `streamable_http_app()` under a Starlette/FastAPI sub-path | ready | |
| 72 | +| [`sse_polling`](sse_polling/) | SEP-1699 `closeSSE()` + `Last-Event-ID` resume via `EventStore` | ready | |
| 73 | +| [`standalone_get`](standalone_get/) | server-initiated `list_changed` over the sessionful GET stream | ready | |
| 74 | +| [`reconnect`](reconnect/) | explicit `discover()`, persist `DiscoverResult`, zero-RTT reconnect | ready | |
| 75 | +| [`bearer_auth`](bearer_auth/) | `requireBearerAuth`, PRM metadata, static-token verifier, `ctx.authInfo` | ready | |
| 76 | +| [`oauth`](oauth/) | full `authorization_code` grant against an in-process AS | ready | |
| 77 | +| [`oauth_client_credentials`](oauth_client_credentials/) | `client_credentials` grant; minimal in-process token endpoint | ready | |
| 78 | +| **— deferred (README only) —** | | | |
| 79 | +| [`caching`](caching/) | `CacheableResult` ttl/scope hints; client honouring | not yet implemented | |
| 80 | +| [`mrtr`](mrtr/) | `InputRequiredResult` round-trip with `requestState` HMAC | not yet implemented — [#2898](https://github.com/modelcontextprotocol/python-sdk/issues/2898) | |
| 81 | +| [`subscriptions`](subscriptions/) | `subscriptions/listen`, `ServerEventBus`, `Client.listen()` | not yet implemented — [#2901](https://github.com/modelcontextprotocol/python-sdk/issues/2901) | |
| 82 | +| [`tasks`](tasks/) | `io.modelcontextprotocol/tasks` extension | not yet implemented | |
| 83 | +| [`apps`](apps/) | MCP Apps: `ui://` resource + `_meta.ui` | not yet implemented — [#2896](https://github.com/modelcontextprotocol/python-sdk/issues/2896) | |
| 84 | +| [`skills`](skills/) | SEP-2640 skills extension | not yet implemented — [#2896](https://github.com/modelcontextprotocol/python-sdk/issues/2896) | |
| 85 | +| [`events`](events/) | `io.modelcontextprotocol/events` extension | not yet implemented | |
| 86 | + |
| 87 | +The TypeScript SDK's `repl`, `client-quickstart`, and `server-quickstart` |
| 88 | +examples are intentionally not ported (interactive / external network deps); |
| 89 | +its `hono` example maps to `starlette_mount/`. |
0 commit comments