Skip to content

docs(mcp): document servers with createMcpHandler only - #2654

Open
mattzcarey wants to merge 2 commits into
mainfrom
docs/mcp-servers-createmcphandler-only
Open

mattzcarey wants to merge 2 commits into
mainfrom
docs/mcp-servers-createmcphandler-only

Conversation

@mattzcarey

@mattzcarey mattzcarey commented Oct 21, 2026 •

Copy link
Copy Markdown
Member

The MCP docs now show one way to build a server: a stateless createMcpHandler from agents/mcp/server with an SDK v2 McpServer. McpAgent, WorkerTransport, createLegacyMcpHandler and the McpAgent RPC transport are gone from the docs. Docs only, no code changes.

McpAgent has been deprecated since 0.20.0, but mcp-servers.md still walked through it next to createMcpHandler as if you had to choose between them.

  • mcp-servers.md is rewritten around createMcpHandler: install, a minimal server, keeping state in bindings or an Agent (getAgentByName from a tool), handler options, Origin checks, notifications, OAuthProvider auth with getMcpAuthContext(), inputRequired elicitation, and 2025-era clients. One short section links existing McpAgent users to the SDK v2 migration guide.
  • mcp-transports.md covers Streamable HTTP on the server and the auto / streamable-http / sse client options. The McpAgent SSE, auto and RPC transport sections are removed.
  • mcp-client.md, human-in-the-loop.md, get-current-agent.md, routing.md, index.md and the package README lose their McpAgent, RPC transport and Legacy Elicitation references.

I type-checked the new snippets in mcp-servers.md (bindings, the Notes Agent, auth) against the built package.

Overlaps with #2634 in mcp-servers.md, mcp-transports.md, mcp-client.md and the README; I'll rebase whichever merges second.


Devin Review

Remove McpAgent, WorkerTransport, createLegacyMcpHandler, and the McpAgent RPC
transport from the MCP docs. Servers are documented as stateless
createMcpHandler handlers, with state in bindings or an Agent, OAuthProvider
auth, and inputRequired elicitation. mcp-servers.md keeps one link to the SDK v2
migration guide for existing McpAgent servers.
@changeset-bot

changeset-bot Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 94794c2

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

@agent-think

agent-think Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

✅ agents import sizes: no significant changes (f4045474 → 94794c2e, workflow run)

@devin-ai-integration devin-ai-integration Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Note

Newer findings are available below. Devin Review posted a newer report on this PR, in addition to the findings presented here.

Devin Review found 2 potential issues.

Devin Review

# Creating MCP Servers

This guide covers the different ways to create MCP servers with the Agents SDK and helps you choose the right approach.
Build an MCP server on Workers with `createMcpHandler` from `agents/mcp/server` and an MCP SDK v2 `McpServer`. The handler is stateless: every request gets a fresh server from your factory, so there is no Durable Object, session, or WebSocket to manage. It serves draft MCP `2026-07-28` and stateless 2025-era clients from the same endpoint.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔍 Verify the upstream documentation update

The documentation rules require matching updates in cloudflare/cloudflare-docs. Confirm these MCP pages are ported; this repository has no automated sync.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +106 to +109
const userId = String(getMcpAuthContext()?.props.userId ?? "anonymous");
const notes = await getAgentByName(env.Notes, userId);
const count = await notes.add(note);
return { content: [{ type: "text", text: `You have ${count} notes` }] };

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟨 Anonymous clients share private notes state

Without OAuth, getMcpAuthContext() is empty, so every caller writes to the same Notes agent. Each caller receives a count that includes other callers' notes.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

@pkg-pr-new

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

Copy link
Copy Markdown

Open in StackBlitz

agents

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

@cloudflare/ai-chat

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

@cloudflare/codemode

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

hono-agents

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

@cloudflare/shell

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

@cloudflare/think

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

@cloudflare/voice

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

@cloudflare/worker-bundler

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

commit: 94794c2

OAuthProvider only accepts an ExportedHandler object or a WorkerEntrypoint
class, so passing the handler function directly throws at startup.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

Devin Review

- All MCP session data stays within the EU
- User data processed by your tools remains in the EU
- State stored in the Durable Object's storage API stays in the EU
`OAuthProvider` needs an object with a `fetch` method, so wrap the handler as shown. Passing the handler function directly throws at startup.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔍 OAuth startup claim conflicts with callable handler

createMcpHandler returns a function with a fetch property, and the authenticated example passes it directly to OAuthProvider. The claim that this throws at startup needs verification against the provider's runtime behavior.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

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