Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions docs/decisions.md
Original file line number Diff line number Diff line change
Expand Up @@ -366,3 +366,45 @@ The page also did not state its protocol-revision baseline, so dropping the SEP'
- [conformance#330](https://github.com/modelcontextprotocol/conformance/pull/330), the SEP-2640 conformance suite.
- [SEP-2549](https://modelcontextprotocol.io/seps/2549-TTL-for-list-results), which defines `CacheableResult`.
- SEP-2640, "Retrieval via `skills/get`", final semantics bullet (the "left open" sentence this entry resolves).

---

### 2026-10-11: Align the spec page's types and examples with the `2026-07-28` base schema

**Status:** Proposed. On acceptance, applied to `specification/stable/skills.mdx` by [PR #157](https://github.com/modelcontextprotocol/ext-skills/pull/157), as the 2026-09-08 and [PR #147](https://github.com/modelcontextprotocol/ext-skills/pull/147) corrections were, rather than through a draft revision.

**Context:** [`specification/stable/skills.mdx`](../specification/stable/skills.mdx) states that its referenced types are those of the `2026-07-28` base schema and that every request **MUST** carry the required request metadata (`_meta`). [Issue #156](https://github.com/modelcontextprotocol/ext-skills/issues/156) reports that `ReadResourceDirectoryRequest` does not compile against that schema: it extends `PaginatedRequest` but declares an inline `params` without the `_meta` that `PaginatedRequestParams` inherits from `RequestParams` (`TS2430`).

Auditing the whole page against the base schema's conventions found further departures:

1. `GetSkillRequest` extends the open `Request` type with an inline `params: { uri }`, so a `skills/get` request without `_meta` type-checks. The base schema's concrete requests extend `JSONRPCRequest` with a named params interface.
2. `ReadResourceDirectoryResult` extends only `PaginatedResult`. Every base list-shaped result (`resources/list`, `resources/templates/list`, `tools/list`, `prompts/list`) also extends `CacheableResult`, making `ttlMs` and `cacheScope` required. It is the only paginated result on the page without them.
3. The base schema defines a `*ResultResponse` type for each method. The page defines none.
4. Base entity types (`Resource`, `Tool`, `Prompt`) carry an optional `_meta: MetaObject`. `Skill` does not.
5. Request examples omit `_meta`, where every base request example includes the required `io.modelcontextprotocol/protocolVersion` and `io.modelcontextprotocol/clientCapabilities` (and `clientInfo`).
6. The page uses `Request` without listing it among the base types it references.

**Decision:** Bring the page into line with the base schema's conventions, accepting that some changes tighten what a conformant implementation sends:

1. `skills/get`: `GetSkillRequestParams extends RequestParams` with `uri`; `GetSkillRequest extends JSONRPCRequest`; `GetSkillResultResponse.result` is `GetSkillResult`. The method does not take input responses (see Rationale).
2. `resources/directory/read`: `ReadResourceDirectoryRequestParams extends PaginatedRequestParams` with `uri`; `ReadResourceDirectoryResult extends PaginatedResult, CacheableResult`, so `ttlMs` and `cacheScope` are **REQUIRED**. It stays list-shaped and does not take input responses, matching the base list methods.
3. Add `ListSkillsResultResponse`, `GetSkillResultResponse` and `ReadResourceDirectoryResultResponse`.
4. Add optional `_meta?: MetaObject` to `Skill`. Keys defined by this extension use the `io.modelcontextprotocol.skills/` prefix.
5. Every request example carries the full required `_meta`, and the "examples omit `_meta` for brevity" sentence is replaced. Directory-read result examples carry `ttlMs` and `cacheScope`.
6. The Protocol Revision sentence lists every base type the page references.

**Rationale:** The page targets `2026-07-28` and says so, so its types should be the ones an implementer gets by extending that schema in the usual way. Where the page and the base schema disagree, implementers generating types from both get incompatible shapes, and conformance tooling cannot check the extension's methods the way it checks base methods.

Changes that alter conformance, rather than only correcting the rendering:

- **`ttlMs` and `cacheScope` become required on `resources/directory/read` results.** A server that omits them is non-conformant under the new text. This mirrors the 2026-09-08 decision for `skills/list` and `skills/get`.
- **`_meta` on requests** was already required by the page's text; only the types and examples change.

`skills/get` does not take input responses. In the base schema only content-producing methods (`resources/read`, `prompts/get`, `tools/call`) do; `skills/get` returns metadata, and a server needing input before releasing content can request it on `resources/read`.

The wire format of a successful exchange is otherwise unchanged. `skills/list` already matched the base convention and is unchanged apart from its response type.

**References:**
- [Issue #156](https://github.com/modelcontextprotocol/ext-skills/issues/156) from @paulbalandan, which reports the compile error and proposes named params interfaces for both requests.
- Base schema `2026-07-28`: `RequestParams`, `RequestMetaObject`, `PaginatedRequestParams` and `CacheableResult`.
- [2026-09-08 entry](#2026-09-08-stable-spec-page-caching-attributes-on-skills-list-and-skills-get-and-the-resources-capability-dependency), the previous alignment of the page's types with the base schema.
10 changes: 5 additions & 5 deletions index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ title: Overview

<!--@include: ./specification/stable/skills.mdx{35,79}-->

<!--@include: ./specification/stable/skills.mdx{243,246}-->
<!--@include: ./specification/stable/skills.mdx{249,252}-->

<!--@include: ./specification/stable/skills.mdx{339,342}-->
<!--@include: ./specification/stable/skills.mdx{358,361}-->

<!--@include: ./specification/stable/skills.mdx{429,442}-->
<!--@include: ./specification/stable/skills.mdx{462,475}-->

<!--@include: ./specification/stable/skills.mdx{481,484}-->
<!--@include: ./specification/stable/skills.mdx{514,517}-->

<!--@include: ./specification/stable/skills.mdx{443,446}-->
<!--@include: ./specification/stable/skills.mdx{476,479}-->

For verification requirements and the skill-loading lifecycle, see
[Integrity and Verification](/specification/stable/skills#integrity-and-verification).
Expand Down
118 changes: 101 additions & 17 deletions specification/stable/skills.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ This extension is identified as: `io.modelcontextprotocol/skills`.

## Protocol Revision

This page specifies the extension against base protocol revision `2026-07-28` or later. Type names it references without defining (`Result`, `PaginatedRequest`, `PaginatedResult`, `CacheableResult`, `Resource`, `Cursor`) are those of the base schema at that revision.
This page specifies the extension against base protocol revision `2026-07-28` or later. Type names it references without defining (`MetaObject`, `JSONRPCRequest`, `JSONRPCResultResponse`, `RequestParams`, `PaginatedRequest`, `PaginatedRequestParams`, `PaginatedResult`, `CacheableResult`, `Resource`) are those of the base schema at that revision.

For brevity, request examples omit `_meta`. Every request **MUST** include the required [request metadata](https://modelcontextprotocol.io/specification/2026-07-28/basic/index#_meta).
Every request **MUST** include the required [request metadata](https://modelcontextprotocol.io/specification/2026-07-28/basic/index#_meta) in `params._meta`. The request types below require it, and the request examples show it.

## Capability Negotiation

Expand Down Expand Up @@ -184,6 +184,12 @@ interface Skill {
* that stable digests cannot be published.
*/
resources: SkillResource[] | "dynamic";

/**
* See the base protocol's notes on `_meta` usage. Keys defined by this
* extension use the `io.modelcontextprotocol.skills/` prefix.
*/
_meta?: MetaObject;
}
```

Expand Down Expand Up @@ -257,7 +263,16 @@ interface ListSkillsRequest extends PaginatedRequest {
"jsonrpc": "2.0",
"id": 4,
"method": "skills/list",
"params": {}
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "ExampleClient",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}
```

Expand All @@ -267,6 +282,10 @@ interface ListSkillsRequest extends PaginatedRequest {
interface ListSkillsResult extends PaginatedResult, CacheableResult {
skills: Skill[];
}

interface ListSkillsResultResponse extends JSONRPCResultResponse {
result: ListSkillsResult;
}
```

```json
Expand Down Expand Up @@ -343,12 +362,14 @@ A server declaring this extension **MUST** implement the `skills/get` method, wh
### Request

```typescript
interface GetSkillRequest extends Request {
interface GetSkillRequestParams extends RequestParams {
/** URI of the skill's SKILL.md. */
uri: string;
}

interface GetSkillRequest extends JSONRPCRequest {
method: "skills/get";
params: {
/** URI of the skill's SKILL.md. */
uri: string;
};
params: GetSkillRequestParams;
}
```

Expand All @@ -358,6 +379,14 @@ interface GetSkillRequest extends Request {
"id": 5,
"method": "skills/get",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "ExampleClient",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {}
},
"uri": "skill://pdf-processing/SKILL.md"
}
}
Expand All @@ -369,6 +398,10 @@ interface GetSkillRequest extends Request {
interface GetSkillResult extends CacheableResult {
skill: Skill;
}

interface GetSkillResultResponse extends JSONRPCResultResponse {
result: GetSkillResult;
}
```

```json
Expand Down Expand Up @@ -489,13 +522,14 @@ A _directory resource_ is a resource whose `mimeType` is `inode/directory`. In a
### Request

```typescript
interface ReadResourceDirectoryRequestParams extends PaginatedRequestParams {
/** URI of the directory resource to read. */
uri: string;
}

interface ReadResourceDirectoryRequest extends PaginatedRequest {
method: "resources/directory/read";
params: {
/** URI of the directory resource to read. */
uri: string;
cursor?: Cursor;
};
params: ReadResourceDirectoryRequestParams;
}
```

Expand All @@ -505,6 +539,14 @@ interface ReadResourceDirectoryRequest extends PaginatedRequest {
"id": 7,
"method": "resources/directory/read",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "ExampleClient",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {}
},
"uri": "skill://pdf-processing/templates"
}
}
Expand All @@ -513,10 +555,14 @@ interface ReadResourceDirectoryRequest extends PaginatedRequest {
### Response

```typescript
interface ReadResourceDirectoryResult extends PaginatedResult {
interface ReadResourceDirectoryResult extends PaginatedResult, CacheableResult {
/** Resource metadata of the directory's direct children. */
resources: Resource[];
}

interface ReadResourceDirectoryResultResponse extends JSONRPCResultResponse {
result: ReadResourceDirectoryResult;
}
```

```json
Expand All @@ -541,7 +587,9 @@ interface ReadResourceDirectoryResult extends PaginatedResult {
"name": "regional",
"mimeType": "inode/directory"
}
]
],
"ttlMs": 300000,
"cacheScope": "public"
}
}
```
Expand All @@ -554,6 +602,7 @@ Semantics:
- The result contains every direct child of the directory. Files carry their ordinary `Resource` metadata and subdirectories are listed as directory resources (`mimeType: "inode/directory"`). The listing is not recursive, and clients descend by calling the method again on a child directory.
- An empty directory yields an empty `resources` array.
- Pagination mirrors `resources/list`. When the result includes `nextCursor`, the client passes it back as `cursor` to retrieve the next page.
- `ReadResourceDirectoryResult` extends `CacheableResult`, so `ttlMs` and `cacheScope` are **REQUIRED**, as they are on `resources/list`, and carry the same semantics. They describe the freshness of the directory listing, not of the held entry, and do not alter [Directory Reads and the Held Entry](#directory-reads-and-the-held-entry).
- A server that declares `directoryRead` **MUST** support the method for every directory within the skill namespaces it serves as individual files.
- The method itself is not skill-specific, and a server **MAY** support it on any directory resource it serves, under any scheme.

Expand All @@ -580,7 +629,16 @@ Consider a host connected to a server it labels `docs-server`, which declares th
"jsonrpc": "2.0",
"id": 2,
"method": "skills/list",
"params": {}
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "ExampleClient",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}
```

Expand Down Expand Up @@ -652,6 +710,14 @@ Later the model asks to load the skill. The host obtains user approval, binding
"id": 3,
"method": "resources/read",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "ExampleClient",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {}
},
"uri": "skill://pdf-processing/SKILL.md"
}
}
Expand Down Expand Up @@ -686,6 +752,14 @@ The instructions reference `templates/`. The model lists the directory, and the
"id": 4,
"method": "resources/directory/read",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "ExampleClient",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {}
},
"uri": "skill://pdf-processing/templates"
}
}
Expand Down Expand Up @@ -713,7 +787,9 @@ The instructions reference `templates/`. The model lists the directory, and the
"name": "credit-note.md",
"mimeType": "text/markdown"
}
]
],
"ttlMs": 300000,
"cacheScope": "public"
}
}
```
Expand All @@ -737,6 +813,14 @@ To make `credit-note.md` available, the host refreshes the entry:
"id": 6,
"method": "skills/get",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "ExampleClient",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {}
},
"uri": "skill://pdf-processing/SKILL.md"
}
}
Expand Down
Loading