官方更新 Google Developers Blog 正文 ok 1860 words

借助 MCP 无状态更新扩展 AI Agent 基础设施

英文标题:Scaling AI Agent Infrastructure with the MCP Stateless updates

2026-07-28 版 Model Context Protocol(MCP)候选规范移除了传输层会话管理,使协议核心完全无状态,可直接运行在普通 HTTP 负载均衡、Kubernetes 和 Serverless 基础设施上。新规范以每次请求携带的 `_meta` 信息替代初始化握手与 `Mcp-Session-Id`,并通过标准 HTTP 头提升路由、限流、审计和缓存能力。规范还引入多轮往返请求(MRTR)、Tasks 异步任务扩展,以及更明确的授权与 Schema 安全边界。对开发者而言,这意味着 MCP 服务可更容易实现水平扩缩容、故障转移和低运维成本,但也需要迁移至新的 SDK 与请求模型。
打开原文相关 6 · 机会 3
media11.7 KB media3.6 MB media224.2 KB media187.5 KB media2.5 MB media254.0 KB media2.5 MB media1.9 MB media64.7 KB media351.9 KB media38.9 KB media608.6 KB

中文

横幅-4209x1253

随着你部署 Agent 工作流并扩大用户规模,瓶颈也会随之变化。Model Context Protocol(MCP)于 2024 年末首次推出时,提供了一个优雅、面向会话的框架,使 LLM 能够协商能力、调用外部工具并检索上下文资源。它非常适合本地机器上的单一客户端与单一服务器通信,并针对 stdio 进行了优化。

但当 Google 开始在云原生基础设施中部署 MCP 服务器时,我们遇到了一个严重障碍。原有的协议级会话模型要求持久状态、握手和会话绑定。简而言之,它构建于有状态传输之上,这违背了现代云原生可扩展性的核心原则。

为解决这一问题,Google 牵头推动协议与有状态传输约束解耦。我们的团队需要让 MCP 能在 Google Cloud 上扩展至数百万并发查询,同时我们也知道,你们同样需要让 MCP 为现实世界的企业级规模做好准备。我们与 Hugging Face 及其他行业合作伙伴紧密协作,共同成立了 MCP Transports Working Group。

今天,我们非常高兴地庆祝这项工作的成果:2026-07-28 Model Context Protocol 规范候选版,它已被广泛采用。这一里程碑式版本完全移除了传输层会话管理,为你提供可通过普通 HTTP 负载均衡基础设施扩展的无状态协议核心。

这是 MCP 规范自发布以来最大的变化;即使你不继续阅读本文,也请放心,这是一项更好的改变——更强扩展性、更高安全性,同样易于使用。

为何会话会成为生产环境瓶颈

在原始协议模型中(规范版本 2025-11-25)[392],通过 HTTP 连接 MCP 服务器需要经历有状态的初始化流程:

// POST /mcp - Legacy 2025-11-25 Handshake
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-11-25",
    "capabilities": {},
    "clientInfo": {
      "name": "my-app",
      "version": "1.0"
    }
  }
}

JSON

服务器会返回一个 Mcp-Session-Id 头。要进行任何后续工具调用或资源查询,客户端都必须在每个请求中携带这个唯一会话 ID,从而将客户端绑定到持有内存会话状态的特定容器或 Pod。

这一有状态约束打破了云原生工程师所依赖的水平扩展模型:

  • 负载均衡税: 标准轮询负载均衡器并不知道哪个容器持有哪个内存会话。在拥有三个 Pod 的 Kubernetes 集群之后部署时,客户端的第二个请求可能随机落到另一个 Pod,并返回 400 Session Not Found 错误。
  • 粘性路由开销: 开发者被迫在负载均衡器层配置粘性会话亲和性规则,这会阻碍流量的均匀分布,并使自动扩缩容效率大幅降低。
  • 零容错能力: 如果一个 Pod 重启或崩溃,会话状态将立即丢失,向活跃的客户端对话返回瞬态错误,破坏用户体验。
  • 复杂的基础设施要求: 运行远程 MCP 服务器需要共享 Redis 会话存储,或复杂的网关层数据包深度检查,从而引入大量延迟和运维成本。

新的请求模型:全面转向无状态

新的 2026-07-28 规范通过使协议核心完全无状态解决了这一问题。握手已被移除。initialize / initialized 握手(SEP-2575)和逻辑 Mcp-Session-Id 头(SEP-2567)均已被完全删除。

取而代之的是,每个请求现在都具有自描述性且相互独立。过去仅在连接建立时交换一次的协议版本、客户端信息和客户端能力,现在会作为内联 _meta 字段随每个请求一同传递。

以下是新 2026-07-28 规范下无状态工具调用的形式:

POST /mcp HTTP/1.1
Host: mcp-server.example
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "search",
    "arguments": {
      "q": "otters"
    },
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientCapabilities": {},
      "io.modelcontextprotocol/clientInfo": {
        "name": "my-app",
        "version": "1.0"
      }
    }
  }
}

Plain text

无状态核心的架构优势

  • 标准轮询路由: 由于任何容器实例都能处理任何传入请求,因此你可以将无状态 MCP 服务器部署在普通轮询负载均衡器之后。
  • 无缝 Serverless 部署: 现在你可以在 Google Cloud Run 或 Google Cloud Functions 等平台上,将 MCP 服务器作为 Serverless 函数运行。由于无需维持持久连接,服务器空闲时可以缩容至零,从而大幅降低成本。
  • 透明故障转移: Pod 重启、滚动发布和自动扩缩容事件对客户端完全透明。如果一个容器崩溃,负载均衡器会将下一次请求路由到健康的对等实例,不会造成任何会话中断。
  • 无需 Redis 会话: GitHub MCP Server 等主要生产服务器已升级至该规范,并完全移除了 Redis 会话存储,消除了每次调用所需的数据库读写,使交互更加敏捷。

HTTP 标准化:可路由、可缓存、可追踪

在没有协议会话后,我们需要标准机制来高效路由和治理流量。在 Transports Working Group 的协作下,我们帮助设计了 SEP-2243(HTTP 标准化)[302, 542]。

可流式 HTTP POST 请求现在携带以下特定 HTTP 头:

  • Mcp-Protocol-Version:协议版本。
  • Mcp-Method:正在执行的 JSON-RPC 方法,例如 tools/call。
  • Mcp-Name:正在调用的特定工具、提示词或资源名称。

这些头与 JSON-RPC 请求体保持镜像一致。如果两者不一致,服务器将以 -32020 头不匹配代码拒绝请求。

不再需要深度数据包检查

通过将这些值提升为标准 HTTP 头,代理、网关和负载均衡器无需检查请求体,即可路由、限流和审计流量。对于安全和日志团队而言,这是重大利好,可大幅降低网关层的延迟和处理开销。

利用 ttlMs 实现智能缓存(SEP-2549)

为消除仅为监控工具或提示词列表是否变化而长期保持 Server-Sent Events(SSE)连接的需求,该规范引入了参考 HTTP Cache-Control 设计的缓存字段。工具和资源结果现在可返回 ttlMs(以毫秒为单位的存活时间)和 cacheScope。客户端可以准确了解 tools/list 响应的新鲜有效期,以及是否可安全地在多个用户之间共享缓存。

多轮往返请求(MRTR):以无状态方式处理征询请求

在无状态世界中,我们面临的最复杂挑战之一,是如何处理服务器到客户端的请求。在早期版本中,如果 MCP 服务器在工具调用期间需要用户澄清信息(“征询提示”)或确认,就必须保持 SSE 连接开启,以便将该请求推送给客户端。

**多轮往返请求(SEP-2322)**通过将交互生命周期重构为自包含的步骤,优雅地解决了这个问题:

服务器不再阻塞线程或保持连接开启,而是立即返回一个 InputRequiredResult,其中包含带有序列化上下文的 requestState 负载[398]:

// InputRequiredResult Returned from Server
{
  "resultType": "inputRequired",
  "inputRequests": {
    "confirm": {
      "type": "elicitation",
      "message": "Are you sure you want to delete these 3 files?",
      "schema": {
        "type": "boolean"
      }
    }
  },
  "requestState": "eyJzdGVwIjoxLCJmaWxlcyI6WyJhIiwiYiIsImMiXX0="
}

JSON

客户端提示用户、收集布尔值回答,然后携带 inputResponses 和原样回传的 requestState 重新发起调用。由于 requestState 包含恢复该任务所需的一切信息,负载均衡器之后的任何服务器实例都能接手这一重试请求!

Tasks 扩展(SEP-2663):无需阻塞的异步工作

有时,一个工具调用的运行时间确实很长。数据库备份、CRM 同步,或通过支付网关退款,都可能耗时 10 至 60 秒。保持客户端连接开启会阻塞客户对话,并产生庞大的连接队列。

Tasks 扩展从实验性功能升级为健壮的一等协议扩展。现在,当客户端调用长时间运行的工具时,服务器会立即返回一个 taskId,并在后台启动执行:

// Example: Kicking off an async task in a TypeScript server
server.tool(
  "process_refund",
  { orderId: z.string(), amount: z.number() },
  async ({ orderId, amount }) => {
    const taskId = randomUUID();
    
    // Store initial task state in a shared datastore (e.g. Redis)
    await setTaskState(taskId, { status: "working" });
    
    // Process the refund asynchronously in the background
    processRefundAsync(taskId, orderId, amount);
    
    // Return immediately to keep the conversation flowing
    return {
      content: [
        {
          type: "text",
          text: JSON.stringify({
            taskId,
            status: "working",
            message: `Refund of $${amount} for order ${orderId} is processing. Task ID: ${taskId}`
          })
        }
      ]
    };
  }
);

JavaScript

客户端可以继续对话,告知用户其请求正在处理中,并可使用标准 tasks/get 和 tasks/update 原语轮询或订阅进度,以及获取最终结果。

清晰的安全与能力边界

随着状态管理责任从传输层转移至应用层,安全性变得至关重要。2026-07-28 规范带来了多项关键安全增强:

  • 签发者验证(RFC 9207): 公共客户端必须验证授权响应中的 iss 参数,以防范多服务器架构中的会话劫持和基于重定向的攻击。
  • 资源指示符(RFC 8707): 客户端明确指定令牌面向哪个 MCP 服务器,从而解决“混淆代理人”(confused deputy)委托问题。
  • 工具全面支持 JSON Schema 2020-12: 输入 Schema 现在可使用高级组合结构,例如 oneOf、anyOf、allOf 以及本地 $ref 定义,使参数具有高度描述性并得到严格验证。

弃用与可预测的未来(SEP-2577)

MCP 首次拥有了正式的弃用政策。功能将经历结构化的 Active - > Deprecated -> Removed 生命周期,并具有至少 12 个月的过渡窗口。以下三项功能从今天起进入弃用状态:

  1. Roots: 由显式工具参数、资源 URI 或服务器配置替代。
  2. Sampling: 由直接调用 LLM 提供商 API 替代。
  3. Logging: 对于 stdio 连接,由标准 stderr 替代;对于结构化云可观测性,则由 OpenTelemetry 替代。

开始使用与迁移

全部四个 Tier-1 SDK(TypeScript、Python、Go 和 C#)均已提供支持 2026-07-28 规范的 Beta 版本。我们强烈建议你从今天开始在预发布环境中测试这些版本。

Python(mcp v2)

在 Python 中,MCPServer 装饰器 API 完全兼容[303]。你可以通过以下命令直接安装 Beta 版本:

pip install "mcp[cli]==2.0.0b1"

Shell

TypeScript(拆分包)

TypeScript v2 使用模块化、专注的库替代单体式 @modelcontextprotocol/sdk 包,以保持依赖轻量。通过以下命令安装:

npm install @modelcontextprotocol/server@beta
npm install @modelcontextprotocol/client@beta

Shell

提供了一个便捷的 codemod,可处理标准 API 重命名,例如将 .tool() 重命名为 registerTool:

npx @modelcontextprotocol/codemod@beta v1-to-v2 .

Shell

结论

2026-07-28 规范标志着 Model Context Protocol 的分水岭时刻:它从一个前景广阔的本地集成层,转型为企业 AI 应用的基础性开放基础设施。

感谢所有 MCP Transports Working Group 成员及其他参与团队在多家公司间付出的巨大努力,促成了这一成果。同时感谢维护 Go MCP SDK 的 Google 团队;该团队于 7 月 28 日发布了已在首发日就绪的 v1.7.0,并为 Github MCP Server 等重大集成提供支持。

Google 推动无状态传输的初衷源于实际需求。W

English / 原文

banner-4209x1253

As you deploy agentic workflows and scale up your users, your bottlenecks change. When the Model Context Protocol (MCP) was first introduced in late 2024, it provided an elegant, session-oriented framework that allowed LLMs to negotiate capabilities, invoke external tools, and retrieve contextual resources. It was perfect for a single client talking to a single server on a local machine and optimized for stdio.

But when we at Google began deploying MCP servers across our cloud-native infrastructure, we hit a hard wall. The original protocol-level session model required persistent state, handshakes, and session pinning. In short, it was built on stateful transports that broke the core tenets of modern cloud-native scalability.

To solve this, Google led the charge to decouple the protocol from stateful transport constraints. Our teams needed MCP to scale across millions of concurrent queries on Google Cloud, and we knew that you all needed MCP to be ready for real-world enterprise scale too. Working closely with Hugging Face and other industry partners, we co-founded the MCP Transports Working Group.

Today, we are thrilled to celebrate the culmination of that work: the 2026-07-28 Model Context Protocol specification release candidate , which is already being widely adopted. This landmark release removes transport-level session management entirely, giving you a stateless protocol core that scales on ordinary HTTP load-balanced infrastructure.

It’s the biggest change to MCP spec since launch, and if you don’t read the rest of this article, rest assured, it’s a change for the better - more scale, more secure, just as easy.

Why Sessions Were a Production Bottleneck

In the original protocol model (specification version 2025-11-25) [392], connecting to an MCP server over HTTP required a stateful initialization process:

// POST /mcp - Legacy 2025-11-25 Handshake
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-11-25",
    "capabilities": {},
    "clientInfo": {
      "name": "my-app",
      "version": "1.0"
    }
  }
}

JSON

The server responded with an Mcp-Session-Id header. To make any subsequent tool call or resource query, the client had to include that unique session ID on every request, pinning the client to the specific container or pod that held its in-memory session state.

This stateful constraint breaks the horizontal scaling models that cloud-native engineers depend on:

  • The Load Balancing Tax: Standard round-robin load balancers do not know which container holds which in-memory session. Deploying behind a Kubernetes cluster with three pods meant a second request from a client would randomly hit another pod, returning a 400 Session Not Found error.
  • Sticky Routing Overheads: Developers were forced to configure sticky session affinity rules at the load balancer level, which prevents even distribution of traffic and makes autoscaling highly inefficient.
  • Zero Fault Tolerance: If a pod restarts or crashes, the session state is instantly lost, throwing transient errors back to active client chats and ruining the user experience.
  • Complex Infrastructure Demands: Running remote MCP servers required shared Redis session stores or complex gateway-level packet inspection, introducing massive latency and operational costs.

The New Request Model: Going Fully Stateless

The new 2026-07-28 specification solves this by making the protocol core completely stateless. The handshake is gone. The initialize / initialized handshake (SEP-2575) and the logical Mcp-Session-Id header (SEP-2567) have been removed entirely.

Instead, every request is now self-describing and independent. Protocol version, client info, and client capabilities that used to be exchanged once at connection setup now travel in a _meta field inline on every single request.

Here is how a stateless tool call looks under the new 2026-07-28 specification:

POST /mcp HTTP/1.1
Host: mcp-server.example
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "search",
    "arguments": {
      "q": "otters"
    },
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientCapabilities": {},
      "io.modelcontextprotocol/clientInfo": {
        "name": "my-app",
        "version": "1.0"
      }
    }
  }
}

Plain text

Architectural Advantages of Stateless Core

  • Standard Round-Robin Routing: Because any container instance can handle any incoming request, you can throw your stateful MCP servers behind a plain round-robin load balancer.
  • Seamless Serverless Deployment: You can now run MCP servers as serverless functions on platforms like Google Cloud Run or Google Cloud Functions. Since there is no persistent connection to maintain, your servers spin down to zero when idle, drastically reducing costs.
  • Transparent Failover: Pod restarts, rollouts, and autoscaling events are completely invisible to the client. If a container crashes, the load balancer routes the very next request to a healthy peer with zero session disruption.
  • No Redis Sessions Needed: Major production servers, such as the GitHub MCP Server, have already upgraded to this spec and completely removed Redis session storage, eliminating database writes and reads on every single call to make interactions snappier.

HTTP Standardization: Routable, Cacheable, and Traceable

Without protocol sessions, we needed standard mechanisms to route and govern traffic efficiently. Working under the Transports Working Group, we helped design SEP-2243 (HTTP Standardization) [302, 542].

Streamable HTTP POST requests now carry specific HTTP headers:

  • Mcp-Protocol-Version: The version of the protocol.
  • Mcp-Method: The JSON-RPC method being executed (such as tools/call).
  • Mcp-Name: The specific tool, prompt, or resource name being invoked.

These headers are mirrored to match the JSON-RPC body. If they disagree, the server rejects the request with a -32020 header mismatch code.

No More Deep Packet Inspection

By promoting these values to standard HTTP headers, proxies, gateways, and load balancers can route, rate-limit, and audit traffic without inspecting the request body. For security and logging teams, this is a massive win that drastically lowers the latency and processing overhead at the gateway layer.

Intelligent Caching with ttlMs (SEP-2549)

To eliminate the need for long-lived Server-Sent Events (SSE) connections just to monitor if a tool or prompt list changed, the spec introduces caching fields modeled after HTTP's Cache-Control. Tool and resource results can now return a ttlMs (Time-to-Live in milliseconds) and a cacheScope. Clients know exactly how long a tools/list response is fresh and whether it is safe to cache across multiple users.

Multi Round-Trip Requests (MRTR): Handling Elicitations Statelessly

One of the most complex challenges we faced in a stateless world was how to handle server-to-client requests. Under previous versions, if an MCP server needed user clarification (an "elicitation prompt") or a confirmation during a tool call, it had to keep an SSE connection open to push that request to the client.

Multi Round-Trip Requests (SEP-2322) solves this problem beautifully by restructuring the interaction lifecycle into self-contained steps:

Instead of blocking the thread or holding a connection open, the server immediately returns an InputRequiredResult with a requestState payload containing serialized context [398]:

// InputRequiredResult Returned from Server
{
  "resultType": "inputRequired",
  "inputRequests": {
    "confirm": {
      "type": "elicitation",
      "message": "Are you sure you want to delete these 3 files?",
      "schema": {
        "type": "boolean"
      }
    }
  },
  "requestState": "eyJzdGVwIjoxLCJmaWxlcyI6WyJhIiwiYiIsImMiXX0="
}

JSON

The client prompts the user, gathers the boolean answer, and reissues the call with inputResponses and the echoed requestState. Because the requestState contains everything needed to resume the task, any server instance behind your load balancer can pick up the retry request!

The Tasks Extension (SEP-2663): Async Work Without Blocking

Sometimes a tool call simply takes a long time to run. A database backup, a CRM sync, or a refund through a payment gateway can take anywhere from 10 to 60 seconds. Holding the client connection open blocks the customer conversation and creates massive connection queues.

The Tasks Extension graduates from an experimental feature to a robust, first-class protocol extension. Now, when a client calls a long-running tool, the server immediately returns a taskId and kicks off the execution in the background:

// Example: Kicking off an async task in a TypeScript server
server.tool(
  "process_refund",
  { orderId: z.string(), amount: z.number() },
  async ({ orderId, amount }) => {
    const taskId = randomUUID();
    
    // Store initial task state in a shared datastore (e.g. Redis)
    await setTaskState(taskId, { status: "working" });
    
    // Process the refund asynchronously in the background
    processRefundAsync(taskId, orderId, amount);
    
    // Return immediately to keep the conversation flowing
    return {
      content: [
        {
          type: "text",
          text: JSON.stringify({
            taskId,
            status: "working",
            message: `Refund of $${amount} for order ${orderId} is processing. Task ID: ${taskId}`
          })
        }
      ]
    };
  }
);

JavaScript

The client continues the conversation, telling the user their request is processing, and can poll or subscribe using standard tasks/get and tasks/update primitives to monitor progress and fetch the final results.

Clear Security & Capability Boundaries

As the responsibility of managing state shifts from the transport layer to the application layer, security becomes paramount. The 2026-07-28 spec delivers several crucial security enhancements:

  • Issuer Verification (RFC 9207): Public clients must validate the iss parameter on authorization responses, protecting against session hijacking and redirect-based attacks in multi-server architectures.
  • Resource Indicators (RFC 8707): Clients explicitly specify which MCP server a token is intended for, solving the "confused deputy" delegation problem.
  • Full JSON Schema 2020-12 for Tools: Input schemas can now use advanced composition structures (such as oneOf, anyOf, allOf) and local $ref definitions, making parameters highly descriptive and strictly validated.

Deprecations and a Predictable Future (SEP-2577)

For the first time, MCP now has a formal deprecation policy. Features move through a structured Active - > Deprecated -> Removed lifecycle with a minimum 12-month transition window. Three features enter deprecation today:

  1. Roots: Replaced by explicit tool parameters, resource URIs, or server configuration.
  2. Sampling: Replaced by calling LLM provider APIs directly.
  3. Logging: Replaced by standard stderr for stdio connections, or OpenTelemetry for structured cloud observability.

Getting Started and Migrating

All four Tier-1 SDKs (TypeScript, Python, Go, and C#) already have beta releases available supporting the 2026-07-28 specification. We highly encourage you to start testing these in your staging environments today.

Python (mcp v2)

In Python, the MCPServer decorator API is fully compatible [303]. You can install the beta directly with:

pip install "mcp[cli]==2.0.0b1"

Shell

TypeScript (split packages)

TypeScript v2 replaces the monolithic @modelcontextprotocol/sdk package with modular, focused libraries to keep your dependencies light. Install them with:

npm install @modelcontextprotocol/server@beta
npm install @modelcontextprotocol/client@beta

Shell

A convenient codemod is available to handle standard API renames (like renaming .tool() to registerTool):

npx @modelcontextprotocol/codemod@beta v1-to-v2 .

Shell

Conclusion

The 2026-07-28 specification marks a watershed moment for the Model Context Protocol, transitioning it from a promising local integration layer into the foundational, open infrastructure for enterprise AI applications.

Thank you to the huge effort from all of the MCP Transports Working Group and other teams who worked to make this happen, from across many companies. Thanks also to the Google team who maintain the Go MCP SDK and shipped v1.7.0 on July 28th which was ready on launch day and powers major integrations like Github MCP Server.

Google’s push for stateless transports was born out of necessity. We needed a protocol robust enough to handle the massive scale of our global developers, and we wanted to ensure that every developer, whether building on Google Cloud or anywhere else, had access to highly reliable, secure, and infinitely scalable agentic infrastructure.

By decoupling state from the transport layer, we have made load balancing boring, autoscaling seamless, and serverless deployment a reality. We can’t wait to see the incredibly scalable AI agents you build on top of this new stateless foundation!

Explore more: