
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title><![CDATA[ The Cloudflare Blog ]]></title>
        <description><![CDATA[ Get the latest news on how products at Cloudflare are built, technologies used, and join the teams helping to build a better Internet. ]]></description>
        <link>https://blog.cloudflare.com</link>
        <atom:link href="https://blog.cloudflare.com/" rel="self" type="application/rss+xml"/>
        <language>en-us</language>
        <image>
            <url>https://blog.cloudflare.com/favicon.png</url>
            <title>The Cloudflare Blog</title>
            <link>https://blog.cloudflare.com</link>
        </image>
        <lastBuildDate>Thu, 09 Apr 2026 22:48:28 GMT</lastBuildDate>
        <item>
            <title><![CDATA[Sandboxing AI agents, 100x faster]]></title>
            <link>https://blog.cloudflare.com/dynamic-workers/</link>
            <pubDate>Tue, 24 Mar 2026 13:00:00 GMT</pubDate>
            <description><![CDATA[ We’re introducing Dynamic Workers, which allow you to execute AI-generated code in secure, lightweight isolates. This approach is 100 times faster than traditional containers, enabling millisecond startup times for AI agent sandboxing. ]]></description>
            <content:encoded><![CDATA[ <p>Last September we introduced <a href="https://blog.cloudflare.com/code-mode/"><u>Code Mode</u></a>, the idea that agents should perform tasks not by making tool calls, but instead by writing code that calls APIs. We've shown that simply converting an MCP server into a TypeScript API can <a href="https://www.youtube.com/watch?v=L2j3tYTtJwk"><u>cut token usage by 81%</u></a>. We demonstrated that Code Mode can also operate <i>behind</i> an MCP server instead of in front of it, creating the new <a href="https://blog.cloudflare.com/code-mode-mcp/"><u>Cloudflare MCP server that exposes the entire Cloudflare API with just two tools and under 1,000 tokens</u></a>.</p><p>But if an agent (or an MCP server) is going to execute code generated on-the-fly by AI to perform tasks, that code needs to run somewhere, and that somewhere needs to be secure. You can't just <code>eval() </code>AI-generated code directly in your app: a malicious user could trivially prompt the AI to inject vulnerabilities.</p><p>You need a <b>sandbox</b>: a place to execute code that is isolated from your application and from the rest of the world, except for the specific capabilities the code is meant to access.</p><p>Sandboxing is a hot topic in the AI industry. For this task, most people are reaching for containers. Using a Linux-based container, you can start up any sort of code execution environment you want. Cloudflare even offers <a href="https://developers.cloudflare.com/containers/"><u>our container runtime</u></a> and <a href="https://developers.cloudflare.com/sandbox/"><u>our Sandbox SDK</u></a> for this purpose.</p><p>But containers are expensive and slow to start, taking hundreds of milliseconds to boot and hundreds of megabytes of memory to run. You probably need to keep them warm to avoid delays, and you may be tempted to reuse existing containers for multiple tasks, compromising the security.</p><p><b>If we want to support consumer-scale agents, where every end user has an agent (or many!) and every agent writes code, containers are not enough. We need something lighter.</b></p><h6>And we have it.</h6>
    <div>
      <h2>Dynamic Worker Loader: a lean sandbox</h2>
      <a href="#dynamic-worker-loader-a-lean-sandbox">
        
      </a>
    </div>
    <p>Tucked into our Code Mode post in September was the announcement of a new, experimental feature: the Dynamic Worker Loader API. This API allows a Cloudflare Worker to instantiate a new Worker, in its own sandbox, with code specified at runtime, all on the fly.</p><p><b>Dynamic Worker Loader is now in open beta, available to all paid Workers users.</b></p><p><a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/worker-loader/"><u>Read the docs for full details</u></a>, but here's what it looks like:</p>
            <pre><code>// Have your LLM generate code like this.
let agentCode: string = `
  export default {
    async myAgent(param, env, ctx) {
      // ...
    }
  }
`;

// Get RPC stubs representing APIs the agent should be able
// to access. (This can be any Workers RPC API you define.)
let chatRoomRpcStub = ...;

// Load a worker to run the code, using the worker loader
// binding.
let worker = env.LOADER.load({
  // Specify the code.
  compatibilityDate: "2026-03-01",
  mainModule: "agent.js",
  modules: { "agent.js": agentCode },

  // Give agent access to the chat room API.
  env: { CHAT_ROOM: chatRoomRpcStub },

  // Block internet access. (You can also intercept it.)
  globalOutbound: null,
});

// Call RPC methods exported by the agent code.
await worker.getEntrypoint().myAgent(param);
</code></pre>
            <p>That's it.</p>
    <div>
      <h3>100x faster</h3>
      <a href="#100x-faster">
        
      </a>
    </div>
    <p>Dynamic Workers use the same underlying sandboxing mechanism that the entire Cloudflare Workers platform has been built on since its launch, eight years ago: isolates. An isolate is an instance of the V8 JavaScript execution engine, the same engine used by Google Chrome. They are <a href="https://developers.cloudflare.com/workers/reference/how-workers-works/"><u>how Workers work</u></a>.</p><p>An isolate takes a few milliseconds to start and uses a few megabytes of memory. That's around 100x faster and 10x-100x more memory efficient than a typical container.</p><p><b>That means that if you want to start a new isolate for every user request, on-demand, to run one snippet of code, then throw it away, you can.</b></p>
    <div>
      <h3>Unlimited scalability</h3>
      <a href="#unlimited-scalability">
        
      </a>
    </div>
    <p>Many container-based sandbox providers impose limits on global concurrent sandboxes and rate of sandbox creation. Dynamic Worker Loader has no such limits. It doesn't need to, because it is simply an API to the same technology that has powered our platform all along, which has always allowed Workers to seamlessly scale to millions of requests per second.</p><p>Want to handle a million requests per second, where <i>every single request</i> loads a separate Dynamic Worker sandbox, all running concurrently? No problem!</p>
    <div>
      <h3>Zero latency</h3>
      <a href="#zero-latency">
        
      </a>
    </div>
    <p>One-off Dynamic Workers usually run on the same machine — the same thread, even — as the Worker that created them. No need to communicate around the world to find a warm sandbox. Isolates are so lightweight that we can just run them wherever the request landed. Dynamic Workers are supported in every one of Cloudflare's hundreds of locations around the world.</p>
    <div>
      <h3>It's all JavaScript</h3>
      <a href="#its-all-javascript">
        
      </a>
    </div>
    <p>The only catch, vs. containers, is that your agent needs to write JavaScript.</p><p>Technically, Workers (including dynamic ones) can use Python and WebAssembly, but for small snippets of code — like that written on-demand by an agent — JavaScript will load and run much faster.</p><p>We humans tend to have strong preferences on programming languages, and while many love JavaScript, others might prefer Python, Rust, or countless others.</p><p>But we aren't talking about humans here. We're talking about AI. AI will write any language you want it to. LLMs are experts in every major language. Their training data in JavaScript is immense.</p><p>JavaScript, by its nature on the web, is designed to be sandboxed. It is the correct language for the job.</p>
    <div>
      <h3>Tools defined in TypeScript</h3>
      <a href="#tools-defined-in-typescript">
        
      </a>
    </div>
    <p>If we want our agent to be able to do anything useful, it needs to talk to external APIs. How do we tell it about the APIs it has access to?</p><p>MCP defines schemas for flat tool calls, but not programming APIs. OpenAPI offers a way to express REST APIs, but it is verbose, both in the schema itself and the code you'd have to write to call it.</p><p>For APIs exposed to JavaScript, there is a single, obvious answer: TypeScript.</p><p>Agents know TypeScript. TypeScript is designed to be concise. With very few tokens, you can give your agent a precise understanding of your API.</p>
            <pre><code>// Interface to interact with a chat room.
interface ChatRoom {
  // Get the last `limit` messages of the chat log.
  getHistory(limit: number): Promise&lt;Message[]&gt;;

  // Subscribe to new messages. Dispose the returned object
  // to unsubscribe.
  subscribe(callback: (msg: Message) =&gt; void): Promise&lt;Disposable&gt;;

  // Post a message to chat.
  post(text: string): Promise&lt;void&gt;;
}

type Message = {
  author: string;
  time: Date;
  text: string;
}
</code></pre>
            <p>Compare this with the equivalent OpenAPI spec (which is so long you have to scroll to see it all):</p><pre>
openapi: 3.1.0
info:
  title: ChatRoom API
  description: &gt;
    Interface to interact with a chat room.
  version: 1.0.0

paths:
  /messages:
    get:
      operationId: getHistory
      summary: Get recent chat history
      description: Returns the last `limit` messages from the chat log, newest first.
      parameters:
        - name: limit
          in: query
          required: true
          schema:
            type: integer
            minimum: 1
      responses:
        "200":
          description: A list of messages.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Message"

    post:
      operationId: postMessage
      summary: Post a message to the chat room
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - text
              properties:
                text:
                  type: string
      responses:
        "204":
          description: Message posted successfully.

  /messages/stream:
    get:
      operationId: subscribeMessages
      summary: Subscribe to new messages via SSE
      description: &gt;
        Opens a Server-Sent Events stream. Each event carries a JSON-encoded
        Message object. The client unsubscribes by closing the connection.
      responses:
        "200":
          description: An SSE stream of new messages.
          content:
            text/event-stream:
              schema:
                description: &gt;
                  Each SSE `data` field contains a JSON-encoded Message object.
                $ref: "#/components/schemas/Message"

components:
  schemas:
    Message:
      type: object
      required:
        - author
        - time
        - text
      properties:
        author:
          type: string
        time:
          type: string
          format: date-time
        text:
          type: string
</pre><p>We think the TypeScript API is better. It's fewer tokens and much easier to understand (for both agents and humans).  </p><p>Dynamic Worker Loader makes it easy to implement a TypeScript API like this in your own Worker and then pass it in to the Dynamic Worker either as a method parameter or in the env object. The Workers Runtime will automatically set up a <a href="https://blog.cloudflare.com/capnweb-javascript-rpc-library/"><u>Cap'n Web RPC</u></a> bridge between the sandbox and your harness code, so that the agent can invoke your API across the security boundary without ever realizing that it isn't using a local library.</p><p>That means your agent can write code like this:</p>
            <pre><code>// Thinking: The user asked me to summarize recent chat messages from Alice.
// I will filter the recent message history in code so that I only have to
// read the relevant messages.
let history = await env.CHAT_ROOM.getHistory(1000);
return history.filter(msg =&gt; msg.author == "alice");
</code></pre>
            
    <div>
      <h3>HTTP filtering and credential injection</h3>
      <a href="#http-filtering-and-credential-injection">
        
      </a>
    </div>
    <p>If you prefer to give your agents HTTP APIs, that's fully supported. Using the <code>globalOutbound</code> option to the worker loader API, you can register a callback to be invoked on every HTTP request, in which you can inspect the request, rewrite it, inject auth keys, respond to it directly, block it, or anything else you might like.</p><p>For example, you can use this to implement <b>credential injection</b> (token injection): When the agent makes an HTTP request to a service that requires authorization, you add credentials to the request on the way out. This way, the agent itself never knows the secret credentials, and therefore cannot leak them.</p><p>Using a plain HTTP interface may be desirable when an agent is talking to a well-known API that is in its training set, or when you want your agent to use a library that is built on a REST API (the library can run inside the agent's sandbox).</p><p>With that said, <b>in the absence of a compatibility requirement, TypeScript RPC interfaces are better than HTTP:</b></p><ul><li><p>As shown above, a TypeScript interface requires far fewer tokens to describe than an HTTP interface.</p></li><li><p>The agent can write code to call TypeScript interfaces using far fewer tokens than equivalent HTTP.</p></li><li><p>With TypeScript interfaces, since you are defining your own wrapper interface anyway, it is easier to narrow the interface to expose exactly the capabilities that you want to provide to your agent, both for simplicity and security. With HTTP, you are more likely implementing <i>filtering</i> of requests made against some existing API. This is hard, because your proxy must fully interpret the meaning of every API call in order to properly decide whether to allow it, and HTTP requests are complicated, with many headers and other parameters that could all be meaningful. It ends up being easier to just write a TypeScript wrapper that only implements the functions you want to allow.</p></li></ul>
    <div>
      <h3>Battle-hardened security</h3>
      <a href="#battle-hardened-security">
        
      </a>
    </div>
    <p>Hardening an isolate-based sandbox is tricky, as it is a more complicated attack surface than hardware virtual machines. Although all sandboxing mechanisms have bugs, security bugs in V8 are more common than security bugs in typical hypervisors. When using isolates to sandbox possibly-malicious code, it's important to have additional layers of defense-in-depth. Google Chrome, for example, implemented strict process isolation for this reason, but it is not the only possible solution.</p><p>We have nearly a decade of experience securing our isolate-based platform. Our systems automatically deploy V8 security patches to production within hours — faster than Chrome itself. Our <a href="https://blog.cloudflare.com/mitigating-spectre-and-other-security-threats-the-cloudflare-workers-security-model/"><u>security architecture</u></a> features a custom second-layer sandbox with dynamic cordoning of tenants based on risk assessments. <a href="https://blog.cloudflare.com/safe-in-the-sandbox-security-hardening-for-cloudflare-workers/"><u>We've extended the V8 sandbox itself</u></a> to leverage hardware features like MPK. We've teamed up with (and hired) leading researchers to develop <a href="https://blog.cloudflare.com/spectre-research-with-tu-graz/"><u>novel defenses against Spectre</u></a>. We also have systems that scan code for malicious patterns and automatically block them or apply additional layers of sandboxing. And much more.</p><p>When you use Dynamic Workers on Cloudflare, you get all of this automatically.</p>
    <div>
      <h2>Helper libraries</h2>
      <a href="#helper-libraries">
        
      </a>
    </div>
    <p>We've built a number of libraries that you might find useful when working with Dynamic Workers: </p>
    <div>
      <h3>Code Mode</h3>
      <a href="#code-mode">
        
      </a>
    </div>
    <p><a href="https://www.npmjs.com/package/@cloudflare/codemode"><code>@cloudflare/codemode</code></a> simplifies running model-generated code against AI tools using Dynamic Workers. At its core is <code>DynamicWorkerExecutor()</code>, which constructs a purpose-built sandbox with code normalisation to handle common formatting errors, and direct access to a <code>globalOutbound</code> fetcher for controlling <code>fetch()</code> behaviour inside the sandbox — set it to <code>null</code> for full isolation, or pass a <code>Fetcher</code> binding to route, intercept or enrich outbound requests from the sandbox.</p>
            <pre><code>const executor = new DynamicWorkerExecutor({
  loader: env.LOADER,
  globalOutbound: null, // fully isolated 
});

const codemode = createCodeTool({
  tools: myTools,
  executor,
});

return generateText({
  model,
  messages,
  tools: { codemode },
});
</code></pre>
            <p>The Code Mode SDK also provides two server-side utility functions. <code>codeMcpServer({ server, executor })</code> wraps an existing MCP Server, replacing its tool surface with a single <code>code()</code> tool. <code>openApiMcpServer({ spec, executor, request })</code> goes further: given an OpenAPI spec and an executor, it builds a complete MCP Server with <code>search()</code> and <code>execute()</code> tools as used by the Cloudflare MCP Server, and better suited to larger APIs.</p><p>In both cases, the code generated by the model runs inside Dynamic Workers, with calls to external services made over RPC bindings passed to the executor.</p><p><a href="https://www.npmjs.com/package/@cloudflare/codemode"><u>Learn more about the library and how to use it.</u></a> </p>
    <div>
      <h3>Bundling</h3>
      <a href="#bundling">
        
      </a>
    </div>
    <p>Dynamic Workers expect pre-bundled modules. <a href="https://www.npmjs.com/package/@cloudflare/worker-bundler"><code>@cloudflare/worker-bundler</code></a> handles that for you: give it source files and a <code>package.json</code>, and it resolves npm dependencies from the registry, bundles everything with <code>esbuild</code>, and returns the module map the Worker Loader expects.</p>
            <pre><code>import { createWorker } from "@cloudflare/worker-bundler";

const worker = env.LOADER.get("my-worker", async () =&gt; {
  const { mainModule, modules } = await createWorker({
    files: {
      "src/index.ts": `
        import { Hono } from 'hono';
        import { cors } from 'hono/cors';

        const app = new Hono();
        app.use('*', cors());
        app.get('/', (c) =&gt; c.text('Hello from Hono!'));
        app.get('/json', (c) =&gt; c.json({ message: 'It works!' }));

        export default app;
      `,
      "package.json": JSON.stringify({
        dependencies: { hono: "^4.0.0" }
      })
    }
  });

  return { mainModule, modules, compatibilityDate: "2026-01-01" };
});

await worker.getEntrypoint().fetch(request);
</code></pre>
            <p>It also supports full-stack apps via <code>createApp</code> — bundle a server Worker, client-side JavaScript, and static assets together, with built-in asset serving that handles content types, ETags, and SPA routing.</p><p><a href="https://www.npmjs.com/package/@cloudflare/worker-bundler"><u>Learn more about the library and how to use it.</u></a></p>
    <div>
      <h3>File manipulation</h3>
      <a href="#file-manipulation">
        
      </a>
    </div>
    <p><a href="https://www.npmjs.com/package/@cloudflare/shell"><code>@cloudflare/shell</code></a> gives your agent a virtual filesystem inside a Dynamic Worker. Agent code calls typed methods on a <code>state</code> object — read, write, search, replace, diff, glob, JSON query/update, archive — with structured inputs and outputs instead of string parsing.</p><p>Storage is backed by a durable <code>Workspace</code> (SQLite + R2), so files persist across executions. Coarse operations like <code>searchFiles</code>, <code>replaceInFiles</code>, and <code>planEdits</code> minimize RPC round-trips — the agent issues one call instead of looping over individual files. Batch writes are transactional by default: if any write fails, earlier writes roll back automatically.</p>
            <pre><code>import { Workspace } from "@cloudflare/shell";
import { stateTools } from "@cloudflare/shell/workers";
import { DynamicWorkerExecutor, resolveProvider } from "@cloudflare/codemode";

const workspace = new Workspace({
  sql: this.ctx.storage.sql, // Works with any DO's SqlStorage, D1, or custom SQL backend
  r2: this.env.MY_BUCKET, // large files spill to R2 automatically
  name: () =&gt; this.name   // lazy — resolved when needed, not at construction
});

// Code runs in an isolated Worker sandbox with no network access
const executor = new DynamicWorkerExecutor({ loader: env.LOADER });

// The LLM writes this code; `state.*` calls dispatch back to the host via RPC
const result = await executor.execute(
  `async () =&gt; {
    // Search across all TypeScript files for a pattern
    const hits = await state.searchFiles("src/**/*.ts", "answer");
    // Plan multiple edits as a single transaction
    const plan = await state.planEdits([
      { kind: "replace", path: "/src/app.ts",
        search: "42", replacement: "43" },
      { kind: "writeJson", path: "/src/config.json",
        value: { version: 2 } }
    ]);
    // Apply atomically — rolls back on failure
    return await state.applyEditPlan(plan);
  }`,
  [resolveProvider(stateTools(workspace))]
);</code></pre>
            <p>The package also ships prebuilt TypeScript type declarations and a system prompt template, so you can drop the full <code>state</code> API into your LLM context in a handful of tokens.</p><p><a href="https://www.npmjs.com/package/@cloudflare/shell"><u>Learn more about the library and how to use it.</u></a></p>
    <div>
      <h2>How are people using it?</h2>
      <a href="#how-are-people-using-it">
        
      </a>
    </div>
    
    <div>
      <h4>Code Mode</h4>
      <a href="#code-mode">
        
      </a>
    </div>
    <p>Developers want their agents to write and execute code against tool APIs, rather than making sequential tool calls one at a time. With Dynamic Workers, the LLM generates a single TypeScript function that chains multiple API calls together, runs it in a Dynamic Worker, and returns the final result back to the agent. As a result, only the output, and not every intermediate step, ends up in the context window. This cuts both latency and token usage, and produces better results, especially when the tool surface is large.</p><p>Our own <a href="https://github.com/cloudflare/mcp-server-cloudflare">Cloudflare MCP server</a> is built exactly this way: it exposes the entire Cloudflare API through just two tools — search and execute — in under 1,000 tokens, because the agent writes code against a typed API instead of navigating hundreds of individual tool definitions.</p>
    <div>
      <h4>Building custom automations </h4>
      <a href="#building-custom-automations">
        
      </a>
    </div>
    <p>Developers are using Dynamic Workers to let agents build custom automations on the fly. <a href="https://www.zite.com/"><u>Zite</u></a>, for example, is building an app platform where users interact through a chat interface — the LLM writes TypeScript behind the scenes to build CRUD apps, connect to services like Stripe, Airtable, and Google Calendar, and run backend logic, all without the user ever seeing a line of code. Every automation runs in its own Dynamic Worker, with access to only the specific services and libraries that the endpoint needs.</p><blockquote><p><i>“To enable server-side code for Zite’s LLM-generated apps, we needed an execution layer that was instant, isolated, and secure. Cloudflare’s Dynamic Workers hit the mark on all three, and out-performed all of the other platforms we benchmarked for speed and library support. The NodeJS compatible runtime supported all of Zite’s workflows, allowing hundreds of third party integrations, without sacrificing on startup time. Zite now services millions of execution requests daily thanks to Dynamic Workers.” </i></p><p><i>— </i><b><i>Antony Toron</i></b><i>, CTO and Co-Founder, Zite </i></p></blockquote>
    <div>
      <h4>Running AI-generated applications</h4>
      <a href="#running-ai-generated-applications">
        
      </a>
    </div>
    <p>Developers are building platforms that generate full applications from AI — either for their customers or for internal teams building prototypes. With Dynamic Workers, each app can be spun up on demand, then put back into cold storage until it's invoked again. Fast startup times make it easy to preview changes during active development. Platforms can also block or intercept any network requests the generated code makes, keeping AI-generated apps safe to run.</p>
    <div>
      <h2>Pricing</h2>
      <a href="#pricing">
        
      </a>
    </div>
    <p>Dynamically-loaded Workers are priced at $0.002 per unique Worker loaded per day (as of this post’s publication), in addition to the usual CPU time and invocation pricing of regular Workers.</p><p>For AI-generated "code mode" use cases, where every Worker is a unique one-off, this means the price is $0.002 per Worker loaded (plus CPU and invocations). This cost is typically negligible compared to the inference costs to generate the code.</p><p>During the beta period, the $0.002 charge is waived. As pricing is subject to change, please always check our Dynamic Workers <a href="https://developers.cloudflare.com/dynamic-workers/pricing/"><u>pricing</u></a> for the most current information. </p>
    <div>
      <h2>Get Started</h2>
      <a href="#get-started">
        
      </a>
    </div>
    <p>If you’re on the Workers Paid plan, you can start using <a href="https://developers.cloudflare.com/dynamic-workers/">Dynamic Workers</a> today. </p>
    <div>
      <h4>Dynamic Workers Starter</h4>
      <a href="#dynamic-workers-starter">
        
      </a>
    </div>
    <a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/agents/tree/main/examples/dynamic-workers"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p>
<p>Use this “hello world” <a href="https://github.com/cloudflare/agents/tree/main/examples/dynamic-workers">starter</a> to get a Worker deployed that can load and execute Dynamic Workers. </p>
    <div>
      <h4>Dynamic Workers Playground</h4>
      <a href="#dynamic-workers-playground">
        
      </a>
    </div>
    <a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/agents/tree/main/examples/dynamic-workers-playground"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p>You can also deploy the <a href="https://github.com/cloudflare/agents/tree/main/examples/dynamic-workers-playground">Dynamic Workers Playground</a>, where you’ll be able to write or import code, bundle it at runtime with <code>@cloudflare/worker-bundler</code>, execute it through a Dynamic Worker, see real-time responses and execution logs. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/32d0ficYALnSneKc4jZPja/0d4d07d747fc14936f16071714b7a8e5/BLOG-3243_2.png" />
          </figure><p>Dynamic Workers are fast, scalable, and lightweight. <a href="https://discord.com/channels/595317990191398933/1460655307255578695"><u>Find us on Discord</u></a> if you have any questions. We’d love to see what you build!</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/mQOJLnMtXULmj6l3DgKZg/ef2ee4cef616bc2d9a7caf35df5834f5/BLOG-3243_3.png" />
          </figure><p></p> ]]></content:encoded>
            <category><![CDATA[MCP]]></category>
            <category><![CDATA[Workers AI]]></category>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Agents]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">1tc7f8AggVLw5D8OmaZri5</guid>
            <dc:creator>Kenton Varda</dc:creator>
            <dc:creator>Sunil Pai</dc:creator>
            <dc:creator>Ketan Gupta</dc:creator>
        </item>
        <item>
            <title><![CDATA[Powering the agents: Workers AI now runs large models, starting with Kimi K2.5]]></title>
            <link>https://blog.cloudflare.com/workers-ai-large-models/</link>
            <pubDate>Thu, 19 Mar 2026 19:53:16 GMT</pubDate>
            <description><![CDATA[ Kimi K2.5 is now on Workers AI, helping you power agents entirely on Cloudflare’s Developer Platform. Learn how we optimized our inference stack and reduced inference costs for internal agent use cases.  ]]></description>
            <content:encoded><![CDATA[ <p>We're making Cloudflare the best place for building and deploying agents. But reliable agents aren't built on prompts alone; they require a robust, coordinated infrastructure of underlying primitives. </p><p>At Cloudflare, we have been building these primitives for years: <a href="https://developers.cloudflare.com/durable-objects/"><u>Durable Objects</u></a> for state persistence, <a href="https://developers.cloudflare.com/workflows/"><u>Workflows</u></a> for long running tasks, and <a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/worker-loader/"><u>Dynamic Workers</u></a> or <a href="https://developers.cloudflare.com/sandbox/"><u>Sandbox</u></a> containers for secure execution. Powerful abstractions like the <a href="https://developers.cloudflare.com/agents/"><u>Agents SDK</u></a> are designed to help you build agents on top of Cloudflare’s Developer Platform.</p><p>But these primitives only provided the execution environment. The agent still needed a model capable of powering it. </p><p>Starting today, Workers AI is officially in the big models game. We now offer frontier open-source models on our AI inference platform. We’re starting by releasing <a href="https://www.kimi.com/blog/kimi-k2-5"><u>Moonshot AI’s Kimi K2.5</u></a> model <a href="https://developers.cloudflare.com/workers-ai/models/kimi-k2.5"><u>on Workers AI</u></a>. With a full 256k context window and support for multi-turn tool calling, vision inputs, and structured outputs, the Kimi K2.5 model is excellent for all kinds of agentic tasks. By bringing a frontier-scale model directly into the Cloudflare Developer Platform, we’re making it possible to run the entire agent lifecycle on a single, unified platform.</p><p>The heart of an agent is the AI model that powers it, and that model needs to be smart, with high reasoning capabilities and a large context window. Workers AI now runs those models.</p>
    <div>
      <h2>The price-performance sweet spot</h2>
      <a href="#the-price-performance-sweet-spot">
        
      </a>
    </div>
    <p>We spent the last few weeks testing Kimi K2.5 as the engine for our internal development tools. Within our <a href="https://opencode.ai/"><u>OpenCode</u></a> environment, Cloudflare engineers use Kimi as a daily driver for agentic coding tasks. We have also integrated the model into our automated code review pipeline; you can see this in action via our public code review agent, <a href="https://github.com/ask-bonk/ask-bonk"><u>Bonk</u></a>, on Cloudflare GitHub repos. In production, the model has proven to be a fast, efficient alternative to larger proprietary models without sacrificing quality.</p><p>Serving Kimi K2.5 began as an experiment, but it quickly became critical after reviewing how the model performs and how cost-efficient it is. As an illustrative example: we have an agent that does security reviews of Cloudflare’s codebases. This agent processes over 7B tokens per day, and using Kimi, it has caught more than 15 confirmed issues in a single codebase. Doing some rough math, if we had run this agent on a mid-tier proprietary model, we would have spent $2.4M a year for this single use case, on a single codebase. Running this agent with Kimi K2.5 cost just a fraction of that: we cut costs by 77% simply by making the switch to Workers AI.</p><p>As AI adoption increases, we are seeing a fundamental shift not only in how engineering teams are operating, but how individuals are operating. It is becoming increasingly common for people to have a personal agent like <a href="https://openclaw.ai/"><u>OpenClaw</u></a> running 24/7. The volume of inference is skyrocketing.</p><p>This new rise in personal and coding agents means that cost is no longer a secondary concern; it is the primary blocker to scaling. When every employee has multiple agents processing hundreds of thousands of tokens per hour, the math for proprietary models stops working. Enterprises will look to transition to open-source models that offer frontier-level reasoning without the proprietary price tag. Workers AI is here to facilitate this shift, providing everything from serverless endpoints for a personal agent to dedicated instances powering autonomous agents across an entire organization.</p>
    <div>
      <h2>The large model inference stack</h2>
      <a href="#the-large-model-inference-stack">
        
      </a>
    </div>
    <p>Workers AI has served models, including LLMs, since its launch two years ago, but we’ve historically prioritized smaller models. Part of the reason was that for some time, open-source LLMs fell far behind the models from frontier model labs. This changed with models like Kimi K2.5, but to serve this type of very large LLM, we had to make changes to our inference stack. We wanted to share with you some of what goes on behind the scenes to support a model like Kimi.</p><p>We’ve been working on custom kernels for Kimi K2.5 to optimize how we serve the model, which is built on top of our proprietary <a href="https://blog.cloudflare.com/cloudflares-most-efficient-ai-inference-engine/"><u>Infire inference engine</u></a>. Custom kernels improve the model’s performance and GPU utilization, unlocking gains that would otherwise go unclaimed if you were just running the model out of the box. There are also multiple techniques and hardware configurations that can be leveraged to serve a large model. Developers typically use a combination of data, tensor, and expert parallelization techniques to optimize model performance. Strategies like disaggregated prefill are also important, in which you separate the prefill and generation stages onto different machines in order to get better throughput or higher GPU utilization. Implementing these techniques and incorporating them into the inference stack takes a lot of dedicated experience to get right. </p><p>Workers AI has already done the experimentation with serving techniques to yield excellent throughput on Kimi K2.5. A lot of this does not come out of the box when you self-host an open-source model. The benefit of using a platform like Workers AI is that you don’t need to be a Machine Learning Engineer, a DevOps expert, or a Site Reliability Engineer to do the optimizations required to host it: we’ve already done the hard part, you just need to call an API.</p>
    <div>
      <h2>Beyond the model — platform improvements for agentic workloads</h2>
      <a href="#beyond-the-model-platform-improvements-for-agentic-workloads">
        
      </a>
    </div>
    <p>In concert with this launch, we’ve also improved our platform and are releasing several new features to help you build better agents.</p>
    <div>
      <h3>Prefix caching and surfacing cached tokens</h3>
      <a href="#prefix-caching-and-surfacing-cached-tokens">
        
      </a>
    </div>
    <p>When you work with agents, you are likely sending a large number of input tokens as part of the context: this could be detailed system prompts, tool definitions, MCP server tools, or entire codebases. Inputs can be as large as the model context window, so in theory, you could be sending requests with almost 256k input tokens. That’s a lot of tokens.</p><p>When an LLM processes a request, the request is broken down into two stages: the prefill stage processes input tokens and the output stage generates output tokens. These stages are usually sequential, where input tokens have to be fully processed before you can generate output tokens. This means that sometimes the GPU is not fully utilized while the model is doing prefill.</p><p>With multi-turn conversations, when you send a new prompt, the client sends all the previous prompts, tools, and context from the session to the model as well. The delta between consecutive requests is usually just a few new lines of input; all the other context has already gone through the prefill stage during a previous request. This is where prefix caching helps. Instead of doing prefill on the entire request, we can cache the input tensors from a previous request, and only do prefill on the new input tokens. This saves a lot of time and compute from the prefill stage, which means a faster Time to First Token (TTFT) and a higher Tokens Per Second (TPS) throughput as you’re not blocked on prefill.</p><p>Workers AI has always done prefix caching, but we are now surfacing cached tokens as a usage metric and offering a discount on cached tokens compared to input tokens. (Pricing can be found on the <a href="https://developers.cloudflare.com/workers-ai/models/kimi-k2.5/"><u>model page</u></a>.) We also have new techniques for you to leverage in order to get a higher prefix cache hit rate, reducing your costs.</p>
    <div>
      <h3>New session affinity header for higher cache hit rates</h3>
      <a href="#new-session-affinity-header-for-higher-cache-hit-rates">
        
      </a>
    </div>
    <p>In order to route to the same model instance and take advantage of prefix caching, we use a new <code>x-session-affinity</code> header. When you send this header, you’ll improve your cache hit ratio, leading to more cached tokens and subsequently, faster TTFT, TPS, and lower inference costs.</p><p>You can pass the new header like below, with a unique string per session or per agent. Some clients like OpenCode implement this automatically out of the box. Our <a href="https://github.com/cloudflare/agents-starter"><u>Agents SDK starter</u></a> has already set up the wiring to do this for you, too.</p>
            <pre><code>curl -X POST \
"https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/ai/run/@cf/moonshotai/kimi-k2.5" \
  -H "Authorization: Bearer {API_TOKEN}" \
  -H "Content-Type: application/json" \
  -H "x-session-affinity: ses_12345678" \
  -d '{
    "messages": [
      {
        "role": "system",
        "content": "You are a helpful assistant."
      },
      {
        "role": "user",
        "content": "What is prefix caching and why does it matter?"
      }
    ],
    "max_tokens": 2400,
    "stream": true
  }'
</code></pre>
            
    <div>
      <h3>Redesigned async APIs</h3>
      <a href="#redesigned-async-apis">
        
      </a>
    </div>
    <p>Serverless inference is really hard. With a pay-per-token business model, it’s cheaper on a single request basis because you don’t need to pay for entire GPUs to service your requests. But there’s a trade-off: you have to contend with other people’s traffic and capacity constraints, and there’s no strict guarantee that your request will be processed. This is not unique to Workers AI — it’s evidently the case across serverless model providers, given the frequent news reports of overloaded providers and service disruptions. While we always strive to serve your request and have built-in autoscaling and rebalancing, there are hard limitations (like hardware) that make this a challenge.</p><p>For volumes of requests that would exceed synchronous rate limits, you can submit batches of inferences to be completed asynchronously. We’re introducing a revamped Asynchronous API, which means that for asynchronous use cases, you won’t run into Out of Capacity errors and inference will execute durably at some point. Our async API looks more like flex processing than a batch API, where we process requests in the async queue as long as we have headroom in our model instances. With internal testing, our async requests usually execute within 5 minutes, but this will depend on what live traffic looks like. As we bring Kimi to the public, we will tune our scaling accordingly, but the async API is the best way to make sure you don’t run into capacity errors in durable workflows. This is perfect for use cases that are not real-time, such as code scanning agents or research agents.</p><p>Workers AI previously had an asynchronous API, but we’ve recently revamped the systems under the hood. We now rely on a pull-based system versus the historical push-based system, allowing us to pull in queued requests as soon as we have capacity. We’ve also added better controls to tune the throughput of async requests, monitoring GPU utilization in real-time and pulling in async requests when utilization is low, so that critical synchronous requests get priority while still processing asynchronous requests efficiently.</p><p>To use the asynchronous API, you would send your requests as seen below. We also have a way to <a href="https://developers.cloudflare.com/workers-ai/platform/event-subscriptions/"><u>set up event notifications</u></a> so that you can know when the inference is complete instead of polling for the request. </p>
            <pre><code>// (1.) Push a request in queue
// pass queueRequest: true
let res = await env.AI.run("@cf/moonshotai/kimi-k2.5", {
  "requests": [{
    "messages": [{
      "role": "user",
      "content": "Tell me a joke"
    }]
  }, {
    "messages": [{
      "role": "user",
      "content": "Explain the Pythagoras theorem"
    }]
  }, ...{&lt;add more requests in a batch&gt;} ];
}, {
  queueRequest: true,
});


// (2.) grab the request id
let request_id;
if(res &amp;&amp; res.request_id){
  request_id = res.request_id;
}
// (3.) poll the status
let res = await env.AI.run("@cf/moonshotai/kimi-k2.5", {
  request_id: request_id
});

if(res &amp;&amp; res.status === "queued" || res.status === "running") {
 // retry by polling again
 ...
}
else 
 return Response.json(res); // This will contain the final completed response 
</code></pre>
            
    <div>
      <h2>Try it out today</h2>
      <a href="#try-it-out-today">
        
      </a>
    </div>
    <p>Get started with Kimi K2.5 on Workers AI today. You can read our developer docs to find out <a href="https://developers.cloudflare.com/workers-ai/models/kimi-k2.5/"><u>model information and pricing</u></a>, and how to take advantage of <a href="https://developers.cloudflare.com/workers-ai/features/prompt-caching/"><u>prompt caching via session affinity headers</u></a> and <a href="https://developers.cloudflare.com/workers-ai/features/batch-api/"><u>asynchronous API</u></a>. The <a href="https://github.com/cloudflare/agents-starter"><u>Agents SDK starter</u></a> also now uses Kimi K2.5 as its default model. You can also <a href="https://opencode.ai/docs/providers/"><u>connect to Kimi K2.5 on Workers AI via Opencode</u></a>. For a live demo, try it in our <a href="https://playground.ai.cloudflare.com/"><u>playground</u></a>.</p><p>And if this set of problems around serverless inference, ML optimizations, and GPU infrastructure sound  interesting to you — <a href="https://job-boards.greenhouse.io/cloudflare/jobs/6297179?gh_jid=6297179"><u>we’re hiring</u></a>!</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/36JzF0zePj2z7kZQK8Q2fg/73b0a7206d46f0eef170ffd1494dc4b3/BLOG-3247_2.png" />
          </figure><p></p> ]]></content:encoded>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Workers AI]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Agents]]></category>
            <guid isPermaLink="false">1wSO33KRdd5aUPAlSVDiqU</guid>
            <dc:creator>Michelle Chen</dc:creator>
            <dc:creator>Kevin Flansburg</dc:creator>
            <dc:creator>Ashish Datta</dc:creator>
            <dc:creator>Kevin Jain</dc:creator>
        </item>
        <item>
            <title><![CDATA[Introducing Markdown for Agents]]></title>
            <link>https://blog.cloudflare.com/markdown-for-agents/</link>
            <pubDate>Thu, 12 Feb 2026 14:03:00 GMT</pubDate>
            <description><![CDATA[ The way content is discovered online is shifting, from traditional search engines to AI agents that need structured data from a Web built for humans. It’s time to consider not just human visitors, but start to treat agents as first-class citizens. Markdown for Agents automatically converts any HTML page requested from our network to markdown. ]]></description>
            <content:encoded><![CDATA[ <p>The way content and businesses are discovered online is changing rapidly. In the past, traffic originated from traditional search engines, and SEO determined who got found first. Now the traffic is increasingly coming from AI crawlers and agents that demand structured data within the often-unstructured Web that was built for humans.</p><p>As a business, to continue to stay ahead, now is the time to consider not just human visitors, or traditional wisdom for SEO-optimization, but start to treat agents as first-class citizens. </p>
    <div>
      <h2>Why markdown is important</h2>
      <a href="#why-markdown-is-important">
        
      </a>
    </div>
    <p>Feeding raw HTML to an AI is like paying by the word to read packaging instead of the letter inside. A simple <code>## About Us</code> on a page in markdown costs roughly 3 tokens; its HTML equivalent – <code>&lt;h2 class="section-title" id="about"&gt;About Us&lt;/h2&gt;</code> – burns 12-15, and that's before you account for the <code>&lt;div&gt;</code> wrappers, nav bars, and script tags that pad every real web page and have zero semantic value.</p><p>This blog post you’re reading takes 16,180 tokens in HTML and 3,150 tokens when converted to markdown. <b>That’s a 80% reduction in token usage</b>.</p><p><a href="https://en.wikipedia.org/wiki/Markdown"><u>Markdown</u></a> has quickly become the <i>lingua franca</i> for agents and AI systems as a whole. The format’s explicit structure makes it ideal for AI processing, ultimately resulting in better results while minimizing token waste.</p><p>The problem is that the Web is made of HTML, not markdown, and page weight has been <a href="https://almanac.httparchive.org/en/2025/page-weight#page-weight-over-time"><u>steadily increasing</u></a> over the years, making pages hard to parse. For agents, their goal is to filter out all non-essential elements and scan the relevant content.</p><p>The conversion of HTML to markdown is now a common step for any AI pipeline. Still, this process is far from ideal: it wastes computation, adds costs and processing complexity, and above all, it may not be how the content creator intended their content to be used in the first place.</p><p>What if AI agents could bypass the complexities of intent analysis and document conversion, and instead receive structured markdown directly from the source?</p>
    <div>
      <h2>Convert HTML to markdown, automatically</h2>
      <a href="#convert-html-to-markdown-automatically">
        
      </a>
    </div>
    <p>Cloudflare's network now supports real-time content conversion at the source, for <a href="https://developers.cloudflare.com/fundamentals/reference/markdown-for-agents/"><u>enabled zones</u></a> using <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Content_negotiation"><u>content negotiation</u></a> headers. Now when AI systems request pages from any website that uses Cloudflare and has Markdown for Agents enabled, they can express the preference for text/markdown in the request. Our network will automatically and efficiently convert the HTML to markdown, when possible, on the fly.</p><p>Here’s how it works. To fetch the markdown version of any page from a zone with Markdown for Agents enabled, the client needs to add the <b>Accept</b> negotiation header with <code>text/markdown</code><b> </b>as one of the options. Cloudflare will detect this, fetch the original HTML version from the origin, and convert it to markdown before serving it to the client.</p><p>Here's a curl example with the Accept negotiation header requesting a page from our developer documentation:</p>
            <pre><code>curl https://developers.cloudflare.com/fundamentals/reference/markdown-for-agents/ \
  -H "Accept: text/markdown"
</code></pre>
            <p>Or if you’re building an AI Agent using Workers, you can use TypeScript:</p>
            <pre><code>const r = await fetch(
  `https://developers.cloudflare.com/fundamentals/reference/markdown-for-agents/`,
  {
    headers: {
      Accept: "text/markdown, text/html",
    },
  },
);
const tokenCount = r.headers.get("x-markdown-tokens");
const markdown = await r.text();
</code></pre>
            <p>We already see some of the most popular coding agents today – like Claude Code and OpenCode – send these accept headers with their requests for content. Now, the response to this request is formatted  in markdown. It's that simple.  </p>
            <pre><code>HTTP/2 200
date: Wed, 11 Feb 2026 11:44:48 GMT
content-type: text/markdown; charset=utf-8
content-length: 2899
vary: accept
x-markdown-tokens: 725
content-signal: ai-train=yes, search=yes, ai-input=yes

---
title: Markdown for Agents · Cloudflare Agents docs
---

## What is Markdown for Agents

The ability to parse and convert HTML to Markdown has become foundational for AI.
...
</code></pre>
            <p>Note that we include an <code>x-markdown-tokens</code> header with the converted response that indicates the estimated number of tokens in the markdown document. You can use this value in your flow, for example to calculate the size of a context window or to decide on your chunking strategy.</p><p>Here’s a diagram of how it works:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6Zw1Q5kBBqTrouN1362H5I/3080d74a2a971be1f1e7e0ba79611998/BLOG-3162_2.png" />
          </figure>
    <div>
      <h3>Content Signals Policy</h3>
      <a href="#content-signals-policy">
        
      </a>
    </div>
    <p>During our last Birthday Week, Cloudflare <a href="https://blog.cloudflare.com/content-signals-policy/"><u>announced</u></a> Content Signals — <a href="http://contentsignals.org"><u>a framework</u></a> that allows anyone to express their preferences for how their content can be used after it has been accessed. </p><p>When you return markdown, you want to make sure your content is being used by the Agent or AI crawler. That’s why Markdown for Agents converted responses include the <code>Content-Signal: ai-train=yes, search=yes, ai-input=yes</code> header signaling that indicates content can be used for AI Training, Search results and AI Input, which includes agentic use. Markdown for Agents will provide options to define custom Content Signal policies in the future.</p><p>Check our dedicated <a href="https://contentsignals.org/"><u>Content Signals</u></a> page for more information on this framework.</p>
    <div>
      <h3>Try it with the Cloudflare Blog &amp; Developer Documentation </h3>
      <a href="#try-it-with-the-cloudflare-blog-developer-documentation">
        
      </a>
    </div>
    <p>We enabled this feature in our <a href="https://developers.cloudflare.com/"><u>Developer Documentation</u></a> and our <a href="https://blog.cloudflare.com/"><u>Blog</u></a>, inviting all AI crawlers and agents to consume our content using markdown instead of HTML.</p><p>Try it out now by requesting this blog with <code>Accept: text/markdown</code>.</p>
            <pre><code>curl https://blog.cloudflare.com/markdown-for-agents/ \
  -H "Accept: text/markdown"</code></pre>
            <p>The result is:</p>
            <pre><code>---
description: The way content is discovered online is shifting, from traditional search engines to AI agents that need structured data from a Web built for humans. It’s time to consider not just human visitors, but start to treat agents as first-class citizens. Markdown for Agents automatically converts any HTML page requested from our network to markdown.
title: Introducing Markdown for Agents
image: https://blog.cloudflare.com/images/markdown-for-agents.png
---

# Introducing Markdown for Agents

The way content and businesses are discovered online is changing rapidly. In the past, traffic originated from traditional search engines and SEO determined who got found first. Now the traffic is increasingly coming from AI crawlers and agents that demand structured data within the often-unstructured Web that was built for humans.

...</code></pre>
            
    <div>
      <h3>Other ways to convert to Markdown</h3>
      <a href="#other-ways-to-convert-to-markdown">
        
      </a>
    </div>
    <p>If you’re building AI systems that require arbitrary document conversion from outside Cloudflare or Markdown for Agents is not available from the content source, we provide other ways to convert documents to Markdown for your applications:</p><ul><li><p>Workers AI <a href="https://developers.cloudflare.com/workers-ai/features/markdown-conversion/"><u>AI.toMarkdown()</u></a> supports multiple document types, not just HTML, and summarization.</p></li><li><p>Browser Rendering <a href="https://developers.cloudflare.com/browser-rendering/rest-api/markdown-endpoint/"><u>/markdown</u></a> REST API supports markdown conversion if you need to render a dynamic page or application in a real browser before converting it.</p></li></ul>
    <div>
      <h2>Tracking markdown usage</h2>
      <a href="#tracking-markdown-usage">
        
      </a>
    </div>
    <p>Anticipating a shift in how AI systems browse the Web, Cloudflare Radar now includes content type insights for AI bot and crawler traffic, both globally on the <a href="https://radar.cloudflare.com/ai-insights#content-type"><u>AI Insights</u></a> page and in the <a href="https://radar.cloudflare.com/bots/directory/gptbot"><u>individual bot</u></a> information pages.</p><p>The new <code>content_type</code> dimension and filter shows the distribution of content types returned to AI agents and crawlers, grouped by <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types"><u>MIME type</u></a> category.  </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7vQzvzHsTLPXGhoQK0Xbr5/183129a8947990bc4ee5bb5ca7ba71b5/BLOG-3162_3.png" />
          </figure><p>You can also see the requests for markdown filtered by a specific agent or crawler. Here are the requests that return markdown to OAI-Searchbot, the crawler used by OpenAI to power ChatGPT’s search: </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7Ah99DWLxnYjadW6xJhAXg/afef4a29ae504d4fe69df4f9823dd103/BLOG-3162_4.png" />
          </figure><p>This new data will allow us to track the evolution of how AI bots, crawlers, and agents are consuming Web content over time. As always, everything on Radar is freely accessible via the <a href="https://developers.cloudflare.com/api/resources/radar/"><u>public APIs</u></a> and the <a href="https://radar.cloudflare.com/explorer?dataSet=ai.bots&amp;groupBy=content_type&amp;filters=userAgent%253DGPTBot&amp;timeCompare=1"><u>Data Explorer</u></a>. </p>
    <div>
      <h2>Start using today</h2>
      <a href="#start-using-today">
        
      </a>
    </div>
    <p>To enable Markdown for Agents for your zone, log into the Cloudflare <a href="https://dash.cloudflare.com/"><u>dashboard</u></a>, select your account, select the zone, look for Quick Actions and toggle the Markdown for Agents button to enable. This feature is available today in Beta at no cost for Pro, Business and Enterprise plans, as well as SSL for SaaS customers.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1UqzmHrNa1UdCCI6eXIfmn/3da0ff51dd94219d8af87c172d83fc72/BLOG-3162_5.png" />
          </figure><p>You can find more information about Markdown for Agents on our<a href="https://developers.cloudflare.com/fundamentals/reference/markdown-for-agents/"> Developer Docs</a>. We welcome your feedback as we continue to refine and enhance this feature. We’re curious to see how AI crawlers and agents navigate and adapt to the unstructured nature of the Web as it evolves.</p> ]]></content:encoded>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Agents]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <guid isPermaLink="false">5uEb99xvnHVk3QfN0KMjb6</guid>
            <dc:creator>Celso Martinho</dc:creator>
            <dc:creator>Will Allen</dc:creator>
        </item>
        <item>
            <title><![CDATA[Introducing Moltworker: a self-hosted personal AI agent, minus the minis]]></title>
            <link>https://blog.cloudflare.com/moltworker-self-hosted-ai-agent/</link>
            <pubDate>Thu, 29 Jan 2026 14:00:00 GMT</pubDate>
            <description><![CDATA[ Moltworker is a middleware Worker and adapted scripts that allows running OpenClaw (formerly Moltbot, formerly Clawdbot) on Cloudflare's Sandbox SDK and our Developer Platform APIs. So you can self-host an AI personal assistant — without any new hardware. ]]></description>
            <content:encoded><![CDATA[ <p><i></i></p><p><i>Editorial note: As of January 30, 2026, Moltbot has been </i><a href="https://openclaw.ai/blog/introducing-openclaw"><i><u>renamed</u></i></a><i> to OpenClaw.</i></p><p>The Internet woke up this week to a flood of people <a href="https://x.com/AlexFinn/status/2015133627043270750"><u>buying Mac minis</u></a> to run <a href="https://github.com/moltbot/moltbot"><u>Moltbot</u></a> (formerly Clawdbot), an open-source, self-hosted AI agent designed to act as a personal assistant. Moltbot runs in the background on a user's own hardware, has a sizable and growing list of integrations for chat applications, AI models, and other popular tools, and can be controlled remotely. Moltbot can help you with your finances, social media, organize your day — all through your favorite messaging app.</p><p>But what if you don’t want to buy new dedicated hardware? And what if you could still run your Moltbot efficiently and securely online? Meet <a href="https://github.com/cloudflare/moltworker"><u>Moltworker</u></a>, a middleware Worker and adapted scripts that allows running Moltbot on Cloudflare's Sandbox SDK and our Developer Platform APIs.</p>
    <div>
      <h2>A personal assistant on Cloudflare — how does that work? </h2>
      <a href="#a-personal-assistant-on-cloudflare-how-does-that-work">
        
      </a>
    </div>
    <p>Cloudflare Workers has never been <a href="https://developers.cloudflare.com/workers/runtime-apis/nodejs/"><u>as compatible</u></a> with Node.js as it is now. Where in the past we had to mock APIs to get some packages running, now those APIs are supported natively by the Workers Runtime.</p><p>This has changed how we can build tools on Cloudflare Workers. When we first implemented <a href="https://developers.cloudflare.com/browser-rendering/playwright/"><u>Playwright</u></a>, a popular framework for web testing and automation that runs on <a href="https://developers.cloudflare.com/browser-rendering/"><u>Browser Rendering</u></a>, we had to rely on <a href="https://www.npmjs.com/package/memfs"><u>memfs</u></a>. This was bad because not only is memfs a hack and an external dependency, but it also forced us to drift away from the official Playwright codebase. Thankfully, with more Node.js compatibility, we were able to start using <a href="https://github.com/cloudflare/playwright/pull/62/changes"><u>node:fs natively</u></a>, reducing complexity and maintainability, which makes upgrades to the latest versions of Playwright easy to do.</p><p>The list of Node.js APIs we support natively keeps growing. The blog post “<a href="https://blog.cloudflare.com/nodejs-workers-2025/"><u>A year of improving Node.js compatibility in Cloudflare Workers</u></a>” provides an overview of where we are and what we’re doing.</p><p>We measure this progress, too. We recently ran an experiment where we took the 1,000 most popular NPM packages, installed and let AI loose, to try to run them in Cloudflare Workers, <a href="https://ghuntley.com/ralph/"><u>Ralph Wiggum as a "software engineer"</u></a> style, and the results were surprisingly good. Excluding the packages that are build tools, CLI tools or browser-only and don’t apply, only 15 packages genuinely didn’t work. <b>That's 1.5%</b>.</p><p>Here’s a graphic of our Node.js API support over time:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5GhwKJq2A2wG79I3NdhhDl/e462c30daf46b1b36d3f06bff479596b/image9.png" />
          </figure><p>We put together a page with the results of our internal experiment on npm packages support <a href="https://worksonworkers.southpolesteve.workers.dev/"><u>here</u></a>, so you can check for yourself.</p><p>Moltbot doesn’t necessarily require a lot of Workers Node.js compatibility because most of the code runs in a container anyway, but we thought it would be important to highlight how far we got supporting so many packages using native APIs. This is because when starting a new AI agent application from scratch, we can actually run a lot of the logic in Workers, closer to the user.</p><p>The other important part of the story is that the list of <a href="https://developers.cloudflare.com/directory/?product-group=Developer+platform"><u>products and APIs</u></a> on our Developer Platform has grown to the point where anyone can <a href="https://www.cloudflare.com/developer-platform/solutions/hosting/">build and run any kind of application</a> — even the most complex and demanding ones — on Cloudflare. And once launched, every application running on our Developer Platform immediately benefits from our secure and scalable global network.</p><p>Those products and services gave us the ingredients we needed to get started. First, we now have <a href="https://sandbox.cloudflare.com/"><u>Sandboxes</u></a>, where you can run untrusted code securely in isolated environments, providing a place to run the service. Next, we now have <a href="https://developers.cloudflare.com/browser-rendering/"><u>Browser Rendering</u></a>, where you can programmatically control and interact with headless browser instances. And finally, <a href="https://developers.cloudflare.com/r2/"><u>R2</u></a>, where you can store objects persistently. With those building blocks available, we could begin work on adapting Moltbot.</p>
    <div>
      <h2>How we adapted Moltbot to run on us</h2>
      <a href="#how-we-adapted-moltbot-to-run-on-us">
        
      </a>
    </div>
    <p>Moltbot on Workers, or Moltworker, is a combination of an entrypoint Worker that acts as an API router and a proxy between our APIs and the isolated environment, both protected by Cloudflare Access. It also provides an administration UI and connects to the Sandbox container where the standard Moltbot Gateway runtime and its integrations are running, using R2 for persistent storage.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3OD2oHgy5ilHpQO2GJvcLU/836a55b67a626d2cd378a654ad47901d/newdiagram.png" />
          </figure><p><sup>High-level architecture diagram of Moltworker.</sup></p><p>Let's dive in more.</p>
    <div>
      <h3>AI Gateway</h3>
      <a href="#ai-gateway">
        
      </a>
    </div>
    <p>Cloudflare AI Gateway acts as a proxy between your AI applications and any popular <a href="https://developers.cloudflare.com/ai-gateway/usage/providers/"><u>AI provider</u></a>, and gives our customers centralized visibility and control over the requests going through.</p><p>Recently we announced support for <a href="https://developers.cloudflare.com/changelog/2025-08-25-secrets-store-ai-gateway/"><u>Bring Your Own Key (BYOK)</u></a>, where instead of passing your provider secrets in plain text with every request, we centrally manage the secrets for you and can use them with your gateway configuration.</p><p>An even better option where you don’t have to manage AI providers' secrets at all end-to-end is to use <a href="https://developers.cloudflare.com/ai-gateway/features/unified-billing/"><u>Unified Billing</u></a>. In this case you top up your account with credits and use AI Gateway with any of the supported providers directly, Cloudflare gets charged, and we will deduct credits from your account.</p><p>To make Moltbot use AI Gateway, first we create a new gateway instance, then we enable the Anthropic provider for it, then we either add our Claude key or purchase credits to use Unified Billing, and then all we need to do is set the ANTHROPIC_BASE_URL environment variable so Moltbot uses the AI Gateway endpoint. That’s it, no code changes necessary.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/cMWRXgHR0mFLc5kp74nYk/a47fa09bdbb6acb3deb60fb16537945d/image11.png" />
          </figure><p>Once Moltbot starts using AI Gateway, you’ll have full visibility on costs and have access to logs and analytics that will help you understand how your AI agent is using the AI providers.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5GOrNdgtdwMcU4bE8oLE19/6bc29bcac643125f5332a8ffba9d1322/image1.png" />
          </figure><p>Note that Anthropic is one option; Moltbot supports <a href="https://www.molt.bot/integrations"><u>other</u></a> AI providers and so does <a href="https://developers.cloudflare.com/ai-gateway/usage/providers/"><u>AI Gateway</u></a>. The advantage of using AI Gateway is that if a better model comes along from any provider, you don’t have to swap keys in your AI Agent configuration and redeploy — you can simply switch the model in your gateway configuration. And more, you specify model or provider <a href="https://developers.cloudflare.com/ai-gateway/configuration/fallbacks/"><u>fallbacks</u></a> to handle request failures and ensure reliability.</p>
    <div>
      <h3>Sandboxes</h3>
      <a href="#sandboxes">
        
      </a>
    </div>
    <p>Last year we anticipated the growing need for AI agents to run untrusted code securely in isolated environments, and we <a href="https://developers.cloudflare.com/changelog/2025-06-24-announcing-sandboxes/"><u>announced</u></a> the <a href="https://developers.cloudflare.com/sandbox/"><u>Sandbox SDK</u></a>. This SDK is built on top of <a href="https://developers.cloudflare.com/containers/"><u>Cloudflare Containers</u></a>, but it provides a simple API for executing commands, managing files, running background processes, and exposing services — all from your Workers applications.</p><p>In short, instead of having to deal with the lower-level Container APIs, the Sandbox SDK gives you developer-friendly APIs for secure code execution and handles the complexity of container lifecycle, networking, file systems, and process management — letting you focus on building your application logic with just a few lines of TypeScript. Here’s an example:</p>
            <pre><code>import { getSandbox } from '@cloudflare/sandbox';
export { Sandbox } from '@cloudflare/sandbox';

export default {
  async fetch(request: Request, env: Env): Promise&lt;Response&gt; {
    const sandbox = getSandbox(env.Sandbox, 'user-123');

    // Create a project structure
    await sandbox.mkdir('/workspace/project/src', { recursive: true });

    // Check node version
    const version = await sandbox.exec('node -v');

    // Run some python code
    const ctx = await sandbox.createCodeContext({ language: 'python' });
    await sandbox.runCode('import math; radius = 5', { context: ctx });
    const result = await sandbox.runCode('math.pi * radius ** 2', { context: ctx });

    return Response.json({ version, result });
  }
};</code></pre>
            <p>This fits like a glove for Moltbot. Instead of running Docker in your local Mac mini, we run Docker on Containers, use the Sandbox SDK to issue commands into the isolated environment and use callbacks to our entrypoint Worker, effectively establishing a two-way communication channel between the two systems.</p>
    <div>
      <h3>R2 for persistent storage</h3>
      <a href="#r2-for-persistent-storage">
        
      </a>
    </div>
    <p>The good thing about running things in your local computer or VPS is you get persistent storage for free. Containers, however, are inherently <a href="https://developers.cloudflare.com/containers/platform-details/architecture/"><u>ephemeral</u></a>, meaning data generated within them is lost upon deletion. Fear not, though — the Sandbox SDK provides the sandbox.mountBucket() that you can use to automatically, well, mount your R2 bucket as a filesystem partition when the container starts.</p><p>Once we have a local directory that is guaranteed to survive the container lifecycle, we can use that for Moltbot to store session memory files, conversations and other assets that are required to persist.</p>
    <div>
      <h3>Browser Rendering for browser automation</h3>
      <a href="#browser-rendering-for-browser-automation">
        
      </a>
    </div>
    <p>AI agents rely heavily on browsing the sometimes not-so-structured web. Moltbot utilizes dedicated Chromium instances to perform actions, navigate the web, fill out forms, take snapshots, and handle tasks that require a web browser. Sure, we can run Chromium on Sandboxes too, but what if we could simplify and use an API instead?</p><p>With Cloudflare’s <a href="https://developers.cloudflare.com/browser-rendering/"><u>Browser Rendering</u></a>, you can programmatically control and interact with headless browser instances running at scale in our edge network. We support <a href="https://developers.cloudflare.com/browser-rendering/puppeteer/"><u>Puppeteer</u></a>, <a href="https://developers.cloudflare.com/browser-rendering/stagehand/"><u>Stagehand</u></a>, <a href="https://developers.cloudflare.com/browser-rendering/playwright/"><u>Playwright</u></a> and other popular packages so that developers can onboard with minimal code changes. We even support <a href="https://developers.cloudflare.com/browser-rendering/playwright/playwright-mcp/"><u>MCP</u></a> for AI.</p><p>In order to get Browser Rendering to work with Moltbot we do two things:</p><ul><li><p>First we create a <a href="https://github.com/cloudflare/moltworker/blob/main/src/routes/cdp.ts"><u>thin CDP proxy</u></a> (<a href="https://chromedevtools.github.io/devtools-protocol/"><u>CDP</u></a> is the protocol that allows instrumenting Chromium-based browsers) from the Sandbox container to the Moltbot Worker, back to Browser Rendering using the Puppeteer APIs.</p></li><li><p>Then we inject a <a href="https://github.com/cloudflare/moltworker/pull/20"><u>Browser Rendering skill</u></a> into the runtime when the Sandbox starts.</p></li></ul>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1ZvQa7vS1T9Mm3nywqarQZ/9dec3d8d06870ee575a519440d34c499/image12.png" />
          </figure><p>From the Moltbot runtime perspective, it has a local CDP port it can connect to and perform browser tasks.</p>
    <div>
      <h3>Zero Trust Access for authentication policies</h3>
      <a href="#zero-trust-access-for-authentication-policies">
        
      </a>
    </div>
    <p>Next up we want to protect our APIs and Admin UI from unauthorized access. Doing authentication from scratch is hard, and is typically the kind of wheel you don’t want to reinvent or have to deal with. Zero Trust Access makes it incredibly easy to protect your application by defining specific policies and login methods for the endpoints. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1MDXXjbMs4PViN3kp9iFBY/a3095f07c986594d0c07d0276dbf22cc/image3.png" />
          </figure><p><sup>Zero Trust Access Login methods configuration for the Moltworker application.</sup></p><p>Once the endpoints are protected, Cloudflare will handle authentication for you and automatically include a <a href="https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/authorization-cookie/application-token/"><u>JWT token</u></a> with every request to your origin endpoints. You can then <a href="https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/authorization-cookie/validating-json/"><u>validate</u></a> that JWT for extra protection, to ensure that the request came from Access and not a malicious third party.</p><p>Like with AI Gateway, once all your APIs are behind Access you get great observability on who the users are and what they are doing with your Moltbot instance.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3BV4eqxKPXTiq18vvVpmZh/e034b7e7ea637a00c73c2ebe4d1400aa/image8.png" />
          </figure>
    <div>
      <h2>Moltworker in action</h2>
      <a href="#moltworker-in-action">
        
      </a>
    </div>
    <p>Demo time. We’ve put up a Slack instance where we could play with our own instance of Moltbot on Workers. Here are some of the fun things we’ve done with it.</p><p>We hate bad news.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4FxN935AgINZ8953WSswKB/e52d3eb268aa0732c5e6aa64a8e2adba/image6.png" />
          </figure><p>Here’s a chat session where we ask Moltbot to find the shortest route between Cloudflare in London and Cloudflare in Lisbon using Google Maps and take a screenshot in a Slack channel. It goes through a sequence of steps using Browser Rendering to navigate Google Maps and does a pretty good job at it. Also look at Moltbot’s memory in action when we ask him the second time.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1phWt3cVUwxe9tvCYpuAW3/97f456094ede6ca8fb55bf0dddf65d5b/image10.png" />
          </figure><p>We’re in the mood for some Asian food today, let’s get Moltbot to work for help.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6nJY7GOCopGnMy4IY7KMcf/0d57794df524780c3f4b27e65c968e19/image5.png" />
          </figure><p>We eat with our eyes too.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5BzB9pqJhuevRbOSJloeG0/23c2905f0c12c1e7f104aa28fcc1f595/image7.png" />
          </figure><p>Let’s get more creative and ask Moltbot to create a video where it browses our developer documentation. As you can see, it downloads and runs ffmpeg to generate the video out of the frames it captured in the browser.</p><div>
  
</div>
    <div>
      <h2>Run your own Moltworker</h2>
      <a href="#run-your-own-moltworker">
        
      </a>
    </div>
    <p>We open-sourced our implementation and made it available at<a href="https://github.com/cloudflare/moltworker"> <u>https://github.com/cloudflare/moltworker</u></a>, so you can deploy and run your own Moltbot on top of Workers today.</p><p>The <a href="https://github.com/cloudflare/moltworker/blob/main/README.md">README</a> guides you through the necessary setup steps. You will need a Cloudflare account and a <a href="https://developers.cloudflare.com/workers/platform/pricing/"><u>Workers Paid plan</u></a> to access Sandbox Containers; however, all other products are either entirely free (like <a href="https://developers.cloudflare.com/ai-gateway/reference/pricing/"><u>AI Gateway</u></a>) or include generous <a href="https://developers.cloudflare.com/r2/pricing/#free-tier"><u>free tiers </u></a>that allow you to get started and scale under reasonable limits.</p><p><b>Note that Moltworker is a proof of concept, not a Cloudflare product</b>. Our goal is to showcase some of the most exciting features of our <a href="https://developers.cloudflare.com/learning-paths/workers/devplat/intro-to-devplat/">Developer Platform</a> that can be used to run AI agents and unsupervised code efficiently and securely, and get great observability while taking advantage of our global network.</p><p>Feel free to contribute to or fork our <a href="https://github.com/cloudflare/moltworker"><u>GitHub</u></a> repository; we will keep an eye on it for a while for support. We are also considering contributing upstream to the official project with Cloudflare skills in parallel.</p>
    <div>
      <h2>Conclusion</h2>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>We hope you enjoyed this experiment, and we were able to convince you that Cloudflare is the perfect place to run your AI applications and agents. We’ve been working relentlessly trying to anticipate the future and release features like the <a href="https://developers.cloudflare.com/agents/"><u>Agents SDK</u></a> that you can use to build your first agent <a href="https://developers.cloudflare.com/agents/guides/slack-agent/"><u>in minutes</u></a>, <a href="https://developers.cloudflare.com/sandbox/"><u>Sandboxes</u></a> where you can run arbitrary code in an isolated environment without the complications of the lifecycle of a container, and <a href="https://developers.cloudflare.com/ai-search/"><u>AI Search</u></a>, Cloudflare’s managed vector-based search service, to name a few.</p><p>Cloudflare now offers a complete toolkit for AI development: inference, storage APIs, databases, durable execution for stateful workflows, and built-in AI capabilities. Together, these building blocks make it possible to build and run even the most demanding AI applications on our global edge network.</p><p>If you're excited about AI and want to help us build the next generation of products and APIs, we're <a href="https://www.cloudflare.com/en-gb/careers/jobs/?department=Engineering"><u>hiring</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Agents]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Containers]]></category>
            <category><![CDATA[Sandbox]]></category>
            <guid isPermaLink="false">45LuZGCXAcs7EMnB64zTQm</guid>
            <dc:creator>Celso Martinho</dc:creator>
            <dc:creator>Brian Brunner</dc:creator>
            <dc:creator>Sid Chatterjee</dc:creator>
            <dc:creator>Andreas Jansson</dc:creator>
        </item>
        <item>
            <title><![CDATA[Securing agentic commerce: helping AI Agents transact with Visa and Mastercard]]></title>
            <link>https://blog.cloudflare.com/secure-agentic-commerce/</link>
            <pubDate>Fri, 24 Oct 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare is partnering with Visa and Mastercard to help secure the future of agentic commerce. ]]></description>
            <content:encoded><![CDATA[ <p>The era of agentic commerce is coming, and it brings with it significant new challenges for security. That’s why Cloudflare is partnering with Visa and Mastercard to help secure automated commerce as AI agents search, compare, and purchase on behalf of consumers.</p><p>Through our collaboration, Visa developed the <a href="https://github.com/visa/trusted-agent-protocol"><u>Trusted Agent Protocol</u></a> and Mastercard developed <a href="https://www.mastercard.com/us/en/business/artificial-intelligence/mastercard-agent-pay.html"><u>Agent Pay</u></a> to help merchants distinguish legitimate, approved agents from malicious bots. Both Trusted Agent Protocol and Agent Pay leverage <a href="https://blog.cloudflare.com/web-bot-auth/"><u>Web Bot Auth</u></a> as the agent authentication layer to allow networks like Cloudflare to verify traffic from AI shopping agents that register with a payment network.</p>
    <div>
      <h2>The challenges with agentic commerce</h2>
      <a href="#the-challenges-with-agentic-commerce">
        
      </a>
    </div>
    <p>Agentic commerce is commerce driven by AI agents. As AI agents execute more transactions, merchants need to protect themselves and maintain trust with their customers. Merchants are beginning to see the promise of agentic commerce but face significant challenges: </p><ul><li><p>How can they distinguish a helpful, approved AI shopping agent from a malicious bot or web crawler? </p></li><li><p>Is the agent representing a known, repeat customer or someone entirely new? </p></li><li><p>Are there particular instructions the consumer gave to their agent that the merchant should respect?</p></li></ul><p>We are working with Visa and Mastercard, two of the most trusted consumer brands in payments, to address each of these challenges. </p>
    <div>
      <h2>Web Bot Auth is the foundation to securing agentic commerce</h2>
      <a href="#web-bot-auth-is-the-foundation-to-securing-agentic-commerce">
        
      </a>
    </div>
    <p>In May, we shared a new proposal called <a href="https://blog.cloudflare.com/web-bot-auth/"><u>Web Bot Auth</u></a> to cryptographically authenticate agent traffic. Historically, agent traffic has been classified using the user agent and IP address. However, these fields can be spoofed, leading to inaccurate classifications and bot mitigations can be applied inaccurately. Web Bot Auth allows an agent to provide a stable identifier by using <a href="https://datatracker.ietf.org/doc/html/draft-meunier-web-bot-auth-architecture"><u>HTTP Message Signatures</u></a> with public key cryptography.</p><p>As we spent time collaborating with the teams at Visa and Mastercard, we found that we could leverage Web Bot Auth as the foundation to ensure that each commerce agent request was verifiable, time-based, and non-replayable.</p><p>Visa’s Trusted Agent Protocol and Mastercard’s Agent Pay present three key solutions for merchants to manage agentic commerce transactions. First, merchants can identify a registered agent and distinguish whether a particular interaction is intended to browse or to pay. Second, merchants can link an agent to a consumer identity. Last, merchants can indicate to agents how a payment is expected, whether that is through a network token, browser-use guest checkout, or a micropayment.</p><p>This allows merchants that integrate with these protocols to instantly recognize a trusted agent during two key interactions: the initial browsing phase to determine product details and final costs, and the final payment interaction to complete a purchase. Ultimately, this provides merchants with the tools to verify these signatures, identify trusted interactions, and securely manage how these agents can interact with their site.</p>
    <div>
      <h2>How it works: leveraging HTTP message signatures </h2>
      <a href="#how-it-works-leveraging-http-message-signatures">
        
      </a>
    </div>
    <p>To make this work, an ecosystem of participants need to be on the same page. It all starts with <i>agent</i> <i>developers</i>, who build the agents to shop on behalf of consumers. These agents then interact with <i>merchants</i>, who need a reliable way to assess the request is made on behalf of consumers. Merchants rely on networks like Cloudflare to verify the agent's cryptographic signatures and ensure the interaction is legitimate. Finally, there are payment networks like Visa and Mastercard, who can link cardholder identity to agentic commerce transactions, helping ensure that transactions are verifiable and accountable.</p><p>When developing their protocols, Visa and Mastercard needed a secure way to authenticate each agent developer and securely transmit information from the agent to the merchant’s website. That’s where we came in and worked with their teams to build upon Web Bot Auth. <a href="https://datatracker.ietf.org/doc/html/draft-meunier-web-bot-auth-architecture"><u>Web Bot Auth</u></a> proposals specify how developers of bots and agents can attach their cryptographic signatures in HTTP requests by using <a href="https://www.rfc-editor.org/rfc/rfc9421"><u>HTTP Message Signatures</u></a>. </p><p>Both Visa and Mastercard protocols require agents to register and have their public keys (referenced as the <code>keyid</code> in the Signature-Input header) in a well-known directory, allowing merchants and networks to fetch the keys to validate these HTTP message signatures. To start, Visa and Mastercard will be hosting their own directories for Visa-registered and Mastercard-registered agents, respectively</p><p>The newly created agents then communicate their registration, identity, and payment details with the merchant using these HTTP Message Signatures. Both protocols build on Web Bot Auth by introducing a new tag that agents must supply in the <code>Signature-Input </code>header, which indicates whether the agent is browsing or purchasing. Merchants can use the tag to determine whether to interact with the agent. Agents must also include the nonce field, a unique sequence included in the signature, to provide protection against replay attacks.</p><p>An agent visiting a merchant’s website to browse a catalog would include an HTTP Message Signature in their request to verify their agent is authorized to browse the merchant’s storefront on behalf of a specific Visa cardholder:</p>
            <pre><code>GET /path/to/resource HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 Chrome/113.0.0 MyShoppingAgent/1.1
Signature-Input: 
  sig2=("@authority" "@path"); 
  created=1735689600; 
  expires=1735693200; 
  keyid="poqkLGiymh_W0uP6PZFw-dvez3QJT5SolqXBCW38r0U"; 
  alg="Ed25519";   nonce="e8N7S2MFd/qrd6T2R3tdfAuuANngKI7LFtKYI/vowzk4IAZyadIX6wW25MwG7DCT9RUKAJ0qVkU0mEeLEIW1qg=="; 
  tag="web-bot-auth"
Signature: sig2=:jdq0SqOwHdyHr9+r5jw3iYZH6aNGKijYp/EstF4RQTQdi5N5YYKrD+mCT1HA1nZDsi6nJKuHxUi/5Syp3rLWBA==:</code></pre>
            <p>Trusted Agent Protocol and Agent Pay are designed for merchants to benefit from its validation mechanisms without changing their infrastructure. Instead, merchants can set the rules for agent interactions on their site and rely upon Cloudflare as the validator. For these requests, Cloudflare will run <a href="https://blog.cloudflare.com/verified-bots-with-cryptography/#message-signature-verification-for-origins"><u>the following checks</u></a>:</p><ol><li><p>Confirm the presence of the <code>Signature-Input</code> and <code>Signature</code> headers.</p></li><li><p>Pull the <code>keyid</code> from the Signature-Input. If Cloudflare has not previously retrieved and cached the key, fetch it from the public key directory.</p></li><li><p>Confirm the current time falls between the <code>created</code> and <code>expires</code> timestamps.</p></li><li><p>Check <code>nonce</code> uniqueness in the cache. By checking if a nonce has been recently used, Cloudflare can reject reused or expired signatures, ensuring the request is not a malicious copy of a prior, legitimate interaction.</p></li><li><p>Check the validity of the <code>tag</code>, as defined by the protocol. If the agent is browsing, the tag should be <code>agent-browser-auth</code>. If the agent is paying, the tag should be <code>agent-payer-auth</code>. </p></li><li><p>Reconstruct the canonical <a href="https://www.rfc-editor.org/rfc/rfc9421#name-creating-the-signature-base"><u>signature base</u></a> using the <a href="https://www.rfc-editor.org/rfc/rfc9421#covered-components"><u>components</u></a> from the <code>Signature-Input</code> header. </p></li><li><p>Perform the cryptographic <a href="https://www.rfc-editor.org/rfc/rfc9421#name-eddsa-using-curve-edwards25"><u>ed25519 signature verification</u></a> using the key supplied in <code>keyid</code>.</p></li></ol><p>Here is an <a href="https://github.com/visa/trusted-agent-protocol"><u>example from Visa</u></a> on the flow for agent validation:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4Preu2aFUSuW5o3UWE6281/caf5354a009fb89c8b01cfef10fc3e87/image3.png" />
          </figure><p>Mastercard’s Agent Pay validation flow is outlined below:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1vzpRtW4dRzsNGdc4Vnxf1/c780ef45a0b1fc263eb13b62b2af5457/image2.png" />
          </figure>
    <div>
      <h3>What’s next: Cloudflare’s Agent SDK &amp; Managed Rules</h3>
      <a href="#whats-next-cloudflares-agent-sdk-managed-rules">
        
      </a>
    </div>
    <p>We recently introduced support for <a href="https://blog.cloudflare.com/x402/#cloudflares-mcp-servers-agents-sdk-and-x402-payments"><u>x402 transactions</u></a> into Cloudflare’s <a href="https://agents.cloudflare.com/"><u>Agent SDK</u></a>, allowing anyone building an agent to easily transact using the new x402 protocol. We will similarly be working with Visa and Mastercard over the coming months to bring support for their protocols directly to the Agents SDK. This will allow developers to manage their registered agent’s private keys and to easily create the correct HTTP message signatures to authorize their agent to browse and transact on a merchant website.</p><p>Conceptually, the requests in a Cloudflare Worker would look something like this:</p>
            <pre><code>/**
 * Pseudocode example of a Cloudflare Worker acting as a trusted agent.
 * This version explicitly illustrates the signing logic to show the core flow. 
 */


// Helper function to encapsulate the signing protocol logic.
async function createSignatureHeaders(targetUrl, credentials) {
    // Internally, this function would perform the detailed cryptographic steps:
    // 1. Generate timestamps and a unique nonce.
    // 2. Construct the 'Signature-Input' header string with all required parameters.
    // 3. Build the canonical 'Signature Base' string according to the spec.
    // 4. Use the private key to sign the base string.
    // 5. Return the fully formed 'Signature-Input' and 'Signature' headers.
    
    const signedHeaders = new Headers();
    
    signedHeaders.set('Signature-Input', 'sig2=(...); keyid="..."; ...');
    signedHeaders.set('Signature', 'sig2=:...');
    return signedHeaders;
}


export default {
    async fetch(request, env) {
        // 1. Load the final API endpoint and private signing credentials.
        const targetUrl = new URL(request.url).searchParams.get('target');
        const credentials = { 
            privateKey: env.PAYMENT_NETWORK_PRIVATE_KEY, 
            keyId: env.PAYMENT_NETWORK_KEY_ID 
        };


        // 2. Generate the required signature headers using the helper.
        const signatureHeaders = await createSignatureHeaders(targetUrl, credentials);


        // 3. Attach the newly created signature headers to the request for authentication.
        const signedRequestHeaders = new Headers(request.headers);
        signedRequestHeaders.set('Host', new URL(targetUrl).hostname);
        signedRequestHeaders.set('Signature-Input', signatureHeaders.get('Signature-Input'));
        signedRequestHeaders.set('Signature', signatureHeaders.get('Signature'));


       // 4. Forward the fully signed request to the protected API.
        return fetch(targetUrl, { headers: signedRequestHeaders });
    },
};</code></pre>
            <p>We’ll also be creating new <a href="https://developers.cloudflare.com/waf/managed-rules/"><u>managed rulesets</u></a> for our customers that make it easy to allow agents that are using the Trusted Agent Protocol or Agent Pay. You might want to disallow most automated traffic to your storefront but not miss out on revenue opportunities from agents authorized to make a purchase on behalf of a cardholder. A managed rule would make this straightforward to implement. As the website owner, you could enable a managed rule that automatically allows all trusted agents registered with Visa or Mastercard to come to your site, passing your other bot protection &amp; WAF rules. </p><p>These will continue to evolve, and we will incorporate feedback to ensure that agent registration and validation works seamlessly across all networks and aligns with the Web Bot Auth proposal. American Express will also be leveraging Web Bot Auth as the foundation to their agentic commerce offering.</p>
    <div>
      <h2>How to get started today </h2>
      <a href="#how-to-get-started-today">
        
      </a>
    </div>
    <p>You can start building with Cloudflare’s <a href="https://agents.cloudflare.com/"><u>Agent SDK today</u></a>, see a sample implementation of the <a href="https://github.com/visa/trusted-agent-protocol"><u>Trusted Agent Protocol</u></a>, and view the <a href="https://developer.visa.com/capabilities/trusted-agent-protocol/trusted-agent-protocol-specifications"><u>Trusted Agent Protocol</u></a> and <a href="https://www.mastercard.com/us/en/business/artificial-intelligence/mastercard-agent-pay.html"><u>Agent Pay</u></a> docs. </p><p>We look forward to your contribution and feedback, should this be engaging on GitHub, building apps, or engaging in mailing lists discussions.</p> ]]></content:encoded>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Agents]]></category>
            <category><![CDATA[AI Bots]]></category>
            <guid isPermaLink="false">7EMx28KsZIufcu4wEq5YtV</guid>
            <dc:creator>Rohin Lohe</dc:creator>
            <dc:creator>Will Allen</dc:creator>
        </item>
        <item>
            <title><![CDATA[Code Mode: the better way to use MCP]]></title>
            <link>https://blog.cloudflare.com/code-mode/</link>
            <pubDate>Fri, 26 Sep 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ It turns out we've all been using MCP wrong. Most agents today use MCP by exposing the "tools" directly to the LLM. ]]></description>
            <content:encoded><![CDATA[ <p>It turns out we've all been using MCP wrong.</p><p>Most agents today use MCP by directly exposing the "tools" to the <a href="https://www.cloudflare.com/learning/ai/what-is-large-language-model/"><u>LLM</u></a>.</p><p>We tried something different: Convert the MCP tools into a TypeScript API, and then ask an LLM to write code that calls that API.</p><p>The results are striking:</p><ol><li><p>We found agents are able to handle many more tools, and more complex tools, when those tools are presented as a TypeScript API rather than directly. Perhaps this is because LLMs have an enormous amount of real-world TypeScript in their training set, but only a small set of contrived examples of tool calls.</p></li><li><p>The approach really shines when an agent needs to string together multiple calls. With the traditional approach, the output of each tool call must feed into the LLM's neural network, just to be copied over to the inputs of the next call, wasting time, energy, and tokens. When the LLM can write code, it can skip all that, and only read back the final results it needs.</p></li></ol><p>In short, LLMs are better at writing code to call MCP, than at calling MCP directly.</p>
    <div>
      <h2>What's MCP?</h2>
      <a href="#whats-mcp">
        
      </a>
    </div>
    <p>For those that aren't familiar: <a href="https://modelcontextprotocol.io/docs/getting-started/intro"><u>Model Context Protocol</u></a> is a standard protocol for giving AI agents access to external tools, so that they can directly perform work, rather than just chat with you.</p><p>Seen another way, MCP is a uniform way to:</p><ul><li><p>expose an API for doing something,</p></li><li><p>along with documentation needed for an LLM to understand it,</p></li><li><p>with authorization handled out-of-band.</p></li></ul><p>MCP has been making waves throughout 2025 as it has suddenly greatly expanded the capabilities of AI agents.</p><p>The "API" exposed by an MCP server is expressed as a set of "tools". Each tool is essentially a remote procedure call (RPC) function – it is called with some parameters and returns a response. Most modern LLMs have <a href="https://developers.cloudflare.com/workers-ai/features/function-calling/"><u>the capability to use "tools" (sometimes called "function calling")</u></a>, meaning they are trained to output text in a certain format when they want to invoke a tool. The program invoking the LLM sees this format and invokes the tool as specified, then feeds the results back into the LLM as input.</p>
    <div>
      <h3>Anatomy of a tool call</h3>
      <a href="#anatomy-of-a-tool-call">
        
      </a>
    </div>
    <p>Under the hood, an LLM generates a stream of "tokens" representing its output. A token might represent a word, a syllable, some sort of punctuation, or some other component of text.</p><p>A tool call, though, involves a token that does <i>not</i> have any textual equivalent. The LLM is trained (or, more often, fine-tuned) to understand a special token that it can output that means "the following should be interpreted as a tool call," and another special token that means "this is the end of the tool call." Between these two tokens, the LLM will typically write tokens corresponding to some sort of JSON message that describes the call.</p><p>For instance, imagine you have connected an agent to an MCP server that provides weather info, and you then ask the agent what the weather is like in Austin, TX. Under the hood, the LLM might generate output like the following. Note that here we've used words in <code>&lt;|</code> and <code>|&gt;</code> to represent our special tokens, but in fact, these tokens do not represent text at all; this is just for illustration.</p><p>I will use the Weather MCP server to find out the weather in Austin, TX.</p>
            <pre><code>I will use the Weather MCP server to find out the weather in Austin, TX.

&lt;|tool_call|&gt;
{
  "name": "get_current_weather",
  "arguments": {
    "location": "Austin, TX, USA"
  }
}
&lt;|end_tool_call|&gt;</code></pre>
            <p>Upon seeing these special tokens in the output, the LLM's harness will interpret the sequence as a tool call. After seeing the end token, the harness pauses execution of the LLM. It parses the JSON message and returns it as a separate component of the structured API result. The agent calling the LLM API sees the tool call, invokes the relevant MCP server, and then sends the results back to the LLM API. The LLM's harness will then use another set of special tokens to feed the result back into the LLM:</p>
            <pre><code>&lt;|tool_result|&gt;
{
  "location": "Austin, TX, USA",
  "temperature": 93,
  "unit": "fahrenheit",
  "conditions": "sunny"
}
&lt;|end_tool_result|&gt;</code></pre>
            <p>The LLM reads these tokens in exactly the same way it would read input from the user – except that the user cannot produce these special tokens, so the LLM knows it is the result of the tool call. The LLM then continues generating output like normal.</p><p>Different LLMs may use different formats for tool calling, but this is the basic idea.</p>
    <div>
      <h3>What's wrong with this?</h3>
      <a href="#whats-wrong-with-this">
        
      </a>
    </div>
    <p>The special tokens used in tool calls are things LLMs have never seen in the wild. They must be specially trained to use tools, based on synthetic training data. They aren't always that good at it. If you present an LLM with too many tools, or overly complex tools, it may struggle to choose the right one or to use it correctly. As a result, MCP server designers are encouraged to present greatly simplified APIs as compared to the more traditional API they might expose to developers.</p><p>Meanwhile, LLMs are getting really good at writing code. In fact, LLMs asked to write code against the full, complex APIs normally exposed to developers don't seem to have too much trouble with it. Why, then, do MCP interfaces have to "dumb it down"? Writing code and calling tools are almost the same thing, but it seems like LLMs can do one much better than the other?</p><p>The answer is simple: LLMs have seen a lot of code. They have not seen a lot of "tool calls". In fact, the tool calls they have seen are probably limited to a contrived training set constructed by the LLM's own developers, in order to try to train it. Whereas they have seen real-world code from millions of open source projects.</p><p><b><i>Making an LLM perform tasks with tool calling is like putting Shakespeare through a month-long class in Mandarin and then asking him to write a play in it. It's just not going to be his best work.</i></b></p>
    <div>
      <h3>But MCP is still useful, because it is uniform</h3>
      <a href="#but-mcp-is-still-useful-because-it-is-uniform">
        
      </a>
    </div>
    <p>MCP is designed for tool-calling, but it doesn't actually <i>have to</i> be used that way.</p><p>The "tools" that an MCP server exposes are really just an RPC interface with attached documentation. We don't really <i>have to</i> present them as tools. We can take the tools, and turn them into a programming language API instead.</p><p>But why would we do that, when the programming language APIs already exist independently? Almost every MCP server is just a wrapper around an existing traditional API – why not expose those APIs?</p><p>Well, it turns out MCP does something else that's really useful: <b>It provides a uniform way to connect to and learn about an API.</b></p><p>An AI agent can use an MCP server even if the agent's developers never heard of the particular MCP server, and the MCP server's developers never heard of the particular agent. This has rarely been true of traditional APIs in the past. Usually, the client developer always knows exactly what API they are coding for. As a result, every API is able to do things like basic connectivity, authorization, and documentation a little bit differently.</p><p>This uniformity is useful even when the AI agent is writing code. We'd like the AI agent to run in a sandbox such that it can only access the tools we give it. MCP makes it possible for the agentic framework to implement this, by handling connectivity and authorization in a standard way, independent of the AI code. We also don't want the AI to have to search the Internet for documentation; MCP provides it directly in the protocol.</p>
    <div>
      <h2>OK, how does it work?</h2>
      <a href="#ok-how-does-it-work">
        
      </a>
    </div>
    <p>We have already extended the <a href="https://developers.cloudflare.com/agents/"><u>Cloudflare Agents SDK</u></a> to support this new model!</p><p>For example, say you have an app built with ai-sdk that looks like this:</p>
            <pre><code>const stream = streamText({
  model: openai("gpt-5"),
  system: "You are a helpful assistant",
  messages: [
    { role: "user", content: "Write a function that adds two numbers" }
  ],
  tools: {
    // tool definitions 
  }
})</code></pre>
            <p>You can wrap the tools and prompt with the codemode helper, and use them in your app: </p>
            <pre><code>import { codemode } from "agents/codemode/ai";

const {system, tools} = codemode({
  system: "You are a helpful assistant",
  tools: {
    // tool definitions 
  },
  // ...config
})

const stream = streamText({
  model: openai("gpt-5"),
  system,
  tools,
  messages: [
    { role: "user", content: "Write a function that adds two numbers" }
  ]
})</code></pre>
            <p>With this change, your app will now start generating and running code that itself will make calls to the tools you defined, MCP servers included. We will introduce variants for other libraries in the very near future. <a href="https://github.com/cloudflare/agents/blob/main/docs/codemode.md"><u>Read the docs</u></a> for more details and examples. </p>
    <div>
      <h3>Converting MCP to TypeScript</h3>
      <a href="#converting-mcp-to-typescript">
        
      </a>
    </div>
    <p>When you connect to an MCP server in "code mode", the Agents SDK will fetch the MCP server's schema, and then convert it into a TypeScript API, complete with doc comments based on the schema.</p><p>For example, connecting to the MCP server at <a href="https://gitmcp.io/cloudflare/agents"><u>https://gitmcp.io/cloudflare/agents</u></a>, will generate a TypeScript definition like this:</p>
            <pre><code>interface FetchAgentsDocumentationInput {
  [k: string]: unknown;
}
interface FetchAgentsDocumentationOutput {
  [key: string]: any;
}

interface SearchAgentsDocumentationInput {
  /**
   * The search query to find relevant documentation
   */
  query: string;
}
interface SearchAgentsDocumentationOutput {
  [key: string]: any;
}

interface SearchAgentsCodeInput {
  /**
   * The search query to find relevant code files
   */
  query: string;
  /**
   * Page number to retrieve (starting from 1). Each page contains 30
   * results.
   */
  page?: number;
}
interface SearchAgentsCodeOutput {
  [key: string]: any;
}

interface FetchGenericUrlContentInput {
  /**
   * The URL of the document or page to fetch
   */
  url: string;
}
interface FetchGenericUrlContentOutput {
  [key: string]: any;
}

declare const codemode: {
  /**
   * Fetch entire documentation file from GitHub repository:
   * cloudflare/agents. Useful for general questions. Always call
   * this tool first if asked about cloudflare/agents.
   */
  fetch_agents_documentation: (
    input: FetchAgentsDocumentationInput
  ) =&gt; Promise&lt;FetchAgentsDocumentationOutput&gt;;

  /**
   * Semantically search within the fetched documentation from
   * GitHub repository: cloudflare/agents. Useful for specific queries.
   */
  search_agents_documentation: (
    input: SearchAgentsDocumentationInput
  ) =&gt; Promise&lt;SearchAgentsDocumentationOutput&gt;;

  /**
   * Search for code within the GitHub repository: "cloudflare/agents"
   * using the GitHub Search API (exact match). Returns matching files
   * for you to query further if relevant.
   */
  search_agents_code: (
    input: SearchAgentsCodeInput
  ) =&gt; Promise&lt;SearchAgentsCodeOutput&gt;;

  /**
   * Generic tool to fetch content from any absolute URL, respecting
   * robots.txt rules. Use this to retrieve referenced urls (absolute
   * urls) that were mentioned in previously fetched documentation.
   */
  fetch_generic_url_content: (
    input: FetchGenericUrlContentInput
  ) =&gt; Promise&lt;FetchGenericUrlContentOutput&gt;;
};</code></pre>
            <p>This TypeScript is then loaded into the agent's context. Currently, the entire API is loaded, but future improvements could allow an agent to search and browse the API more dynamically – much like an agentic coding assistant would.</p>
    <div>
      <h3>Running code in a sandbox</h3>
      <a href="#running-code-in-a-sandbox">
        
      </a>
    </div>
    <p>Instead of being presented with all the tools of all the connected MCP servers, our agent is presented with just one tool, which simply executes some TypeScript code.</p><p>The code is then executed in a secure sandbox. The sandbox is totally isolated from the Internet. Its only access to the outside world is through the TypeScript APIs representing its connected MCP servers.</p><p>These APIs are backed by RPC invocation which calls back to the agent loop. There, the Agents SDK dispatches the call to the appropriate MCP server.</p><p>The sandboxed code returns results to the agent in the obvious way: by invoking <code>console.log()</code>. When the script finishes, all the output logs are passed back to the agent.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6DRERHP138FSj3GG0QYj3M/99e8c09b352560b7d4547ca299482c27/image2.png" />
          </figure>
    <div>
      <h2>Dynamic Worker loading: no containers here</h2>
      <a href="#dynamic-worker-loading-no-containers-here">
        
      </a>
    </div>
    <p>This new approach requires access to a secure sandbox where arbitrary code can run. So where do we find one? Do we have to run containers? Is that expensive?</p><p>No. There are no containers. We have something much better: isolates.</p><p>The Cloudflare Workers platform has always been based on V8 isolates, that is, isolated JavaScript runtimes powered by the <a href="https://v8.dev/"><u>V8 JavaScript engine</u></a>.</p><p><b>Isolates are far more lightweight than containers.</b> An isolate can start in a handful of milliseconds using only a few megabytes of memory.</p><p>Isolates are so fast that we can just create a new one for every piece of code the agent runs. There's no need to reuse them. There's no need to prewarm them. Just create it, on demand, run the code, and throw it away. It all happens so fast that the overhead is negligible; it's almost as if you were just eval()ing the code directly. But with security.</p>
    <div>
      <h3>The Worker Loader API</h3>
      <a href="#the-worker-loader-api">
        
      </a>
    </div>
    <p>Until now, though, there was no way for a Worker to directly load an isolate containing arbitrary code. All Worker code instead had to be uploaded via the Cloudflare API, which would then deploy it globally, so that it could run anywhere. That's not what we want for Agents! We want the code to just run right where the agent is.</p><p>To that end, we've added a new API to the Workers platform: the <a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/worker-loader/"><u>Worker Loader API</u></a>. With it, you can load Worker code on-demand. Here's what it looks like:</p>
            <pre><code>// Gets the Worker with the given ID, creating it if no such Worker exists yet.
let worker = env.LOADER.get(id, async () =&gt; {
  // If the Worker does not already exist, this callback is invoked to fetch
  // its code.

  return {
    compatibilityDate: "2025-06-01",

    // Specify the worker's code (module files).
    mainModule: "foo.js",
    modules: {
      "foo.js":
        "export default {\n" +
        "  fetch(req, env, ctx) { return new Response('Hello'); }\n" +
        "}\n",
    },

    // Specify the dynamic Worker's environment (`env`).
    env: {
      // It can contain basic serializable data types...
      SOME_NUMBER: 123,

      // ... and bindings back to the parent worker's exported RPC
      // interfaces, using the new `ctx.exports` loopback bindings API.
      SOME_RPC_BINDING: ctx.exports.MyBindingImpl({props})
    },

    // Redirect the Worker's `fetch()` and `connect()` to proxy through
    // the parent worker, to monitor or filter all Internet access. You
    // can also block Internet access completely by passing `null`.
    globalOutbound: ctx.exports.OutboundProxy({props}),
  };
});

// Now you can get the Worker's entrypoint and send requests to it.
let defaultEntrypoint = worker.getEntrypoint();
await defaultEntrypoint.fetch("http://example.com");

// You can get non-default entrypoints as well, and specify the
// `ctx.props` value to be delivered to the entrypoint.
let someEntrypoint = worker.getEntrypoint("SomeEntrypointClass", {
  props: {someProp: 123}
});</code></pre>
            <p>You can start playing with this API right now when running <code>workerd</code> locally with Wrangler (<a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/worker-loader/"><u>check out the docs</u></a>), and you can <a href="https://forms.gle/MoeDxE9wNiqdf8ri9"><u>sign up for beta access</u></a> to use it in production.</p>
    <div>
      <h2>Workers are better sandboxes</h2>
      <a href="#workers-are-better-sandboxes">
        
      </a>
    </div>
    <p>The design of Workers makes it unusually good at sandboxing, especially for this use case, for a few reasons:</p>
    <div>
      <h3>Faster, cheaper, disposable sandboxes</h3>
      <a href="#faster-cheaper-disposable-sandboxes">
        
      </a>
    </div>
    <p><a href="https://developers.cloudflare.com/workers/reference/how-workers-works/"><u>The Workers platform uses isolates instead of containers.</u></a> Isolates are much lighter-weight and faster to start up. It takes mere milliseconds to start a fresh isolate, and it's so cheap we can just create a new one for every single code snippet the agent generates. There's no need to worry about pooling isolates for reuse, prewarming, etc.</p><p>We have not yet finalized pricing for the Worker Loader API, but because it is based on isolates, we will be able to offer it at a significantly lower cost than container-based solutions.</p>
    <div>
      <h3>Isolated by default, but connected with bindings</h3>
      <a href="#isolated-by-default-but-connected-with-bindings">
        
      </a>
    </div>
    <p>Workers are just better at handling isolation.</p><p>In Code Mode, we prohibit the sandboxed worker from talking to the Internet. The global <code>fetch()</code> and <code>connect()</code> functions throw errors.</p><p>But on most platforms, this would be a problem. On most platforms, the way you get access to private resources is, you <i>start</i> with general network access. Then, using that network access, you send requests to specific services, passing them some sort of API key to authorize private access.</p><p>But Workers has always had a better answer. In Workers, the "environment" (<code>env</code> object) doesn't just contain strings, <a href="https://blog.cloudflare.com/workers-environment-live-object-bindings/"><u>it contains live objects</u></a>, also known as "bindings". These objects can provide direct access to private resources without involving generic network requests.</p><p>In Code Mode, we give the sandbox access to bindings representing the MCP servers it is connected to. Thus, the agent can specifically access those MCP servers <i>without</i> having network access in general.</p><p>Limiting access via bindings is much cleaner than doing it via, say, network-level filtering or HTTP proxies. Filtering is hard on both the LLM and the supervisor, because the boundaries are often unclear: the supervisor may have a hard time identifying exactly what traffic is legitimately necessary to talk to an API. Meanwhile, the LLM may have difficulty guessing what kinds of requests will be blocked. With the bindings approach, it's well-defined: the binding provides a JavaScript interface, and that interface is allowed to be used. It's just better this way.</p>
    <div>
      <h3>No API keys to leak</h3>
      <a href="#no-api-keys-to-leak">
        
      </a>
    </div>
    <p>An additional benefit of bindings is that they hide API keys. The binding itself provides an already-authorized client interface to the MCP server. All calls made on it go to the agent supervisor first, which holds the access tokens and adds them into requests sent on to MCP.</p><p>This means that the AI cannot possibly write code that leaks any keys, solving a common security problem seen in AI-authored code today.</p>
    <div>
      <h2>Try it now!</h2>
      <a href="#try-it-now">
        
      </a>
    </div>
    
    <div>
      <h3>Sign up for the production beta</h3>
      <a href="#sign-up-for-the-production-beta">
        
      </a>
    </div>
    <p>The Dynamic Worker Loader API is in closed beta. To use it in production, <a href="https://forms.gle/MoeDxE9wNiqdf8ri9"><u>sign up today</u></a>.</p>
    <div>
      <h3>Or try it locally</h3>
      <a href="#or-try-it-locally">
        
      </a>
    </div>
    <p>If you just want to play around, though, Dynamic Worker Loading is fully available today when developing locally with Wrangler and <code>workerd</code> – check out the docs for <a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/worker-loader/"><u>Dynamic Worker Loading</u></a> and <a href="https://github.com/cloudflare/agents/blob/main/docs/codemode.md"><u>code mode in the Agents SDK</u></a> to get started.</p> ]]></content:encoded>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Birthday Week]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Agents]]></category>
            <category><![CDATA[MCP]]></category>
            <guid isPermaLink="false">61nEdL3TSdS4diA4x21O5e</guid>
            <dc:creator>Kenton Varda</dc:creator>
            <dc:creator>Sunil Pai</dc:creator>
        </item>
        <item>
            <title><![CDATA[Building agents with OpenAI and Cloudflare’s Agents SDK]]></title>
            <link>https://blog.cloudflare.com/building-agents-with-openai-and-cloudflares-agents-sdk/</link>
            <pubDate>Wed, 25 Jun 2025 14:00:00 GMT</pubDate>
            <description><![CDATA[ We’re building AI agents where logic and reasoning are handled by OpenAI’s Agents SDK, and execution happens across Cloudflare's global network via Cloudflare’s Agents SDK.  ]]></description>
            <content:encoded><![CDATA[ 
    <div>
      <h2>What even <i>is</i> an Agents SDK?</h2>
      <a href="#what-even-is-an-agents-sdk">
        
      </a>
    </div>
    <p>The AI landscape is evolving at an incredible pace, and with it, the tools and platforms available to developers are becoming more powerful and interconnected than ever. Here at Cloudflare, we're genuinely passionate about empowering you to build the next generation of applications, and that absolutely includes intelligent agents that can reason, act, and interact with the world.</p><p>When we talk about "<b>Agents SDKs</b>", it can sometimes feel a bit… fuzzy. Some SDKs (software development kits) <b>described as 'agent' SDKs</b> are really about providing frameworks for tool calling and interacting with models. They're fantastic for defining an agent's "brain" – its intelligence, its ability to reason, and how it uses external tools. Here’s the thing: all these agents need a place to actually run. Then there's what we offer at Cloudflare: <a href="https://developers.cloudflare.com/agents/"><u>an SDK purpose-built to provide a seamless execution layer for agents</u></a>. While orchestration frameworks define how agents think, our SDK focuses on where they run, abstracting away infrastructure to enable persistent, scalable execution across our global network.</p><p>Think of it as the ultimate shell, the place where any agent, defined by any agent SDK (like the powerful new OpenAI Agents SDK), can truly live, persist, and run at global scale.</p><p>We’ve chosen OpenAI’s Agents SDK for this example, but the infrastructure is not specific to it. The execution layer is designed to integrate with any agent runtime.</p><p>That’s what this post is about: what we built, what we learned, and the design patterns that emerged from fusing these two pieces together.</p>
    <div>
      <h2>Why use two SDKs?</h2>
      <a href="#why-use-two-sdks">
        
      </a>
    </div>
    <p><a href="https://openai.github.io/openai-agents-js/"><u>OpenAI’s Agents SDK</u></a> gives you the <i>agent</i>: a reasoning loop, tool definitions, and memory abstraction. But it assumes you bring your own runtime and state.</p><p><a href="https://developers.cloudflare.com/agents/"><u>Cloudflare’s Agents SDK</u></a> gives you the <i>environment</i>: a persistent object on our network with identity, state, and built-in concurrency control. But it doesn’t tell you how your agent should behave.</p><p>By combining them, we get a clear split:</p><ul><li><p><b>OpenAI</b>: cognition, planning, tool orchestration</p></li><li><p><b>Cloudflare</b>: location, identity, memory, execution</p></li></ul><p>This separation of concerns let us stay focused on logic, not glue code.</p>
    <div>
      <h2>What you can build with persistent agents</h2>
      <a href="#what-you-can-build-with-persistent-agents">
        
      </a>
    </div>
    <p>Cloudflare <a href="https://developers.cloudflare.com/durable-objects/"><u>Durable Objects</u></a> let agents go beyond simple, stateless functions. They can persist memory, coordinate across workflows, and respond in real time. Combined with the OpenAI Agents SDK, this enables systems that reason, remember, and adapt over time.</p><p>Here are three architectural patterns that show how agents can be composed, guided, and connected:</p><p><b>Multi-agent systems: </b>Divide responsibilities across specialized agents that collaborate on tasks.</p><p><b>Human-in-the-loop: </b>Let agents plan independently but wait for human input at key decision points.</p><p><b>Addressable agents: </b>Make agents reachable through real-world interfaces like phone calls or WebSockets.</p>
    <div>
      <h3>Multi-agent systems </h3>
      <a href="#multi-agent-systems">
        
      </a>
    </div>
    <p>Multi-agent systems let you break down a task into specialized agents that handle distinct responsibilities. In the example below, a triage agent routes questions to either a history or math tutor based on the query. Each agent has its own memory, logic, and instructions. With Cloudflare <a href="https://developers.cloudflare.com/durable-objects/"><u>Durable Objects</u></a>, these agents persist across sessions and can coordinate responses, making it easy to build systems that feel modular but work together intelligently.</p>
            <pre><code>export class MyAgent extends Agent {
  async onRequest() {
    const historyTutorAgent = new Agent({
      instructions:
        "You provide assistance with historical queries. Explain important events and context clearly.",
      name: "History Tutor",
    });

    const mathTutorAgent = new Agent({
      instructions:
        "You provide help with math problems. Explain your reasoning at each step and include examples",
      name: "Math Tutor",
    });

    const triageAgent = new Agent({
      handoffs: [historyTutorAgent, mathTutorAgent],
      instructions:
        "You determine which agent to use based on the user's homework question",
      name: "Triage Agent",
    });

    const result = await run(triageAgent, "What is the capital of France?");
    return Response.json(result.finalOutput);
  }
}</code></pre>
            
    <div>
      <h3>Human-in-the-loop</h3>
      <a href="#human-in-the-loop">
        
      </a>
    </div>
    <p>We implemented a<a href="https://github.com/cloudflare/agents/tree/main/openai-sdk/human-in-the-loop"> <u>human-in-the-loop agent example</u></a> using these two SDKs together. The goal: run an OpenAI agent with a planning loop, allow human decisions to intercept the plan, and preserve state across invocations via Durable Objects.</p><p>The architecture looked like this:</p><ul><li><p>An OpenAI <code>Agent</code> instance runs inside a Durable Object</p></li><li><p>User submits a prompt</p></li><li><p>The agent plans multiple steps</p></li><li><p>After each step, it yields control and waits for a human to approve or intervene</p></li><li><p>State (including memory and intermediate steps) is persisted in <code>this.state</code></p></li></ul><p>It looks like this:</p>
            <pre><code>export class MyAgent extends Agent {
  // ...
  async onStart() {
    if (this.state.serialisedRunState) {
      const runState = await RunState.fromString(
        this.agent,
        this.state.serialisedRunState
      );
      this.result = await run(this.agent, runState);</code></pre>
            <p>This design lets us intercept the agent’s plan at every step and store it. The client could then:</p><ul><li><p>Fetch the pending step via another route</p></li><li><p>Review or modify it</p></li><li><p>Send approval or rejection back to the agent to resume execution</p></li></ul><p>This is only possible because the agent lives inside a Durable Object. It has persistent memory and identity, allowing multi-turn interaction even across sessions</p>
    <div>
      <h3>Addressable agents: “Call my Agent”</h3>
      <a href="#addressable-agents-call-my-agent">
        
      </a>
    </div>
    <p>One of the most interesting takeaways from this pattern is that agents are not just HTTP endpoints. Yes, you can <code>fetch() </code>them via Durable Objects, but conceptually, <b>agents are addressable entities</b> — and there's no reason those addresses have to be tied to URLs.</p><p>You could imagine agents reachable by phone call, by email, or via pub/sub systems. Durable Objects give each agent a global identity that can be referenced however you want.</p><p>In this design:</p><ul><li><p>External sources of input connect to the Cloudflare network; via email, HTTP, or any network interface. In this demo, we use Twilio to route a phone call to a WebSocket input on the Agent.</p></li><li><p>The call is routed through Cloudflare’s infrastructure, so latency is low and identity is preserved.</p></li><li><p>We also store the real-time state updates within the agent, so we can view it on a website (served by the agent itself). This is great for use cases like customer service and education. </p></li></ul>
            <pre><code>export class MyAgent extends Agent {
  // receive phone calls via websocket
  async onConnect(connection: Connection, ctx: ConnectionContext) {
    if (ctx.request.url.includes("media-stream")) {
      const agent = new RealtimeAgent({
        instructions:
          "You are a helpful assistant that starts every conversation with a creative greeting.",
        name: "Triage Agent",
      });

      connection.send(`Welcome! You are connected with ID: ${connection.id}`);

      const twilioTransportLayer = new TwilioRealtimeTransportLayer({
        twilioWebSocket: connection,
      });

      const session = new RealtimeSession(agent, {
        transport: twilioTransportLayer,
      });

      await session.connect({
        apiKey: process.env.OPENAI_API_KEY as string,
      });

      session.on("history_updated", (history) =&gt; {
        this.setState({ history });
      });
    }
  }
}</code></pre>
            <p>This lets an agent become truly multimodal, accepting and outputting data as audio, video, text, email. This pattern opened up exciting possibilities for modular agents and long-running workflows where each agent focuses on a specific domain.</p>
    <div>
      <h2>What we learned (and what you should know)</h2>
      <a href="#what-we-learned-and-what-you-should-know">
        
      </a>
    </div>
    
    <div>
      <h3>1. OpenAI assumes you bring your own state — Cloudflare gives you one</h3>
      <a href="#1-openai-assumes-you-bring-your-own-state-cloudflare-gives-you-one">
        
      </a>
    </div>
    <p>OpenAI’s SDK is stateless by default. You can attach memory abstractions, but the SDK doesn’t tell you where or how to persist it. Cloudflare’s Durable Objects, by contrast, <i>are</i> persistent — that’s the whole point. Every instance has a unique identity and storage API <code>(this.ctx.storage)</code>. This means we can:</p><ul><li><p>Store long-term memory across invocations</p></li><li><p>Hydrate the agent’s memory before <code>run()</code></p></li><li><p>Save any updates after <code>run()</code> completes</p></li></ul>
    <div>
      <h3>2. Durable Object routing isn’t just routing — it’s your agent factory</h3>
      <a href="#2-durable-object-routing-isnt-just-routing-its-your-agent-factory">
        
      </a>
    </div>
    <p>At first glance, <code>routeAgentRequest</code> looks like a simple dispatcher: map a request to a Durable Object based on a URL. But it plays a deeper role — it defines the identity boundary for your agents. We realized this while trying to scope agent instances per user and per task.</p><p>In Durable Objects, identity is tied to an ID. When you call <code>idFromName()</code>, you get a stable, name-based ID that always maps to the same object. This means repeated calls with the same name return the same agent instance — along with its memory and state. In contrast, calling <code>.newUniqueId()</code> creates a new, isolated object each time.</p><p>This is where routing becomes critical: it's where you decide how long an agent should live, and what it should remember.</p><p>This lets us:</p><ul><li><p>Spin up multiple agents per user (e.g. one per session or task)</p></li><li><p>Co-locate memory and logic</p></li><li><p>Avoid unintended memory sharing between conversations</p></li></ul><p><b>Gotcha:</b> If you forget to use <code>idFromName()</code> and just call <code>.newUniqueId()</code>, you’ll get a new agent each time, and your memory will never persist. This is a common early bug that silently kills statefulness.</p>
    <div>
      <h3>​​3. Agents are composable — and that’s powerful</h3>
      <a href="#3-agents-are-composable-and-thats-powerful">
        
      </a>
    </div>
    <p>Agents can invoke each other using Durable Object routing, forming workflows where each agent owns its own memory and logic. This enables composition — building systems from specialized parts that cooperate.</p><p>This makes agent architecture more like microservices — composable, stateful, and distributed.</p>
    <div>
      <h2>Final thoughts: building agents that think <i>and</i> live</h2>
      <a href="#final-thoughts-building-agents-that-think-and-live">
        
      </a>
    </div>
    <p>This pattern — OpenAI cognition + Cloudflare execution — worked better than we expected. It let us:</p><ul><li><p>Write agents with full planning and memory</p></li><li><p>Pause and resume them asynchronously</p></li><li><p>Avoid building orchestration from scratch</p></li><li><p>Compose multiple agents into larger systems</p></li></ul><p>The hardest parts:</p><ul><li><p>Correctly scoping agent architecture</p></li><li><p>Persisting only valid state</p></li><li><p>Debugging with good observability</p></li></ul><p>At Cloudflare, we are incredibly excited to see what <i>you</i> build with this powerful combination. The future of AI agents is intelligent, distributed, and incredibly capable. Get started today by exploring the <a href="https://github.com/openai/openai-agents-js"><u>OpenAI Agents SDK</u></a> and diving into the <a href="https://developers.cloudflare.com/agents/"><u>Cloudflare Agents SDK documentation </u></a>(which leverages Cloudflare Workers and Durable Objects).</p><p>We’re just getting started, and we love to see all that you build. Please <a href="https://discord.com/invite/cloudflaredev"><u>join our Discord</u></a>, ask questions, and tell us what you’re building.</p> ]]></content:encoded>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Agents]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">3RJX3pjuKNyVyxPYsPBbGg</guid>
            <dc:creator>Kate Reznykova</dc:creator>
            <dc:creator>Sunil Pai</dc:creator>
        </item>
        <item>
            <title><![CDATA[Connect any React application to an MCP server in three lines of code]]></title>
            <link>https://blog.cloudflare.com/connect-any-react-application-to-an-mcp-server-in-three-lines-of-code/</link>
            <pubDate>Wed, 18 Jun 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ We're open-sourcing use-mcp, a React library that connects to any MCP server in just 3 lines of code, as well as our AI Playground, a complete chat interface that can connect to remote MCP servers.  ]]></description>
            <content:encoded><![CDATA[ <p>You can <a href="https://developers.cloudflare.com/agents/guides/remote-mcp-server/"><u>deploy</u></a> a <a href="https://blog.cloudflare.com/remote-model-context-protocol-servers-mcp/"><u>remote Model Context Protocol (MCP) server</u></a> on Cloudflare in just one-click. Don’t believe us? Click the button below. </p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-authless"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p>This will get you started with a remote MCP server that supports the latest MCP standards and is the reason why thousands of remote MCP servers have been deployed on Cloudflare, including ones from companies like <a href="https://blog.cloudflare.com/mcp-demo-day/"><u>Atlassian, Linear, PayPal, and more</u></a>. </p><p>But deploying servers is only half of the equation — we also wanted to make it just as easy to build and deploy remote MCP clients that can connect to these servers to enable new AI-powered service integrations. That's why we built <code>use-mcp</code>, a React library for connecting to remote MCP servers, and we're excited to contribute it to the MCP ecosystem to enable more developers to build remote MCP clients.</p><p>Today, we're open-sourcing two tools that make it easy to build and deploy MCP clients:</p><ol><li><p><a href="https://github.com/modelcontextprotocol/use-mcp"><u>use-mcp</u></a> — A React library that connects to any remote MCP server in just 3 lines of code, with transport, authentication, and session management automatically handled. We're excited to contribute this library to the <a href="https://github.com/modelcontextprotocol"><u>MCP ecosystem</u></a> to enable more developers to build remote MCP clients. </p></li><li><p><a href="https://github.com/cloudflare/ai/tree/main/playground/ai"><u>The AI Playground</u></a> — Cloudflare’s <a href="https://playground.ai.cloudflare.com/"><u>AI chat interface</u></a> platform that uses a number of LLM models to interact with remote MCP servers, with support for the latest MCP standard, which you can now deploy yourself. </p></li></ol><p>Whether you're building an AI-powered chat bot, a support agent, or an internal company interface, you can leverage these tools to connect your AI agents and applications to external services via MCP. </p><p>Ready to get started? Click on the button below to deploy your own instance of Cloudflare’s AI Playground to see it in action. </p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/ai/tree/main/playground/ai"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p>
    <div>
      <h2>use-mcp: a React library for building remote MCP clients</h2>
      <a href="#use-mcp-a-react-library-for-building-remote-mcp-clients">
        
      </a>
    </div>
    <p><a href="https://github.com/modelcontextprotocol/use-mcp"><u>use-mcp</u></a> is a <a href="https://www.npmjs.com/package/use-mcp"><u>React library</u></a> that abstracts away all the complexity of building MCP clients. Add the <code>useMCP()</code> hook into any React application to connect to remote MCP servers that users can interact with. </p><p>Here’s all the code you need to add to connect to a remote MCP server: </p>
            <pre><code>mport { useMcp } from 'use-mcp/react'
function MyComponent() {
  const { state, tools, callTool } = useMcp({
    url: 'https://mcp-server.example.com'
  })
  return &lt;div&gt;Your actual UI code&lt;/div&gt;
}</code></pre>
            <p>Just specify the URL, and you're instantly connected. </p><p>Behind the scenes, <code>use-mcp</code> handles the transport protocols (both Streamable HTTP and Server-Sent Events), authentication flows, and session management. It also includes a number of features to help you build reliable, scalable, and production-ready MCP clients. </p>
    <div>
      <h3>Connection management </h3>
      <a href="#connection-management">
        
      </a>
    </div>
    <p>Network reliability shouldn’t impact user experience. <code>use-mcp </code>manages connection retries and reconnections with a backoff schedule to ensure your client can recover the connection during a network issue and continue where it left off. The hook exposes real-time <a href="https://github.com/modelcontextprotocol/use-mcp/tree/main?tab=readme-ov-file#return-value"><u>connection states</u></a> ("connecting", "ready", "failed"), allowing you to build responsive UIs that keep users informed without requiring you to write any custom connection handling logic. </p>
            <pre><code>const { state } = useMcp({ url: 'https://mcp-server.example.com' })

if (state === 'connecting') {
  return &lt;div&gt;Establishing connection...&lt;/div&gt;
}
if (state === 'ready') {
  return &lt;div&gt;Connected and ready!&lt;/div&gt;
}
if (state === 'failed') {
  return &lt;div&gt;Connection failed&lt;/div&gt;
}</code></pre>
            
    <div>
      <h3>Authentication &amp; authorization</h3>
      <a href="#authentication-authorization">
        
      </a>
    </div>
    <p>Many MCP servers require some form of authentication in order to make tool calls. <code>use-mcp</code> supports <a href="https://oauth.net/2.1/"><u>OAuth 2.1</u></a> and handles the entire OAuth flow.  It redirects users to the login page, allows them to grant access, securely stores the access token returned by the OAuth provider, and uses it for all subsequent requests to the server. The library also provides <a href="https://github.com/modelcontextprotocol/use-mcp/tree/main?tab=readme-ov-file#api-reference"><u>methods</u></a> for users to revoke access and clear stored credentials. This gives you a complete authentication system that allows you to securely connect to remote MCP servers, without writing any of the logic. </p>
            <pre><code>const { clearStorage } = useMcp({ url: 'https://mcp-server.example.com' })

// Revoke access and clear stored credentials
const handleLogout = () =&gt; {
  clearStorage() // Removes all stored tokens, client info, and auth state
}</code></pre>
            
    <div>
      <h3>Dynamic tool discovery</h3>
      <a href="#dynamic-tool-discovery">
        
      </a>
    </div>
    <p>When you connect to an MCP server, <code>use-mcp</code> fetches the tools it exposes. If the server adds new capabilities, your app will see them without any code changes. Each tool provides type-safe metadata about its required inputs and functionality, so your client can automatically validate user input and make the right tool calls.</p>
    <div>
      <h3>Debugging &amp; monitoring capabilities</h3>
      <a href="#debugging-monitoring-capabilities">
        
      </a>
    </div>
    <p>To help you troubleshoot MCP integrations, <code>use-mcp </code>exposes a <code>log</code> array containing structured messages at debug, info, warn, and error levels, with timestamps for each one. You can enable detailed logging with the <code>debug</code> option to track tool calls, authentication flows, connection state changes, and errors. This real-time visibility makes it easier to diagnose issues during development and production. </p>
    <div>
      <h3>Future-proofed &amp; backwards compatible</h3>
      <a href="#future-proofed-backwards-compatible">
        
      </a>
    </div>
    <p>MCP is evolving rapidly, with recent updates to transport mechanisms and upcoming changes to authorization. <code>use-mcp</code> supports both Server-Sent Events (SSE) and the newer Streamable HTTP transport, automatically detecting and upgrading to newer protocols, when supported by the MCP server. </p><p>As the MCP specification continues to evolve, we'll keep the library updated with the latest standards, while maintaining backwards compatibility. We are also excited to contribute <code>use-mcp</code> to the <a href="https://github.com/modelcontextprotocol/"><u>MCP project</u></a>, so it can grow with help from the wider community.</p>
    <div>
      <h3>MCP Inspector, built with use-mcp</h3>
      <a href="#mcp-inspector-built-with-use-mcp">
        
      </a>
    </div>
    <p>In use-mcp’s <a href="https://github.com/modelcontextprotocol/use-mcp/tree/main/examples"><u>examples directory</u></a>, you’ll see a minimal <a href="https://inspector.use-mcp.dev/"><u>MCP Inspector</u></a> that was built with the <code>use-mcp</code> hook. . Enter any MCP server URL to test connections, see available tools, and monitor interactions through the debug logs. It's a great starting point for building your own MCP clients or something you can use to debug connections to your MCP server. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6PmPcZicaO39x9SuRqzqSX/b6caa6c7af1d6b03f17c41771598d1b5/image1.png" />
          </figure><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/modelcontextprotocol/use-mcp/tree/main/examples/inspector"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p>
    <div>
      <h2>Open-sourcing the AI Playground </h2>
      <a href="#open-sourcing-the-ai-playground">
        
      </a>
    </div>
    <p>We initially built the <a href="https://playground.ai.cloudflare.com/"><u>AI Playground</u></a> to give users a chat interface for testing different AI models supported by Workers AI. We then added MCP support, so it could be used as a remote MCP client to connect to and test MCP servers. Today, we're open-sourcing the playground, giving you the complete chat interface with the MCP client built in, so you can deploy it yourself and customize it to fit your needs. </p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/ai/tree/main/playground/ai"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p>The playground comes with built-in support for the latest MCP standards, including both Streamable HTTP and Server-Sent Events transport methods, OAuth authentication flows that allow users to sign-in and grant permissions, as well as support for bearer token authentication for direct MCP server connections.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5iaUzuxBZafrH1q0VYHTJf/a7585da38f75818111b3521c9a5ef4e3/image2.png" />
          </figure>
    <div>
      <h3>How the AI Playground works</h3>
      <a href="#how-the-ai-playground-works">
        
      </a>
    </div>
    <p>The AI Playground is built on Workers AI, giving you access to a full catalog of large language models (LLMs) running on Cloudflare's network, combined with the Agents SDK and <code>use-mcp</code> library for MCP server connections.</p><p>The AI Playground uses the <code>use-mcp</code> library to manage connections to remote MCP servers. When the playground starts up, it initializes the MCP connection system with <code>const{tools: mcpTools} = useMcp()</code>, which provides access to all tools from connected servers. At first, this list is empty because it’s not connected to any MCP servers, but once a connection to a remote MCP server is established, the tools are automatically discovered and populated into the list. </p><p>Once <a href="https://github.com/cloudflare/ai/blob/af1ce8be87d6a4e6bc10bb83f7959e63b28c1c8e/playground/ai/src/McpServers.tsx#L550"><u>connected</u></a>, the playground immediately has access to any tools that the MCP server exposes. The <code>use-mcp</code> library handles all the protocol communication and tool discovery, and maintains the connection state. If the MCP server requires authentication, the playground handles OAuth flows through a dedicated callback page that uses <code>onMcpAuthorization </code>from <code>use-mcp</code> to complete the authentication process.</p><p>When a user sends a chat message, the playground takes the <code>mcpTools</code> from the <code>use-mcp</code> hook and passes them directly to Workers AI, enabling the model to understand what capabilities are available and invoke them as needed. </p>
            <pre><code>const stream = useChat({
  api: "/api/inference",
  body: {
    model: params.model,
    tools: mcpTools, // Tools from connected MCP servers
    max_tokens: params.max_tokens,
    system_message: params.system_message,
  },
})</code></pre>
            
    <div>
      <h3>Debugging and monitoring</h3>
      <a href="#debugging-and-monitoring">
        
      </a>
    </div>
    <p>To monitor and debug connections to MCP servers, we’ve added a Debug Log interface to the playground. This displays real-time information about the MCP server connections, including connection status, authentication state, and any connection errors. </p><p>During the chat interactions, the debug interface will show the raw message exchanged between the playground and the MCP server, including the tool invocation and its result. This allows you to monitor the JSON payload being sent to the MCP server, the raw response returned, and track whether the tool call succeeded or failed. This is especially helpful for anyone building remote MCP servers, as it allows you to see how your tools are behaving when integrated with different language models. </p>
    <div>
      <h2>Contributing to the MCP ecosystem</h2>
      <a href="#contributing-to-the-mcp-ecosystem">
        
      </a>
    </div>
    <p>One of the reasons why MCP has evolved so quickly is that it's an open source project, powered by the community. We're excited to contribute the <code>use-mcp</code> library to the <a href="https://github.com/modelcontextprotocol"><u>MCP ecosystem</u></a> to enable more developers to build remote MCP clients. </p><p>If you're looking for examples of MCP clients or MCP servers to get started with, check out the<a href="https://github.com/cloudflare/ai"> <u>Cloudflare AI GitHub repository</u></a> for working examples you can deploy and modify. This includes the complete AI Playground <a href="https://github.com/cloudflare/ai/tree/main/playground/ai"><u>source code,</u></a> a number of remote MCP servers that use different authentication &amp; authorization providers, and the <a href="https://github.com/cloudflare/ai/tree/main/demos/use-mcp-inspector"><u>MCP Inspector</u></a>. </p><p>We’re also building the <a href="https://github.com/cloudflare/mcp-server-cloudflare"><u>Cloudflare MCP servers</u></a> in public and welcome contributions to help make them better. </p><p>Whether you're building your first MCP server, integrating MCP into an existing application, or contributing to the broader ecosystem, we'd love to hear from you. If you have any questions, feedback, or ideas for collaboration, you can reach us via email at <a><u>1800-mcp@cloudflare.com</u></a>. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7sYYS9c45orRX6SaUw5qTx/b975c5221ab538cc8f1167b706da375f/image3.png" />
          </figure><p></p> ]]></content:encoded>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Agents]]></category>
            <category><![CDATA[MCP]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">4gk3k2ZiTN6DZoHu3e090r</guid>
            <dc:creator>Dina Kozlov</dc:creator>
            <dc:creator>Glen Maddern</dc:creator>
            <dc:creator>Sunil Pai</dc:creator>
        </item>
        <item>
            <title><![CDATA[Building an AI Agent that puts humans in the loop with Knock and Cloudflare’s Agents SDK]]></title>
            <link>https://blog.cloudflare.com/building-agents-at-knock-agents-sdk/</link>
            <pubDate>Tue, 03 Jun 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ How Knock shipped an AI Agent with human-in-the-loop capabilities with Cloudflare’s Agents SDK and Cloudflare Workers. ]]></description>
            <content:encoded><![CDATA[ <p><sub><i>This is a guest post by Chris Bell, CTO of </i></sub><a href="https://knock.app/"><sub><i><u>Knock</u></i></sub></a></p><p>There’s a lot of talk right now about building <a href="https://www.cloudflare.com/learning/ai/what-is-agentic-ai/">AI agents</a>, but not a lot out there about what it takes to make those agents truly <i>useful</i>.</p><p>An Agent is an autonomous system designed to make decisions and perform actions to achieve a specific goal or set of goals, without human input.</p><p>No matter how good your agent is at making decisions, you will need a person to provide guidance or input on the agent’s path towards its goal. After all, an agent that cannot interact or respond to the outside world and the systems that govern it will be limited in the problems it can solve.</p><p>That’s where the “human-in-the-loop” interaction pattern comes in. You're bringing a human <i>into</i> the agent's loop and requiring an input from that human before the agent can continue on its task.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6dhEhrOtwdaWOjJqhrzmMw/cc8576e7ccce43e2df1bacfd91b125ff/image3.png" />
          </figure><p>In this blog post, we'll use<a href="https://knock.app/"> <u>Knock</u></a> and the Cloudflare<a href="https://developers.cloudflare.com/agents/"> <u>Agents SDK</u></a> to build an AI Agent for a virtual card issuing workflow that requires human approval when a new card is requested.</p><p>You can find the complete code for this example<a href="https://github.com/knocklabs/ai-agent-examples/tree/main/card-issue-agent"> <u>in the repository</u></a>.</p>
    <div>
      <h2>What is Knock?</h2>
      <a href="#what-is-knock">
        
      </a>
    </div>
    <p><a href="https://knock.app/"><u>Knock</u></a> is messaging infrastructure you can use to send multi-channel messages across in-app, email, SMS, push, and Slack, without writing any integration code.</p><p>With Knock, you gain complete visibility into the messages being sent to your users while also handling reliable delivery, user notification preferences, and more.</p><p>You can use Knock to power human-in-the-loop flows for your agents using Knock’s<a href="https://docs.knock.app/developer-tools/agent-toolkit/overview"> <u>Agent Toolkit</u></a>, which is a set of tools that expose Knock’s APIs and messaging capabilities to your AI agents.</p>
    <div>
      <h2>Using the Agent SDK as the foundation of our AI Agent</h2>
      <a href="#using-the-agent-sdk-as-the-foundation-of-our-ai-agent">
        
      </a>
    </div>
    <p>The Agents SDK provides an abstraction for building stateful, real-time agents on top of <a href="https://developers.cloudflare.com/durable-objects/"><u>Durable Objects</u></a> that are globally addressable and persist state using an embedded, <a href="https://blog.cloudflare.com/sqlite-in-durable-objects/"><u>zero-latency</u></a> SQLite database.</p><p>Building an AI agent outside of using the Agents SDK and the Cloudflare platform means we need to consider WebSocket servers, state persistence, and how to scale our service horizontally. Because a Durable Object backs the Agents SDK, we receive these benefits for free, while having a globally addressable piece of compute with built-in storage, that’s completely serverless and scales to zero.</p><p>In the example, we’ll use these features to build an agent that users interact with in real-time via chat, and that can be paused and resumed as needed. The Agents SDK is the ideal platform for powering asynchronous agentic workflows, such as those required in human-in-the-loop interactions.</p>
    <div>
      <h2>Setting up our Knock messaging workflow</h2>
      <a href="#setting-up-our-knock-messaging-workflow">
        
      </a>
    </div>
    <p>Within Knock, we design our approval workflow using the visual workflow builder to create the cross-channel messaging logic. We then make the notification templates associated with each channel to which we want to send messages.</p><p>Knock will automatically apply the<a href="https://docs.knock.app/concepts/preferences"> <u>user’s preferences</u></a> as part of the workflow execution, ensuring that your user’s notification settings are respected.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5f1hOpKg3xTxZwYuJYmUAl/83088b52e8cb26aaed561d00733fd2e1/image1.png" />
          </figure><p>You can find an example workflow that we’ve already created for this demo in the repository. You can use this workflow template via the<a href="https://docs.knock.app/cli"> <u>Knock CLI</u></a> to import it into your account.</p>
    <div>
      <h2>Building our chat UI</h2>
      <a href="#building-our-chat-ui">
        
      </a>
    </div>
    <p>We’ve built the AI Agent as a chat interface on top of the <code>AIChatAgent</code> abstraction from Cloudflare’s Agents SDK (<a href="https://developers.cloudflare.com/agents/api-reference/agents-api/#chat-agent"><u>docs</u></a>). The Agents SDK here takes care of the bulk of the complexity, and we’re left to implement our LLM calling code with our system prompt.</p>
            <pre><code>// src/index.ts

import { AIChatAgent } from "agents/ai-chat-agent";
import { openai } from "@ai-sdk/openai";
import { createDataStreamResponse, streamText } from "ai";

export class AIAgent extends AIChatAgent {
  async onChatMessage(onFinish) {
    return createDataStreamResponse({
      execute: async (dataStream) =&gt; {
        try {
          const stream = streamText({
            model: openai("gpt-4o-mini"),
            system: `You are a helpful assistant for a financial services company. You help customers with credit card issuing.`,
            messages: this.messages,
            onFinish,
            maxSteps: 5,
          });

          stream.mergeIntoDataStream(dataStream);
        } catch (error) {
          console.error(error);
        }
      },
    });
  }
}</code></pre>
            <p>On the client side, we’re using the <code>useAgentChat</code> hook from the <code>agents/ai-react</code> package to power the real-time user-to-agent chat.</p><p>We’ve modeled our agent as a chat per user, which we set up using the <code>useAgent</code> hook by specifying the name of the process as the <code>userId</code>.</p>
            <pre><code>// src/index.ts

import { useAgent } from "agents/react";
import { useAgentChat } from "agents/ai-react";

function Chat({ userId }: { userId: string }) {
  const agent = useAgent({ agent: "AIAgent", name: userId });
  const { messages, input, handleInputChange, handleSubmit, isLoading } = useAgentChat({ agent });
  // ... 
}</code></pre>
            <p>This means we have an agent process, and therefore a durable object, per-user. For our human-in-the-loop use case, this becomes important later on as we talk about resuming our deferred tool call.</p>
    <div>
      <h2>Deferring the tool call to Knock</h2>
      <a href="#deferring-the-tool-call-to-knock">
        
      </a>
    </div>
    <p>We give the agent our card issuing capability through exposing an <code>issueCard</code> tool. However, instead of writing the approval flow and cross-channel logic ourselves, we delegate it entirely to Knock by wrapping the issue card tool in our <code>requireHumanInput</code> method.</p><p>Now when the user asks to request a new card, we make a call out to Knock to initiate our card request, which will notify the appropriate admins in the organization to request an approval.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3siyPnpYiEmoNIQ7eNCRP/13bd33905cfb5c7ad6812a4359d35627/image2.png" />
          </figure><p>To set this up, we need to use Knock’s Agent Toolkit, which exposes methods to work with Knock in our AI agent and power cross-channel messaging.</p>
            <pre><code>import { createKnockToolkit } from "@knocklabs/agent-toolkit/ai-sdk";
import { tool } from "ai";
import { z } from "zod";

import { AIAgent } from "./index";
import { issueCard } from "./api";
import { BASE_URL } from "./constants";

async function initializeToolkit(agent: AIAgent) {
  const toolkit = await createKnockToolkit({ serviceToken: agent.env.KNOCK_SERVICE_TOKEN });

  const issueCardTool = tool({
    description: "Issue a new credit card to a customer.",
    parameters: z.object({
      customerId: z.string(),
    }),
    execute: async ({ customerId }) =&gt; {
      return await issueCard(customerId);
    },
  });

  const { issueCard } = toolkit.requireHumanInput(
    { issueCard: issueCardTool },
    {
      workflow: "approve-issued-card",
      actor: agent.name,
      recipients: ["admin_user_1"],
      metadata: {
        approve_url: `${BASE_URL}/card-issued/approve`,
        reject_url: `${BASE_URL}/card-issued/reject`,
      },
    }
  );
  
  return { toolkit, tools: { issueCard } };  
}</code></pre>
            <p>There’s a lot going on here, so let’s walk through the key parts:</p><ul><li><p>We wrap our <code>issueCard</code> tool in the <code>requireHumanInput</code> method, exposed from the Knock Agent Toolkit</p></li><li><p>We want the messaging workflow to be invoked to be our <code>approve-issued-card</code> workflow</p></li><li><p>We pass the agent.name as the <code>actor</code> of the request, which translates to the user ID</p></li><li><p>We set the recipient of this workflow to be the user <code>admin_user_1</code></p></li><li><p>We pass the approve and reject URLs so that they can be used in our message templates</p></li><li><p>The wrapped tool is then returned as <code>issueCard</code></p></li></ul><p>Under the hood, these options are passed to the<a href="https://docs.knock.app/api-reference/workflows/trigger"> <u>Knock workflow trigger API</u></a> to invoke a workflow per-recipient. The set of the recipients listed here could be dynamic, or go to a group of users through<a href="https://docs.knock.app/concepts/subscriptions"> <u>Knock’s subscriptions API</u></a>.</p><p>We can then pass the wrapped issue card tool to our LLM call in the <code>onChatMessage</code> method on the agent so that the tool call can be called as part of the interaction with the agent.</p>
            <pre><code>export class AIAgent extends AIChatAgent {
  // ... other methods

  async onChatMessage(onFinish) {
    const { tools } = await initializeToolkit(this);

    return createDataStreamResponse({
      execute: async (dataStream) =&gt; {
        const stream = streamText({
          model: openai("gpt-4o-mini"),
          system: "You are a helpful assistant for a financial services company. You help customers with credit card issuing.",
          messages: this.messages,
          onFinish,
          tools,
          maxSteps: 5,
        });

        stream.mergeIntoDataStream(dataStream);
      },
    });
  }
}</code></pre>
            <p>Now when the agent calls the <code>issueCardTool</code>, we invoke Knock to send our approval notifications, deferring the tool call to issue the card until we receive an approval. Knock’s workflows take care of sending out the message to the set of recipient’s specified, generating and delivering messages according to each user’s preferences.</p><p>Using Knock<a href="https://docs.knock.app/concepts/workflows"> <u>workflows</u></a> for our approval message makes it easy to build cross-channel messaging to reach the user according to their communication<a href="https://docs.knock.app/concepts/preferences"> <u>preferences</u></a>. We can also leverage<a href="https://docs.knock.app/designing-workflows/delay-function"> <u>delays</u></a>,<a href="https://docs.knock.app/designing-workflows/throttle-function"> <u>throttles</u></a>,<a href="https://docs.knock.app/designing-workflows/batch-function"> <u>batching</u></a>, and<a href="https://docs.knock.app/designing-workflows/step-conditions"> <u>conditions</u></a> to orchestrate more complex messaging.</p>
    <div>
      <h2>Handling the approval</h2>
      <a href="#handling-the-approval">
        
      </a>
    </div>
    <p>Once the message has been sent to our approvers, the next step is to handle the approval coming back, bringing the human into the agent’s loop.</p><p>The approval request is asynchronous, meaning that the response can come at any point in the future. Fortunately, Knock takes care of the heavy lifting here for you, routing the event to the agent worker via a<a href="https://docs.knock.app/developer-tools/outbound-webhooks/overview"> <u>webhook</u></a> that tracks the interaction with the underlying message. In our case, that’s a click to the "approve" or "reject" button.</p><p>First, we set up a <code>message.interacted</code> webhook handler within the Knock dashboard to forward the interactions to our worker, and ultimately to our agent process.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5CZkwJmmOw09FNmhRUqFrC/7e7d195276331b42778518b821f7707f/image4.png" />
          </figure><p>In our example here, we route the approval click back to the worker to handle, appending a Knock message ID to the end of the <code>approve_url</code> and <code>reject_url</code> to track engagement against the specific message sent. We do this via liquid inside of our message templates in Knock: <code>{{ data.approve_url }}?messageId={{ current_message.id }} </code>. One caveat here is that if this were a production application, we’re likely going to handle our approval click in a different application than this agent is running. We co-located it here for the purposes of this demo only.</p><p>Once the link is clicked, we have a handler in our worker to mark the message as interacted using Knock’s<a href="https://docs.knock.app/api-reference/messages/mark_as_interacted"> <u>message interaction API</u></a>, passing through the status as metadata so that it can be used later.</p>
            <pre><code>import Knock from '@knocklabs/node';
import { Hono } from "hono";

const app = new Hono();
const client = new Knock();

app.get("/card-issued/approve", async (c) =&gt; {
  const { messageId } = c.req.query();
  
  if (!messageId) return c.text("No message ID found", { status: 400 });

  await client.messages.markAsInteracted(messageId, {
    status: "approved",
  });

  return c.text("Approved");
});</code></pre>
            <p>The message interaction will flow from Knock to our worker via the webhook we set up, ensuring that the process is fully asynchronous. The payload of the webhook includes the full message, including metadata about the user that generated the original request, and keeps details about the request itself, which in our case contains the tool call.</p>
            <pre><code>import { getAgentByName, routeAgentRequest } from "agents";
import { Hono } from "hono";

const app = new Hono();

app.post("/incoming/knock/webhook", async (c) =&gt; {
  const body = await c.req.json();
  const env = c.env as Env;

  // Find the user ID from the tool call for the calling user
  const userId = body?.data?.actors[0];

  if (!userId) {
    return c.text("No user ID found", { status: 400 });
  }

  // Find the agent DO for the user
  const existingAgent = await getAgentByName(env.AIAgent, userId);

  if (existingAgent) {
    // Route the request to the agent DO to process
    const result = await existingAgent.handleIncomingWebhook(body);

    return c.json(result);
  } else {
    return c.text("Not found", { status: 404 });
  }
});</code></pre>
            <p>We leverage the agent’s ability to be addressed by a named identifier to route the request from the worker to the agent. In our case, that’s the <code>userId</code>. Because the agent is backed by a durable object, this process of going from incoming worker request to finding and resuming the agent is trivial.</p>
    <div>
      <h2>Resuming the deferred tool call</h2>
      <a href="#resuming-the-deferred-tool-call">
        
      </a>
    </div>
    <p>We then use the context about the original tool call, passed through to Knock and round tripped back to the agent, to resume the tool execution and issue the card.</p>
            <pre><code>export class AIAgent extends AIChatAgent {
  // ... other methods

  async handleIncomingWebhook(body: any) {
    const { toolkit } = await initializeToolkit(this);

    const deferredToolCall = toolkit.handleMessageInteraction(body);

    if (!deferredToolCall) {
      return { error: "No deferred tool call given" };
    }

    // If we received an "approved" status then we know the call was approved 
    // so we can resume the deferred tool call execution
    if (result.interaction.status === "approved") {
      const toolCallResult = 
	      await toolkit.resumeToolExecution(result.toolCall);

      const { response } = await generateText({
        model: openai("gpt-4o-mini"),
        prompt: `You were asked to issue a card for a customer. The card is now approved. The result was: ${JSON.stringify(toolCallResult)}.`,
      });

      const message = responseToAssistantMessage(
        response.messages[0],
        result.toolCall,
        toolCallResult
      );

      // Save the message so that it's displayed to the user
      this.persistMessages([...this.messages, message]);
    }

    return { status: "success" };
  }
}</code></pre>
            <p>Again, there’s a lot going on here, so let’s step through the important parts:</p><ul><li><p>We attempt to transform the body, which is the webhook payload from Knock, into a deferred tool call via the <code>handleMessageInteraction</code> method</p></li><li><p>If the metadata status we passed through to the interaction call earlier has an “approved” status then we resume the tool call via the <code>resumeToolExecution</code> method</p></li><li><p>Finally, we generate a message from the LLM and persist it, ensuring that the user is informed of the approved card</p></li></ul><p>With this last piece in place, we can now request a new card be issued, have an approval request be dispatched from the agent, send the approval messages, and route those approvals back to our agent to be processed. The agent will asynchronously process our card issue request and the deferred tool call will be resumed for us, with very little code.</p>
    <div>
      <h2>Protecting against duplicate approvals</h2>
      <a href="#protecting-against-duplicate-approvals">
        
      </a>
    </div>
    <p>One issue with the above implementation is that we’re prone to issuing multiple cards if someone clicks on the approve button more than once. To rectify this, we want to keep track of the tool calls being issued, and ensure that the call is processed at most once.</p><p>To power this we leverage the<a href="https://developers.cloudflare.com/agents/api-reference/store-and-sync-state/"> <u>agent’s built-in state</u></a>, which can be used to persist information without reaching for another persistence store like a database or Redis, although we could absolutely do so if we wished. We can track the tool calls by their ID and capture their current status, right inside the agent process.</p>
            <pre><code>type ToolCallStatus = "requested" | "approved" | "rejected";

export interface AgentState {
  toolCalls: Record&lt;string, ToolCallStatus&gt;;
}

class AIAgent extends AIChatAgent&lt;Env, AgentState&gt; {
  initialState: AgentState = {
    toolCalls: {},
  };
  
  setToolCallStatus(toolCallId: string, status: ToolCallStatus) {
    this.setState({
      ...this.state,
      toolCalls: { ...this.state.toolCalls, [toolCallId]: status },
    });
  } 
  // ... 
}</code></pre>
            <p>Here, we create the initial state for the tool calls as an empty object. We also add a quick setter helper method to make interactions easier.</p><p>Next up, we need to record the tool call being made. To do so, we can use the <code>onAfterCallKnock</code> option in the <code>requireHumanInput</code> helper to capture that the tool call has been requested for the user.</p>
            <pre><code>const { issueCard }  = toolkit.requireHumanInput(
  { issueCard: issueCardTool },
  {
    // Keep track of the tool call state once it's been sent to Knock
    onAfterCallKnock: async (toolCall) =&gt; 
      agent.setToolCallStatus(toolCall.id, "requested"),
    // ... as before
  }
);</code></pre>
            <p>Finally, we then need to check the state when we’re processing the incoming webhook, and mark the tool call as approved (some code omitted for brevity).</p>
            <pre><code>export class AIAgent extends AIChatAgent {
  async handleIncomingWebhook(body: any) {
    const { toolkit } = await initializeToolkit(this);
    const deferredToolCall = toolkit.handleMessageInteraction(body);
    const toolCallId = result.toolCall.id;

    // Make sure this is a tool call that can be processed
    if (this.state.toolCalls[toolCallId] !== "requested") {
      return { error: "Tool call is not requested" };
    }

    if (result.interaction.status === "approved") {
      const toolCallResult = await toolkit.resumeToolExecution(result.toolCall);
      this.setToolCallStatus(toolCallId, "approved");
      // ... rest as before
    }
  }
}</code></pre>
            
    <div>
      <h2>Conclusion</h2>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>Using the Agents SDK and Knock, it’s easy to build advanced human-in-the-loop experiences that defer tool calls.</p><p>Knock’s workflow builder and notification engine gives you building blocks to create sophisticated cross-channel messaging for your agents. You can easily create escalation flows that send messages through SMS, push, email, or Slack that respect the notification preferences of your users. Knock also gives you complete visibility into the messages your users are receiving.</p><p>The Durable Object abstraction underneath the Agents SDK means that we get a globally addressable agent process that’s easy to yield and resume back to. The persistent storage in the Durable Object means we can retain the complete chat history per-user, and any other state that’s required in the agent process to resume the agent with (like our tool calls). Finally, the serverless nature of the underlying Durable Object means we’re able to horizontally scale to support a large number of users with no effort.</p><p>If you’re looking to build your own AI Agent chat experience with a multiplayer human-in-the-loop experience, you’ll find the complete code from this guide<a href="https://github.com/knocklabs/ai-agent-examples/tree/main/card-issue-agent"> <u>available in GitHub</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Agents]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Durable Objects]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">3YwK1RRHXn4kGrNazu4AKd</guid>
            <dc:creator>Chris Bell (Guest author)</dc:creator>
        </item>
        <item>
            <title><![CDATA[Thirteen new MCP servers from Cloudflare you can use today]]></title>
            <link>https://blog.cloudflare.com/thirteen-new-mcp-servers-from-cloudflare/</link>
            <pubDate>Thu, 01 May 2025 13:01:19 GMT</pubDate>
            <description><![CDATA[ You can now connect to Cloudflare's first publicly available remote Model Context Protocol (MCP) servers from any MCP client that supports remote servers.  ]]></description>
            <content:encoded><![CDATA[ <p>You can now connect to Cloudflare's first publicly available <a href="https://blog.cloudflare.com/remote-model-context-protocol-servers-mcp/"><u>remote Model Context Protocol (MCP) servers</u></a> from Claude.ai (<a href="http://anthropic.com/news/integrations"><u>now supporting remote MCP connections!</u></a>) and other <a href="https://modelcontextprotocol.io/clients"><u>MCP clients</u></a> like Cursor, Windsurf, or our own <a href="https://playground.ai.cloudflare.com/"><u>AI Playground</u></a>. Unlock Cloudflare tools, resources, and real time information through our new suite of MCP servers including: </p>
<div><table><thead>
  <tr>
    <th><span>Server</span></th>
    <th><span>Description </span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/docs-vectorize"><span>Cloudflare Documentation server</span></a></td>
    <td><span>Get up to date reference information from Cloudflare Developer Documentation</span></td>
  </tr>
  <tr>
    <td><a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/workers-bindings"><span>Workers Bindings server </span></a></td>
    <td><span>Build Workers applications with storage, AI, and compute primitives</span></td>
  </tr>
  <tr>
    <td><a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/workers-observability"><span>Workers Observability server </span></a></td>
    <td><span>Debug and get insight into your Workers application’s logs and analytics</span></td>
  </tr>
  <tr>
    <td><a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/sandbox-container"><span>Container server</span></a></td>
    <td><span>Spin up a sandbox development environment </span></td>
  </tr>
  <tr>
    <td><a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/browser-rendering"><span>Browser rendering server</span></a><span> </span></td>
    <td><span>Fetch web pages, convert them to markdown and take screenshots</span></td>
  </tr>
  <tr>
    <td><a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/radar"><span>Radar server </span></a></td>
    <td><span>Get global Internet traffic insights, trends, URL scans, and other utilities</span></td>
  </tr>
  <tr>
    <td><a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/logpush"><span>Logpush server </span></a></td>
    <td><span>Get quick summaries for Logpush job health</span></td>
  </tr>
  <tr>
    <td><a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/ai-gateway"><span>AI Gateway server </span></a></td>
    <td><span>Search your logs, get details about the prompts and responses</span></td>
  </tr>
  <tr>
    <td><a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/autorag"><span>AutoRAG server</span></a></td>
    <td><span>List and search documents on your AutoRAGs</span></td>
  </tr>
  <tr>
    <td><a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/auditlogs"><span>Audit Logs server </span></a></td>
    <td><span>Query audit logs and generate reports for review</span></td>
  </tr>
  <tr>
    <td><a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/dns-analytics"><span>DNS Analytics server </span></a></td>
    <td><span>Optimize DNS performance and debug issues based on current set up</span></td>
  </tr>
  <tr>
    <td><a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/dex-analysis"><span>Digital Experience Monitoring server </span></a></td>
    <td><span>Get quick insight on critical applications for your organization</span></td>
  </tr>
  <tr>
    <td><a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/cloudflare-one-casb"><span>Cloudflare One CASB server </span></a></td>
    <td><span>Quickly identify any security misconfigurations for SaaS applications to safeguard applications, users, and data</span></td>
  </tr>
</tbody></table></div><p>… all through a natural language interface! </p><p>Today, we also <a href="http://blog.cloudflare.com/mcp-demo-day"><u>announced our collaboration with Anthropic</u></a> to bring remote MCP to <a href="https://claude.ai/"><u>Claude</u></a> users, and showcased how other leading companies such as <a href="https://www.atlassian.com/platform/remote-mcp-server"><u>Atlassian</u></a>, <a href="https://developer.paypal.com/tools/mcp-server/"><u>PayPal</u></a>, <a href="https://docs.sentry.io/product/sentry-mcp/"><u>Sentry</u></a>, and <a href="https://mcp.webflow.com"><u>Webflow</u></a> have built remote MCP servers on Cloudflare to extend their service to their users. We’ve also been using the same infrastructure and tooling to build out our own suite of remote servers, and today we’re excited to show customers what’s ready for use and share what we’ve learned along the way. </p>
    <div>
      <h3>Cloudflare’s MCP servers available today: </h3>
      <a href="#cloudflares-mcp-servers-available-today">
        
      </a>
    </div>
    <p>These <a href="https://www.cloudflare.com/learning/ai/what-is-model-context-protocol-mcp/">MCP servers</a> allow your <a href="https://modelcontextprotocol.io/clients"><u>MCP Client</u></a> to read configurations from your account, process information, make suggestions based on data, and even make those suggested changes for you. All of these actions can happen across Cloudflare's many services including application development, security, and performance.</p>
    <div>
      <h4><b>Cloudflare Documentation Server: </b>Get up-to-date reference information on Cloudflare </h4>
      <a href="#cloudflare-documentation-server-get-up-to-date-reference-information-on-cloudflare">
        
      </a>
    </div>
    <p>Our <a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/docs-vectorize"><u>Cloudflare Documentation server</u></a> enables any MCP Client to access up-to-date <a href="https://developers.cloudflare.com/"><u>documentation</u></a> in real-time, rather than relying on potentially outdated information from the model's training data. If you’re new to building with Cloudflare, this server synthesizes information right from our documentation and exposes it to your MCP Client, so you can get reliable, up-to-date responses to any complex question like “Search Cloudflare for the best way to build an AI Agent”.  </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3vanQPwy6YSwI7bsDTk2md/09cb4763ddbd4858fcd90aca00106bb9/BLOG-2808_2.png" />
          </figure>
    <div>
      <h4><b>Workers Bindings server: </b>Build with developer resources </h4>
      <a href="#workers-bindings-server-build-with-developer-resources">
        
      </a>
    </div>
    <p>Connecting to the <a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/workers-bindings"><u>Bindings MCP server</u></a> lets you leverage application development primitives like D1 databases, <a href="https://www.cloudflare.com/developer-platform/products/r2/">R2 object storage</a> and Key Value stores on the fly as you build out a Workers application. If you're leveraging your MCP Client to generate code, the bindings server provides access to read existing resources from your account or create fresh resources to implement in your application. In combination with our <a href="https://developers.cloudflare.com/workers/get-started/prompting/"><u>base prompt</u></a> designed to help you build robust Workers applications, you can add the Bindings MCP server to give your client all it needs to start generating full stack applications from natural language. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6N0Y8BCBz5ULSHbj0JCIkL/3a6a9ef269202a6c05d18444f313ce87/BLOG-2808_3.png" />
          </figure><p>
Full example output using the Workers Bindings MCP server can be found <a href="https://claude.ai/share/273dadf7-b060-422d-b2b6-4f436d537136"><u>here</u></a>.</p>
    <div>
      <h4><b>Workers Observability server: </b>Debug your application </h4>
      <a href="#workers-observability-server-debug-your-application">
        
      </a>
    </div>
    <p>The <a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/workers-observability"><u>Workers Observability MCP server</u></a> integrates with <a href="https://developers.cloudflare.com/workers/observability/logs/workers-logs/"><u>Workers Logs</u></a> to browse invocation logs and errors, compute statistics across invocations, and find specific invocations matching specific criteria. By querying logs across all of your Workers, this MCP server can help isolate errors and trends quickly. The telemetry data that the MCP server returns can also be used to create new visualizations and improve <a href="https://www.cloudflare.com/learning/performance/what-is-observability/">observability</a>.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1rydyUALBbwtPrT477xAKM/81547e1fb3cec5ffadd90ee5e68e1a5e/BLOG-2808_4.png" />
          </figure>
    <div>
      <h4><b>Container server:</b> Spin up a development environment</h4>
      <a href="#container-server-spin-up-a-development-environment">
        
      </a>
    </div>
    <p>The <a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/sandbox-container"><u>Container MCP server</u></a> provides any MCP client with access to a secure, isolated execution environment running on Cloudflare’s network where it can run and test code if your MCP client does not have a built in development environment (e.g. claude.ai). When building and generating application code, this lets the AI run its own commands and validate its assumptions in real time. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1rXgpQ3znIE01ccY1Qd2cQ/058902719a90af14175b8e838b09b78e/BLOG-2808_5.png" />
          </figure>
    <div>
      <h4><b>Browser Rendering server: </b>Fetch and convert web pages, take screenshots </h4>
      <a href="#browser-rendering-server-fetch-and-convert-web-pages-take-screenshots">
        
      </a>
    </div>
    <p>The <a href="https://developers.cloudflare.com/browser-rendering/"><u>Browser Rendering</u></a> MCP server provides AI friendly tools from our <a href="https://developers.cloudflare.com/browser-rendering/rest-api/"><u>RESTful interface</u></a> for common browser actions such as capturing screenshots, extracting HTML content, and <a href="https://blog.cloudflare.com/markdown-for-agents/">converting pages to Markdown</a>. These are particularly useful when building agents that require interacting with a web browser.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3aQtQxzj1hP6cbtbY4CHXI/27535e9f9a041187c12f6b41ba36afdb/BLOG-2808_6.png" />
          </figure>
    <div>
      <h4><b>Radar server: </b>Ask questions about how we see the Internet and Scan URLs</h4>
      <a href="#radar-server-ask-questions-about-how-we-see-the-internet-and-scan-urls">
        
      </a>
    </div>
    <p>The <a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/radar"><u>Cloudflare Radar MCP server</u></a> exposes tools that allow any MCP client to explore our aggregated <a href="https://radar.cloudflare.com/traffic#http-traffic"><u>HTTP traffic data</u></a>, get information on <a href="https://radar.cloudflare.com/traffic/as701"><u>Autonomous Systems</u></a> (AS) and <a href="https://radar.cloudflare.com/ip/72.74.50.251"><u>IP addresses</u></a>, list traffic anomalies from our <a href="https://radar.cloudflare.com/outage-center"><u>Outage Center</u></a>, get <a href="https://radar.cloudflare.com/domains"><u>trending domains</u></a>, and domain rank information. It can even create charts. Here’s a chat where we ask "show me the <a href="https://claude.ai/public/artifacts/34c8a494-abdc-4755-9ca7-cd8e0a8bea41"><u>HTTP traffic from Portugal</u></a> for the last week":</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/9yg9Fnkoz6t6QOwUK1a5r/b11756fd82058f04037740678160cc7c/BLOG-2808_7.png" />
          </figure>
    <div>
      <h4><b>Logpush server: </b>Get quick summaries for Logpush job health </h4>
      <a href="#logpush-server-get-quick-summaries-for-logpush-job-health">
        
      </a>
    </div>
    <p><a href="https://developers.cloudflare.com/logs/about/"><u>Logpush</u></a> jobs deliver comprehensive logs to your destination of choice, allowing near real-time information processing. The Logpush MCP server can help you analyze your Logpush job results and understand your job health at a high level, allowing you to filter and narrow down for jobs or scenarios you care about. For example, you can ask “provide me with a list of recently failed jobs.” Now, you can quickly find out which jobs are failing with which error message and when, summarized in a human-readable format. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4ltuXD2TgEhiblx6aNhm4d/d63b14f151fd3a239b0a3cf0dfb92ebf/BLOG-2808_8.png" />
          </figure>
    <div>
      <h4><b>AI Gateway server: </b>Check out your AI Gateway logs </h4>
      <a href="#ai-gateway-server-check-out-your-ai-gateway-logs">
        
      </a>
    </div>
    <p>Use this <a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/ai-gateway"><u>MCP server</u></a> to inspect your <a href="https://www.cloudflare.com/developer-platform/products/ai-gateway/">AI Gateway</a> logs and get details about the data from your prompts and the AI models responses. In this example we ask our agent “What is my average latency for my AI Gateway logs in the <i>Cloudflare Radar</i> account?”</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7dYzkZ0cYcXPjFKlhdqkMp/52f2b7e62fe2bb05c91fc563738ddfc2/BLOG-2808_9.png" />
          </figure>
    <div>
      <h4><b>AutoRAG server:</b> List and search documents on your AutoRAGs</h4>
      <a href="#autorag-server-list-and-search-documents-on-your-autorags">
        
      </a>
    </div>
    <p>Having AutoRAG RAGs available to query as MCP tools greatly expands the typical static one-shot retrieval​ and opens doors to use cases where the agent can dynamically decide if and when to retrieve information from one or more <a href="https://www.cloudflare.com/learning/ai/retrieval-augmented-generation-rag/">RAGs</a>, combine them with other tools and APIs, cross-check information and generate a much more rich and complete final answer.</p><p>Here we have a RAG that has a few blog posts that talk about retrocomputers. If we ask "tell me about restoring an amiga 1000 using the blog-celso autorag" the agent will go into a sequence of <a href="https://claude.ai/share/18f1be31-9936-48c0-9de0-151d64f3534e"><u>reasoning steps</u></a>:</p><ul><li><p>“Now that I have some information about Amiga 1000 restoration from blog-celso, let me search for more specific details.”</p></li><li><p>“Let me get more specific information about hardware upgrades and fixes for the Amiga 1000.”</p></li><li><p>“Let me get more information about the DiagROM and other tools used in the restoration.”</p></li><li><p>“Let me search for information about GBA1000 and other expansions mentioned in the blog.”</p></li><li><p>And finally, “Based on the comprehensive information I've gathered from the blog-celso AutoRAG, I can now provide you with a detailed guide on restoring an Amiga 1000.”</p></li></ul><p>And at the end, it generates a very detailed answer based on all the data from all the queries:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4Z8BJSvd4x233FPZDePeSk/e59b8676a92f828d32feb1d28381a216/BLOG-2808_10.png" />
          </figure>
    <div>
      <h4><b>Audit Logs server: </b>Query audit logs and generate reports for review</h4>
      <a href="#audit-logs-server-query-audit-logs-and-generate-reports-for-review">
        
      </a>
    </div>
    <p>Audit Logs record detailed information about actions and events within a system, providing a transparent history of all activity. However, because these logs can be large and complex, it may take effort to query and reconstruct a clear sequence of events. The <a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/auditlogs"><u>Audit Logs MCP server</u></a> helps by allowing you to query audit logs and generate reports. Common queries include if anything notable happened in a Cloudflare account under a user around a particular time of the day, or identifying whether any users used API keys to perform actions on the account. For example, you can ask “Were there any suspicious changes made to my Cloudflare account yesterday around lunchtime?” and obtain the following response: </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/YdV73LhsCmjdQtOK8U7Ii/89f11db15e079190a234665ac4794754/BLOG-2808_11.png" />
          </figure>
    <div>
      <h4><b>DNS Analytics server: </b>Optimize DNS performance and debug issues based on current set up</h4>
      <a href="#dns-analytics-server-optimize-dns-performance-and-debug-issues-based-on-current-set-up">
        
      </a>
    </div>
    <p><a href="https://www.cloudflare.com/application-services/products/analytics/"><u>Cloudflare’s DNS Analytics</u></a> provides detailed insights into DNS traffic, which helps you monitor, analyze, and troubleshoot DNS performance and security across your domains. With Cloudflare’s <a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/dns-analytics"><u>DNS Analytics MCP server</u></a>, you can review DNS configurations across all domains in your account, access comprehensive DNS performance reports, and receive recommendations for performance improvements. By leveraging documentation, the MCP server can help identify opportunities for improving performance. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3X7w64xQvvFbv24HaFeLDv/3fefb7ff9e912207c5897200beefd26f/image4.png" />
          </figure>
    <div>
      <h4><b>Digital Experience Monitoring server</b>: Get quick insight on critical applications for your organization </h4>
      <a href="#digital-experience-monitoring-server-get-quick-insight-on-critical-applications-for-your-organization">
        
      </a>
    </div>
    <p>Cloudflare <a href="https://www.cloudflare.com/learning/performance/what-is-digital-experience-monitoring/">Digital Experience Monitoring (DEM)</a> was built to help network professionals understand the performance and availability of their critical applications from self-hosted applications like Jira and Bitbucket to SaaS applications like Figma or Salesforce. The <a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/dex-analysis"><u>Digital Experience Monitoring MCP server</u></a> fetches DEM test results to surface performance and availability trends within your Cloudflare One deployment, providing quick insights on users, applications, and the networks they are connected to. You can ask questions like: Which users had the worst experience? What times of the day were applications most and least performant? When do I see the most HTTP status errors? When do I see the shortest, longest, or most instability in the network path? </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7Ctxdt7tw04Rfzl9Ihxnkw/fc9c9ab553daa58f59e024dd66dd3dea/BLOG-2808_12.png" />
          </figure>
    <div>
      <h4><b>CASB server</b>: Insights from SaaS Integrations</h4>
      <a href="#casb-server-insights-from-saas-integrations">
        
      </a>
    </div>
    <p><a href="https://www.cloudflare.com/zero-trust/products/casb/"><u>Cloudflare CASB</u></a> provides the ability to integrate with your organization’s <a href="https://developers.cloudflare.com/cloudflare-one/applications/casb/casb-integrations/"><u>SaaS and cloud applications</u></a> to discover assets and surface any security misconfigurations that may be present. A core task is helping security teams understand information about users, files, and other assets they care about that transcends any one SaaS application. The <a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main/apps/cloudflare-one-casb"><u>CASB MCP server</u></a> can explore across users, files, and the many other asset categories to help understand relationships from data that can exist across many different integrations. A common query may include “Tell me about “Frank Meszaros” and what SaaS tools they appear to have accessed”.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3aJOta5YYZ1FqZyHF0wVnx/2c79512fb674eb2762395e5ccaac9700/BLOG-2808_13.png" />
          </figure>
    <div>
      <h3>Get started with our MCP servers </h3>
      <a href="#get-started-with-our-mcp-servers">
        
      </a>
    </div>
    <p>You can start using our Cloudflare MCP servers today! If you’d like to read more about specific tools available in each server, you can find them in our <a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main"><u>public GitHub repository</u></a>. Each server is deployed to a server URL, such as</p><p><code>https://observability.mcp.cloudflare.com/sse.</code></p><p>If your MCP client has first class support for remote MCP servers, the client will provide a way to accept the server URL directly within its interface. For example, if you are using <a href="https://claude.ai/settings/profile"><u>claude.ai</u></a>, you can: </p><ol><li><p>Navigate to your <a href="https://claude.ai/settings/profile"><u>settings</u></a> and add a new “Integration” by entering the URL of your MCP server</p></li><li><p>Authenticate with Cloudflare</p></li><li><p>Select the tools you’d like claude.ai to be able to call</p></li></ol>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5zWyWq2gS08CZsCQNB2fFZ/4e2c88abc90e11055159127e2abaf7b2/BLOG-2808_14.png" />
          </figure><p>If your client does not yet support remote MCP servers, you will need to set up its respective configuration file (mcp_config.json) using <a href="https://www.npmjs.com/package/mcp-remote"><u>mcp-remote</u></a> to specify which servers your client can access.</p>
            <pre><code>{
	"mcpServers": {
		"cloudflare-observability": {
			"command": "npx",
			"args": ["mcp-remote", "https://observability.mcp.cloudflare.com/sse"]
		},
		"cloudflare-bindings": {
			"command": "npx",
			"args": ["mcp-remote", "https://bindings.mcp.cloudflare.com/sse"]
		}
	}
}
</code></pre>
            
    <div>
      <h3>Have feedback on our servers?</h3>
      <a href="#have-feedback-on-our-servers">
        
      </a>
    </div>
    <p>While we're launching with these initial 13 MCP servers, we are just getting started! We want to hear your feedback as we shape existing and build out more Cloudflare MCP servers that unlock the most value for your teams leveraging AI in their daily workflows. If you’d like to provide feedback, request a new MCP server, or report bugs, please raise an issue on our <a href="https://github.com/cloudflare/mcp-server-cloudflare/tree/main"><u>GitHub repository. </u></a> </p>
    <div>
      <h3>Building your own MCP server?</h3>
      <a href="#building-your-own-mcp-server">
        
      </a>
    </div>
    <p>If you’re interested in building your own servers, we've discovered valuable best practices that we're excited to share with you as we’ve been building ours. While MCP is really starting to gain momentum and many organizations are just beginning to build their own servers, these principals should help guide you as you start building out MCP servers for your customers. </p><ol><li><p><b>An MCP server is not our entire API schema: </b>Our goal isn't to build a large wrapper around all of Cloudflare’s API schema, but instead focus on optimizing for specific jobs to be done and reliability of the outcome. This means while one tool from our MCP server may map to one API, another tool may map to many. We’ve found that fewer but more powerful tools may be better for the agent with smaller context windows, less costs, a faster output, and likely more valid answers from LLMs. Our MCP servers were created directly by the product teams who are responsible for each of these areas of Cloudflare – application development, security and performance – and are designed with user stories in mind. This is a pattern you will continue to see us use as we build out more Cloudflare servers. </p></li><li><p><b>Specialize permissions with multiple servers:</b> We built out several specialized servers rather than one for a critical reason: security through precise permission scoping. Each MCP server operates with exactly the permissions needed for its specific task – nothing more. By separating capabilities across multiple servers, each with its own authentication scope, we prevent the common security pitfall of over-privileged access. </p></li><li><p><b>Add robust server descriptions within parameters:</b> Tool descriptions were core to providing helpful context to the agent. We’ve found that more detailed descriptions help the agent understand not just the expected data type, but also the parameter's purpose, acceptable value ranges, and impact on server behavior. This context allows agents to make intelligent decisions about parameter values rather than providing arbitrary and potentially problematic inputs, allowing your natural language to go further with the agent. </p></li><li><p><b>Using evals at each iteration:</b> For each server, we implemented evaluation tests or “evals” to assess the model's ability to follow instructions, select appropriate tools, and provide correct arguments to those tools. This gave us a programmatic way to understand if any regressions occurred through each iteration, especially when tweaking tool descriptions. </p></li></ol><p>Ready to start building? Click the button below to deploy your first remote MCP server to production: </p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-authless"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p>Or check out our documentation to learn more! If you have any questions or feedback for us, you can reach us via email at <a><u>1800-mcp@cloudflare.com</u></a> or join the chatter in the <a href="https://discord.com/channels/595317990191398933/1354548448635912324"><u>Cloudflare Developers Discord</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[Model Context Protocol]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Agents]]></category>
            <category><![CDATA[Open Source]]></category>
            <category><![CDATA[MCP]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <guid isPermaLink="false">17j3OSuM89oMb5wurF4Tij</guid>
            <dc:creator>Nevi Shah</dc:creator>
            <dc:creator>Maximo Guk </dc:creator>
            <dc:creator>Christian Sparks</dc:creator>
        </item>
        <item>
            <title><![CDATA[MCP Demo Day: How 10 leading AI companies built MCP servers on Cloudflare]]></title>
            <link>https://blog.cloudflare.com/mcp-demo-day/</link>
            <pubDate>Thu, 01 May 2025 13:00:21 GMT</pubDate>
            <description><![CDATA[ We’re teaming up with Anthropic, Asana, Atlassian, Block, Intercom, Linear, PayPal, Sentry, Stripe, and Webflow to launch new remote MCP servers, built on Cloudflare, to enable Claude users to manage ]]></description>
            <content:encoded><![CDATA[ <p>Today, we're excited to collaborate with Anthropic, Asana, Atlassian, Block, Intercom, Linear, PayPal, Sentry, Stripe, and Webflow to bring a whole new set of remote MCP servers, all built on Cloudflare, to enable <a href="https://claude.ai/"><u>Claude</u></a> users to manage projects, generate invoices, query databases, and even deploy full stack applications — without ever leaving the chat interface. </p><p>Since <a href="https://www.anthropic.com/news/model-context-protocol">Anthropic’s</a> introduction of the <a href="https://www.cloudflare.com/learning/ai/what-is-model-context-protocol-mcp/">Model Context Protocol</a> (MCP) in November, there’s been more and more excitement about it, and it seems like a new MCP server is being released nearly every day. And for good reason!  MCP has been the missing piece to make <a href="https://www.cloudflare.com/learning/ai/what-is-agentic-ai/">AI agents</a> a reality, and helped define how AI agents interact with tools to take actions and get additional context.</p><p>But to date, end-users have had to install MCP servers on their local machine to use them. Today, with <a href="http://anthropic.com/news/integrations"><u>Anthropic’s announcement</u></a> of Integrations, you can access an MCP server the same way you would a website: type a URL and go.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5FLvAIrlxVcKPZNRG5Qhwj/f252d4de66f45e1f06bb94d76e1bf4c1/BLOG-2811_2.png" />
          </figure><p>At Cloudflare, we’ve been focused on<a href="https://blog.cloudflare.com/remote-model-context-protocol-servers-mcp/"><u> building out the tooling</u></a> that simplifies the development of remote MCP servers, so that our customers’ engineering teams can focus their time on building out the MCP tools for their application, rather than managing the complexities of the protocol. And if you’re wondering just how easy is it to deploy a remote MCP server on Cloudflare, we’re happy to tell you that it only takes one click to get an MCP server — pre-built with support for the latest MCP standards — deployed. </p><p>But you don’t have to take our word for it, see it for yourself! Industry leaders are taking advantage of the ease of use to deliver new AI-powered experiences to their users by building their MCP servers on Cloudflare and now, you can do the same — just click “Deploy to Cloudflare” to get started. </p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-authless"><img src="https://deploy.workers.cloudflare.com/button" /></a><p><code></code></p><p>Keep reading to learn more about the new capabilities that these companies are unlocking for their users and how they were able to deliver them. Or, see it in action by joining us for <a href="https://demo-day.mcp.cloudflare.com/"><u>Demo Day</u></a> on May 1 (today) at 10:00 AM PST. </p><p>We’re also making <a href="https://blog.cloudflare.com/thirteen-new-mcp-servers-from-cloudflare"><u>Cloudflare's remote MCP servers</u></a> available to customers today and sharing what we learned from building them out. </p>
    <div>
      <h2>MCP: Powering the next generation of applications</h2>
      <a href="#mcp-powering-the-next-generation-of-applications">
        
      </a>
    </div>
    <p>It wasn’t always the expectation that every service, whether a store, real estate agent, or service would have a website. But as more people gained access to an Internet connection, that quickly became the case.</p><p>We’re in the midst of a similar transition now to every web user having access to AI tools, turning to them for many tasks. If you’re a developer, it’s likely the case that the first place you turn when you go to write code now is to a tool like Claude. It seems reasonable then, that if Claude helped you write the code, it would also help you deploy it.</p><p>Or if you’re not a developer, if Claude helped you come up with a recipe, that it would also help you order the required groceries. </p><p>With remote MCP, all of these scenarios are now possible. And just like the first businesses built on the web had a first mover advantage, the first businesses to be built in an MCP-forward way are likely to reap the benefits. </p><p>The faster a user can experience the value of your product, the more likely they will be to succeed, upgrade, and continue to use your product. By connecting services to agents through MCP, users can simply ask for what they need and the agent will handle the rest, getting them to that “aha” moment faster. </p>
    <div>
      <h2>Making your service AI-first with MCP</h2>
      <a href="#making-your-service-ai-first-with-mcp">
        
      </a>
    </div>
    <p>Businesses that adopt MCP will quickly see the impact: </p>
    <div>
      <h3>Lower the barrier to entry</h3>
      <a href="#lower-the-barrier-to-entry">
        
      </a>
    </div>
    <p>Not every user has the time to learn your dashboard or read through documentation to understand your product. With MCP, they don’t need to. They just describe what they want, and the agent figures out the rest. </p>
    <div>
      <h3>Create personalized experiences</h3>
      <a href="#create-personalized-experiences">
        
      </a>
    </div>
    <p>MCP can keep track of a user’s requests and interactions, so future tool calls can be adapted to their usage patterns and preferences. This makes it easy to deliver more personalized, relevant experiences based on how each person actually uses your product.</p>
    <div>
      <h3>Drive upgrades naturally</h3>
      <a href="#drive-upgrades-naturally">
        
      </a>
    </div>
    <p>Rather than relying on feature comparison tables, the AI agent can explain how a higher-tier plan helps a specific user accomplish <i>their</i> goals. </p>
    <div>
      <h3>Ship new features and integrations</h3>
      <a href="#ship-new-features-and-integrations">
        
      </a>
    </div>
    <p>You don’t need to build every integration or experience in-house. By exposing your tools via MCP, you let users connect your product to the rest of their stack. Agents can combine tools across providers, enabling integrations without requiring you to support every third-party service directly.</p>
    <div>
      <h2>Why build MCP on Cloudflare? </h2>
      <a href="#why-build-mcp-on-cloudflare">
        
      </a>
    </div>
    <p>Since the launch of MCP, we’ve <a href="https://blog.cloudflare.com/remote-model-context-protocol-servers-mcp/"><u>shared</u></a> how we’re making it easy for developers to <a href="https://developers.cloudflare.com/agents/guides/remote-mcp-server/"><u>build and deploy remote MCP servers</u></a> — from abstracting away protocol complexity to handling auth and transport, to <a href="https://blog.cloudflare.com/building-ai-agents-with-mcp-authn-authz-and-durable-objects/"><u>supporting fully stateful MCP servers</u></a> (by default) that <a href="https://developers.cloudflare.com/agents/model-context-protocol/mcp-agent-api/#hibernation-support"><u>“sleep”</u></a> when they’re not used to minimize idle costs.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7rTqqs8gSYef4uIiS1aSqz/5147063aff613078af22e5b5b5b55570/BLOG-2811_3.png" />
          </figure><p>We’re continuing to ship updates regularly — <a href="https://blog.cloudflare.com/streamable-http-mcp-servers-python/"><u>adding support</u></a> for the <a href="https://modelcontextprotocol.io/specification/2025-03-26"><u>latest changes</u></a> to the MCP standard and making it even easier to get your server to production:</p><ul><li><p><a href="https://developers.cloudflare.com/agents/model-context-protocol/transport/"><b><u>Supporting the new Streamable HTTP transport</u></b></a><b>:</b> Your MCP servers can now use the latest Streamable HTTP transport alongside SSE, ensuring compatibility with the latest standards. We’ve updated the AI Playground and <a href="https://www.npmjs.com/package/mcp-remote"><u>mcp-remote</u></a> proxy as well, giving you a remote MCP client to easily test the new transport.</p></li><li><p><a href="https://github.com/cloudflare/ai/tree/main/demos/python-workers-mcp"><b><u>Python support for MCP servers</u></b></a><b>: </b>You can now build MCP servers on Cloudflare using Python, not just JavaScript/TypeScript. </p></li><li><p><b>Improved docs, starter templates, and deploy flows:</b> We’ve added <a href="https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-authless"><u>new quickstart templates</u></a>, expanded our <a href="https://developers.cloudflare.com/agents/model-context-protocol/transport/"><u>documentation</u></a> to cover the new transport method, and shared <a href="https://developers.cloudflare.com/agents/model-context-protocol/#best-practices"><u>best practices</u></a> for building MCP servers based on our learnings. </p></li></ul><p>But rather than telling you, we thought it would be better to show you what our customers have built and why they chose Cloudflare for their MCP deployment. </p>
    <div>
      <h2>Remote MCP servers you can connect to today</h2>
      <a href="#remote-mcp-servers-you-can-connect-to-today">
        
      </a>
    </div>
    
    <div>
      <h3>Asana</h3>
      <a href="#asana">
        
      </a>
    </div>
    <p>Today, work lives across many different apps and services. By investing in MCP, Asana can meet users where they are, enabling agent-driven interoperability across tools and workflows. Users can interact with the Asana Work Graph using natural language to get project updates, search for tasks, manage projects, send comments, and update deadlines from an MCP client.</p><p>Users will be able to orchestrate and integrate different pieces of work seamlessly — for example, turning a project plan or meeting notes from another app into a fully assigned set of tasks in Asana, or pulling Asana tasks directly into an MCP-enabled IDE for implementation. This flexibility makes managing work across systems easier, faster, and more natural than ever before.</p><p>To accelerate the launch of our first-party MCP server, Asana built on Cloudflare's tooling, taking advantage of the foundational infrastructure to move quickly and reliably in this fast-evolving space.</p><p><i>"At Asana, we've always focused on helping teams coordinate work effortlessly. MCP connects our Work Graph directly to AI tools like Claude.ai, enabling AI to become a true teammate in work management. Our integration transforms natural language into structured work – creating projects from meeting notes or pulling updates into AI. Building on Cloudflare's infrastructure allowed us to deploy quickly, handling authentication and scaling while we focused on creating the best experience for our users." – Prashant Pandey, Chief Technology Officer, Asana</i></p><p>Learn more about Asana’s MCP server <a href="https://developers.asana.com/docs/using-asanas-model-control-protocol-mcp-server"><u>here</u></a>. </p>
    <div>
      <h3>Atlassian</h3>
      <a href="#atlassian">
        
      </a>
    </div>
    <p>Jira and Confluence Cloud customers can now securely interact with their data directly from Anthropic’s Claude app via the <a href="http://atlassian.com/platform/remote-mcp-server"><u>Atlassian Remote MCP</u></a> Server in beta. Hosted on Cloudflare infrastructure, users can summarize work, create issues or pages, and perform multi-step actions, all while keeping data secure and within permissioned boundaries.</p><p>Users can access information from Jira and Confluence wherever they use Claude to:</p><ul><li><p>Summarize Jira work items or Confluence pages</p></li><li><p>Create Jira work items or Confluence pages directly from Claude</p></li><li><p>Get the model to take multiple actions in one go, like creating issues or pages in bulk</p></li><li><p>Enrich Jira work items with context from many different sources to which Claude has access</p></li><li><p>And so much more!</p></li></ul><p><i>“AI is not one-size-fits-all and we believe that it needs to be embedded within a team’s jobs to be done. That’s why we’re so excited to invest in MCP and meet teams in more places where they already work. Hosting on Cloudflare infrastructure means we can bring this powerful integration to our customers faster and empower them to do more than ever with Jira and Confluence, all while keeping their enterprise data secure. Cloudflare provided everything from OAuth to out-of-the-box remote MCP support so we could quickly build, secure, and scale a fully operational setup.” — Taroon Mandhana, Head of Product Engineering, Atlassian</i></p><p>Learn more about Atlassian’s MCP server <a href="https://www.atlassian.com/blog/announcements/remote-mcp-server"><u>here</u></a>. </p>
    <div>
      <h3>Intercom</h3>
      <a href="#intercom">
        
      </a>
    </div>
    <p>At Intercom, the transformative power of AI is becoming increasingly clear. Fin, Intercom’s AI Agent, is now autonomously resolving over 50% of customer support conversations for leading companies such as Anthropic. With MCP, connecting AI to internal tools and systems is easier than ever, enabling greater business value.</p><p>Customer conversations, for instance, offer valuable insights into how products are being used and the experiences customers are having. However, this data is often locked within the support platform. The Intercom MCP server unlocks this rich source of customer data, making it accessible to anyone in the organization using AI tools. Engineers, for example, can leverage conversation history and user data from Intercom in tools like Cursor or Claude Code to diagnose and resolve issues more efficiently.</p><p><i>“The momentum behind MCP is exciting. It’s making it easier and easier to connect assistants like Claude.ai and agents like Fin to your systems and get real work done. Cloudflare's toolkit is accelerating that movement even faster. Their clear documentation, purpose-built tools, and developer-first platform helped Intercom go from concept to production in under a day, making the Intercom MCP server launch effortless. We’ll be encouraging our customers to leverage Cloudflare to build and deploy their own MCP servers to securely and reliably connect their internal systems to Fin and other clients.” — Jordan Neill, SVP Engineering, Intercom</i></p>
    <div>
      <h3>Linear</h3>
      <a href="#linear">
        
      </a>
    </div>
    <p>The Linear MCP server allows users to bring the context of their issues and product development process directly into AI assistants when it's needed. Whether that is refining a product spec in Claude, collaborating on fixing a bug with Cursor, or creating issues on the fly from an email. </p><p><i>“We're building on Cloudflare to take advantage of their frameworks in this fast-moving space and flexible, fast, compute at the edge. With MCP, we're bringing Linear's issue tracking and product development workflows directly into their AI tools of choice, eliminating context switching for teams. Our goal is simple: let developers and product teams access their work where they already are—whether refining specs in Claude, debugging in Cursor, or creating issues from conversations. This seamless integration helps our customers stay in flow and focused on building great products” — Tom Moor, Head of US Engineering, Linear</i></p><p>Learn more about Linear’s MCP server <a href="https://linear.app/docs/mcp"><u>here</u></a>. </p>
    <div>
      <h3>PayPal</h3>
      <a href="#paypal">
        
      </a>
    </div>
    <p><i>"MCPs represent a new paradigm for software development. With PayPal's remote MCP server on Cloudflare, now developers can delegate to an agent with natural language to seamlessly integrate with PayPal's portfolio of commerce capabilities. Whether it's managing inventory, processing payments, tracking shipping, handling refunds, AI agents via MCP can tap into these capabilities to autonomously execute and optimize commerce workflows. This is a revolutionary development for commerce, and the best part is, developers can begin integrating with our MCP server on Cloudflare today." - Prakhar Mehrotra, SVP of Artificial Intelligence, PayPal</i></p><p>Learn more about PayPal’s MCP server <a href="https://developer.paypal.com/tools/mcp-server/"><u>here</u></a>. </p>
    <div>
      <h3>Sentry</h3>
      <a href="#sentry">
        
      </a>
    </div>
    <p>With the Sentry MCP server, developers are able to query Sentry’s context right from their IDE, or an assistant like Claude, to get errors and issue information across projects or even for individual files.</p><p>Developers can also use the MCP to create projects, capture setup information, and query project and organization information - and use the information to set up their applications for Sentry. As we continue to build out the MCP further, we'll allow teams to bring in root cause analysis and solution information from Seer, our Agent, and also look at simplifying instrumentation for sentry functionality like traces, and exception handling. </p><p>Hosting this on Cloudflare and using Remote MCP, we were able to sidestep a number of the complications of trying to run locally, like scaling or authentication. Remote MCP lets us leverage Sentry’s own OAuth configuration directly. Durable Object support also lets us maintain state within the MCP, which is important when you’re not running locally. </p><p><i>“Sentry’s commitment has always been to the developer, and making it easier to keep production software running stable, and that’s going to be even more true in the AI era. Developers are utilizing tools like MCP to integrate their stack with AI models and data sources. We chose to build our MCP on Cloudflare because we share a vision of making it easier for developers to ship software, and are both invested in ensuring teams can build and safely run the next generation of AI agents. Debugging the complex interactions arising from these integrations is increasingly vital, and Sentry provides the essential visibility needed to rapidly diagnose and resolve issues. MCP integrates this crucial Sentry context directly into the developer workflow, empowering teams to consistently build and deploy reliable applications.” — David Cramer, CPO and Co-Founder, Sentry</i></p><p>Learn more about Sentry’s MCP server <a href="https://docs.sentry.io/product/sentry-mcp/"><u>here</u></a>. </p>
    <div>
      <h3>Block </h3>
      <a href="#block">
        
      </a>
    </div>
    <p>Square's <a href="https://developer.squareup.com/us/en"><u>APIs</u></a> are a comprehensive set of tools that help sellers take payments, create and track orders, manage inventory, organize customers, and more. Now, with a dedicated Square MCP server, sellers can enlist the help of an AI agent to build their business on Square’s entire suite of API resources and endpoints. By integrating with AI agents like Claude and <a href="https://block.github.io/goose/"><u>codename goose</u></a>, sellers can craft sophisticated, customized use cases that fully utilize Square’s capabilities, at a lower technical barrier.</p><p>Learn more about Block’s MCP server <a href="https://developer.squareup.com/docs/mcp"><u>here</u></a>. </p>
    <div>
      <h3>Stripe</h3>
      <a href="#stripe">
        
      </a>
    </div>
    <p><i>“MCP is emerging as a new AI interface. In the near-future, MCP may become the default way, or in some cases the only way, people, businesses, and code discover and interact with services. With </i><a href="https://docs.stripe.com/agents"><i><u>Stripe's agent toolkit</u></i></a><i> and Cloudflare’s Agent SDK, developers can now monetize their MCPs with just a few lines of code.” — Jeff Weinstein, Product Lead at Stripe</i></p>
    <div>
      <h3>Webflow</h3>
      <a href="#webflow">
        
      </a>
    </div>
    <p>The Webflow MCP server supports CMS management, auditing and improving SEO, content localization, site publishing, and more. This enables users to manage and improve their site directly from their AI agent. </p><p><i>"We see MCP as a new way to interact with Webflow that aligns well with our mission of bringing development superpowers to everyone. MCP is not just a different surface over our APIs, instead we’re thinking of it in terms of the actions it supports: publish a website, create a CMS collection, update content, and more. MCP lets us expose those actions in a way that’s discoverable, secure, and deeply contextual. It opens the door to new workflows where AI and humans can work side-by-side, without needing to cobble together solutions or handle low-level API details. Cloudflare supports this aim by offering the reliability, performance, and developer tooling we need to build modern web infrastructure. Their support for remote MCP servers is mature and well-integrated, and their approach to authentication and durability aligns with how we think about the scale and security of these offerings.” — Utkarsh Sengar, VP of Engineering, Webflow</i></p><p>Learn more about Webflow’s MCP server <a href="https://mcp.webflow.com"><u>here</u></a>. </p>
    <div>
      <h2>Start building today </h2>
      <a href="#start-building-today">
        
      </a>
    </div>
    <p>If you’re looking to build a remote MCP server for your service, get started with our documentation, watch the tutorial below, or use the button below to get a starter remote MCP server deployed to production. Once the remote MCP server is deployed, it can be used from <a href="https://claude.ai/"><u>Claude</u></a>, Cloudflare’s <a href="https://playground.ai.cloudflare.com/"><u>AI playground</u></a>, or any remote MCP client. </p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-authless"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p><code></code></p><p>In addition, we launched a <a href="https://youtu.be/Pjc8cC8zVRY"><u>new YouTube video</u></a> walking you through building MCP servers, using two of our MCP templates.</p><p>If you have any questions or feedback for us, you can reach us via email at <a><u>1800-mcp@cloudflare.com</u></a>. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6WNNRZBcgfCv5xVM3MNYwI/39ebfda250c4524ebce323511bffc72e/BLOG-2811_4.png" />
          </figure><p></p> ]]></content:encoded>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Agents]]></category>
            <category><![CDATA[MCP]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <guid isPermaLink="false">6VjjFQfl3i9xgTfebvWEk4</guid>
            <dc:creator>Dina Kozlov</dc:creator>
        </item>
        <item>
            <title><![CDATA[Piecing together the Agent puzzle: MCP, authentication & authorization, and Durable Objects free tier]]></title>
            <link>https://blog.cloudflare.com/building-ai-agents-with-mcp-authn-authz-and-durable-objects/</link>
            <pubDate>Mon, 07 Apr 2025 13:10:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare delivers toolkit for AI agents with new Agents SDK support for MCP (Model Context Protocol) clients, authentication/authorization/hibernation for MCP servers and Durable Objects free tier.  ]]></description>
            <content:encoded><![CDATA[ <p>It’s not a secret that at Cloudflare <a href="https://blog.cloudflare.com/build-ai-agents-on-cloudflare/"><u>we are bullish</u></a> on the future of <a href="https://www.cloudflare.com/learning/ai/what-is-agentic-ai/">agents</a>. We’re excited about a future where AI can not only co-pilot alongside us, but where we can actually start to delegate entire tasks to AI. </p><p>While it hasn’t been too long since we <a href="https://blog.cloudflare.com/build-ai-agents-on-cloudflare/"><u>first announced</u></a> our Agents SDK to make it easier for developers to build agents, building towards an agentic future requires continuous delivery towards this goal. Today, we’re making several announcements to help accelerate agentic development, including:</p><ul><li><p><b>New Agents SDK capabilities:</b> Build remote MCP clients, with transport and authentication built-in, to allow AI agents to connect to external services. </p></li><li><p><a href="https://developers.cloudflare.com/agents/model-context-protocol/authorization/#3-bring-your-own-oauth-provider"><b><u>BYO Auth provider for MCP</u></b></a><b>:</b> Integrations with <a href="https://stytch.com/"><u>Stytch</u></a>, <a href="https://auth0.com/"><u>Auth0</u></a>, and <a href="https://workos.com/"><u>WorkOS</u></a> to add authentication and authorization to your remote MCP server. </p></li><li><p><a href="https://developers.cloudflare.com/agents/model-context-protocol/mcp-agent-api/#hibernation-support"><b><u>Hibernation for McpAgent</u></b></a><b>:</b> Automatically sleep stateful, remote MCP servers when inactive and wake them when needed. This allows you to maintain connections for long-running sessions while ensuring you’re not paying for idle time. </p></li><li><p><a href="https://developers.cloudflare.com/changelog/2025-04-07-durable-objects-free-tier"><b><u>Durable Objects free tier</u></b></a><b>:</b> We view <a href="https://www.cloudflare.com/developer-platform/products/durable-objects/">Durable Objects</a> as a key component for building agents, and if you’re using our Agents SDK, you need access to it. Until today, Durable Objects was only accessible as part of our paid plans, and today we’re excited to include it in our free tier.</p></li><li><p><a href="https://blog.cloudflare.com/workflows-ga-production-ready-durable-execution"><b><u>Workflows GA</u></b></a><b>:</b> Enables you to ship production-ready, long-running, multi-step actions in agents.</p></li><li><p><a href="https://blog.cloudflare.com/introducing-autorag-on-cloudflare"><b><u>AutoRAG</u></b></a><b>:</b> Helps you <a href="https://www.cloudflare.com/learning/ai/how-to-build-rag-pipelines/">integrate context-aware AI</a> into your applications, in just a few clicks</p></li><li><p><a href="https://agents.cloudflare.com"><b><u>agents.cloudflare.com</u></b></a><b>:</b> our new landing page for all things agents.</p></li></ul>
    <div>
      <h2>New MCP capabilities in Agents SDK</h2>
      <a href="#new-mcp-capabilities-in-agents-sdk">
        
      </a>
    </div>
    <p>AI agents can now connect to and interact with external services through MCP (<a href="https://www.cloudflare.com/learning/ai/what-is-model-context-protocol-mcp/"><u>Model Context Protocol</u></a>). We’ve updated the Agents SDK to allow you to build a remote MCP client into your AI agent, with all the components — authentication flows, tool discovery, and connection management — built-in for you.</p><p>This allows you to build agents that can:</p><ol><li><p>Prompt the end user to grant access to a 3rd party service (MCP server).</p></li><li><p>Use tools from these external services, acting on behalf of the end user.</p></li><li><p>Call MCP servers from Workflows, scheduled tasks, or any part of your agent.</p></li><li><p>Connect to multiple MCP servers and automatically discover new tools or capabilities presented by the 3rd party service.</p></li></ol>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/X3RvQHewsVwJhq3TVOD0w/bbc5690d2d687f7a390f91474b3eb385/1.png" />
          </figure><p>MCP (Model Context Protocol) — <a href="https://www.anthropic.com/news/model-context-protocol"><u>first introduced by Anthropic</u></a> — is quickly becoming the standard way for AI agents to interact with external services, with providers like OpenAI, Cursor, and Copilot adopting the protocol.</p><p>We <a href="https://blog.cloudflare.com/remote-model-context-protocol-servers-mcp/"><u>recently announced</u></a> support for <a href="https://developers.cloudflare.com/agents/guides/remote-mcp-server/"><u>building remote MCP servers</u></a> on Cloudflare, and added an <code>McpAgent</code> class to our Agents SDK that automatically handles the remote aspects of MCP: transport and authentication/authorization. Now, we’re excited to extend the same capabilities to agents acting as MCP clients.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3nxl3bIRTbfRzpdLhHF720/41bea06c9e48b7d356d11a6f254b76ef/2.png" />
          </figure><p>Want to see it in action? Use the button below to deploy a fully remote MCP client that can be used to connect to remote MCP servers.</p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/ai/tree/main/demos/mcp-client"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p>
    <div>
      <h2>AI Agents can now act as remote MCP clients, with transport and auth included</h2>
      <a href="#ai-agents-can-now-act-as-remote-mcp-clients-with-transport-and-auth-included">
        
      </a>
    </div>
    <p>AI agents need to connect to external services to access tools, data, and capabilities beyond their built-in knowledge. That means AI agents need to be able to act as remote MCP clients, so they can connect to remote MCP servers that are hosting these tools and capabilities. </p><p>We’ve added a new class, <code>MCPClientManager</code>, into the Agents SDK to give you all the tooling you need to allow your AI agent to make calls to external services via MCP. The <code>MCPClientManager</code> class automatically handles: </p><ul><li><p><b>Transport: </b>Connect to remote MCP servers over SSE and HTTP, with support for <a href="https://spec.modelcontextprotocol.io/specification/2025-03-26/basic/transports/#streamable-http"><u>Streamable HTTP</u></a> coming soon. </p></li><li><p><b>Connection management: </b>The client tracks the state of all connections and automatically reconnects if a connection is lost.</p></li><li><p><b>Capability discovery: </b>Automatically discovers all capabilities, tools, resources, and prompts presented by the MCP server.</p></li><li><p><b>Real-time updates</b>: When a server's tools, resources, or prompts change, the client automatically receives notifications and updates its internal state.</p></li><li><p><b>Namespacing: </b>When connecting to multiple MCP servers, all tools and resources are automatically namespaced to avoid conflicts.</p></li></ul>
    <div>
      <h3>Granting agents access to tools with built-in auth check for MCP Clients</h3>
      <a href="#granting-agents-access-to-tools-with-built-in-auth-check-for-mcp-clients">
        
      </a>
    </div>
    <p>We've integrated the complete OAuth authentication flow directly into the Agents SDK, so your AI agents can securely connect and authenticate to any remote MCP server without you having to build authentication flow from scratch.</p><p>This allows you to give users a secure way to log in and explicitly grant access to allow the agent to act on their behalf by automatically: </p><ul><li><p>Supporting the OAuth 2.1 protocol.</p></li><li><p>Redirecting users to the service’s login page.</p></li><li><p>Generating the code challenge and exchanging an authorization code for an access token.</p></li><li><p>Using the access token to make authenticated requests to the MCP server.</p></li></ul><p>Here is an example of an agent that can securely connect to MCP servers by initializing the client manager, adding the server, and handling the authentication callbacks:</p>
            <pre><code>async onStart(): Promise&lt;void&gt; {
  // initialize MCPClientManager which manages multiple MCP clients with optional auth
  this.mcp = new MCPClientManager("my-agent", "1.0.0", {
    baseCallbackUri: `${serverHost}/agents/${agentNamespace}/${this.name}/callback`,
    storage: this.ctx.storage,
  });
}

async addMcpServer(url: string): Promise&lt;string&gt; {
  // Add one MCP client to our MCPClientManager
  const { id, authUrl } = await this.mcp.connect(url);
  // Return authUrl to redirect the user to if the user is unauthorized
  return authUrl
}

async onRequest(req: Request): Promise&lt;void&gt; {
  // handle the auth callback after being finishing the MCP server auth flow
  if (this.mcp.isCallbackRequest(req)) {
    await this.mcp.handleCallbackRequest(req);
    return new Response("Authorized")
  }
  
  // ...
}</code></pre>
            <p>Connecting to multiple MCP servers and discovering what capabilities they offer</p><p>You can use the Agents SDK to connect an MCP client to multiple MCP servers simultaneously. This is particularly useful when you want your agent to access and interact with tools and resources served by different service providers. </p><p>The <code>MCPClientManager</code> class maintains connections to multiple MCP servers through the <code>mcpConnections</code> object, a dictionary that maps unique server names to their respective <code>MCPClientConnection</code> instances. </p><p>When you register a new server connection using <code>connect()</code>, the manager: </p><ol><li><p>Creates a new connection instance with server-specific authentication.</p></li><li><p>Initializes the connections and registers for server capability notifications.</p></li></ol>
            <pre><code>async onStart(): Promise&lt;void&gt; {
  // Connect to an image generation MCP server
  await this.mcp.connect("https://image-gen.example.com/mcp/sse");
  
  // Connect to a code analysis MCP server
  await this.mcp.connect("https://code-analysis.example.org/sse");
  
  // Now we can access tools with proper namespacing
  const allTools = this.mcp.listTools();
  console.log(`Total tools available: ${allTools.length}`);
}</code></pre>
            <p>Each connection manages its own authentication context, allowing one AI agent to authenticate to multiple servers simultaneously. In addition, <code>MCPClientManager</code> automatically handles namespacing to prevent collisions between tools with identical names from different servers. </p><p>For example, if both an “Image MCP Server” and “Code MCP Server” have a tool named “analyze”, they will both be independently callable without any naming conflicts.</p>
    <div>
      <h2>Use Stytch, Auth0, and WorkOS to bring authentication &amp; authorization to your MCP server </h2>
      <a href="#use-stytch-auth0-and-workos-to-bring-authentication-authorization-to-your-mcp-server">
        
      </a>
    </div>
    <p>With MCP, users will have a new way of interacting with your application, no longer relying on the dashboard or API as the entrypoint. Instead, the service will now be accessed by AI agents that are acting on a user’s behalf. To ensure users and agents can connect to your service securely, you’ll need to extend your existing authentication and authorization system to support these agentic interactions, implementing login flows, permissions scopes, consent forms, and access enforcement for your MCP server. </p><p>We’re adding integrations with <a href="https://stytch.com/"><u>Stytch</u></a>, <a href="https://auth0.com/"><u>Auth0</u></a>, and <a href="https://workos.com/"><u>WorkOS</u></a> to make it easier for anyone building an MCP server to configure authentication &amp; authorization for their MCP server. </p><p>You can leverage our MCP server integration with Stytch, Auth0, and WorkOS to: </p><ul><li><p>Allow users to authenticate to your MCP server through email, social logins, SSO (single sign-on), and MFA (multi-factor authentication).</p></li><li><p>Define scopes and permissions that directly map to your MCP tools.</p></li><li><p>Present users with a consent page corresponding with the requested permissions.</p></li></ul><p>Enforce the permissions so that agents can only invoke permitted tools. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6oYchjMwoMxwYxsqq4PObk/381937e89c249b87c1930295b407faf6/3.png" />
          </figure><p>Get started with the examples below by using the “Deploy to Cloudflare” button to deploy the demo MCP servers in your Cloudflare account. These demos include pre-configured authentication endpoints, consent flows, and permission models that you can tailor to fit your needs. Once you deploy the demo MCP servers, you can use the <a href="https://playground.ai.cloudflare.com/"><u>Workers AI playground</u></a>, a browser-based remote MCP client, to test out the end-to-end user flow. </p>
    <div>
      <h3>Stytch</h3>
      <a href="#stytch">
        
      </a>
    </div>
    <p><a href="https://stytch.com/docs/guides/connected-apps/mcp-servers"><u>Get started</u></a> with a remote MCP server that uses Stytch to allow users to sign in with email, Google login or enterprise SSO and authorize their AI agent to view and manage their company’s OKRs on their behalf. Stytch will handle restricting the scopes granted to the AI agent based on the user’s role and permissions within their organization. When authorizing the MCP Client, each user will see a consent page that outlines the permissions that the agent is requesting that they are able to grant based on their role.</p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/ai/tree/main/demos/mcp-stytch-b2b-okr-manager"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p>For more consumer use cases, deploy a remote MCP server for a To Do app that uses Stytch for authentication and MCP client authorization. Users can sign in with email and immediately access the To Do lists associated with their account, and grant access to any AI assistant to help them manage their tasks.</p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/ai/tree/main/demos/mcp-stytch-consumer-todo-list"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p>Regardless of use case, Stytch allows you to easily turn your application into an OAuth 2.0 identity provider and make your remote MCP server into a Relying Party so that it can easily inherit identity and permissions from your app. To learn more about how Stytch is enabling secure authentication to remote MCP servers, read their <a href="http://stytch.com/blog/remote-mcp-stytch-cloudflare"><u>blog post</u></a>.</p><blockquote><p><i>“One of the challenges of realizing the promise of AI agents is enabling those agents to securely and reliably access data from other platforms. Stytch Connected Apps is purpose-built for these agentic use cases, making it simple to turn your app into an OAuth 2.0 identity provider to enable secure access to remote MCP servers. By combining Cloudflare Workers with Stytch Connected Apps, we're removing the barriers for developers, enabling them to rapidly transition from AI proofs-of-concept to secure, deployed implementations.” — Julianna Lamb, Co-Founder &amp; CTO, Stytch.</i></p></blockquote>
    <div>
      <h3>Auth0</h3>
      <a href="#auth0">
        
      </a>
    </div>
    <p>Get started with a remote MCP server that uses Auth0 to authenticate users through email, social logins, or enterprise SSO to interact with their todos and personal data through AI agents. The MCP server securely connects to API endpoints on behalf of users, showing exactly which resources the agent will be able to access once it gets consent from the user. In this implementation, access tokens are automatically refreshed during long running interactions.</p><p>To set it up, first deploy the protected API endpoint: </p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-auth0/todos-api"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p>Then, deploy the MCP server that handles authentication through Auth0 and securely connects AI agents to your API endpoint. </p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-auth0/mcp-auth0-oidc"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><blockquote><p><i>"Cloudflare continues to empower developers building AI products with tools like AI Gateway, Vectorize, and Workers AI. The recent addition of Remote MCP servers further demonstrates that Cloudflare Workers and Durable Objects are a leading platform for deploying serverless AI. We’re very proud that Auth0 can help solve the authentication and authorization needs for these cutting-edge workloads." — Sandrino Di Mattia, Auth0 Sr. Director, Product Architecture.</i></p></blockquote>
    <div>
      <h3>WorkOS</h3>
      <a href="#workos">
        
      </a>
    </div>
    <p>Get started with a remote MCP server that uses WorkOS's AuthKit to authenticate users and manage the permissions granted to AI agents. In this example, the MCP server dynamically exposes tools based on the user's role and access rights. All authenticated users get access to the <code>add</code> tool, but only users who have been assigned the <code>image_generation</code> permission in WorkOS can grant the AI agent access to the image generation tool. This showcases how MCP servers can conditionally expose capabilities to AI agents based on the authenticated user's role and permission.</p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-authkit"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><blockquote><p><i>“MCP is becoming the standard for AI agent integration, but authentication and authorization are still major gaps for enterprise adoption. WorkOS Connect enables any application to become an OAuth 2.0 authorization server, allowing agents and MCP clients to securely obtain tokens for fine-grained permission authorization and resource access. With Cloudflare Workers, developers can rapidly deploy remote MCP servers with built-in OAuth and enterprise-grade access control. Together, WorkOS and Cloudflare make it easy to ship secure, enterprise-ready agent infrastructure.” — Michael Grinich, CEO of WorkOS.</i></p></blockquote>
    <div>
      <h2>Hibernate-able WebSockets: put AI agents to sleep when they’re not in use</h2>
      <a href="#hibernate-able-websockets-put-ai-agents-to-sleep-when-theyre-not-in-use">
        
      </a>
    </div>
    <p>Starting today, a new improvement is landing in the McpAgent class: support for the <a href="https://developers.cloudflare.com/durable-objects/best-practices/websockets/#websocket-hibernation-api"><u>WebSockets Hibernation API</u></a> that allows your MCP server to go to sleep when it’s not receiving requests and instantly wake up when it’s needed. That means that you now only pay for compute when your agent is actually working.</p><p>We <a href="https://blog.cloudflare.com/remote-model-context-protocol-servers-mcp/"><u>recently introduced</u></a> the <a href="https://developers.cloudflare.com/agents/model-context-protocol/tools/?cf_history_state=%7B%22guid%22%3A%22C255D9FF78CD46CDA4F76812EA68C350%22%2C%22historyId%22%3A11%2C%22targetId%22%3A%22DF3E523E0077ACCB6730439891CDD7D4%22%7D"><u>McpAgent class</u></a>, which allows developers to build remote MCP servers on Cloudflare by using Durable Objects to maintain stateful connections for every client session. We decided to build McpAgent to be stateful from the start, allowing developers to build servers that can remember context, user preferences, and conversation history. But maintaining client connections means that the session can remain active for a long time, even when it’s not being used. </p>
    <div>
      <h3>MCP Agents are hibernate-able by default</h3>
      <a href="#mcp-agents-are-hibernate-able-by-default">
        
      </a>
    </div>
    <p>You don’t need to change your code to take advantage of hibernation. With our latest SDK update, all McpAgent instances automatically include hibernation support, allowing your stateful MCP servers to sleep during inactive periods and wake up with their state preserved when needed. </p>
    <div>
      <h3>How it works</h3>
      <a href="#how-it-works">
        
      </a>
    </div>
    <p>When a request comes in on the Server-Sent Events endpoint, /sse, the Worker initializes a WebSocket connection to the appropriate Durable Object for the session and returns an SSE stream back to the client. All responses flow over this stream.</p><p>The implementation leverages the WebSocket Hibernation API within Durable Objects. When periods of inactivity occur, the Durable Object can be evicted from memory while keeping the WebSocket connection open. If the WebSocket later receives a message, the runtime recreates the Durable Object and delivers the message to the appropriate handler.</p>
    <div>
      <h2>Durable Objects on free tier</h2>
      <a href="#durable-objects-on-free-tier">
        
      </a>
    </div>
    <p>To help you build AI agents on Cloudflare, we’re making <a href="http://developers.cloudflare.com/durable-objects/what-are-durable-objects/"><u>Durable Objects</u></a> available on the free tier, so you can start with zero commitment. With Agents SDK, your AI agents deploy to Cloudflare running on Durable Objects.</p><p>Durable Objects offer compute alongside durable storage, that when combined with <a href="https://www.cloudflare.com/developer-platform/products/workers/">Workers</a>, unlock stateful, serverless applications. Each Durable Object is a stateful coordinator for handling client real-time interactions, making requests to external services like LLMs, and creating agentic “memory” through state persistence in <a href="https://blog.cloudflare.com/sqlite-in-durable-objects/"><u>zero-latency SQLite storage</u></a> — all tasks required in an AI agent. Durable Objects scale out to millions of agents effortlessly, with each agent created near the user interacting with their agent for fast performance, all managed by Cloudflare. </p><p>Zero-latency SQLite storage in Durable Objects was <a href="https://blog.cloudflare.com/sqlite-in-durable-objects/"><u>introduced in public beta</u></a> September 2024 for Birthday Week. Since then, we’ve focused on missing features and robustness compared to pre-existing key-value storage in Durable Objects. We are excited to make SQLite storage generally available, with a 10 GB SQLite database per Durable Object, and recommend SQLite storage for all new Durable Object classes. Durable Objects free tier can only access SQLite storage.</p><p><a href="https://www.cloudflare.com/plans/free/">Cloudflare’s free tier</a> allows you to build real-world applications. On the free plan, every Worker request can call a Durable Object. For <a href="https://developers.cloudflare.com/durable-objects/platform/pricing/"><u>usage-based pricing</u></a>, Durable Objects incur compute and storage usage with the following free tier limits.</p><div>
    <figure>
        <table>
            <colgroup>
                <col></col>
                <col></col>
                <col></col>
            </colgroup>
            <tbody>
                <tr>
                    <td> </td>
                    <td>
                        <p><span><span><strong>Workers Free</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>Workers Paid</strong></span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span>Compute: Requests</span></span></p>
                    </td>
                    <td>
                        <p><span><span>100,000 / day</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1 million / month included</span></span></p>
                        <p><span><span>+ $0.15 / million</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span>Compute: Duration</span></span></p>
                    </td>
                    <td>
                        <p><span><span>13,000 GB-s / day</span></span></p>
                    </td>
                    <td>
                        <p><span><span>400,000 GB-s / month  included </span></span></p>
                        <p><span><span>+ $12.50 / million GB-s</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span>Storage: Rows read</span></span></p>
                    </td>
                    <td>
                        <p><span><span>5 million / day</span></span></p>
                    </td>
                    <td>
                        <p><span><span>25 billion / month included</span></span></p>
                        <p><span><span>+ $0.001 / million </span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span>Storage: Rows written</span></span></p>
                    </td>
                    <td>
                        <p><span><span>100,000 / day</span></span></p>
                    </td>
                    <td>
                        <p><span><span>50 million / month included</span></span></p>
                        <p><span><span>+ $1.00 / million</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span>Storage: SQL stored data</span></span></p>
                    </td>
                    <td>
                        <p><span><span>5 GB (total)</span></span></p>
                    </td>
                    <td>
                        <p><span><span>5 GB-month included</span></span></p>
                        <p><span><span>+ $0.20 / GB-month</span></span></p>
                    </td>
                </tr>
            </tbody>
        </table>
    </figure>
</div>
    <div>
      <h3>Find us at agents.cloudflare.com</h3>
      <a href="#find-us-at-agents-cloudflare-com">
        
      </a>
    </div>
    <p>We realize this is a lot of information to take in, but don’t worry. Whether you’re new to agents as a whole, or looking to learn more about how Cloudflare can help you build agents, today we launched a new site to help get you started — <a href="https://agents.cloudflare.com"><u>agents.cloudflare.com</u></a>. </p><p>Let us know what you build!</p> ]]></content:encoded>
            <category><![CDATA[Developer Week]]></category>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Agents]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Model Context Protocol]]></category>
            <category><![CDATA[MCP]]></category>
            <guid isPermaLink="false">6lQQWDqELUkL4c1y13VL0V</guid>
            <dc:creator>Rita Kozlov</dc:creator>
            <dc:creator>Dina Kozlov</dc:creator>
            <dc:creator>Vy Ton</dc:creator>
        </item>
        <item>
            <title><![CDATA[Build and deploy Remote Model Context Protocol (MCP) servers to Cloudflare]]></title>
            <link>https://blog.cloudflare.com/remote-model-context-protocol-servers-mcp/</link>
            <pubDate>Tue, 25 Mar 2025 13:59:00 GMT</pubDate>
            <description><![CDATA[ You can now build and deploy remote MCP servers to Cloudflare, and we handle the hard parts of building remote MCP servers for you. ]]></description>
            <content:encoded><![CDATA[ <p>It feels like almost everyone building AI applications and <a href="https://www.cloudflare.com/learning/ai/what-is-agentic-ai/">agents</a> is talking about the <a href="https://www.cloudflare.com/learning/ai/what-is-model-context-protocol-mcp/">Model Context Protocol</a> (MCP), as well as building MCP servers that you install and run locally on your own computer.</p><p>You can now <a href="https://developers.cloudflare.com/agents/guides/remote-mcp-server/"><u>build and deploy remote MCP servers</u></a> to Cloudflare. We’ve added four things to Cloudflare that handle the hard parts of building remote MCP servers for you:</p><ol><li><p><a href="https://developers.cloudflare.com/agents/model-context-protocol/authorization"><u>workers-oauth-provider</u></a> — an <a href="https://www.cloudflare.com/learning/access-management/what-is-oauth/"><u>OAuth</u></a> Provider that makes authorization easy</p></li><li><p><a href="https://developers.cloudflare.com/agents/model-context-protocol/tools/"><u>McpAgent</u></a> — a class built into the <a href="https://developers.cloudflare.com/agents/"><u>Cloudflare Agents SDK</u></a> that handles remote transport</p></li><li><p><a href="https://developers.cloudflare.com/agents/guides/test-remote-mcp-server/"><u>mcp-remote</u></a> — an adapter that lets MCP clients that otherwise only support local connections work with remote MCP servers</p></li><li><p><a href="https://playground.ai.cloudflare.com/"><u>AI playground as a remote MCP client</u></a> — a chat interface that allows you to connect to remote MCP servers, with the authentication check included</p></li></ol><p>The button below, or the <a href="https://developers.cloudflare.com/agents/guides/remote-mcp-server/"><u>developer docs</u></a>, will get you up and running in production with <a href="https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-server"><u>this example MCP server</u></a> in less than two minutes:</p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-server"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p>Unlike the local MCP servers you may have previously used, remote MCP servers are accessible on the Internet. People simply sign in and grant permissions to MCP clients using familiar authorization flows. We think this is going to be a massive deal — connecting coding agents to MCP servers has blown developers’ minds over the past few months, and remote MCP servers have the same potential to open up similar new ways of working with LLMs and agents to a much wider audience, including more everyday consumer use cases.</p>
    <div>
      <h2>From local to remote — bringing MCP to the masses</h2>
      <a href="#from-local-to-remote-bringing-mcp-to-the-masses">
        
      </a>
    </div>
    <p>MCP is quickly becoming the common protocol that enables LLMs to go beyond <a href="https://www.cloudflare.com/learning/ai/inference-vs-training/"><u>inference</u></a> and <a href="https://developers.cloudflare.com/reference-architecture/diagrams/ai/ai-rag/"><u>RAG</u></a>, and take actions that require access beyond the AI application itself (like sending an email, deploying a code change, publishing blog posts, you name it). It enables AI agents (MCP clients) to access tools and resources from external services (MCP servers).</p><p>To date, MCP has been limited to running locally on your own machine — if you want to access a tool on the web using MCP, it’s up to you to set up the server locally. You haven’t been able to use MCP from web-based interfaces or mobile apps, and there hasn’t been a way to let people authenticate and grant the MCP client permission. Effectively, MCP servers haven’t yet been brought online.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1EyiTXzB4FvBs2zEfzuNTp/5ce4b55457348e9ab83e6d9cf35d8c3c/image7.png" />
          </figure><p>Support for <a href="https://spec.modelcontextprotocol.io/specification/draft/basic/transports/#streamable-http"><u>remote MCP connections</u></a> changes this. It creates the opportunity to reach a wider audience of Internet users who aren’t going to install and run MCP servers locally for use with desktop apps. Remote MCP support is like the transition from desktop software to web-based software. People expect to continue tasks across devices and to login and have things just work. Local MCP is great for developers, but remote MCP connections are the missing piece to reach everyone on the Internet.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7bI7rJtLh89jmZaibSgiLl/e426f93616a8210d80b979c47d89dc75/image4.png" />
          </figure>
    <div>
      <h2>Making authentication and authorization just work with MCP</h2>
      <a href="#making-authentication-and-authorization-just-work-with-mcp">
        
      </a>
    </div>
    <p>Beyond just changing the transport layer — from <a href="https://modelcontextprotocol.io/docs/concepts/transports#standard-input%2Foutput-stdio"><u>stdio</u></a> to <a href="https://github.com/modelcontextprotocol/specification/pull/206"><u>streamable HTTP</u></a> — when you build a remote MCP server that uses information from the end user’s account, you need <a href="https://www.cloudflare.com/learning/access-management/authn-vs-authz/"><u>authentication and authorization</u></a>. You need a way to allow users to login and prove who they are (authentication) and a way for users to control what the AI agent will be able to access when using a service (authorization).</p><p>MCP does this with <a href="https://oauth.net/2/"><u>OAuth</u></a>, which has been the standard protocol that allows users to grant applications to access their information or services, without sharing passwords. Here, the MCP Server itself acts as the OAuth Provider. However, OAuth with MCP is hard to implement yourself, so when you build MCP servers on Cloudflare we provide it for you.</p>
    <div>
      <h3>workers-oauth-provider — an OAuth 2.1 Provider library for Cloudflare Workers</h3>
      <a href="#workers-oauth-provider-an-oauth-2-1-provider-library-for-cloudflare-workers">
        
      </a>
    </div>
    <p>When you <a href="https://developers.cloudflare.com/agents/guides/remote-mcp-server/"><u>deploy an MCP Server</u></a> to Cloudflare, your Worker acts as an OAuth Provider, using <a href="https://github.com/cloudflare/workers-oauth-provider"><u>workers-oauth-provider</u></a>, a new TypeScript library that wraps your Worker’s code, adding authorization to API endpoints, including (but not limited to) MCP server API endpoints.</p><p>Your MCP server will receive the already-authenticated user details as a parameter. You don’t need to perform any checks of your own, or directly manage tokens. You can still fully control how you authenticate users: from what UI they see when they log in, to which provider they use to log in. You can choose to bring your own third-party authentication and authorization providers like Google or GitHub, or integrate with your own.</p><p>The complete <a href="https://spec.modelcontextprotocol.io/specification/draft/basic/authorization/"><u>MCP OAuth flow</u></a> looks like this:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/VTPBfZ4hRPdq2TWE5VOjS/00abc97e4beedf59a4101957612fd503/image5.png" />
          </figure><p>Here, your MCP server acts as both an OAuth client to your upstream service, <i>and</i> as an OAuth server (also referred to as an OAuth “provider”) to MCP clients. You can use any upstream authentication flow you want, but workers-oauth-provider guarantees that your MCP server is <a href="https://spec.modelcontextprotocol.io/specification/draft/basic/authorization"><u>spec-compliant</u></a> and able to work with the full range of client apps &amp; websites. This includes support for Dynamic Client Registration (<a href="https://datatracker.ietf.org/doc/html/rfc7591"><u>RFC 7591</u></a>) and Authorization Server Metadata (<a href="https://datatracker.ietf.org/doc/html/rfc8414"><u>RFC 8414</u></a>).</p>
    <div>
      <h3>A simple, pluggable interface for OAuth</h3>
      <a href="#a-simple-pluggable-interface-for-oauth">
        
      </a>
    </div>
    <p>When you build an MCP server with Cloudflare Workers, you provide an instance of the OAuth Provider paths to your authorization, token, and client registration endpoints, along with <a href="https://developers.cloudflare.com/workers/runtime-apis/handlers/fetch/"><u>handlers</u></a> for your MCP Server, and for auth:</p>
            <pre><code>import OAuthProvider from "@cloudflare/workers-oauth-provider";
import MyMCPServer from "./my-mcp-server";
import MyAuthHandler from "./auth-handler";

export default new OAuthProvider({
  apiRoute: "/sse", // MCP clients connect to your server at this route
  apiHandler: MyMCPServer.mount('/sse'), // Your MCP Server implmentation
  defaultHandler: MyAuthHandler, // Your authentication implementation
  authorizeEndpoint: "/authorize",
  tokenEndpoint: "/token",
  clientRegistrationEndpoint: "/register",
});</code></pre>
            <p>This abstraction lets you easily plug in your own authentication. Take a look at <a href="https://github.com/cloudflare/ai/blob/main/demos/remote-mcp-github-oauth/src/github-handler.ts"><u>this example</u></a> that uses GitHub as the identity provider for an MCP server, in less than 100 lines of code, by implementing /callback and /authorize routes.</p>
    <div>
      <h3>Why do MCP servers issue their own tokens?</h3>
      <a href="#why-do-mcp-servers-issue-their-own-tokens">
        
      </a>
    </div>
    <p>You may have noticed in the authorization diagram above, and in the <a href="https://spec.modelcontextprotocol.io/specification/draft/basic/authorization"><u>authorization section</u></a> of the MCP spec, that the MCP server issues its own token to the MCP client.</p><p>Instead of passing the token it receives from the upstream provider directly to the MCP client, your Worker stores an encrypted access token in <a href="https://developers.cloudflare.com/kv/"><u>Workers KV</u></a>. It then issues its own token to the client. As shown in the <a href="https://github.com/cloudflare/ai/blob/main/demos/remote-mcp-github-oauth/src/github-handler.ts"><u>GitHub example</u></a> above, this is handled on your behalf by the workers-oauth-provider — your code never directly handles writing this token, preventing mistakes. You can see this in the following code snippet from the <a href="https://github.com/cloudflare/ai/blob/main/demos/remote-mcp-github-oauth/src/github-handler.ts"><u>GitHub example</u></a> above:</p>
            <pre><code>  // When you call completeAuthorization, the accessToken you pass to it
  // is encrypted and stored, and never exposed to the MCP client
  // A new, separate token is generated and provided to the client at the /token endpoint
  const { redirectTo } = await c.env.OAUTH_PROVIDER.completeAuthorization({
    request: oauthReqInfo,
    userId: login,
    metadata: { label: name },
    scope: oauthReqInfo.scope,
    props: {
      accessToken,  // Stored encrypted, never sent to MCP client
    },
  })

  return Response.redirect(redirectTo)</code></pre>
            <p>On the surface, this indirection might sound more complicated. Why does it work this way?</p><p>By issuing its own token, MCP Servers can restrict access and enforce more granular controls than the upstream provider. If a token you issue to an MCP client is compromised, the attacker only gets the limited permissions you've explicitly granted through your MCP tools, not the full access of the original token.</p><p>Let’s say your MCP server requests that the user authorize permission to read emails from their Gmail account, using the <a href="https://developers.google.com/identity/protocols/oauth2/scopes#gmail"><u>gmail.readonly scope</u></a>. The tool that the MCP server exposes is more narrow, and allows reading travel booking notifications from a limited set of senders, to handle a question like “What’s the check-out time for my hotel room tomorrow?” You can enforce this constraint in your MCP server, and if the token you issue to the MCP client is compromised, because the token is to your MCP server — and not the raw token to the upstream provider (Google) — an attacker cannot use it to read arbitrary emails. They can only call the tools your MCP server provides. OWASP calls out <a href="https://genai.owasp.org/llmrisk/llm062025-excessive-agency/"><u>“Excessive Agency”</u></a> as one of the top risk factors for building AI applications, and by issuing its own token to the client and enforcing constraints, your MCP server can limit tools access to only what the client needs.</p><p>Or building off the earlier GitHub example, you can enforce that only a specific user is allowed to access a particular tool. In the example below, only users that are part of an allowlist can see or call the generateImage tool, that uses <a href="https://developers.cloudflare.com/workers-ai/"><u>Workers AI</u></a> to generate an image based on a prompt:</p>
            <pre><code>import { McpAgent } from "agents/mcp";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";

const USER_ALLOWLIST = ["geelen"];

export class MyMCP extends McpAgent&lt;Props, Env&gt; {
  server = new McpServer({
    name: "Github OAuth Proxy Demo",
    version: "1.0.0",
  });

  async init() {
    // Dynamically add tools based on the user's identity
    if (USER_ALLOWLIST.has(this.props.login)) {
      this.server.tool(
        'generateImage',
        'Generate an image using the flux-1-schnell model.',
        {
          prompt: z.string().describe('A text description of the image you want to generate.')
        },
        async ({ prompt }) =&gt; {
          const response = await this.env.AI.run('@cf/black-forest-labs/flux-1-schnell', { 
            prompt, 
            steps: 8 
          })
          return {
            content: [{ type: 'image', data: response.image!, mimeType: 'image/jpeg' }],
          }
        }
      )
    }
  }
}
</code></pre>
            
    <div>
      <h2>Introducing McpAgent: remote transport support that works today, and will work with the revision to the MCP spec</h2>
      <a href="#introducing-mcpagent-remote-transport-support-that-works-today-and-will-work-with-the-revision-to-the-mcp-spec">
        
      </a>
    </div>
    <p>The next step to opening up MCP beyond your local machine is to open up a remote transport layer for communication. MCP servers you run on your local machine just communicate over <a href="https://modelcontextprotocol.io/docs/concepts/transports#standard-input%2Foutput-stdio"><u>stdio</u></a>, but for an MCP server to be callable over the Internet, it must implement <a href="https://spec.modelcontextprotocol.io/specification/draft/basic/transports/#http-with-sse"><u>remote transport</u></a>.</p><p>The <a href="https://github.com/cloudflare/agents/blob/2f82f51784f4e27292249747b5fbeeef94305552/packages/agents/src/mcp.ts"><u>McpAgent</u></a> class we introduced today as part of our <a href="https://github.com/cloudflare/agents"><u>Agents SDK</u></a> handles this for you, using <a href="https://developers.cloudflare.com/durable-objects/"><u>Durable Objects</u></a> behind the scenes to hold a persistent connection open, so that the MCP client can send <a href="https://modelcontextprotocol.io/docs/concepts/transports#server-sent-events-sse"><u>server-sent events (SSE)</u></a> to your MCP server. You don’t have to write code to deal with transport or serialization yourself. A minimal MCP server in 15 lines of code can look like this:</p>
            <pre><code>import { McpAgent } from "agents/mcp";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";

export class MyMCP extends McpAgent {
  server = new McpServer({
    name: "Demo",
    version: "1.0.0",
  });
  async init() {
    this.server.tool("add", { a: z.number(), b: z.number() }, async ({ a, b }) =&gt; ({
      content: [{ type: "text", text: String(a + b) }],
    }));
  }
}</code></pre>
            <p>After much <a href="https://github.com/modelcontextprotocol/specification/discussions/102"><u>discussion</u></a>, remote transport in the MCP spec is changing, with <a href="https://github.com/modelcontextprotocol/specification/pull/206"><u>Streamable HTTP replacing HTTP+SSE</u></a> This allows for stateless, pure HTTP connections to MCP servers, with an option to upgrade to SSE, and removes the need for the MCP client to send messages to a separate endpoint than the one it first connects to. The McpAgent class will change with it and just work with streamable HTTP, so that you don’t have to start over to support the revision to how transport works.</p><p>This applies to future iterations of transport as well. Today, the vast majority of MCP servers only expose tools, which are simple <a href="https://en.wikipedia.org/wiki/Remote_procedure_call"><u>remote procedure call (RPC)</u></a> methods that can be provided by a stateless transport. But more complex human-in-the-loop and agent-to-agent interactions will need <a href="https://modelcontextprotocol.io/docs/concepts/prompts"><u>prompts</u></a> and <a href="https://modelcontextprotocol.io/docs/concepts/sampling"><u>sampling</u></a>. We expect these types of chatty, two-way interactions will need to be real-time, which will be challenging to do well without a bidirectional transport layer. When that time comes, Cloudflare, the <a href="https://developers.cloudflare.com/agents/"><u>Agents SDK</u></a>, and Durable Objects all natively support <a href="https://developers.cloudflare.com/durable-objects/best-practices/websockets/"><u>WebSockets</u></a>, which enable full-duplex, bidirectional real-time communication. </p>
    <div>
      <h2>Stateful, agentic MCP servers</h2>
      <a href="#stateful-agentic-mcp-servers">
        
      </a>
    </div>
    <p>When you build MCP servers on Cloudflare, each MCP client session is backed by a Durable Object, via the <a href="https://developers.cloudflare.com/agents/"><u>Agents SDK</u></a>. This means each session can manage and persist its own state, <a href="https://developers.cloudflare.com/agents/api-reference/store-and-sync-state/"><u>backed by its own SQL database</u></a>.</p><p>This opens the door to building stateful MCP servers. Rather than just acting as a stateless layer between a client app and an external API, MCP servers on Cloudflare can themselves be stateful applications — games, a shopping cart plus checkout flow, a <a href="https://github.com/modelcontextprotocol/servers/tree/main/src/memory"><u>persistent knowledge graph</u></a>, or anything else you can dream up. When you build on Cloudflare, MCP servers can be much more than a layer in front of your REST API.</p><p>To understand the basics of how this works, let’s look at a minimal example that increments a counter:</p>
            <pre><code>import { McpAgent } from "agents/mcp";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";

type State = { counter: number }

export class MyMCP extends McpAgent&lt;Env, State, {}&gt; {
  server = new McpServer({
    name: "Demo",
    version: "1.0.0",
  });

  initialState: State = {
    counter: 1,
  }

  async init() {
    this.server.resource(`counter`, `mcp://resource/counter`, (uri) =&gt; {
      return {
        contents: [{ uri: uri.href, text: String(this.state.counter) }],
      }
    })

    this.server.tool('add', 'Add to the counter, stored in the MCP', { a: z.number() }, async ({ a }) =&gt; {
      this.setState({ ...this.state, counter: this.state.counter + a })

      return {
        content: [{ type: 'text', text: String(`Added ${a}, total is now ${this.state.counter}`) }],
      }
    })
  }

  onStateUpdate(state: State) {
    console.log({ stateUpdate: state })
  }

}</code></pre>
            <p>For a given session, the MCP server above will remember the state of the counter across tool calls.</p><p>From within an MCP server, you can use Cloudflare’s whole developer platform, and have your MCP server <a href="https://developers.cloudflare.com/agents/api-reference/browse-the-web/"><u>spin up its own web browser</u></a>, <a href="https://developers.cloudflare.com/agents/api-reference/run-workflows/"><u>trigger a Workflow</u></a>, <a href="https://developers.cloudflare.com/agents/api-reference/using-ai-models/"><u>call AI models</u></a>, and more. We’re excited to see the MCP ecosystem evolve into more advanced use cases.</p>
    <div>
      <h2>Connect to remote MCP servers from MCP clients that today only support local MCP</h2>
      <a href="#connect-to-remote-mcp-servers-from-mcp-clients-that-today-only-support-local-mcp">
        
      </a>
    </div>
    <p>Cloudflare is supporting remote MCP early — before the most prominent MCP client applications support remote, authenticated MCP, and before other platforms support remote MCP. We’re doing this to give you a head start building for where MCP is headed.</p><p>But if you build a remote MCP server today, this presents a challenge — how can people start using your MCP server if there aren’t MCP clients that support remote MCP?</p><p>We have two new tools that allow you to test your remote MCP server and simulate how users will interact with it in the future:</p><p>We updated the <a href="https://playground.ai.cloudflare.com/"><u>Workers AI Playground</u></a> to be a fully remote MCP client that allows you to connect to any remote MCP server with built-in authentication support. This online chat interface lets you immediately test your remote MCP servers without having to install anything on your device. Instead, just enter the remote MCP server’s URL (e.g. https://remote-server.example.com/sse) and click Connect.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4N64nJHJiQygmMdSK7clIs/c0bf8c64f1607674f81be10c3871a64b/image1.png" />
          </figure><p>Once you click Connect, you’ll go through the authentication flow (if you set one up) and after, you will be able to interact with the MCP server tools directly from the chat interface.</p><p>If you prefer to use a client like Claude Desktop or Cursor that already supports MCP but doesn’t yet handle remote connections with authentication, you can use <a href="https://www.npmjs.com/package/mcp-remote"><u>mcp-remote</u></a>. mcp-remote is an adapter that  lets MCP clients that otherwise only support local connections to work with remote MCP servers. This gives you and your users the ability to preview what interactions with your remote MCP server will be like from the tools you’re already using today, without having to wait for the client to support remote MCP natively. </p><p>We’ve <a href="https://developers.cloudflare.com/agents/guides/test-remote-mcp-server/"><u>published a guide</u></a> on how to use mcp-remote with popular MCP clients including Claude Desktop, Cursor, and Windsurf. In Claude Desktop, you add the following to your configuration file:</p>
            <pre><code>{
  "mcpServers": {
    "remote-example": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://remote-server.example.com/sse"
      ]
    }
  }
}</code></pre>
            
    <div>
      <h2>1800-mcp@cloudflare.com — start building remote MCP servers today</h2>
      <a href="#1800-mcp-cloudflare-com-start-building-remote-mcp-servers-today">
        
      </a>
    </div>
    <p>Remote Model Context Protocol (MCP) is coming! When client apps support remote MCP servers, the audience of people who can use them opens up from just us, developers, to the rest of the population — who may never even know what MCP is or stands for. </p><p>Building a remote MCP server is the way to bring your service into the AI assistants and tools that millions of people use. We’re excited to see many of the biggest companies on the Internet are busy building MCP servers right now, and we are curious about the businesses that pop-up in an agent-first, MCP-native way.</p><p>On Cloudflare, <a href="https://developers.cloudflare.com/agents/guides/remote-mcp-server/"><u>you can start building today</u></a>. We’re ready for you, and ready to help build with you. Email us at <a><u>1800-mcp@cloudflare.com</u></a>, and we’ll help get you going. There’s lots more to come with MCP, and we’re excited to see what you build.</p> ]]></content:encoded>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[MCP]]></category>
            <category><![CDATA[Agents]]></category>
            <guid isPermaLink="false">4e3J8mxEIN24iNKfw9ToEH</guid>
            <dc:creator>Brendan Irvine-Broque</dc:creator>
            <dc:creator>Dina Kozlov</dc:creator>
            <dc:creator>Glen Maddern</dc:creator>
        </item>
    </channel>
</rss>