Skip to content

fix(mcp): guard callTool/readResource/getPrompt against missing connections#1653

Draft
mattzcarey wants to merge 1 commit into
cloudflare:mainfrom
mattzcarey:fix/guard-mcp-call-undefined-connection
Draft

fix(mcp): guard callTool/readResource/getPrompt against missing connections#1653
mattzcarey wants to merge 1 commit into
cloudflare:mainfrom
mattzcarey:fix/guard-mcp-call-undefined-connection

Conversation

@mattzcarey
Copy link
Copy Markdown
Contributor

Problem

MCPClientManager.callTool, readResource, and getPrompt dereference
this.mcpConnections[serverId].client directly. When no in-memory connection
exists for the id, this surfaces as the opaque:

Cannot read properties of undefined (reading 'client')

The in-memory mcpConnections map and the storage-backed listServers() can
legitimately diverge:

  • a caller holds a serverId from an earlier snapshot whose connection has
    since been removed;
  • the agent woke from hibernation and connection restore is still in flight;
  • the id is stale after a reconnect (e.g. a remove+add that minted a new id).

In all three cases callers get a TypeError with no way to react.

Fix

Route all three call sites through a private #requireConnection(serverId)
helper that throws a named, actionable error when the connection is missing,
so callers can retry, re-sync, or fail gracefully instead of crashing.

Tests

Adds coverage for the missing-connection path of all three methods plus the
happy path for callTool (client-manager.test.ts). Full workers project
suite passes locally (145 tests).

Context

Surfaced in a downstream consumer (per-user MCPClientManager in a Durable
Object, tools proxied across a second DO) where a snapshotted serverId could
outlive its connection within a single turn. That consumer also adds its own
wait+recheck guard, but the SDK dereferencing undefined is the root defect.

…ctions

MCPClientManager.callTool, readResource and getPrompt dereferenced
this.mcpConnections[serverId].client directly. When no in-memory
connection exists for the id, this surfaced as the opaque
"Cannot read properties of undefined (reading 'client')".

The in-memory mcpConnections map and the storage-backed listServers()
can legitimately diverge: a caller may hold a serverId from an earlier
snapshot whose connection has since been removed, the agent may have
woken from hibernation with restore still in flight, or the id may be
stale after a reconnect. Route all three call sites through a new
#requireConnection helper that throws a named, actionable error so
callers can retry, re-sync, or fail gracefully instead of crashing.

Adds tests covering the missing-connection path for all three methods
plus the happy path for callTool.
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jun 2, 2026

⚠️ No Changeset found

Latest commit: d5816c4

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

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.

1 participant