Model Context Protocol đã công bố cập nhật spec quan trọng vào ngày 28 tháng 7 năm 2026. Thay đổi chính: session bị loại bỏ. Không còn initialize/initialized handshake, không còn header Mcp-Session-Id, không còn server-initiated request qua standing SSE stream. Mỗi MCP request bây giờ tự chứa đủ thông tin.

Đây là breaking change với các server hiện tại, nhưng động lực rõ ràng và migration path được định nghĩa tốt. Bài viết này phân tích những gì thay đổi về mặt kỹ thuật, tại sao quan trọng cho deployment, và cách thích nghi các implementation hiện tại.

Vấn Đề Session Giải Quyết (và Tạo Ra)

Trong mọi spec MCP trước đây từ 2025-03-26 đến 2025-11-25, client mở kết nối đến MCP server bằng trao đổi initialize. Server trả về capabilities và client gửi initialized để xác nhận. Session ID gắn tất cả request tiếp theo với instance server cụ thể đó.

Cách này hoạt động tốt cho single-server deployment. Nó trở thành vấn đề ở scale.

Remote MCP server đằng sau load balancer cần sticky session — mỗi request từ client nhất định phải route đến cùng backend instance, vì chỉ instance đó có session context. Không có session context nghĩa là không có thông tin capability, không có kết quả version negotiation, không có record về những gì client có thể làm. Nếu instance đó chết, session của client chết theo.

Sticky session là gánh nặng vận hành. Chúng hạn chế horizontal scaling, phức tạp hóa zero-downtime deployment, và đòi hỏi shared storage cho bất kỳ failover nào. Chúng cũng không tương thích với loại infrastructure stateless, disposable mà cloud-native deployment giả định.

Spec 2026-07-28 giải quyết điều này ở cấp protocol: nhúng mọi thứ server cần vào mỗi request.

Định Dạng Request Mới

Mỗi modern MCP request (method: 2026-07-28 hoặc mới hơn) bao gồm các trường này trong parameter _meta:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_weather",
    "arguments": { "location": "Hà Nội" },
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientInfo": {
        "name": "ExampleClient",
        "version": "1.0.0"
      },
      "io.modelcontextprotocol/clientCapabilities": {}
    }
  }
}

Hai trường là bắt buộc trên mỗi request:

  • io.modelcontextprotocol/protocolVersion — version protocol cho request cụ thể này
  • io.modelcontextprotocol/clientCapabilities — những gì client này có thể làm

clientInfo được khuyến nghị mạnh nhưng không bắt buộc. Server phải reject request thiếu các trường bắt buộc với -32602 Invalid params và, trên HTTP, 400 Bad Request.

Mỗi response kết quả cũng bao gồm trường bắt buộc mới resultType: "complete" cho request hoàn thành, "input_required" cho pattern multi-round-trip mới được mô tả dưới đây. Client phải coi resultType vắng mặt là "complete" để backward compatibility với server cũ hơn.

server/discover RPC bây giờ là bắt buộc trên tất cả server. Nó chỉ lấy _meta và trả về supportedVersions[], capabilities, và server info — client có thể gọi nó trước để probe server hỗ trợ gì mà không cần risk một request đầy đủ.

HTTP Header Mới Cho Infrastructure Routing

Spec thêm ba HTTP header mới phản ánh request metadata vào HTTP layer:

  • Mcp-Protocol-Version — protocol version
  • Mcp-Method — tên JSON-RPC method
  • Mcp-Name — tên tool/prompt/resource được gọi

Các header này tồn tại để load balancer, WAF, gateway, và rate limiter có thể route và inspect request mà không cần parse JSON body. Gateway có thể áp dụng rate limit khác nhau cho tools/call đối với expensive_tool so với fast_tool thuần túy từ header, không cần body inspection.

Server phải reject request khi header không khớp body — mismatch trả về error code -32020 HeaderMismatch.

Tool definition cũng có thể annotate parameter với x-mcp-header để các giá trị argument cụ thể được phản ánh vào header Mcp-Param-{Name}. Điều này cho phép tenant-based hoặc region-based routing ở infrastructure layer mà không cần body parsing.

Multi Round-Trip Requests (MRTR): Thay Thế Server Push

Trong các spec trước, server có thể gửi request đến client bằng cách push JSON-RPC message qua standing SSE stream. Điều này cho phép các pattern như sampling (yêu cầu client chạy LLM call), elicitation (thu thập user input), và roots (yêu cầu filesystem directory). Tất cả đều cần kết nối mở để server push lên.

Spec stateless phá vỡ model đó. Không có standing connection nào để push.

MRTR là sự thay thế. Khi server cần thông tin từ client trong request, thay vì push message, nó respond với request hiện tại bằng resultType: "input_required" và map inputRequests:

{
  "resultType": "input_required",
  "inputRequests": {
    "user_confirmation": {
      "method": "elicitation/create",
      "params": {
        "mode": "form",
        "message": "Xác nhận deployment target",
        "requestedSchema": {
          "type": "object",
          "properties": { "confirmed": { "type": "boolean" } },
          "required": ["confirmed"]
        }
      }
    }
  },
  "requestState": "AEAD-protected-blob"
}

Request ban đầu kết thúc. Client thu thập thông tin được yêu cầu, rồi retry call ban đầu với id khác (quan trọng: chúng là independent request) cộng thêm inputResponsesrequestState được echo lại. Server decode requestState để tái cấu trúc bất kỳ context nào cần và hoàn thành operation.

Trường requestState là cơ chế cho state continuity. Server encode bất cứ thứ gì cần (serialize dưới dạng base64 blob, JWT, AEAD-protected payload) và client echo lại nguyên vẹn. Client phải coi nó là opaque — không parse, không modify. Vì nó đi qua untrusted client, server phải bảo vệ tính toàn vẹn của nó bằng HMAC hoặc AEAD nếu nó ảnh hưởng đến quyết định authorization. Spec khuyến nghị bao gồm authenticated principal, TTL ngắn, và identifier request gốc bên trong payload được bảo vệ tính toàn vẹn để ngăn chặn replay.

MRTR được hỗ trợ trên prompts/get, resources/read, và tools/call. Đây là sự thay thế bắt buộc cho tất cả pattern server-to-client push trước đây.

Những Gì Bị Deprecated

Spec chính thức deprecated bốn tính năng, với việc xóa mục tiêu sớm nhất là tháng 7 năm 2027:

Roots — cơ chế cho server yêu cầu client cung cấp filesystem root directory. Migration: pass directory qua tool parameter, resource URI, hoặc server config. Trong thời gian chuyển đổi, dùng MRTR elicitation/create bên trong inputRequests.

Sampling — cơ chế cho server yêu cầu client chạy LLM call thay mặt họ. Migration: gọi LLM provider API trực tiếp từ server. Trong thời gian chuyển đổi, sampling/createMessage vẫn được hỗ trợ như loại request bên trong inputRequests của MRTR, ngay cả khi Sampling là client capability standalone bị deprecated.

Logging — trước đây gửi log message đến client qua push channel. Migration: log ra stderr cho stdio transport; dùng OpenTelemetry cho observability. Spec lưu ý các trường OTel (traceparent, tracestate, baggage) bây giờ là reserved _meta key theo tiêu chuẩn W3C Trace Context.

Dynamic Client Registration — thay thế bằng Client ID Metadata Documents (CIMD). Đây là OAuth flow plumbing ảnh hưởng chủ yếu đến authorization layer.

GET stream endpoint trên Streamable HTTP (nơi client có thể mở standing SSE channel để nhận server-initiated message) cũng bị xóa. Server phải respond 405 Method Not Allowed với GET request.

Tasks: Async Long-Running Operations

Tasks extension (io.modelcontextprotocol/tasks) giải quyết vấn đề MRTR không giải quyết: điều gì xảy ra khi operation mất lâu hơn transport sẽ chờ?

Long-running tool call luôn luôn khó xử lý. Bạn không thể giữ kết nối HTTP mở hàng phút mà không bị infrastructure timeout. Pattern trước đây thường là “chỉ cần trả về nhanh và để client poll” — nhưng không có cơ chế tiêu chuẩn hóa.

Tasks chính thức hóa điều này. Khi server quyết định một operation sẽ là long-running, nó trả về resultType: "task" với CreateTaskResult chứa taskId, initial status, ttlMs, và pollIntervalMs. Client poll tasks/get { taskId } để kiểm tra status.

Task states: workinginput_required (nếu cần input giữa task, qua cơ chế inputRequests tương tự) → completed hoặc failed hoặc cancelled. Khi completed, trường result chứa những gì synchronous call ban đầu sẽ trả về.

Task ID là durable — client disconnect và restart vẫn có thể resume polling. Spec khuyến nghị client persist task ID chính vì lý do này.

Notification là optional: server có thể push status update qua notifications/tasks thông qua subscriptions/listen stream, nhưng polling là default pattern. Điều này cho server tùy chọn có push capability mà không bắt buộc.

Migration Cho Server Hiện Tại

Spec định nghĩa backward compatibility detection rõ ràng:

Dual-era server trên cùng endpoint — phục vụ cả modern và legacy trên cùng URL. Nếu request có _meta field modern, phục vụ stateless. Nếu là initialize request, vào legacy mode.

HTTP detection — modern client thử modern POST. Nếu nhận 400 Bad Request và body là recognized modern JSON-RPC error, server là modern và request bị malformed. Nếu body 400 là thứ khác, fall back về initialize.

stdio detection — client gửi server/discover trước. Nếu nhận DiscoverResult hoặc UnsupportedProtocolVersionError, nó là modern. Bất kỳ thứ gì khác → fall back về initialize.

Thứ tự migration thực tế:

  1. Thêm _meta parsing vào request handler — extract version và capabilities
  2. Thêm server/discover implementation
  3. Thêm resultType vào tất cả response
  4. Implement MRTR cho bất kỳ pattern nào hiện đang dùng server-initiated request (sampling, roots, elicitation)
  5. Implement Tasks extension cho bất kỳ long-running operation nào
  6. Xóa session tracking khi tất cả client hỗ trợ modern spec

SDK: TypeScript, Python, Go, và C# là Tier 1 và đã được cập nhật. Rust đang ở beta.

Điều Này Thay Đổi Gì Cho AI Agent Infrastructure

Hàm ý kiến trúc mở rộng ra ngoài MCP server implementation:

Cấu hình load balancer đơn giản hóa. Xóa sticky session rule cho MCP backend. Round-robin qua tất cả instance hoạt động đúng. Điều này mở khóa auto-scaling đơn giản hơn và loại bỏ failure mode khi load balancer route đến instance chết giữ session của client.

Multi-tenant deployment trở nên rõ ràng hơn. Mỗi request mang identity riêng; không có session state nào rò rỉ qua các tenant nếu instance được tái sử dụng. Điều này giảm blast radius của session isolation failure.

Khả năng gateway mở rộng. Các HTTP header mới cho phép routing, rate limiting, và access control ở infrastructure layer mà không cần thay đổi application. Expensive tool call có thể bị rate limit theo tên ở WAF trước khi request đến server.

Observability cải thiện. Với OTel field là first-class _meta key, distributed trace bây giờ có thể span từ MCP client qua server đến downstream LLM call mà không cần custom instrumentation glue.

Chuyển đổi stateless là breaking change với implementation server hiện tại, nhưng là quyết định đúng đắn ở infrastructure level. Session model trước đây không phù hợp với cách cloud deployment hiện đại hoạt động. Spec 2026-07-28 đồng bộ MCP với các pattern vận hành mà phần còn lại của distributed systems infrastructure đã hội tụ qua thập kỷ qua.


Thuận Lương là Tech Lead với 15+ năm kinh nghiệm về .NET, cloud architecture, và AI systems. Anh viết về những bài học từ việc xây dựng các hệ thống production thực tế.

Xuất nội dung

Bình luận