agents@0.15.0

cloudflare/agentsagents@0.15.0Jun 8, 2026by github-actions[bot]

AI Summary

Major refactor of `WorkerTransport` to extend the official MCP SDK's transport, reducing code complexity and improving state handling across Durable Object hibernation.

Key Highlights

  • Refactored to use official MCP SDK's `WebStandardStreamableHTTPServerTransport`
  • Reduces codebase by approximately 500 lines
  • Improved persistent transport state across DO hibernation
  • Enhanced CORS and SSE keepalive handling

Breaking Changes

  • `handleRequest` second argument signature changed from positional to object `{ parsedBody?, authInfo? }`
  • `retryInterval` behavior changed to follow SDK contract (only writes priming frame on POST streams with eventStore)
  • `onerror` now fires on client/protocol validation failures (400/405/406/415)
  • `onsessionclosed` fires before `onclose` on DELETE
  • `started` is now read-only
  • `createMcpHandler` now forwards SDK transport options (previously dropped)

New Features

  • SDK integration
  • Code simplification
  • State persistence
  • Improved error handling

Full Release Notes

### Minor Changes

-   [#1701](https://github.com/cloudflare/agents/pull/1701) [`6caa6e8`](https://github.com/cloudflare/agents/commit/6caa6e85a48c219b7ceef7a6e575f2812a0668b4) Thanks [@mattzcarey](https://github.com/mattzcarey)! - Refactor `WorkerTransport` to extend the official MCP SDK's `WebStandardStreamableHTTPServerTransport` instead of being a hand-rolled implementation.

    The wrapper is now a thin subclass that layers Workers-specific concerns on top of the SDK transport:

    -   **CORS** — preflight handling and response-header injection (`corsOptions`).
    -   **Persistent transport state** across DO hibernation via the existing `MCPStorageApi` adapter. `sessionId`, `initialized`, and `initializeParams` are snapshotted after each request and replayed on cold start so client capabilities are restored without a fresh initialize round-trip.
    -   **SSE keepalive** — preserves the issue [#1583](https://github.com/cloudflare/agents/issues/1583) fix. Uses the shared `KEEPALIVE_FRAME` (`: keepalive\n\n`) at `KEEPALIVE_INTERVAL_MS` (25s) from `sse-keepalive.ts`. Keepalive is unconditional on POST response streams and disabled on the standalone GET stream when an `eventStore` is configured (clients recover idle drops via `Last-Event-ID` instead).

    Everything else — session validation, SSE streaming, protocol-version negotiation, event-store resumability, send/close lifecycle — is delegated to the SDK transport. Net: ~500 fewer lines of code to maintain.

    The exported shape is unchanged: `WorkerTransport`, `WorkerTransportOptions`, `MCPStorageApi`, and `TransportState` keep the same names, and `WorkerTransportOptions` now also extends the SDK's transport options. The default `createMcpHandler` path (a fresh transport per request) is unaffected.

    There are, however, a few observable behaviour changes for callers who used `WorkerTransport` directly or relied on its previous quirks:

    -   **`handleRequest`'s second argument is now `{ parsedBody?, authInfo? }`** (the SDK shape) instead of a positional `parsedBody`. `createMcpHandler` and `McpAgent` don't pass it, but callers invoking `transport.handleRequest(request, parsedBody)` directly must wrap it as `transport.handleRequest(request, { parsedBody })`.
    -   **`retryInterval` priming now follows the SDK contract.** Previously a `retry:` priming frame was written to _any_ GET SSE stream whenever `retryInterval` was set. The SDK only writes a priming event when an `eventStore` is configured and the negotiated protocol version is `>= 2025-11-25` (older clients can't parse the empty-`data:` priming frame), and on POST streams rather than the standalone GET stream. `retryInterval` is still accepted but only affects that SDK priming event.
    -   **`onerror` now fires on client/protocol validation failures.** The SDK invokes `onerror` for responses such as 400/405/406/415 and session-not-found. The old transport only surfaced internal errors, so handlers that log `onerror` will now see normal client mistakes.
    -   **`onsessionclosed` fires before the underlying `close()`** (and therefore before `onclose`) on DELETE, instead of after. Ordering only; the session id is still passed.
    -   **`started` is now read-only.** It was a writable instance field and is now a getter backed by the SDK's internal `_started` flag. Reading it (e.g. `createMcpHandler`'s reconnect guard) is unchanged; assigning to it is no longer supported.
    -   **`createMcpHandler` now forwards SDK transport options.** Because `WorkerTransportOptions` extends the SDK options, the handler passes through everything except its own `route`/`authContext`/`transport` fields — including `eventStore`, `retryInterval`, `onsessionclosed`, and the SDK DNS-rebinding options (`enableDnsRebindingProtection`, `allowedHosts`, `allowedOrigins`). The previous handler silently dropped these.

    The SDK dependency is pinned exactly (`@modelcontextprotocol/sdk` `1.29.0`, no caret) because the wrapper relies on a handful of SDK internals for state restore and keepalive cleanup. The exact pin stops a patch release from shifting those out from under us, and the tests assert against the SDK field names so a bump fails CI loudly rather than breaking at runtime.