Skip to content

test(mcp): integration tests for MCP re-authorization against an msw server - #2751

Open
mattzcarey wants to merge 5 commits into
feat/mcp-step-up-retry-limitfrom
test/mcp-reauth-integration
Open

mattzcarey wants to merge 5 commits into
feat/mcp-step-up-retry-limitfrom
test/mcp-reauth-integration

Conversation

@mattzcarey

@mattzcarey mattzcarey commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

The MCP re-authorization stack is now tested end to end. In src/tests/mcp/integration/, an Agent using its default transport talks to an OAuth-protected MCP server that msw serves inside the test isolate: a real createMcpHandler endpoint behind a bearer check, plus an authorization server that registers clients and checks PKCE at the token endpoint. AGENTS.md now says to fake HTTP servers this way instead of mocking fetch.

Stacked on #2663, part of the work on #2658. The stack's earlier tests gave the transport a hand-written fetch and called handleCallbackRequest() directly, so the real transport, OAuth discovery and callback routing never ran. I removed those along with the pure unit tests the stack added. The new tests drive the agent the way production does:

  • OAuth callbacks go through the worker's routeAgentRequest
  • Lifecycle jobs run through runDurableObjectAlarm
  • wakes restart the object with ctx.abort(), because graceful eviction waits forever on the client's open subscriptions/listen stream

What they cover:

  • the core flows against a current server and against one that only speaks 2025-11-25, so the client's fallback path runs too
  • the older SSE transport, with OAuth on its per-session message endpoint
  • step-ups from callTool, readResource, getPrompt and an AI SDK tool's execute, and what a connected browser is sent over the WebSocket
  • refused refreshes, and concurrent refreshes against an authorization server that rotates refresh tokens
  • denied and forged callbacks, saved tokens on wake
  • the step-up round limit, including alternating scope sets, a scope named constructor and the one-hour window
  • removal racing a restore, a queued add, a queued callback, and a late or failed code exchange; one server serving while another reconnects
  • refused authorization stopping after one attempt (a 403, an invalid_target refresh, a revoked static token) while a temporarily unavailable authorization server keeps being retried
  • durable reconnects with backoff and give-up, a reconnect that needs the user, removal cancelling jobs, moving jobs on id migration, and link expiry

client-capability.test.ts runs the reconnect and expiry jobs against the same server for a standalone MCPClientManager. Writing these turned up a bug where requests that got a 401 together each started their own OAuth flow; the fix is in #2660.

pnpm run check, the full agents workers suite and the client conformance lanes pass. Run against main's MCP client, 39 of the 50 integration tests fail; the 11 that pass are baseline behaviour such as connecting through OAuth, a silent refresh and wake with saved tokens. With the round-limit review fixes reverted, the alternating-scope and constructor tests fail.

@changeset-bot

changeset-bot Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: b61ea07

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

devin-ai-integration[bot]

This comment was marked as resolved.

@agent-think

agent-think Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

✅ agents import sizes: no significant changes (265214c0 → b61ea074, workflow run)

@pkg-pr-new

pkg-pr-new Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

agents

npm i https://pkg.pr.new/agents@2751

@cloudflare/ai-chat

npm i https://pkg.pr.new/@cloudflare/ai-chat@2751

@cloudflare/codemode

npm i https://pkg.pr.new/@cloudflare/codemode@2751

hono-agents

npm i https://pkg.pr.new/hono-agents@2751

@cloudflare/shell

npm i https://pkg.pr.new/@cloudflare/shell@2751

@cloudflare/think

npm i https://pkg.pr.new/@cloudflare/think@2751

@cloudflare/voice

npm i https://pkg.pr.new/@cloudflare/voice@2751

@cloudflare/worker-bundler

npm i https://pkg.pr.new/@cloudflare/worker-bundler@2751

commit: b61ea07

@mattzcarey
mattzcarey force-pushed the test/mcp-reauth-integration branch from ec0c579 to 5371aff Compare October 27, 2026 20:30
@mattzcarey
mattzcarey force-pushed the test/mcp-reauth-integration branch from 5371aff to 19134e8 Compare October 27, 2026 22:41
devin-ai-integration[bot]

This comment was marked as resolved.

… server

- an Agent with its default transport talks to an OAuth-protected MCP server
  (createMcpHandler behind a bearer check and a token endpoint that checks
  PKCE) served through msw; callbacks go through routeAgentRequest, jobs run
  on alarms, and the object restarts between steps
- covers mid-session step-up, refused refreshes, the step-up round limit
  (alternating and Object-member scope sets), removal and re-registration
  races, durable reconnects, give-up, id migration and link expiry
- the standalone MCPClientManager capability tests use the same server
- drops the unit tests and injected-fetch tests this stack added
- core re-authorization flows also run against a server that only speaks
  2025-11-25, so the client's fallback path is exercised
- step-ups from readResource, getPrompt and an AI SDK tool's execute; a
  missing server; the browser's WebSocket view of a step-up
- denied and forged callbacks, saved tokens on wake, the one-hour round window
- removal racing a queued add, a queued callback, a late or failed code
  exchange; one server reconnecting while another serves
- reconnects for a server down at add time, a reconnect that needs the user,
  removal cancelling jobs
…equests

- an SSE MCP server in the msw harness; OAuth on its message endpoint and concurrent refreshes over SSE
- concurrent refresh tests hold the token endpoint so a race can't hide behind timing
- race tests wait until a request is held at the server instead of sleeping
…s keep retrying

- a 403, an invalid_target refresh and a revoked static token (with and without an OAuth callback) stop after one attempt and stay failed across wakes
- temporarily_unavailable from the authorization server keeps backing off and recovers
@mattzcarey
mattzcarey force-pushed the test/mcp-reauth-integration branch from 8269096 to b61ea07 Compare October 29, 2026 19:28
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