Workspace IndexKnowledge Notes › MCP from three sides — build one, consume one, wrap an agent as one

#68PoC

MCP from three sides — build one, consume one, wrap an agent as one

The 2026-07-28 revision drops the session handshake, so an MCP server becomes an ordinary stateless HTTP service — deployable to serverless and edge, and authorized like any enterprise API. That protocol change is underneath the other two positions, which is why it should be done first.

Build one narrow tool server against 2026-07-28 from the start rather than porting a 2025-11-25 one, deploy it to Cloud Run, and connect it to Claude. Then the client side: hold a Zapier MCP connection in a server-side route (URL plus auth token, never exposed to the browser) and forward tool calls through the Anthropic API's native MCP connector or a generic client via @modelcontextprotocol/sdk — scoped to an explicit allowlist of safe actions rather than handing an agent unrestricted access to real accounts. The framework question is a 30-minute skim afterwards: whether an existing subagent can be wrapped in Google ADK and served over MCP. Spec: blog.modelcontextprotocol.io, release candidate 2026-07-28.

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

  1. 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.
  2. What _meta must actually carry for a client to work without the handshake — the part a spec summary never makes concrete enough to implement from.
  3. 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

Words and phrases from this page worth keeping, with the Korean meaning and the sentence they come from.

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"
LiteLLM100개 이상의 모델 제공자를 하나의 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"

← All Knowledge Notes · Workspace Index · Top ↑

MCP 를 세 방향에서 — 만들고, 쓰고, 에이전트를 그것으로 감싸기

2026-07-28 개정판이 세션 핸드셰이크를 없앴습니다. MCP 서버가 평범한 무상태 HTTP 서비스가 되어 서버리스·엣지에 배포되고, 여느 엔터프라이즈 API처럼 인가됩니다. 그 프로토콜 변화가 나머지 두 위치 밑에 깔려 있고, 그래서 이것부터 해야 합니다.

2025-11-25 서버를 포팅하지 말고 처음부터 2026-07-28 위에 좁은 툴 서버 하나를 만들어 Cloud Run 에 배포하고 Claude 에 연결합니다. 그다음 클라이언트 쪽: Zapier MCP 연결(URL + 인증 토큰, 브라우저에 절대 노출 금지)을 서버 라우트가 들고, Anthropic API 의 네이티브 MCP 커넥터나 @modelcontextprotocol/sdk 범용 클라이언트로 툴 호출을 전달합니다 — 에이전트에게 실제 계정 무제한 접근을 주는 대신 안전한 액션만 명시적 허용 목록으로. 프레임워크 질문은 그 뒤 30분 훑기입니다 — 기존 서브에이전트를 Google ADK 로 감싸 MCP 로 서빙할 수 있는가. 스펙: blog.modelcontextprotocol.io, 릴리스 후보 2026-07-28.

1년 전이 아니라 지금 만들 이유는 답의 모양이 바뀌었기 때문입니다. 이번 개정 전까지 MCP 서버는 상태 있는 대화였습니다 — initialize/initialized 핸드셰이크, Mcp-Session-Id 헤더, 그리고 어느 클라이언트와 말하는 중인지 기억해야 하는 서버. 2026-07-28 개정판이 둘 다 없앱니다 — 모든 요청이 자기완결적이고, 프로토콜 버전·클라이언트 신원·능력이 _meta 로 실려 가며, Streamable HTTP 요청은 Mcp-Method·Mcp-Name 헤더로 라우팅되고, list 와 resource-read 결과는 캐시 가능합니다.

실무적으로 바뀌는 것은 배포입니다. 무상태 요청/응답 서비스는 스티키 세션 없이 서버리스나 엣지에서 돕니다. MCP 서버는 내가 계속 띄워 두는 프로세스MCP 서버는 내가 배포하는 함수 의 차이입니다.

두 번째 변화가 실제 업무에는 더 무겁습니다. 인가가 배포된 OAuth 2.0·OIDC 관행과 정렬되어, Entra 나 Okta 같은 엔터프라이즈 아이덴티티 공급자에 서버를 붙이는 것이 우회책이기를 그만둡니다. MCP 서버가 회사 데이터에 닿아도 되는지를 결정하는 절반이고, 그래서 새 스펙 위에서 만드는 것이 옛 스펙 위에서 만드는 것과 같은 연습이 아닙니다. 채택 수치는 논거가 아니라 맥락입니다 — SDK 다운로드가 월 4억 건을 넘었고, 올해 약 4배입니다.

세 위치는 같은 프로토콜을 다른 자리에서 본 것이고, 쓸모 있는 부분은 순서입니다. 서버를 만드는 것은 프로토콜 질문입니다. Zapier 의 것을 쓰는 것 — 8,000개 이상 앱 연동을 툴로 노출 — 은 클라이언트 질문이고, 흥미로운 엔지니어링보다 보안 결정이 사는 자리입니다. 에이전트를 MCP 서버로 서빙하는 것은 — Google ADK Python 2.5 릴리스가 Cloud Run 샌드박스 코드 실행 격리·ADK Go 신규 릴리스와 함께 추가한 것 — 프레임워크 질문입니다. 프로토콜 질문을 먼저 풀면 나머지 둘이 두 개의 미지수가 아니라 래퍼 작업이 됩니다.

만들기 전 주의 하나: Roots·Sampling·Logging 은 대체재가 문서화된 채 폐기 예정이고 최소 12개월 제거 유예가 있으며, Tasks 는 명시적 파괴적 변경입니다 — 폴링 기반 tasks/get, tasks/update, 협조적 tasks/cancel. 옛 서버를 포팅하면 옛 모델을 두 번 배우게 됩니다.

동작 방식

세 자리, 하나의 프로토콜

자리 질문 무엇을 결정하나 순서
서버를 만든다 프로토콜 — 세션이 없는데 요청은 무엇을 나르나? 애초에 배포·인가가 되는지 첫째
서버를 쓴다(Zapier) 클라이언트 — 연결을 어떻게 들고, 무엇까지 허용하나? 아키텍처가 아니라 폭발 반경 둘째
에이전트를 서버로 서빙(ADK) 프레임워크 — 기존 서브에이전트를 감쌀 수 있나? 재사용 30분 훑기, 마지막

2026-07-28 에 실제로 바뀐 것

이전 이후
세션 initialize/initialized 핸드셰이크, Mcp-Session-Id 없음 — 모든 요청이 자기완결
신원·능력 한 번 협상 요청마다 _meta 로 운반
라우팅 세션 범위 Mcp-Method / Mcp-Name 헤더
list / resource-read 세션별 캐시 가능
인가 임기응변 OAuth 2.0 / OIDC — Entra, Okta
배포 계속 띄워 두는 프로세스 배포하는 함수
Tasks 파괴적 변경: tasks/get, tasks/update, tasks/cancel
Roots·Sampling·Logging 현행 폐기 예정, 최소 12개월 유예

읽기보다 해서 확인할 값이 있는 셋

  1. 콜드 스타트된 서버리스 인스턴스가 사전 상태 0으로 요청을 처리하는가. 무상태 코어의 주장 전부이고, 실제 콜드 스타트에서 성립하거나 아니거나 둘 중 하나입니다.
  2. 핸드셰이크 없이 클라이언트가 동작하려면 _meta 가 실제로 무엇을 날라야 하는가 — 스펙 요약으로는 구현할 만큼 구체적이 되지 않는 부분입니다.
  3. list·resource-read 의 캐시 가능성이 실제 배포에서 살아남는가. 무상태 설계가 요청당 늘어난 페이로드 값을 하는지 못 하는지가 거기서 갈립니다.

인가 절반에 시간을 가장 많이 줄 값이 있습니다 — 서버를 OAuth/OIDC 공급자 뒤에 두고 토큰 경로를 끝까지 걸어 봅니다. 회사 데이터에 대한 승인 경로가 이제 표준화됐다 는 주장은 한 시간 안에 참이거나, 일주일 내내 거짓입니다.

클라이언트 쪽, 결정이 보안 결정인 자리

서버 라우트가 Zapier MCP 연결을 듭니다 — URL 과 인증 토큰은 브라우저에 절대 도달하지 않고 — 그리고 Anthropic API 네이티브 MCP 커넥터로 툴 호출을 전달하거나 @modelcontextprotocol/sdk 로 범용 클라이언트가 되어, 사용 가능한 툴을 나열하고 모델이 고른 것을 실행합니다. 명시적 허용 목록으로 범위를 좁힙니다(예: 내게 이메일 보내기) — 에이전트에게 실제 계정 무제한 접근을 주는 대신. 그 허용 목록이 엔지니어링 결정 전부이고, 나머지는 배관입니다. 그 일반형은 the-harness-not-the-model 에 있습니다.

프레임워크 쪽, 한 문단

Google Agent Development Kit 릴리스는 Cloud Run 샌드박스 코드 실행 격리, 에이전트를 MCP 서버로 서빙, Live API 개선을 추가했고 ADK Go 도 함께 나왔습니다. 30분 질문은 기존 서브에이전트를 ADK 로 감싸 Claude 에서 MCP 로 부를 수 있는가입니다. 프로토콜 질문에 답한 뒤라면 이건 래퍼 작업이고, 정확히 그래서 마지막입니다.

네 번째 자리 — 에이전트와 툴 사이에 앉는 게이트웨이

이 카드에는 자리가 셋입니다: 서버를 만든다, 서버를 쓴다, 에이전트를 서버로 감싼다. 네 번째가 생겼고, 프로토콜이 더 이상 열린 질문이 아니게 된 뒤 관심이 옮겨간 자리입니다. MCP npm SDK가 월 약 1억 9,600만 다운로드인 지금, MCP를 쓸지 말지는 끝난 얘기입니다. 다투는 곳은 그 층 — 에이전트와 그가 호출하는 모든 것 사이에 앉는 게이트웨이입니다.

지금 그 층을 차지한 셋, 그리고 이들은 같은 제품이 아닙니다:

실제로 파는 것
LiteLLM 100개 이상 LLM 제공자 위의 단일 API 표면 + 호출별 비용 추적 — 라우팅·과금 계층
TrueFoundry 에이전트별 신원과 지출 한도 — 인가(authorization) 계층
vLLM 모델을 호출하는 대신 직접 호스팅할 때의 기본값 — 추론 계층

모양은 낯익습니다: 에이전트용 리버스 프록시가 도착한 것입니다. 표의 각 줄은 안 그러면 자기가 어설프게 짜게 될 것들입니다 — 재시도 정책, 키 보관소, 예산, 감사 로그. 그리고 이게 별도 박스가 되려는 이유는 하나입니다: 에이전트에게 자기 한도를 스스로 지키라고 맡길 수 없기 때문. the-harness-not-the-model 과 같은 논지이고, 어떤 한도를 고를지에 대한 경고는 agentic-intent-veto 에 있습니다 — 정작 중요한 게 에이전트가 무엇을 위해 움직이는가라면, 지출 한도는 틀린 불변량입니다.

이건 위의 클라이언트 자리에 그대로 내려앉습니다. 거기 결론은 MCP 서버를 소비하는 일이 보안 결정이라는 것이었습니다 — 연결은 서버 사이드에 두고, URL과 토큰은 브라우저에 절대 내보내지 않는다. 게이트웨이는 그 답을 제품화한 것입니다. 그래서 도입 전에 물을 것은 넷 중 무엇을 실제로 주는가 — 라우팅인가, 신원인가, 비용인가, 관측가능성인가 — 입니다. 이들은 하나의 제품으로 팔리지만 필요해지는 시점은 하나씩이고, 셋 중 대부분의 가장 싼 버전은 이미 짤 줄 아는 서버 사이드 라우트 하나이기 때문입니다.

Jayverse에서의 위치

  • Rabbit: 소비하는 모든 MCP 도구를 서버 사이드 허용목록 뒤에 둔다. 세션 키 서명 근처에서는 에이전트가 Zapier식 MCP 연결을 무제한 계정 권한으로 가져서는 안 된다. URL과 토큰은 서버 사이드에 두고 호출은 명시적 허용목록으로 제한한다. 이 페이지가 클라이언트 자리에 대해 내리는 결정과 같다.
  • Number: 첫 MCP 도구 서버를 구 스펙이 아니라 2026-07-28 스펙으로 만든다. 세션 핸드셰이크가 없는 무상태 서버는 Cloud Run에 바로 배포되고 Claude가 읽기와 지표를 직접 조회할 수 있게 한다. 프레임워크 래핑 전에 프로토콜 질문부터 해결한다.
  • Auditor: 모든 MCP 도구 호출을 확인 항목으로 기록한다. 어느 서버, 어느 도구, 어느 허용목록 항목이 호출을 승인했는지 남겨서 "무엇을 어떤 규칙으로 확인했는지"가 컨트랙트 상태뿐 아니라 에이전트 도구 사용에도 적용되게 한다.
  • gitboard: MCP 서버 배포마다 행을 추가한다. Number와 Rabbit의 MCP 서버를 무상태 Cloud Run 함수로 추적하고, 서버별 OAuth/OIDC 상태를 표시한다.

핵심 표현

이 페이지의 영어 본문에서 배울 만한 단어와 표현, 뜻과 나온 자리.

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"
LiteLLM100개 이상의 모델 제공자를 하나의 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"

← 전체 기술 노트 · 워크스페이스 인덱스 · 맨 위 ↑