A filesystem is a set of refusals
The Model Context Protocol has chartered a working group to give its read-only Resources a write path, complete with optimistic concurrency control. The mechanism is old, modest and correct. It also assumes a client that stops when it is told no.
The argumentServices are presented to models as filesystems because models write that interface fluently, and the write path MCP has now chartered rests on a concurrency contract whose client reads refusal as prose.
The Model Context Protocol's specification contains a sentence that reads like a disclaimer and is closer to a confession. Describing the file:// URI scheme, it says the scheme is "used to identify resources that behave like a filesystem. However, the resources do not need to map to an actual physical filesystem." Nothing behind the path has to be a file. Nothing has to be on a disk. The path is a costume, and the specification is honest enough to say so in the same breath as it hands the costume out.
On 8 September the protocol's maintainers merged a charter for a working group whose job is to give the costume hands.
The Filesystems Working Group — chartered on 24 August, led by Sambhav Kothari and Daniel Temesgen of Bloomberg and Ola Hungerford of Nordstrom — opens with an observation rather than a proposal: "Agent platforms are converging on presenting services to models as filesystems." It is one of twelve working groups the project now documents, alongside transports, registry, interceptors and the rest, and it has a narrow remit. Today MCP Resources are read-only. The released specification defines six methods, and every one of them is a read or a notification: resources/list, resources/read, resources/templates/list, a subscription, and two change notifications. The charter adds create, update, delete and stat, and it commits to specifying "how two writers avoid a lost update, and how a client creates a resource under a create-if-absent precondition."
That is optimistic concurrency control, and it is the most sensible thing in the document. It is also, I think, the place where this design quietly breaks — not because the mechanism is wrong, but because of who is holding the other end of it.
The convergence the charter describes is real, and the reason for it is worth being precise about. Services are not becoming more file-like. Models are fluent in paths. A language model has read more directory listings, more cat and ls and open(), than any other interface humans have built; the filesystem is the API with the deepest representation in the training distribution. When a platform presents a ticketing system or a document store as a tree of paths, it is not making a claim about the resource's semantics. It is choosing the interface its consumer writes most reliably. That is a legitimate design move, and it is a new kind of design move: the shape of the interface is being selected for the fluency of the client rather than the nature of the thing behind it.
Reads survive that trade cheerfully. A read is a snapshot; if the abstraction leaks, the worst case is a stale or oddly-shaped answer. Writes do not survive it, because a write has to interact with every other write, and the mechanism the charter has chosen for that interaction makes a demand on the client that nobody in this system is in a position to enforce.
Optimistic concurrency control is roughly as old as multi-user databases, and its contract is simple. Read a resource and note its version. Derive your change. Submit the write with the version as a precondition. If someone else has written since, the server rejects you. The rejection is not an error. It is a required branch: re-read, re-derive the change against the state that now exists, resubmit. The mechanism does not prevent lost updates on its own. It prevents them exactly to the degree that the client takes the branch.
We know this works because we make it work every day. Git uses the same bargain. A rejected non-fast-forward push is an optimistic concurrency failure, and it holds because git push is a program that refuses. The human cannot proceed. The tool will not let them. The discipline is not in the protocol; it is in the client, and the client is a piece of deterministic software written by people who understood the contract.
Now look at the client MCP is designing for. The rejection arrives as a field inside a tool result, which arrives as text in a context window, adjacent to the model's own reasoning, the user's request, three other tool outputs and whatever the system prompt said. There is no compiler. There is nothing that refuses. Whether the branch is taken is a property of a sampled continuation.
The interesting failure is not that a model is too stupid to understand a version conflict. Models handle conflicts well when they are attending to them. The problem is that the conflict path is rare, under-represented in the behaviour the model has learned, and arrives at precisely the moment the model has already composed its answer and is closing out the task. What happens then is not hallucination; it is something more mundane. The model reissues the write without the precondition, because that is the version that worked. It retries unchanged and reads the second rejection as a transient error. Or it narrates the conflict as completion, because the sentence "the file has been updated" is a very likely continuation of everything that came before it.
Each of those is a lost update. Lost updates are silent by construction: nobody has ever paged on the write that did not happen. And the charter's caching provisions sharpen the edge rather than dulling it. Resource reads already carry ttlMs and cacheScope fields and a lastModified annotation, which means a client can be told, correctly, that a read is good for some period — and then submit a conditional write against the version it was explicitly invited to keep.
Watch how fast the metaphor demands the rest of the operating system, too. The specification already suggests servers mark directories with the XDG MIME type inode/directory. Reviewers on the proposal raised readdir, and asked whether seek could be supported at all. Once you have said "filesystem", every one of these is a reasonable next question, and each one imports a guarantee that took kernels a long time to get approximately right.
The second half of the argument is in the charter's non-goals, and they are worth reading as architecture rather than as boilerplate. Out of scope: a parallel files/* primitive standing beside Resources. Out of scope: "host-side sandbox and local-disk semantics", because "the WG standardizes the client and server wire format." Out of scope: "authorization policy for writes, beyond stating where the existing MCP authorization specification applies." The Transports Working Group, chartered a day earlier, similarly rules out authorization mechanics and credential semantics.
Every one of those exclusions is correct standards practice. A working group that tries to own everything ships nothing. But stack them and notice the shape of the result: the write path is being specified while where the bytes land, who may write them, and under whose credential are each somebody else's charter — or nobody's. The capability will arrive with a well-defined wire format and no single owner of the question "what stops a bad write."
The strongest case against all of this is not hard to make, and I think it is largely right. The filesystem is the most successful universal interface anyone has built. It composes, it is stable across four decades, and a model's fluency in it is evidence of its quality rather than a coincidence. The alternative on offer today is worse in every respect: agents already write to systems of record through bespoke tools with no version check, no precondition and no defined concurrency story whatsoever. Specifying it once in the protocol beats thirty platforms inventing thirty dialects, which is precisely why the charter refuses a separate files/* primitive. A defined mechanism is better than none, and optimistic concurrency is the mildest form of control available — it blocks nothing and costs a header.
I would concede all of that. It is a good reason to do this work, and the working group should do it. But every part of that case is an argument about the server side of the wire, and the failure I am describing is on the client side, in an environment the charter's own non-goals place outside its scope. Choosing a sound mechanism does not create the discipline the mechanism assumes. It is worth saying plainly that this reading is built entirely from the project's own record — its charters, its specification, its review threads — because the implementations that will have to honour any of it do not exist yet.
Which points at something larger than one protocol. We have always chosen interfaces for the convenience of a consumer, but until now the consumer could be taught the contract, and we built an entire apparatus for teaching it: types, compilers, linters, code review, the failing test. A model is fluent, not compliant, and fluency does not come with a mechanism for being bound. When a client's adherence to a protocol is statistical rather than structural, protocol design stops being a specification exercise and becomes a reliability-engineering one. The guarantee has to be enforced where the bytes land, because the wire can no longer carry it.
For anyone exposing a system of record to an agent this month, that translates into something concrete. Do not treat a conditional write as a control. Treat the precondition as telemetry — evidence that the client happened to comply, useful precisely because it tells you how often it does not. Put the invariant in the store, where it has always belonged: the uniqueness constraint, the version column the database itself checks, the append-only log with a reconciler behind it. Design as though the conflict branch is never taken, and make that assumption survivable.
A filesystem is not a set of operations. Anyone can implement open, read, write and close. What makes a filesystem something you can build a business on is the set of refusals — the write it will not accept, the rename it will not half-complete, the lock it will not grant. The working group is chartered to standardise the operations. The refusals are out of scope.
What this is argued from
Reporting and primary material the piece rests on, dated at the time of writing. The interpretation is mine; the facts belong to these.
Editorials on this site are written to be argued with. If you think the reading is wrong, it probably is in some particular way, and that is the useful part.