examples/stories/extensions/README.md
Writing your own extension (SEP-2133): one identifier bundles a settings entry
under ServerCapabilities.extensions, a contributed tool, and a vendor request
method gated on the client declaring the extension back.
# stdio (default — the client spawns the server as a subprocess)
uv run python -m stories.extensions.client
# HTTP — the client self-hosts the server on a free port, runs, then tears it down
uv run python -m stories.extensions.client --http
server.py class Catalog(Extension) — the whole extension: settings()
becomes the advertised capability entry, tools() contributes a regular tool,
methods() registers a vendor verb. The extension never holds the server; it
declares contributions and MCPServer(extensions=[...]) consumes them.server.py require_client_extension(ctx, EXTENSION_ID) — the vendor method
rejects clients that did not declare the extension with -32021 (missing
required client capability) and a machine-readable requiredCapabilities
payload.client.py Client(target, extensions=[advertise(EXTENSION_ID)]) — the client-side
half of the negotiation; on 2026-07-28 it travels in the per-request _meta
envelope.client.py client.session.send_request(...) — vendor methods have no
Client-level helper; the session escape hatch sends them.SEP-2133 — extensions capability
· Capabilities — _meta key grammar
apps/ (the built-in MCP Apps extension) · custom_methods/ (the same verb
registered on the lowlevel Server by hand, without an extension).