Repository navigation
Strawman: Resource operations (stat, create, update, delete) with version-based concurrency - #2
Conversation
README, CONTRIBUTING, AGENTS/CLAUDE, SECURITY and CODEOWNERS following ext-skills; docs/ for open questions (from the charter), decision log, related work and implementations; a python/sdk placeholder package with CI following experimental-ext-interceptors; and a conformance/ folder. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… to SDK extension points Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ersion-based concurrency Draft spec in docs/proposals/resource-operations.md, a Proposed decision log entry, and implementation-independent conflict scenarios under conformance/. Listing reuses SEP-2640's resources/directory/read unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Wire types, typed errors, a pluggable store with an in-memory implementation, the server extension, and client helpers. No SDK patches; gaps are listed in the proposal's SDK extension points section. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Capability negotiation, happy paths, create-if-absent and stale ifMatch conflicts, not found, resources/updated via subscriptions/listen, and the lost-update scenario from docs/use-cases.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… was dropped The File Uploads and Filesystems charter merge (#3389) was abandoned on 2026-10-11, so the references to the Files Working Group, its charter PR and its three workstreams now point at the Filesystems WG charter and the File Uploads WG instead. Scope text follows the Filesystems charter (create, update, delete, stat, concurrency, change notification and caching).
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…h main Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ments Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # README.md # conformance/README.md # docs/decisions.md # docs/implementations.md # docs/open-questions.md # docs/related-work.md # docs/use-cases.md # python/sdk/README.md # python/sdk/src/mcp_ext_filesystems/__init__.py
olaservo
left a comment
There was a problem hiding this comment.
Thanks Jay for getting this started!
A few comments:
(note: "PS4.4" etc below are referring to the Problem Statements in docs/problem-statements.md.)
1. References to open-questions.md are now out of date. I opened #5 so the skeleton docs link to Daniel's problem statements instead of repeating them. As part of that, open-questions.md now keeps only the three cross-cutting questions (#5 is merged). This PR's "Open questions" section and its decision-log entry still cite the old #1–#6. Could they point at the problem-statement items instead, for example PS5.2 for concurrency?
2. Some problem-statement items aren't covered or deferred yet.
Seems like we still need to cover these:
- PS4.4: marking a URI or subtree read-only, writable, or append-only. Today there's
notSupportedper URI, and an open question about a server-wide read-only setting, but nothing per subtree and no append-only. - PS4.5: errors for permission denied and quota exceeded. (Read-only is covered by
notSupported.) - PS5.5: reads pinned to a specific revision.
- PS6.3: subscribing to a directory.
- PS6.4: asks write results to carry
ttlMsandcacheScope. "Write results are not cacheable" goes the other way, so it'd help to say why.
For a strawman, I think adding them to the open questions is enough?
3. Should ifMatch be required on delete too? The reason given for requiring it on update ("rules out lost updates by omission", from the decision-log entry) seems to apply to delete as well: an unconditional delete can wipe out someone else's update. Is there a reason to treat the two differently?
4. Smaller spec points
- The Interactions section says servers that track modification time MUST return
annotations.lastModifiedfrom writes, but the create and update examples leave it out. contents.uriMUST equaluri, so it only adds a way to send a mismatch. Couldcontentsdrop it?
5. Prototype nits (non-blocking)
- Subdirectory entries from
resources/directory/readhave no revision in_meta, though the proposal says listing entries carry one. - Update or delete on a URI outside the store's scheme returns
notFound, but create returnsnotSupported. _check_urirequires://, which rejectsurn:-style URIs.read_directoryreturns all entries in one page, with no cursor.
…pec and prototype fixes - Cite problem-statement items (PSn.m) and the three surviving cross-cutting open questions instead of the old open-questions.md numbering. - Add open questions for PS4.4, PS4.5, PS5.5, PS6.3, PS6.4. - Require ifMatch on resources/delete, as on update. - Drop contents.uri from create/update params; show lastModified in write results. - Prototype: notSupported for foreign schemes on update/delete, accept any RFC 3986 absolute URI, cursor pagination for resources/directory/read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks Ola, all of these made it better. Pushed in db67f78:
I used AI to help with these changes. |
|
|
||
| **Context:** The [charter](https://modelcontextprotocol.io/community/working-groups/filesystems) asks for create, update, delete, and `stat`, typed errors, and optimistic concurrency control on writes including create-if-absent (PS4.1, PS4.3, PS4.5, PS5.1 to PS5.3, PS6.1, and PS6.2 in the [problem statements](problem-statements.md), where PS*n*.*m* is item *m* of Problem Statement *n*; cross-cutting [open questions](open-questions.md) 1 and 3). Options considered for concurrency: no precondition (last writer wins), timestamps (`lastModified`), an opaque server-minted revision compared on write, and that revision optional on update or delete. For listing: a new method, or the `resources/directory/read` method already defined by the Skills extension (SEP-2640). | ||
|
|
||
| **Decision:** Use [docs/proposals/resource-operations.md](proposals/resource-operations.md) as the group's starting strawman: an extension `io.modelcontextprotocol/resource-operations` (provisional) with `resources/stat`, `resources/create` (create-if-absent only), `resources/update` and `resources/delete` (both require `ifMatch`); an opaque `revision` as the concurrency token, the term [Problem Statement 5](problem-statements.md#problem-statement-5-optimistic-concurrency-control) uses; a precondition-failed error carrying `currentRevision`; and reuse of `resources/directory/read` unchanged for listing. Search, glob, bulk reads, and ranges are deferred. |
There was a problem hiding this comment.
The create and update split gives the same guarantees as one resources/write that requires exactly one of ifMatch or ifNoneMatch: "*", as with HTTP PUT. I have a preference for fewer methods if possible, but this shouldn't block.
| """Provisional: the server does not support this operation on this URI.""" | ||
|
|
||
|
|
||
| class ResourceOperationError(MCPError): |
There was a problem hiding this comment.
Prefer sticking with RFC 9457 Problem Details error shapes https://www.rfc-editor.org/info/rfc9457/, but this can be a follow-up.
Builds on #1 (the repository skeleton); the first commit here is that branch, so review from the strawman commits on, or after #1 merges.
Strawman for the Resource operations SEP in the Filesystems WG charter, to give the group something concrete to review and change.
docs/proposals/resource-operations.md:resources/stat,resources/create(create-if-absent),resources/update(requiresifMatch),resources/delete(optionalifMatch); an opaqueversionas the concurrency token; typed errors (provisional-32010precondition failed withcurrentVersion,-32011not supported;-32602for not found, matchingresources/read). Listing reuses SEP-2640'sresources/directory/readunchanged. Search, glob, bulk, and range are deferred.docs/decisions.md: 2026-10-09 entry, Status: Proposed.python/sdk: prototype on the SDK'sExtension/MethodBindingAPI (no SDK changes), pluggable store plus in-memory store, client helpers, tests including the lost-update case fromuse-cases.md.conformance/: two implementation-independent conflict scenarios.The proposal lists five gaps in the Python SDK's extension points as feedback for SEP-3371 (no subscription bus access from extension handlers, no metadata on change events, no hook into
resources/read, one method across two extensions, legacy wire).Vocabulary (
version, change-set entries) follows Kryspin Ziemski's working document shared in #filesystem-wg.AI disclosure: drafted with Claude Code; I reviewed the spec and code and ran the tests locally.
🤖 Generated with Claude Code