Skip to content

Commit f986b9a

Browse files
modified the description of the cursor and list_files contracts as implemented
1 parent 10e13e2 commit f986b9a

2 files changed

Lines changed: 9 additions & 5 deletions

File tree

‎docs/advanced/skills.md‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,10 @@ Each response then holds at most 50 entries and carries a `nextCursor` while mor
254254
`SkillsClient.list_skills()` and `read_directory()` follow it for you. A skill entry is never split
255255
across pages.
256256

257-
The cursor is opaque. A cursor the catalog would not issue is rejected with Invalid params
258-
(`-32602`), and so is any cursor when `page_size` isn't set. A `page_size` below 1 raises `ValueError`.
257+
The cursor is opaque, and the catalog keeps no record of the cursors it has handed out. It accepts
258+
a cursor that marks a page boundary of its listing. A cursor that is malformed, out of range, or
259+
not on a page boundary is rejected with Invalid params (`-32602`), and so is any cursor when
260+
`page_size` isn't set. A `page_size` below 1 raises `ValueError`.
259261

260262
### Invalid skills
261263

@@ -300,7 +302,8 @@ class SkillProvider(Protocol):
300302
async def read_file(self, path: str) -> bytes: ...
301303
```
302304

303-
`list_files()` returns the path of every file, recursively and without directories. `read_file()`
305+
`list_files()` returns the path of every file it serves, recursively and without directories. It
306+
may leave files out; `FilesystemSkillProvider` omits any name that starts with `.`. `read_file()`
304307
returns the raw bytes of one file. Paths use `/` as the separator and are relative to the root of
305308
the provider. A provider can therefore be backed by any storage, such as an archive, a database,
306309
or object storage.

‎src/mcp/server/skills/catalog.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,9 @@ def _encode_cursor(offset: int) -> str:
278278
def _paginate(items: Sequence[_T], cursor: str | None, page_size: int | None) -> tuple[list[_T], str | None]:
279279
"""Return one page of `items` and the cursor for the next page, if any.
280280
281-
The catalog is immutable, so a cursor is just an offset into `items`. Only the offsets this
282-
function issues are valid; anything else is Invalid params.
281+
The catalog is immutable, so a cursor is just an offset into `items`, and no state is kept
282+
about which cursors were issued. Only an offset on a page boundary, in canonical form, is
283+
accepted; anything else is Invalid params.
283284
"""
284285
if page_size is None:
285286
if cursor is not None:

0 commit comments

Comments
 (0)