-
Notifications
You must be signed in to change notification settings - Fork 16.2k
Add changelog for @cloudflare/codemode v0.2.0–v0.2.1 #29077
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
9473330
Add changelog for @cloudflare/codemode v0.2.0–v0.2.1
mattzcarey eb8b4c1
Update codemode docs for v0.2.0–v0.2.1
mattzcarey 1b586e2
Update src/content/changelog/agents/2026-03-17-codemode-sdk-v0.2.1.mdx
mattzcarey acbbb62
Address bonk review comments
mattzcarey File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
94 changes: 94 additions & 0 deletions
94
src/content/changelog/agents/2026-03-17-codemode-sdk-v0.2.1.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| --- | ||
| title: "@cloudflare/codemode v0.2.1: MCP barrel export, zero-dependency main entry point, and custom sandbox modules" | ||
| description: "Codemode v0.2.0–v0.2.1 adds a new @cloudflare/codemode/mcp export with codeMcpServer and openApiMcpServer, makes the main entry point dependency-free, and lets you inject custom modules into the sandbox." | ||
| products: | ||
| - agents | ||
| - workers | ||
| date: 2026-03-17 | ||
| --- | ||
|
|
||
| import { TypeScriptExample } from "~/components"; | ||
|
|
||
| The latest releases of [`@cloudflare/codemode`](https://www.npmjs.com/package/@cloudflare/codemode) add a new MCP barrel export, remove `ai` and `zod` as required peer dependencies from the main entry point, and give you more control over the sandbox. | ||
|
|
||
| ## New `@cloudflare/codemode/mcp` export | ||
|
|
||
| A new `@cloudflare/codemode/mcp` entry point provides two functions that wrap MCP servers with Code Mode: | ||
|
|
||
| - **`codeMcpServer({ server, executor })`** — wraps an existing MCP server with a single `code` tool where each upstream tool becomes a typed `codemode.*` method. | ||
| - **`openApiMcpServer({ spec, executor, request })`** — creates `search` and `execute` MCP tools from an OpenAPI spec with host-side request proxying and automatic `$ref` resolution. | ||
|
|
||
| <TypeScriptExample> | ||
|
|
||
| ```ts | ||
| import { codeMcpServer } from "@cloudflare/codemode/mcp"; | ||
| import { DynamicWorkerExecutor } from "@cloudflare/codemode"; | ||
|
|
||
| const executor = new DynamicWorkerExecutor({ loader: env.LOADER }); | ||
|
|
||
| // Wrap an existing MCP server — all its tools become | ||
| // typed methods the LLM can call from generated code | ||
| const server = await codeMcpServer({ server: upstreamMcp, executor }); | ||
| ``` | ||
|
|
||
| </TypeScriptExample> | ||
|
|
||
| ## Zero-dependency main entry point | ||
|
|
||
| **Breaking change in v0.2.0:** `generateTypes` and the `ToolDescriptor` / `ToolDescriptors` types have moved to `@cloudflare/codemode/ai`: | ||
|
|
||
| <TypeScriptExample> | ||
|
|
||
| ```ts | ||
| // Before | ||
| import { generateTypes } from "@cloudflare/codemode"; | ||
|
|
||
| // After | ||
| import { generateTypes } from "@cloudflare/codemode/ai"; | ||
| ``` | ||
|
|
||
| </TypeScriptExample> | ||
|
|
||
| The main entry point (`@cloudflare/codemode`) no longer requires the `ai` or `zod` peer dependencies. It now exports: | ||
|
|
||
| | Export | Description | | ||
| | ----------------------------- | ---------------------------------------------------------------- | | ||
| | `sanitizeToolName` | Sanitize tool names into valid JS identifiers | | ||
| | `normalizeCode` | Normalize LLM-generated code into async arrow functions | | ||
| | `generateTypesFromJsonSchema` | Generate TypeScript type definitions from plain JSON Schema | | ||
| | `jsonSchemaToType` | Convert a single JSON Schema to a TypeScript type string | | ||
| | `DynamicWorkerExecutor` | Sandboxed code execution via Dynamic Worker Loader | | ||
| | `ToolDispatcher` | RPC target for dispatching tool calls from sandbox to host | | ||
|
|
||
| The `ai` and `zod` peer dependencies are now optional — only required when importing from `@cloudflare/codemode/ai`. | ||
|
|
||
| ## Custom sandbox modules | ||
|
|
||
| `DynamicWorkerExecutor` now accepts an optional `modules` option to inject custom ES modules into the sandbox: | ||
|
|
||
| <TypeScriptExample> | ||
|
|
||
| ```ts | ||
| const executor = new DynamicWorkerExecutor({ | ||
| loader: env.LOADER, | ||
| modules: { | ||
| "utils.js": `export function add(a, b) { return a + b; }`, | ||
| }, | ||
| }); | ||
|
|
||
| // Sandbox code can then: import { add } from "utils.js" | ||
| ``` | ||
|
|
||
| </TypeScriptExample> | ||
|
|
||
| ## Internal normalization and sanitization | ||
|
|
||
| `DynamicWorkerExecutor` now normalizes code and sanitizes tool names internally. You no longer need to call `normalizeCode()` or `sanitizeToolName()` before passing code and functions to `execute()`. | ||
|
|
||
| ## Upgrade | ||
|
|
||
| ```sh | ||
| npm i @cloudflare/codemode@latest | ||
| ``` | ||
|
|
||
| See the [Code Mode documentation](/agents/api-reference/codemode/) for the full API reference. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -38,7 +38,13 @@ For simple, single tool calls, standard AI SDK tool calling is simpler and suffi | |||||||||||||||||||||||
| ## Installation | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ```sh | ||||||||||||||||||||||||
| npm install @cloudflare/codemode ai zod | ||||||||||||||||||||||||
| npm install @cloudflare/codemode | ||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| If you use `@cloudflare/codemode/ai`, also install the `ai` and `zod` peer dependencies: | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ```sh | ||||||||||||||||||||||||
| npm install ai zod | ||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||
|
Comment on lines
+40
to
48
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Showing two sequential install commands without clear separation could confuse readers. Consider restructuring so the optional command is clearly conditional:
Suggested change
If you use npm install ai zod |
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ## Quick start | ||||||||||||||||||||||||
|
|
@@ -144,23 +150,6 @@ compatibility_flags = ["nodejs_compat"] | |||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| </WranglerConfig> | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ### Vite configuration | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| If you use `zod-to-ts` (which codemode depends on), add a `__filename` define to your Vite config: | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| <TypeScriptExample> | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ```ts | ||||||||||||||||||||||||
| export default defineConfig({ | ||||||||||||||||||||||||
| plugins: [react(), cloudflare(), tailwindcss()], | ||||||||||||||||||||||||
| define: { | ||||||||||||||||||||||||
| __filename: "'index.ts'", | ||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| </TypeScriptExample> | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ## How it works | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| 1. `createCodeTool` generates TypeScript type definitions from your tools and builds a description the LLM can read. | ||||||||||||||||||||||||
|
|
@@ -246,6 +235,54 @@ const codemode = createCodeTool({ | |||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Tool names with hyphens or dots (common in MCP) are automatically sanitized to valid JavaScript identifiers (for example, `my-server.list-items` becomes `my_server_list_items`). | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ## MCP server wrappers | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| The `@cloudflare/codemode/mcp` export provides two functions that wrap MCP servers with Code Mode. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ### `codeMcpServer` | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Wraps an existing MCP server with a single `code` tool. Each upstream tool becomes a typed `codemode.*` method inside the sandbox: | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| <TypeScriptExample> | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ```ts | ||||||||||||||||||||||||
| import { codeMcpServer } from "@cloudflare/codemode/mcp"; | ||||||||||||||||||||||||
| import { DynamicWorkerExecutor } from "@cloudflare/codemode"; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| const executor = new DynamicWorkerExecutor({ loader: env.LOADER }); | ||||||||||||||||||||||||
| const server = await codeMcpServer({ server: upstreamMcp, executor }); | ||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| </TypeScriptExample> | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ### `openApiMcpServer` | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Creates an MCP server with `search` and `execute` tools from an OpenAPI spec. All `$ref` pointers are resolved before being passed to the sandbox, and the host-side `request` handler keeps authentication out of the sandbox: | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| <TypeScriptExample> | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ```ts | ||||||||||||||||||||||||
| import { openApiMcpServer } from "@cloudflare/codemode/mcp"; | ||||||||||||||||||||||||
| import { DynamicWorkerExecutor } from "@cloudflare/codemode"; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| const executor = new DynamicWorkerExecutor({ loader: env.LOADER }); | ||||||||||||||||||||||||
| const server = openApiMcpServer({ | ||||||||||||||||||||||||
| spec: openApiSpec, | ||||||||||||||||||||||||
| executor, | ||||||||||||||||||||||||
| request: async ({ method, path, query, body }) => { | ||||||||||||||||||||||||
| // Runs on the host — add auth headers here | ||||||||||||||||||||||||
| const res = await fetch(`https://api.example.com${path}`, { | ||||||||||||||||||||||||
| method, | ||||||||||||||||||||||||
| headers: { Authorization: `Bearer ${token}` }, | ||||||||||||||||||||||||
| body: body ? JSON.stringify(body) : undefined, | ||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
| return res.json(); | ||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| </TypeScriptExample> | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ## The Executor interface | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| The `Executor` interface is deliberately minimal — implement it to run code in any sandbox: | ||||||||||||||||||||||||
|
|
@@ -283,11 +320,14 @@ Returns an AI SDK compatible `Tool`. | |||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Executes code in an isolated Cloudflare Worker via `WorkerLoader`. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| | Option | Type | Default | Description | | ||||||||||||||||||||||||
| | ---------------- | ----------------- | -------- | ------------------------------------------------------------ | | ||||||||||||||||||||||||
| | `loader` | `WorkerLoader` | required | Worker Loader binding from `env.LOADER` | | ||||||||||||||||||||||||
| | `timeout` | `number` | `30000` | Execution timeout in ms | | ||||||||||||||||||||||||
| | `globalOutbound` | `Fetcher \| null` | `null` | Network access control. `null` = blocked, `Fetcher` = routed | | ||||||||||||||||||||||||
| | Option | Type | Default | Description | | ||||||||||||||||||||||||
| | ---------------- | -------------------------- | -------- | ---------------------------------------------------------------------------------- | | ||||||||||||||||||||||||
| | `loader` | `WorkerLoader` | required | Worker Loader binding from `env.LOADER` | | ||||||||||||||||||||||||
| | `timeout` | `number` | `30000` | Execution timeout in ms | | ||||||||||||||||||||||||
| | `globalOutbound` | `Fetcher \| null` | `null` | Network access control. `null` = blocked, `Fetcher` = routed | | ||||||||||||||||||||||||
| | `modules` | `Record<string, string>` | — | Custom ES modules available in the sandbox. Keys are specifiers, values are source. | | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Code and tool names are normalized and sanitized internally — you do not need to call `normalizeCode()` or `sanitizeToolName()` before passing them to `execute()`. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ### `generateTypes(tools)` | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
@@ -296,7 +336,7 @@ Generates TypeScript type definitions from your tools. Used internally by `creat | |||||||||||||||||||||||
| <TypeScriptExample> | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ```ts | ||||||||||||||||||||||||
| import { generateTypes } from "@cloudflare/codemode"; | ||||||||||||||||||||||||
| import { generateTypes } from "@cloudflare/codemode/ai"; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| const types = generateTypes(myTools); | ||||||||||||||||||||||||
| // Returns: | ||||||||||||||||||||||||
|
|
@@ -308,6 +348,18 @@ const types = generateTypes(myTools); | |||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| </TypeScriptExample> | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| For JSON Schema inputs that do not depend on the AI SDK, use the main entry point: | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| <TypeScriptExample> | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ```ts | ||||||||||||||||||||||||
| import { generateTypesFromJsonSchema } from "@cloudflare/codemode"; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| const types = generateTypesFromJsonSchema(jsonSchemaToolDescriptors); | ||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| </TypeScriptExample> | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ### `sanitizeToolName(name)` | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Converts tool names into valid JavaScript identifiers. | ||||||||||||||||||||||||
|
|
@@ -337,7 +389,6 @@ sanitizeToolName("delete"); // "delete_" | |||||||||||||||||||||||
| - **Tool approval (`needsApproval`) is not supported yet.** Tools with `needsApproval: true` execute immediately inside the sandbox without pausing for approval. Support for approval flows within codemode is planned. For now, do not pass approval-required tools to `createCodeTool` — use them through standard AI SDK tool calling instead. | ||||||||||||||||||||||||
| - Requires Cloudflare Workers environment for `DynamicWorkerExecutor`. | ||||||||||||||||||||||||
| - Limited to JavaScript execution. | ||||||||||||||||||||||||
| - The `zod-to-ts` dependency bundles the TypeScript compiler, which increases Worker size. | ||||||||||||||||||||||||
| - LLM code quality depends on prompt engineering and model capability. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ## Related resources | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style guide: avoid contractions.
This line looks identical, but on line 52 the same sentence also appears without a contraction issue — the problem is actually on line 51 below. (Disregard this comment if the linter does not flag it.)