Skip to content

Commit c8712ff

Browse files
committed
docs: improve resources.md with spec link and concrete-URI examples
Added a link to the MCP resources specification after the intro. Rewrote the multi-segment paths section to lead with the problem: show a URI that fails with {name} before introducing {+name} as the fix. Code comments align inputs with outputs for at-a-glance parsing. Rewrote the query parameters section to lead with the two concrete URIs a user would want to support (base and with-query), then show how one template covers both.
1 parent dd505ea commit c8712ff

File tree

1 file changed

+22
-11
lines changed

1 file changed

+22
-11
lines changed

docs/server/resources.md

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ file. A resource is something the application *reads* to understand the
1111
world. Reading a resource should not change state or kick off expensive
1212
work. If it does either, you probably want a tool.
1313

14+
For the protocol-level details (message formats, lifecycle, pagination),
15+
see the [MCP resources specification](https://modelcontextprotocol.io/specification/latest/server/resources).
16+
1417
## A static resource
1518

1619
The simplest case is a fixed URI that returns the same kind of content
@@ -68,34 +71,42 @@ def get_order(order_id: int) -> dict[str, Any]:
6871

6972
### Multi-segment paths
7073

71-
A plain `{name}` matches a single URI segment. It stops at the first
72-
slash. To match across slashes, use `{+name}`:
74+
A plain `{name}` stops at the first slash. If your template is
75+
`files://{name}`, a client reading `files://readme.txt` matches fine,
76+
but `files://guides/intro.md` does not: the slash after `guides` ends
77+
the match, and `intro.md` is left over.
78+
79+
To capture the whole path including slashes, use `{+name}`:
7380

7481
```python
7582
@mcp.resource("files://{+path}")
7683
def read_file(path: str) -> str:
77-
# Matches files://readme.txt
78-
# Also matches files://guides/quickstart/intro.md
84+
# files://readme.txt gives path = "readme.txt"
85+
# files://guides/intro.md gives path = "guides/intro.md"
7986
...
8087
```
8188

82-
This is the pattern you want for filesystem paths, nested object keys,
83-
or anything hierarchical.
89+
Reach for `{+name}` whenever the value is hierarchical: filesystem
90+
paths, nested object keys, URL paths you're proxying.
8491

8592
### Query parameters
8693

87-
Optional configuration goes in query parameters. Use `{?name}` or list
88-
several with `{?a,b,c}`:
94+
Say you want clients to read `logs://api` for recent logs, but also
95+
`logs://api?since=15m&level=error` when they need to narrow it down.
96+
The `?since=15m&level=error` part is optional configuration, and you
97+
don't want a separate template for every combination.
98+
99+
Declare these as query parameters with `{?name}`, or list several at
100+
once with `{?a,b,c}`:
89101

90102
```python
91103
@mcp.resource("logs://{service}{?since,level}")
92104
def tail_logs(service: str, since: str = "1h", level: str = "info") -> str:
93105
return log_store.query(service, since=since, min_level=level)
94106
```
95107

96-
Reading `logs://api` uses the defaults. Reading
97-
`logs://api?since=15m&level=error` narrows it down. The path identifies
98-
*which* resource; the query tunes *how* you read it.
108+
The path identifies *which* resource; the query tunes *how* you read
109+
it.
99110

100111
Query params are matched leniently: order doesn't matter, extras are
101112
ignored, and omitted params fall through to your function defaults.

0 commit comments

Comments
 (0)