Commit f625075
authored
Centralize account-ID resolution; upgrade agents/MCP SDK/zod/ai; migrate to registerTool (#384)
* feat: centralize account-id resolution; remove account-management tools
Replace the tool-based account selection (accounts_list + set_active_account,
per-app getActiveAccountId/setActiveAccountId, UserDetails activeAccountId) with a
centralized AccountManager + a CloudflareMCPServer.accountTool() wrapper.
Resolution precedence (per call):
1. Auth-pinned account — account-scoped token's account, or a single-account OAuth
token (no account_id param exposed in this case).
2. cf-account-id request header (user-configured) — multi-account tokens only.
3. account_id tool argument — auto-appended only for multi-account tokens.
Multi-account credentials get their account list injected into the server initialize
instructions for discovery. All tool error responses now set isError: true.
- New: packages/mcp-common/src/account-manager.ts (3-layer resolver) + account-tool.ts
(buildAccountTool wrapper core, kept ajv-free for testing) + specs (19 tests).
- CloudflareMCPServer gains accountTool(); collapse dead CloudflareMcpAgentNoAccount layer.
- Migrate all account-scoped shared + per-app tools to accountTool.
- Remove account.tools.ts, account.api.ts, constants.ts, accounts.eval.ts; update READMEs
and implementation-guides/tools.md.
Supersedes #316.
* chore: upgrade agents 0.13, MCP SDK 1.29, zod 4, ai 6
Bumps across all packages: agents 0.2.19→0.13.3, @modelcontextprotocol/sdk
1.20.2→1.29.0, zod 3.24.2→4.4.3, ai 4.3.10→6.0.193 (+ @ai-sdk/* v3 providers,
ai-gateway-provider 3.1.3).
Migration fixes:
- zod 4: z.record(key, value) explicit key; z.string().ip() -> z.ipv4()/z.ipv6();
drop removed objectOutputType (use z.infer<z.ZodObject<Shape>>).
- agents 0.13: McpAgent env generic constrained to Cloudflare.Env; api-handler /
api-token-mode infer the env generic (no `any`).
- MCP SDK 1.29: flatten tool annotations to { title, readOnlyHint, ... } (fixes a
latent bug where nested annotations were ignored).
- ai 6: eval tooling (LanguageModel, inputSchema, stopWhen/stepCountIs, tool-call input);
MCPClientManager now takes a storage option.
Typecheck + lint green across all 19 packages. Changeset added for all servers.
* refactor: migrate tool registration to registerTool (MCP SDK 1.29)
The legacy `.tool()` API is deprecated in favour of `.registerTool(name, config, cb)`.
- CloudflareMCPServer now wraps BOTH `tool()` and `registerTool()` for metrics via a shared
`trackCb` helper, so every registration path is tracked identically.
- accountTool() registers via `registerTool({ description, inputSchema, annotations }, cb)`;
buildAccountTool's callback is typed as the SDK `ToolCallback<ZodRawShape>`, so the call is
fully type-checked (removed the `@ts-ignore`).
- Converted all 78 remaining `.tool(...)` call sites across apps + shared tools to
`.registerTool(...)` with the config-object form (61 in radar, 17 across 8 other files).
Typecheck + lint green across all 19 packages; account-manager + accountTool specs pass.
* refactor: remove @ts-ignore from tool/registerTool override forwarding
The two overrides spread `unknown[]` into the bound original methods (`_tool(name, ...rest)`),
which TS rejects with TS2556 (spread into an overloaded signature without a rest param) — the
forwarding is correct at runtime. Type the bound originals as variadic
`(...args: unknown[]) => ReturnType<McpServer['tool' | 'registerTool']>` so the spread is legal.
No suppression, no `any`. Typecheck + lint green.
* chore: point packages/tools zod pin at stable 4.4.3 (syncpack)
* chore: upgrade dev toolchain for agents 0.13 local dev
agents 0.13 needs a newer local workerd than the pinned wrangler provided
(`cloudflare:workers` `exports`), so bump the dev/test toolchain:
- wrangler 4.10.0 → 4.96.0 (recent workerd; fixes `wrangler dev`)
- esbuild override 0.25.1 → 0.27.3 (required by wrangler 4.96)
- @cloudflare/vitest-pool-workers 0.8.14 → 0.12.0 (newest on esbuild 0.27 that
keeps the vitest-3 `/config` API; avoids the vitest-4 config-rewrite migration)
- vitest 3.0.9 → 3.2.6, @vitest/ui → 3.2.6
All dev dependencies — no change to deployed runtime. Verified `wrangler dev` boots
the workers-observability server and tools resolve end-to-end; tests 116/116, types,
lint, deps, format all green.
* chore: migrate to vitest 4 + @cloudflare/vitest-pool-workers 0.16
Completes the test-toolchain upgrade (vitest 3.2 → 4.1.8, pool-workers 0.12 → 0.16.11),
using pool-workers' official `vitest-v3-to-v4` codemod + recipes.
- Ran the codemod across all vitest configs: `defineWorkersConfig`/`defineWorkersProject`
→ `defineConfig` from 'vitest/config' with the `cloudflareTest({...})` Vite plugin (the
`poolOptions.workers` block moves into the plugin). Removed dropped options
(`singleWorker`, `isolatedStorage`).
- Migrated the workspace: `vitest.workspace.ts` → root `vitest.config.ts` with `test.projects`.
- Added `"type": "module"` to the worker packages (pool-workers 0.16 main entry is ESM-only,
so `.ts` configs must load as ESM).
- pool-workers 0.16 removed `fetchMock` from `cloudflare:test`: migrated the 4 specs that
mocked api.cloudflare.com to MSW (per the official request-mocking recipe) — shared
`src/test/msw-server.ts` + `msw-setup.ts`, `server.use(http.<m>(url, () => HttpResponse...))`.
- tsconfig `types`: `@cloudflare/vitest-pool-workers` → `/types` (cloudflare:test module moved).
- eval-tools: import `env` from `cloudflare:workers` (cloudflare:test `env` is deprecated);
typed eval vars via a local `EvalEnv`; added missing credentials guard in getAnthropicModel.
- Deduped `@types/node` to 22.15.17 (override + declarations) to collapse a duplicate `vite`
that made plugin types "unrelated".
All gates green: check:types + check:lint (37/37), tests (116), check:deps, check:format.
* chore(evals): route AI Gateway via BYOK unified provider; connect over /mcp
- test-models: use ai-gateway-provider createUnified() with the gateway's
stored (BYOK) keys instead of an empty per-provider apiKey, fixing the
'Incorrect API key' failures. Judge: gpt-5.4-nano; subjects: gpt-5.4-mini,
gpt-4.1, and workers-ai/@cf/moonshotai/kimi-k2.6.
- drop now-unused providers (@ai-sdk/openai, @ai-sdk/anthropic, @ai-sdk/google,
workers-ai-provider) from eval-tools.
- eval clients connect to /mcp (token-mode servers only serve /mcp, not /sse).
- bump ai 6.0.193 -> 6.0.194.
* refactor: remove dormant UserDetails durable object
The UserDetails DO existed only to persist activeAccountId across sessions
(added in #85) for the old set_active_account / accounts_list flow. Account
resolution is now derived per-request (auth-pinned -> cf-account-id header ->
account_id arg), so nothing reads or writes it — getUserDetails has no callers.
- delete user_details.do.ts and remove the USER_DETAILS binding, export, and
Env type from all 13 account-scoped apps (dev + staging + production).
- add a deleted_classes DO migration (tag v2) to the two owning workers
(workers-observability, workers-builds) so the namespace is torn down.
- strip the dead commented-out tool blocks in r2_bucket.tools.ts and
hyperdrive.tools.ts (they referenced the removed getActiveAccountId API).
- regenerate worker-configuration.d.ts across apps (drops USER_DETAILS).
* fix(types): make worker types current; drop --include-env=false
CI typecheck broke after regenerating worker-configuration.d.ts to the
wrangler 4.96 / workerd 1.20260529 runtime types. Fixes:
- remove '--include-env=false' from every app's 'types' script (and the
run-wrangler-types helper). Under the new wrangler that flag also strips the
global 'interface Env' the app/test code relies on (getEnv<Env>, McpAgent<Env>,
vitest TestEnv extends Env); without it the global Env is emitted again.
- regenerate packages/mcp-common/worker-configuration.d.ts (was stuck at
workerd 1.20250409, predating embeddinggemma in AiModels) so the docs-vectorize
embeddings tool typechecks; drop the now-unnecessary @ts-expect-error directives.
- docs-* and sandbox-container: drop 'public' from the 'ctx: DurableObjectState'
constructor params — the new DurableObjectState<unknown> default conflicts with
the McpAgent/DurableObject base's DurableObjectState<{}>; inheriting it avoids
the redeclaration (matches every other app).
- api-token-mode: ExecutionContext.props is now readonly; assign auth props via a
typed mutable view (runtime sets props before serve()).
* refactor: remove dead activeAccountId agent state
Vestigial leftover from the account-id centralization: 'activeAccountId' was
still declared in each agent's State (and one initialState) but never read or
written — account resolution is now derived per-request via AccountManager.
- drop the field from all 13 account-scoped apps' State (and workers-bindings'
initialState); workers-builds keeps its still-used activeBuildUUID/activeWorkerId.
- mcp-common CloudflareMCPAgentState is now an empty base (Record<string, unknown>)
so servers with their own state (workers-builds) stay assignable to CloudflareMcpAgent.1 parent 55087fe commit f625075
172 files changed
Lines changed: 245744 additions & 66859 deletions
File tree
- .changeset
- apps
- ai-gateway
- src
- tools
- auditlogs
- src
- tools
- autorag
- src
- tools
- browser-rendering
- src
- tools
- cloudflare-one-casb
- src
- tools
- demo-day
- src
- dex-analysis
- src
- tools
- dns-analytics
- src
- tools
- docs-ai-search
- src
- docs-autorag
- src
- tools
- docs-vectorize
- src
- graphql
- src
- tools
- logpush
- src
- tools
- radar
- src
- tools
- types
- sandbox-container
- evals
- server
- workers-bindings
- evals
- src
- workers-builds
- src
- tools
- workers-observability
- src
- tools
- implementation-guides
- packages
- eslint-config
- eval-tools
- src
- mcp-common
- src
- api
- durable-objects
- test
- tools
- types
- mcp-observability
- tools
- bin
- typescript-config
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
27 | | - | |
| 27 | + | |
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| |||
48 | 48 | | |
49 | 49 | | |
50 | 50 | | |
51 | | - | |
| 51 | + | |
52 | 52 | | |
53 | 53 | | |
54 | 54 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | | - | |
| 21 | + | |
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
| 11 | + | |
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
17 | | - | |
| 17 | + | |
18 | 18 | | |
19 | 19 | | |
20 | | - | |
| 20 | + | |
21 | 21 | | |
22 | 22 | | |
23 | | - | |
| 23 | + | |
24 | 24 | | |
25 | 25 | | |
26 | | - | |
27 | | - | |
| 26 | + | |
| 27 | + | |
28 | 28 | | |
29 | 29 | | |
30 | | - | |
31 | | - | |
32 | | - | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
33 | 34 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
8 | 9 | | |
9 | | - | |
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
14 | | - | |
15 | 14 | | |
16 | 15 | | |
17 | 16 | | |
| |||
21 | 20 | | |
22 | 21 | | |
23 | 22 | | |
24 | | - | |
25 | | - | |
26 | 23 | | |
27 | 24 | | |
28 | 25 | | |
| |||
31 | 28 | | |
32 | 29 | | |
33 | 30 | | |
34 | | - | |
| 31 | + | |
35 | 32 | | |
36 | 33 | | |
37 | 34 | | |
| |||
54 | 51 | | |
55 | 52 | | |
56 | 53 | | |
| 54 | + | |
57 | 55 | | |
58 | 56 | | |
59 | 57 | | |
| |||
62 | 60 | | |
63 | 61 | | |
64 | 62 | | |
| 63 | + | |
| 64 | + | |
65 | 65 | | |
66 | 66 | | |
67 | | - | |
68 | | - | |
69 | 67 | | |
70 | 68 | | |
71 | 69 | | |
72 | | - | |
73 | | - | |
74 | | - | |
75 | | - | |
76 | | - | |
77 | | - | |
78 | | - | |
79 | | - | |
80 | | - | |
81 | | - | |
82 | | - | |
83 | | - | |
84 | | - | |
85 | | - | |
86 | | - | |
87 | | - | |
88 | | - | |
89 | | - | |
90 | | - | |
91 | | - | |
92 | | - | |
93 | | - | |
94 | | - | |
95 | | - | |
96 | | - | |
97 | | - | |
98 | | - | |
99 | | - | |
100 | | - | |
101 | | - | |
102 | | - | |
103 | 70 | | |
104 | 71 | | |
105 | 72 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | 1 | | |
3 | 2 | | |
4 | 3 | | |
| |||
10 | 9 | | |
11 | 10 | | |
12 | 11 | | |
13 | | - | |
14 | 12 | | |
15 | 13 | | |
16 | 14 | | |
| |||
0 commit comments