Back to Python Sdk

resources

examples/stories/resources/README.md

2.0.0b12.1 KB
Original Source

resources

Expose data by URI: a static resource (config://app) and an RFC-6570 template (greeting://{name}). One @mcp.resource() decorator handles both — the SDK infers static-vs-template from whether the URI contains {...}. The client lists resources, lists templates, then reads each.

Run it

bash
# stdio (default — the client spawns the server as a subprocess)
uv run python -m stories.resources.client

# HTTP — the client self-hosts the server on a free port, runs, then tears it down
uv run python -m stories.resources.client --http
# same, against the lowlevel-API server variant
uv run python -m stories.resources.client --http --server server_lowlevel

What to look at

  • client.py async with Client(target, mode=mode) as client: — the one line every client example exists to teach. target is anything Client() accepts (an in-process server, a transport, or an HTTP URL) and mode= is always explicit; the rest of the story is the body of that async with.
  • server.py app_config vs greeting — a URI with no {} registers a static resource (appears in resources/list); a URI with {name} registers a template (appears only in resources/templates/list) and the placeholder must match the function parameter name.
  • server_lowlevel.py read_resource — without MCPServer you own the URI dispatch yourself, including raising MCPError(code=INVALID_PARAMS, ...) for unknown URIs (matches what MCPServer sends).
  • client.py isinstance(entry, TextResourceContents)contents is a list of TextResourceContents | BlobResourceContents; narrow before reading .text.

Not shown here

Subscriptions. Per-URI resources/subscribe is a 2025-era RPC being replaced by subscriptions/listen in 2026-07-28; neither is shown in this story. See stickynotes/ for list_changed notifications.

Spec

Resources — server features

See also

stickynotes/ (list-changed notifications), pagination/ (cursor over a long resource list).