Why
The reason to build one now rather than a year ago is that the shape of the answer changed. Until this revision an MCP server was a stateful conversation: an initialize/initialized handshake, an Mcp-Session-Id header, and a server that had to remember which client it was talking to. The 2026-07-28 revision removes both — every request is self-contained, with protocol version, client identity and capabilities travelling in _meta, Streamable HTTP requests routed by Mcp-Method and Mcp-Name headers, and list and resource-read results cacheable.
What that changes practically is deployment. A stateless request/response service runs on serverless or edge without sticky sessions, which is the difference between an MCP server is a process I keep running and an MCP server is a function I deploy.
The second change carries more weight for real work. Authorization now aligns with deployed OAuth 2.0 and OIDC practice, so pointing a server at an enterprise identity provider like Entra or Okta stops being a workaround. That is the half that decides whether an MCP server may ever touch company data, and it is why building against the new spec is not the same exercise as building against the old one. The adoption figure is context rather than argument: SDK downloads passed 400 million a month, roughly 4× this year.
The three positions are the same protocol from different seats, and the ordering is the useful part. Building a server is the protocol question. Consuming Zapier's — 8,000+ app integrations exposed as tools — is the client question, and it is where the security decision lives rather than the interesting engineering. Serving an agent as an MCP server, which Google's ADK Python 2.5 release added alongside sandboxed code execution on Cloud Run and a fresh ADK Go, is the framework question. Doing the protocol one first turns the other two into wrapper exercises instead of two unknowns at once.
One caution before building: Roots, Sampling and Logging are deprecated with documented replacements and a minimum twelve-month removal window, and Tasks is an explicit breaking change — poll-based tasks/get, tasks/update, cooperative tasks/cancel. Porting an old server means learning the old model twice.
How it works
Three seats, one protocol
| Seat | The question | What it decides | Do it |
|---|---|---|---|
| Build a server | Protocol — what does a request carry now that there is no session? | Whether the thing can be deployed and authorized at all | First |
| Consume a server (Zapier) | Client — how do I hold a connection and constrain what it may do? | Blast radius, not architecture | Second |
| Serve an agent as a server (ADK) | Framework — can an existing subagent be wrapped? | Reuse | A 30-minute skim, last |
What actually changed on 2026-07-28
| Before | After | |
|---|---|---|
| Session | initialize/initialized handshake, Mcp-Session-Id |
None — every request self-contained |
| Identity and capabilities | Negotiated once | Carried in _meta per request |
| Routing | Session-scoped | Mcp-Method / Mcp-Name headers |
| list / resource-read | Per-session | Cacheable |
| Authorization | Ad hoc | OAuth 2.0 / OIDC — Entra, Okta |
| Deployment | A process you keep running | A function you deploy |
| Tasks | — | Breaking change: tasks/get, tasks/update, tasks/cancel |
| Roots, Sampling, Logging | Current | Deprecated, 12-month minimum removal window |
Three things worth verifying by doing rather than reading
- That a cold-started serverless instance can serve a request with no prior state at all. That is the whole claim of the stateless core, and it either holds on a real cold start or it does not.
- What
_metamust actually carry for a client to work without the handshake — the part a spec summary never makes concrete enough to implement from. - Whether cacheability of list and resource-read survives a real deployment, since that is where the stateless design either pays for its extra per-request payload or does not.
The authorization half deserves the most time: put the server behind an OAuth/OIDC provider and walk the token path end to end, because the approval path for company data is standardised now is a claim that is either true in an hour or false all week.
The client side, where the decision is a security decision
A server-side route holds the Zapier MCP connection — URL and auth token never reaching the browser — and either forwards tool calls through the Anthropic API's native MCP connector or acts as a generic client via @modelcontextprotocol/sdk, listing available tools and executing whichever the model selects. Scope it to an explicit allowlist (e.g. send email to self) rather than handing an agent unrestricted access to real accounts. That allowlist is the entire engineering decision; everything else is plumbing, and the-harness-not-the-model is where the general version of it lives.
The framework side, in one paragraph
Google's Agent Development Kit release adds sandboxed code execution isolation on Cloud Run, the ability to serve an agent as an MCP server, and an improved Live API; ADK Go shipped alongside. The 30-minute question is whether an existing subagent can be wrapped in ADK and called from Claude over MCP. Once the protocol question is answered that is a wrapper exercise, which is exactly why it is last.
The fourth seat — the gateway between the agent and the tool
This card has three seats: build a server, consume one, wrap an agent as one. A fourth has appeared, and it is where the attention moved once the protocol stopped being the open question. With the MCP npm SDK at roughly 196M downloads a month, whether to speak MCP is settled. What is contested is the layer above it: the gateway that sits between the agent and everything it calls.
Three things currently occupying that layer, and they are not the same product:
| What it actually sells | |
|---|---|
| LiteLLM | One API surface over 100+ model providers, with per-call cost tracking — a routing and billing layer |
| TrueFoundry | Per-agent identity and spending caps — an authorization layer |
| vLLM | The default once the model is hosted rather than called — an inference layer |
The shape is familiar: this is the reverse proxy, arriving for agents. Every line in that table is something you would otherwise write badly yourself — a retry policy, a key vault, a budget, an audit log — and the reason it wants to be a separate box is that an agent cannot be trusted to enforce a limit on itself. That is the same argument as the-harness-not-the-model, and agentic-intent-veto is the warning about which limit to pick: a spending cap is the wrong invariant if what you actually care about is what the agent is for.
This lands directly on the client seat above, where the conclusion was that consuming an MCP server is a security decision — hold the connection server-side, never let the URL and token reach the browser. A gateway is that answer, productised. So the question to ask before adopting one is which of the four it is actually giving you — routing, identity, cost, or observability — because they are sold as a single product and needed one at a time, and the cheapest version of three of them is a server-side route you already know how to write.
Where it lands in Jayverse
- Rabbit: gate every consumed MCP tool behind a server-side allowlist. Near session-key signing, an agent must never hold a Zapier-style MCP connection with unrestricted account access; keep the URL and token server-side and scope calls to an explicit allowlist, the same decision this page makes for the client seat.
- Number: build its first MCP tool server against the 2026-07-28 spec, not the old one. A stateless server (no session handshake) deploys straight to Cloud Run and lets Claude query readings and indicators directly — do the protocol question first, before any framework wrapper.
- Auditor: log every MCP tool call as a checked item. Record which server, which tool and which allowlist entry authorized a call, so "what was checked, by which rule" extends to agent tool use, not just contract state.
- gitboard: add a row per MCP server deployment. Track Number's and Rabbit's MCP servers as stateless Cloud Run functions, with OAuth/OIDC status shown per server.
Key expressions
| Expression | 뜻 · 쓰이는 자리 |
|---|---|
| underneath | ~의 기반에 깔려 있다 · 다른 논의의 전제가 되는 것을 가리킬 때. "is underneath the other two positions" |
| porting | 기존 시스템을 다른 버전·환경으로 이식하는 것 · 오래된 버전을 새 버전으로 옮겨 짜는 작업. "rather than porting a 2025-11-25 one" |
| scoped to | ~로 범위를 한정하다 · 권한·기능을 좁게 제한할 때. "scoped to an explicit allowlist of safe actions" |
| carries more weight | 더 중요하다, 무게가 더 실리다 · 두 사안을 비교하며 비중을 말할 때. "carries more weight for real work" |
| stops being a workaround | 더 이상 임시방편이 아니게 되다 · 정식 해결책으로 자리잡았다는 뜻. "stops being a workaround" |
| blast radius | 피해 반경 · 보안 사고 시 영향 범위를 가리키는 업계 용어. "Blast radius, not architecture" |
| wrapper exercise | 껍데기만 씌우는 작업, 부차적인 작업 · 핵심 문제가 이미 풀려 남은 일이 쉬울 때. "into wrapper exercises instead of two unknowns" |
| productised | 상품화되다 · 개념·답을 실제 제품 형태로 만들었을 때. "A gateway is that answer, productised" |
| sits between | ~사이에 위치하다 · 두 시스템 사이를 중개하는 계층을 설명할 때. "sits between the agent and everything it calls" |
| hand unrestricted access | ~에게 무제한 접근권을 넘겨주다 · 위험한 권한 부여를 경고할 때. "handing an agent unrestricted access to real accounts" |
| ADK | 구글 에이전트 개발 키트(Google Agent Development Kit) · 기존 서브에이전트를 감싸 MCP 서버로 제공하는 프레임워크로 언급. "whether an existing subagent can be wrapped in Google ADK" |
| LiteLLM | 100개 이상의 모델 제공자를 하나의 API로 묶어 호출별 비용을 추적하는 라우팅·과금 계층 제품 · 게이트웨이 사례 중 하나. "One API surface over 100+ model providers, with per-call cost tracking" |
| TrueFoundry | 에이전트별 아이덴티티와 지출 한도를 관리하는 인가 계층 제품 · 게이트웨이 사례 중 하나. "Per-agent identity and spending caps — an authorization layer" |
| vLLM | 모델을 직접 호스팅할 때 기본으로 쓰이는 추론 계층 제품 · 게이트웨이 표에서 추론 계층 예시로 제시됨. "The default once the model is hosted rather than called" |
| Entra / Okta | 마이크로소프트·Okta의 기업용 아이덴티티 제공자 · OAuth/OIDC 인가를 연결하는 대상의 예시로 언급. "pointing a server at an enterprise identity provider like Entra or Okta" |