You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I implemented this before realizing that non-trivial changes should be discussed with maintainers first. I would appreciate feedback on the proposed scope and API design, and I am happy to revise the implementation accordingly.
Thanks for writing this up, and for the implementation-first approach. A few design notes from working with skills extensions across SDKs:
Scope split. Keep the three surfaces you listed (schema types + method constants, client APIs, stateless server registration), but keep the stateless server APIs deliberately thin: skills/list, skills/get (or SKILL.md retrieval), and directory read only when directoryRead is negotiated. Resisting the urge to add a stateful skill registry on the server side keeps the extension aligned with how python-sdk#3485 and go-sdk#1238 landed.
Capability negotiation. Gate the client APIs on io.modelcontextprotocol/skills being advertised in server capabilities. Calling listSkills() against a server that did not negotiate should fail fast with a clear error rather than silently returning an empty list. Same for directoryRead: it is an optional sub-capability, so the directory APIs should be unavailable (not empty) when absent.
SKILL.md retrieval. Avoid duplicating the content payload in both skills/get and resources/read. The ext-skills design treats SKILL.md as a resource addressed by URI; I would have skills/get return metadata plus the canonical resource URI, and let clients fetch content through the existing resources path. That keeps one content source of truth and makes cache invalidation simpler.
Cross-SDK parity. The riskiest part of a fourth SDK landing this extension is JSON shape drift: field naming, capability names, error codes. A small conformance fixture shared across python/TS/C#/Go/Java would pay for itself quickly; otherwise clients like Claude and Cursor end up special-casing per SDK.
Draft/experimental. SEP-2640 is still evolving. Consider marking the Java surface as experimental in javadoc until the spec stabilizes, so later breaking changes are expected rather than surprising.
Happy to look at the implementation PR when you open one.
Activity
Ben-Home commentedon Sep 30, 2026
Thanks for writing this up, and for the implementation-first approach. A few design notes from working with skills extensions across SDKs:
Scope split. Keep the three surfaces you listed (schema types + method constants, client APIs, stateless server registration), but keep the stateless server APIs deliberately thin: skills/list, skills/get (or SKILL.md retrieval), and directory read only when directoryRead is negotiated. Resisting the urge to add a stateful skill registry on the server side keeps the extension aligned with how python-sdk#3485 and go-sdk#1238 landed.
Capability negotiation. Gate the client APIs on io.modelcontextprotocol/skills being advertised in server capabilities. Calling listSkills() against a server that did not negotiate should fail fast with a clear error rather than silently returning an empty list. Same for directoryRead: it is an optional sub-capability, so the directory APIs should be unavailable (not empty) when absent.
SKILL.md retrieval. Avoid duplicating the content payload in both skills/get and resources/read. The ext-skills design treats SKILL.md as a resource addressed by URI; I would have skills/get return metadata plus the canonical resource URI, and let clients fetch content through the existing resources path. That keeps one content source of truth and makes cache invalidation simpler.
Cross-SDK parity. The riskiest part of a fourth SDK landing this extension is JSON shape drift: field naming, capability names, error codes. A small conformance fixture shared across python/TS/C#/Go/Java would pay for itself quickly; otherwise clients like Claude and Cursor end up special-casing per SDK.
Draft/experimental. SEP-2640 is still evolving. Consider marking the Java surface as experimental in javadoc until the spec stabilizes, so later breaking changes are expected rather than surprising.
Happy to look at the implementation PR when you open one.