Skip to content

Strawman: Resource operations (stat, create, update, delete) with version-based concurrency - #2

Merged
DanielTemesgen merged 21 commits into
modelcontextprotocol:mainfrom
jayzuccarelli:resource-operations-strawman
Nov 11, 2026
Merged

DanielTemesgen merged 21 commits into
modelcontextprotocol:mainfrom
jayzuccarelli:resource-operations-strawman

Conversation

@jayzuccarelli

@jayzuccarelli jayzuccarelli commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

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 (requires ifMatch), resources/delete (optional ifMatch); an opaque version as the concurrency token; typed errors (provisional -32010 precondition failed with currentVersion, -32011 not supported; -32602 for not found, matching resources/read). Listing reuses SEP-2640's resources/directory/read unchanged. Search, glob, bulk, and range are deferred.
  • docs/decisions.md: 2026-10-09 entry, Status: Proposed.
  • python/sdk: prototype on the SDK's Extension/MethodBinding API (no SDK changes), pluggable store plus in-memory store, client helpers, tests including the lost-update case from use-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

jayzuccarelli and others added 12 commits October 9, 2026 14:37
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).
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-14T18:49:30.611565Z 8c05c82 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@jayzuccarelli
jayzuccarelli requested a review from a team as a code owner October 20, 2026 21:38
# 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 olaservo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 notSupported per 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 ttlMs and cacheScope. "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.lastModified from writes, but the create and update examples leave it out.
  • contents.uri MUST equal uri, so it only adds a way to send a mismatch. Could contents drop it?
5. Prototype nits (non-blocking)
  • Subdirectory entries from resources/directory/read have 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 returns notSupported.
  • _check_uri requires ://, which rejects urn:-style URIs.
  • read_directory returns 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>
@jayzuccarelli

Copy link
Copy Markdown
Contributor Author

Thanks Ola, all of these made it better. Pushed in db67f78:

  1. Open questions and the decision-log entry now point at problem-statement items (PS5.2/PS5.4 for concurrency, PS6.x for interactions, and so on), plus the three cross-cutting questions where they still apply.

  2. Added PS4.4, PS4.5, PS5.5, PS6.3 and PS6.4 as open questions, each with the current lean. On PS6.4: a write result describes the state right after that write, and another writer can change it at any moment, so the cacheable thing is the next stat or read; the new revision in the write result is what lets a client update its cache safely. Happy to flip that if the group sees it differently.

  3. Agreed, no good reason to treat them differently. ifMatch is now required on delete as well as update (spec, decision log, prototype, and a test).

  4. Added annotations.lastModified to the create and update examples, and dropped uri from contents; the method's uri names the target.

  5. All four prototype nits fixed: listing now says file entries carry a revision and directory entries don't (tied to PS6.3); update and delete on a foreign scheme return notSupported like create; any RFC 3986 scheme is accepted, so urn: works; and resources/directory/read pages with a cursor.

I used AI to help with these changes.

@DanielTemesgen DanielTemesgen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this!

Comment thread docs/decisions.md

**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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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):

@DanielTemesgen DanielTemesgen Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer sticking with RFC 9457 Problem Details error shapes https://www.rfc-editor.org/info/rfc9457/, but this can be a follow-up.

@DanielTemesgen
DanielTemesgen merged commit 80238ac into modelcontextprotocol:main Nov 11, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants