Repository navigation
[Agents] Document MCP servers with createMcpHandler only - #34525
mattzcarey wants to merge 11 commits into
Conversation
AI Review✅ Reviewed 👉 Fix in your agent 👈Fix the following review findings in PR #34525 (https://github.com/cloudflare/cloudflare-docs/pull/34525).
Before making changes, review each finding and present a brief summary table:
- For each finding, state whether you agree, disagree, or need clarification.
- If you disagree, explain why.
- If you need clarification before deciding, ask those questions.
- Then share your plan for which issues to tackle and in what order.
After triaging, follow this order:
1. Post a comment on this PR for any findings you are skipping, with the finding ID and your reasoning.
2. Then commit the fixes for the legitimate findings.
The comment must come before the commit because the next review reads PR comments.
## Code Review
- C-1f701a91 | src/content/docs/agents/model-context-protocol/protocol/tools.mdx:252 | `server` is undefined in the stateful-tools example
The rewritten "Tools that need state" code block imports `env` from `cloudflare:workers` and `getMcpAuthContext` from `agents/mcp/server`, then immediately calls `server.registerTool(...)`, but `server` is never declared in the block and `McpServer` is never imported or constructed. The replaced `McpAgent` example defined its server inline; as written, this snippet cannot run.
```txt
server.registerTool(
```
- C-1b8f927c | src/content/docs/agents/tools/payments/x402/charge-for-mcp-tools.mdx:64 | x402 example contradicts the MCP SDK v2 migration guide
The "Integration compatibility" section of /agents/model-context-protocol/guides/migrate-to-mcp-sdk-v2/ states that the server-side `withX402` helper still retains SDK v1 server output and must be isolated behind `createLegacyMcpHandler` until it produces SDK v2 servers. This page now wraps an SDK v2 `McpServer` from `@modelcontextprotocol/server` and serves it with `createMcpHandler`, directly contradicting that guidance; the migration guide was not updated in this PR, so the two pages disagree about how to serve a `withX402` server.
```txt
const handler = createMcpHandler(createServer);
```
## Style Guide
- S-1d0dfc40 | src/content/docs/agents/model-context-protocol/apis/agent-api.mdx:196 | Lowercase `internet` should be `Internet`
The terminology rule requires `Internet` when referring to the global network. This line uses the incorrect lowercase form in `without going over the public internet`.
- S-097ef774 | src/content/docs/agents/model-context-protocol/apis/agent-api.mdx:200 | Marketing phrase `perfect for`
The marketing-language rule flags `Perfect for` and requires direct language stating what the thing does. This bullet is prose (not a code block or backtick span) and uses `perfect for agents calling MCP servers within the same Worker`.
- S-0ea22145 | src/content/docs/agents/model-context-protocol/apis/agent-api.mdx:330 | Heading begins with `-ing` verb
The heading rule requires imperative form for headings beginning with a verb ending in `-ing`. This heading begins with `Passing`.
- S-0b03c324 | src/content/docs/agents/model-context-protocol/apis/agent-api.mdx:371 | Heading begins with `-ing` verb
The heading rule requires imperative form for headings beginning with a verb ending in `-ing`. This heading begins with `Configuring` (explicitly listed as an example in the rule).
- S-135ba05e | src/content/docs/agents/model-context-protocol/guides/securing-mcp-server.mdx:147 | Heading begins with a verb ending in `-ing`
`## Signing in through a third-party provider` starts with the verb "Signing" in the `-ing` form. Per the headings rule, headings that begin with an `-ing` verb must use the imperative form instead.
- S-02bcb5dc | src/content/docs/agents/model-context-protocol/guides/build-codemode-mcp-server.mdx:36 | Directional word `below` in prose
The added sentence says "as the examples below do", using the directional word `below`. Per the style guide, directional words such as `above`/`below` must be replaced with a direct reference by name or link.
- S-046e672c | src/content/docs/agents/model-context-protocol/protocol/authorization.mdx:279 | Heading begins with a gerund instead of an imperative verb
Per the heading style rule, a heading that begins with a verb ending in `-ing` must use the imperative form. This heading starts with `Using`, so it should be rewritten in the imperative.
## Conventions
- V-16da4b5e | PR | Description omits removal of the Code Mode MCP guide pages
The description states the Code Mode MCP guides were "Left alone", but the changed-file index shows `src/content/docs/agents/model-context-protocol/codemode.mdx` and `src/content/docs/agents/model-context-protocol/guides/build-codemode-openapi-mcp-server.mdx` were removed (117 and 216 lines), and `build-codemode-mcp-server.mdx` was substantially rewritten (+230 -15), absorbing the OpenAPI search-and-execute content. The two redirects added in `public/__redirects` confirm these were removed/moved pages. Removed or moved pages and substantial rewrites are core changes the description should name.Code Review
Style Guide
Conventions
Not reviewed (2)
Resolved (1) · Dismissed (0)
Commands
|
Review coverage✅ All 7 ownership areas are covered. ✅ 7 areas already covered
CODEOWNERS mappings for displayed areas (7)
|
🚀 Deploying Preview to Cloudflare 🚀Preview URL: https://docs-agents-mcp-createmcphandler-only.previews.developers.cloudflare.com (commit 500ab8c)This URL reflects your latest Preview deploymentPreview Deployments by commit
|
Restore agent-api.mdx as the reference for existing McpAgent servers and move the McpAgent RPC transport and this.props auth examples there, so removing them from the transport and authorization pages loses nothing. Point the migration notes at it and drop the redirect.
Authorization now builds an OAuthAuthorizationServer and makes the MCP server an OAuthResourceServer around createMcpHandler, validated over a Service Binding. Securing MCP servers uses the library's consent and upstream sign-in helpers instead of hand-rolled CSRF and state code. Drop the context.http.authInfo claims (no provider release sets it) and fix the 1.x changelog's migration links.
Replace the hand-written escape helper with an API table for describeConsent, beginConsent, approveConsent, denyConsent and isConsentRemembered, and add one for beginUpstream, finishUpstream and tokenExchangeCallback. The library returns consent values but does not render HTML, so the page still escapes them.
Replace the April 2025 list with current guidance: keep tool definitions out of the context window with Code Mode on the client or server, use granular authorization with step-up, and declare accurate input and output schemas so strict clients accept your tools.
Fold the Code Mode MCP server patterns page and the search-and-execute guide into Build a Code Mode MCP server, which now covers choosing a pattern, wrapping an existing server, and publishing a large API with search and execute. Redirect the removed pages and update links.
|
This PR changes current filenames or deletes current files. Make sure you have redirects set up to cover the following paths:
|
TypeScriptExample transpiles each block, so object-literal and route-handler fragments failed the build. Use plain ts blocks for them.
Replace fragments in the handler API, tools, transport, authorization, and securing pages with full modules wrapped in TypeScriptExample. The securing guide now has a complete authorization server with a consent page, one that signs users in with GitHub, and a resource server that checks scopes. Tool examples declare output schemas and return structuredContent. The x402 paidTool signature becomes a parameter table. Every example type-checks against agents 0.29, @modelcontextprotocol/server 2.3.1, and workers-oauth-provider 1.2.4, and was run under wrangler dev.
The Agents MCP docs now show one way to build a server: a stateless
createMcpHandlerfromagents/mcp/serverwith an MCP SDK v2McpServer.McpAgentis now covered only by its own reference page (still marked deprecated) and Migrate to MCP SDK v2. TheMcpAgentRPC transport andthis.propsauth examples move from the transport and authorization pages into that reference page, so nothing is lost for existing users.McpAgenthas been deprecated sinceagents@0.20.0, but the docs still taught it next tocreateMcpHandler, including its RPC transport andthis.propsauth pattern.createMcpHandler. AddsOAuthProviderwrapping,getMcpAuthContext()inside the factory for per-user tools, and theauthContextoption. Removes thecreateLegacyMcpHandlersection and bumps the install to@modelcontextprotocol/server@2.3.1.McpAgentRPC transport section to theMcpAgentreference and removes the legacy-lane section.McpAgentexamples as factory functions, including permission-based tool registration and state in bindings.McpAgent" note, and updates the GitHub template snippet.withX402on an SDK v2 server served bycreateMcpHandler.McpAgentor Durable Object.mppx'sTransport.mcpSdk()still needs SDK v1, so this one usescreateLegacyMcpHandlerper request.agents/mcp/serverinstead of the deprecated v1createMcpHandleroverload.getCurrentAgent, securing MCP servers, the next-steps partial, and Agent Lee.Every
OAuthProviderexample now passes{ fetch }wrapping the handler. Passing thecreateMcpHandlerfunction directly throws at startup, becauseOAuthProvideronly accepts anExportedHandlerobject or aWorkerEntrypointclass.Left alone: the Code Mode MCP guides (
codeMcpServer()andopenApiMcpServer()still return SDK v1 servers) and Browser Run's Playwright MCP page (@cloudflare/playwright-mcpexportscreateMcpAgent).Merge after cloudflare/ai#680, which moves the GitHub OAuth template this guide quotes to
createMcpHandler. Repo-side docs: cloudflare/agents#2654.Every MCP example is a complete Worker in
TypeScriptExample:agents@0.29,@modelcontextprotocol/server@2.3.1and@cloudflare/workers-oauth-provider@1.2.4.wrangler dev. The auth server and resource server went through registration, consent (escaped client name, framing header, approve and deny), token and an authorizedtools/call. The GitHub sign-in example was checked up to the GitHub redirect and the cookie-bound callback. The handler and tools examples were run with real tool calls.