Skip to content

Conversation

@Muhammad-Bin-Ali
Copy link
Contributor

@Muhammad-Bin-Ali Muhammad-Bin-Ali commented Jan 15, 2026

Summary

Persist and restore client capabilities (initializeParams) across serverless restarts when using WorkerTransport with storage.

Problem

When using WorkerTransport with storage in a serverless environment (like Cloudflare Workers), client capabilities (like elicitation support) were not persisted across requests. This caused elicitation and other capability-dependent features to fail after a serverless cold start with:

Error: Client does not support form elicitation.

Root Cause:

  • TransportState only stored { sessionId, initialized }
  • _clientCapabilities is stored in-memory on the MCP SDK's Server instance
  • After serverless restart, _clientCapabilities was undefined because it wasn't restored

Solution

Store the full initializeParams (capabilities, clientInfo, protocolVersion) and replay the initialize request during state restoration to restore _clientCapabilities on the Server instance.

Changes

packages/agents/src/mcp/worker-transport.ts:

  • Added RESTORE_REQUEST_ID constant for the synthetic restore request ID
  • Extended TransportState interface to include initializeParams
  • Capture initializeParams during initialization before calling saveState()
  • Replay initialize request via this.onmessage() during restoreState() to restore _clientCapabilities
  • Filter restore response in send() to prevent error from missing stream

packages/agents/src/tests/mcp/transports/worker-transport.test.ts:

  • Added new test suite "Client Capabilities Persistence (Serverless Restart)" with 5 tests covering persistence, restoration, and backward compatibility

Breaking Changes

None. The TransportState interface change is backward compatible - old stored state without initializeParams will continue to work (capabilities just won't be restored).

Future Improvement

The ideal solution would be to extend the MCP TypeScript SDK with a function to directly update clientCapabilities on the Server instance, rather than replaying the initialize request. This would be a cleaner approach that doesn't rely on internal implementation details.

Closes #777

🤖 Generated with OpenCode using Claude

@changeset-bot
Copy link

changeset-bot bot commented Jan 15, 2026

🦋 Changeset detected

Latest commit: 9bd943a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
agents Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@claude
Copy link

claude bot commented Jan 15, 2026

Claude Code Review

Issue Found:

Line 558: Redundant type guard check

const initMessage = messages.find(isInitializeRequest);
if (initMessage && isInitializeRequest(initMessage)) {

The isInitializeRequest(initMessage) check is redundant since find() already guarantees initMessage satisfies the predicate. Simplify to:

if (initMessage) {

Otherwise: LGTM

The implementation correctly solves the capability persistence problem. The approach of replaying the initialize request is reasonable given SDK limitations. Tests are comprehensive, covering edge cases and backward compatibility.

agents-git-bot bot pushed a commit to cloudflare/cloudflare-docs that referenced this pull request Jan 15, 2026
Update documentation to reflect changes from cloudflare/agents PR #783:
- Add initializeParams field to TransportState interface
- Document automatic persistence and restoration of client capabilities
- Explain behavior in serverless environments (Durable Objects/Agents)
- Note backward compatibility with older stored state

Related to: cloudflare/agents#783
@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 15, 2026

Open in StackBlitz

npm i https://pkg.pr.new/cloudflare/agents@783

commit: 9bd943a

@Muhammad-Bin-Ali Muhammad-Bin-Ali requested a review from a team January 15, 2026 20:39
agents-git-bot bot pushed a commit to cloudflare/cloudflare-docs that referenced this pull request Jan 15, 2026
Update MCP handler API documentation to reflect that WorkerTransport now
persists and restores client capabilities across serverless restarts.

Changes:
- Document that client capabilities (elicitation, sampling) are persisted
- Update TransportState interface to show initializeParams field
- Add explanation of capability restoration mechanism
- Include backward compatibility note
- Add links to elicitation and sampling specifications

Related to cloudflare/agents#783

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Copy link
Contributor

@mattzcarey mattzcarey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix check and a couple of questions. Awesome work :)

agents-git-bot bot pushed a commit to cloudflare/cloudflare-docs that referenced this pull request Jan 16, 2026
Update documentation to reflect PR cloudflare/agents#783 changes:

- Updated TransportState interface to include initializeParams field
- Added documentation explaining that client capabilities, client info,
  and protocol version are now persisted and restored across serverless restarts
- Emphasized importance of capability persistence for elicitation and sampling features
- Added detailed field descriptions for TransportState interface

This enables MCP servers to properly support advanced client features like
elicitation after serverless cold starts.

Related: cloudflare/agents#783

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
agents-git-bot bot pushed a commit to cloudflare/cloudflare-docs that referenced this pull request Jan 16, 2026
Updates documentation to reflect that WorkerTransport now persists
client capabilities across serverless restarts. This fixes an issue
where elicitation and other capability-dependent features would fail
after hibernation or cold starts.

Changes:
- Add initializeParams to TransportState interface documentation
- Document that client capabilities are persisted and restored
- Clarify the behavior of state restoration

Related to cloudflare/agents#783

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@Muhammad-Bin-Ali Muhammad-Bin-Ali force-pushed the muhammad/worker-not-persisting-clientCapabilities branch from 0d65eb7 to b9e1176 Compare January 16, 2026 18:28
@Muhammad-Bin-Ali Muhammad-Bin-Ali requested a review from a team January 16, 2026 18:34
Copy link
Contributor

@mattzcarey mattzcarey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

epic stuff, congrats

@mattzcarey mattzcarey merged commit f27e62c into main Jan 17, 2026
6 checks passed
@mattzcarey mattzcarey deleted the muhammad/worker-not-persisting-clientCapabilities branch January 17, 2026 16:51
@github-actions github-actions bot mentioned this pull request Jan 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WorkerTransport doesn't persist clientCapabilities, breaking elicitation in serverless

2 participants