Skip to main content
Back to Blog

The Factory Upgrades Its Own Foundation: An MCP Spec Marathon

6 min read

labmcpai-agentsloommillsautomationplatform
The Factory Upgrades Its Own Foundation: An MCP Spec Marathon — hero illustration

On July 28, the Model Context Protocol shipped its first deliberately breaking revision: stateless core, a new server-initiated-request model, an extensions framework, and a 12-month deprecation clock on a pile of features. My whole platform speaks MCP. The hub, the ~30 production servers, the agent factory that ships code to them — all of it runs on an in-house Go SDK, about 8.5k lines, that I maintain myself. And it was two spec revisions behind.

Here's the part I want to write down, because I think it's the shape of a lot of engineering to come: I did the analysis, and the factory is doing the migration — including to the SDK it runs on.

TL;DR

  • The 2026-07-28 MCP revision is breaking on purpose: handshake removed, server/discover required, MRTR replaces held-open streams, HTTP+SSE and DCR start their deprecation clocks.
  • I wrote a source-backed gap analysis with a file:line inventory of my own protocol surface, a phased roadmap, and a monthly kill-test for the riskiest assumption.
  • Then I filed the roadmap not as tickets for me, but as backlog for Mills — the autonomous factory that runs on this SDK. Its first task was making the SDK's own repo workable by the factory.
  • Two weeks in: 69 of the last 111 merges to the platform's main branch are factory lanes. The structured-content work has already retired a real data-loss bug class.
  • The marathon is mid-flight, and that's the honest, interesting state: conformance floor landing, SDK-half staged, strategic transport decision deliberately deferred until there's evidence.

The reading is human work

Spec migrations die from vibes: someone skims a changelog, guesses at blast radius, and files an epic called "MCP v2 support." I spent a day doing it the slow way instead — reading the release, the changelog, and the SEPs, then walking my own codebase with the spec in the other window and writing down where they disagree, with file and line numbers.

Two findings set the plan's shape. First, the deprecation list landed almost entirely on features I never adopted — sampling, roots, MCP logging, SSE resumability. Tools-only was the right bet years ago, and the spec just agreed. Second, the genuinely scary items weren't features but contracts: the handshake goes away, every result grows a required resultType, and my leaf servers were answering initialize with a hardcoded version from 2024 while the proxy negotiated something newer — a split-brain that worked only because nothing was checking.

The analysis ends the way I now end every plan: with the riskiest assumption stated out loud, and a kill-test for it. My assumption is that vendor CLIs keep their legacy-handshake fallback long enough for a phased migration. The monthly test is concrete — newest vendor builds, stdio proxy, tools/list plus one tools/call round-trip — and the first run had a nice property: the research session itself was running through the proxy under test. The harness was the conversation.

The migration is factory work

Mills is my cluster's autonomous delivery system: it takes backlog items, plans them in a council, implements in sandboxed spawns, runs gates (fmt, lint, tests, docs, scope), opens MRs, watches CI, and escalates to me with a dollar figure attached when it's stuck. I've written about the orchestration before; the new thing is what I pointed it at.

The roadmap's item zero gives the game away: make libs/mcp-go a Mills-workable project. The SDK the factory's own tools are built on wasn't in its spawnable-projects list — so the first slice of the migration was the factory extending its reach into the repo that defines it. There's a pleasing strange-loop quality to that, but it's also just dependency ordering: you can't rebuild the foundation until you can stand on the scaffolding.

Since then, the factory lanes have been landing the Phase 0 work on the consumer side:

  • Structured tool results, preferred everywhere. My SDK's default output format is a compact text encoding whose tabular form silently drops array-valued columns — the documented root cause of three separate incidents (a plan reader losing its files list, zeroed test verdicts, a blanked cluster HUD). The spec's structuredContent retires that entire class at the contract level, and the consumer half is merged: hub, bridge, and Mills clients now prefer structured JSON when a tool provides it.
  • Auth modernization. The spec deprecates Dynamic Client Registration in favor of Client ID Metadata Documents, on a 12-month clock. A factory lane is carrying the CIMD path alongside DCR so nothing breaks during the window.
  • Transport research. The legacy /sse endpoint is deprecated upstream; a research lane produced the /sse → streamable-HTTP migration writeup that the eventual implementation slices will execute against.

And — this is my favorite part — the factory improved itself in the same window, because the marathon generated the failure data. Two of its MRs escalated after CI failed a docs-guardrail check, burning $2.02 of tokens on doomed pipeline rounds. The response, shipped as another lane: a local, deterministic docs-guardrail gate that replicates the CI check before the MR exists, failing retryably with a remediation prompt. The factory paid two dollars to learn a lesson and then built the reflex so it never pays it again. That's the whole thesis of gates-as-infrastructure, executed by the thing the gates constrain.

The cadence stat, for scale: in the two weeks since the analysis landed, 69 of 111 merges to the platform's main branch came from factory lanes. I review escalations and make the judgment calls; the throughput is the plant's.

What I'm deliberately not doing yet

The strategic decision — whether the hub fabric moves from WebSocket sidecars to the spec's stateless streamable HTTP, and whether the leaf servers eventually adopt the official Tier 1 Go SDK instead of my in-house one — is parked in the roadmap as a decision to make on evidence, not momentum. The plan calls for a one-server spike before choosing. The stateless transport was practically designed for my fleet's shape, which is exactly why I don't trust my own enthusiasm about it; enthusiasm is what the spike is for.

That's also why this post isn't a victory lap. The SDK-half of Phase 0 — version negotiation that actually reads the supported-versions list, structuredContent at the source — is staged behind the enablement work and lands next. Marathons are mostly middles.

Takeaways

  1. Spec reading is judgment work; spec migration is throughput work. Splitting them across human and factory is the highest-leverage division of labor I've found.
  2. File the roadmap as executable backlog. A phased plan whose slices are machine-workable items gets executed; a document gets admired.
  3. Point the factory at its own foundation early. The enablement slice (can the factory even work in that repo?) is the real item zero, and it flushes out the wedges before the meaty work queues behind them.
  4. Let failures buy gates. The $2.02 escalation was cheap tuition — but only because the escalation loop turns tuition into a permanent, deterministic check.
  5. State the assumption that kills you, and test it monthly. Mine is vendor-client fallback; the day that test fails, the queue reorders itself.

The trust-ladder rules from the companion post hold here too — every factory merge went through gates, CI, and human-reviewable MRs, and the escalation path is a feature, not an embarrassment. The factory is rebuilding its own foundation, but it's doing it the way I'd demand of any engineer: with receipts.

Related Articles

Comments

Join the discussion. Be respectful.

The Factory Upgrades Its Own Foundation: An MCP Spec Marathon | FlexInfer