Skip to content

Conversation

@ghostwriternr
Copy link
Member

@ghostwriternr ghostwriternr commented Sep 22, 2025

Summary

This PR fixes OAuth callback handling for MCP servers and adds automatic HOST detection to simplify configuration.

Changes

OAuth Fixes

  • Remove MCPClientManager override in MyAgent example that was preventing OAuth callbacks from working
  • Add callback URL persistence across Durable Object hibernation
  • Fix connection reuse during OAuth reconnect to prevent state loss
  • Add OAuth transport tracking to prevent authorization code consumption during auto-fallback
  • Preserve PKCE verifier across transport attempts

Enhancements

  • Make callbackHost parameter optional in addMcpServer() - automatically derives from request when not provided
  • Update examples to reflect HOST as optional environment variable
  • Refactor transport types for better type safety

Testing

  • Add OAuth test coverage (17 new tests)
  • Test OAuth transport tracking, PKCE preservation, connection reuse
  • Test error scenarios and edge cases

Test Plan

  • OAuth callbacks work with Linear MCP server
  • OAuth state persists across DO hibernation
  • SSE transport connections work with OAuth
  • OAuth works correctly with auto-fallback (no "authorization code already used" errors)
  • HOST auto-detection works when variable is not set
  • All URL formats work correctly: url, url/, url/mcp, url/sse
  • Backward compatibility maintained for existing code and stored URLs
  • All checks pass (formatting, linting, typechecking)
  • Test suite passes (73 tests, all passing)

MyAgent was creating its own MCPClientManager instance, overriding
the parent's instance. This prevented OAuth callbacks from working
since the parent Agent class registers callbacks with its own manager.
Callback URLs were stored in memory and lost when Durable Objects
hibernated, causing OAuth callbacks to fail with "Not found" errors.
Now callback URLs are persisted in the database and restored on wake.

- Add registerCallbackUrl() and unregisterCallbackUrl() methods
- Restore callback URLs from database in onStart()
- Clean up callback URLs when removing MCP servers
The connect() method was always creating a new MCPClientConnection
during OAuth reconnect, losing the existing connection state and
causing "client isn't in authenticating state" errors.

Now reuses the existing connection when reconnecting with OAuth code.
Auto-fallback between transports can consume OAuth codes, causing
authentication to fail. Now explicitly detect transport type from
URL patterns to prevent unnecessary fallback attempts.

- URLs ending with /sse use SSE transport
- URLs ending with /mcp use StreamableHTTP transport
- Others continue using auto-detection
The callbackHost parameter in addMcpServer() is now optional and will
be automatically derived from the current request when not provided.
This simplifies MCP server configuration by removing the need for
manual HOST environment variable setup in most cases.

- Make callbackHost parameter optional in addMcpServer()
- Auto-detect host from request.url when in request context
- Update examples to reflect HOST as optional
- Maintain backward compatibility for existing code
@changeset-bot
Copy link

changeset-bot bot commented Sep 22, 2025

🦋 Changeset detected

Latest commit: b6608fd

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

This PR includes changesets to release 2 packages
Name Type
agents Minor
hono-agents Major

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

@pkg-pr-new
Copy link

pkg-pr-new bot commented Sep 22, 2025

Open in StackBlitz

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

commit: b6608fd

- Normalize all URL formats to base URL for consistent storage
- Append transport endpoints (/mcp, /sse) at runtime
- Track OAuth transport to prevent authorization code consumption
- Preserve PKCE verifier across transport attempts
- Save transport type when OAuth is required (401 Unauthorized)
- Always use auto transport for consistent fallback behavior

This ensures OAuth works correctly when auto-fallback occurs between
transports, preventing "authorization code already used" errors.
Copy link
Contributor

@threepointone threepointone left a comment

Choose a reason for hiding this comment

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

tentatively looks good, think we can add a test?

also pass CI and add a changeset, then I'll review fully and let's land it soon

@ghostwriternr
Copy link
Member Author

tentatively looks good, think we can add a test?

Yep, working on tests! There were quite a lot of minute issues that had to be fixed, which took a lot of time to even discover manually. Need tests.

@threepointone
Copy link
Contributor

no rush then!

Ensures consistent URL handling regardless of how connections are
created and fixes broken auto transport tests.
Copy link
Contributor

@threepointone threepointone left a comment

Choose a reason for hiding this comment

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

did a quick review, this is looking great (and I'm so happy we're fixing auth)

@ghostwriternr
Copy link
Member Author

Fixing CI

@threepointone threepointone merged commit ff9329f into main Sep 23, 2025
3 checks passed
@threepointone threepointone deleted the oauth-fixes branch September 23, 2025 13:53
@threepointone threepointone mentioned this pull request Sep 23, 2025
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.

3 participants