# Three New Hooks Let You Make WebSocket Connections "View-Only"!

Hi there, I'm Shiichan! Today I found a big update to Cloudflare's Agents SDK, so let me walk you through it. There's a lot packed in, so let's go step by step.

## What was announced?

The [Cloudflare Changelog](https://developers.cloudflare.com/changelog/post/2026-02-09-agents-sdk-v0.4.0/) announced the release of Agents SDK v0.4.0. This update has four main pillars:

- Read-only WebSocket connections
- MCP protocol and security improvements
- Migration to x402 payment protocol v2
- A new method for customizing the MCP OAuth provider

If you build apps on top of the `Agent` class, none of these changes are ones you'll want to skip, so let's go through them one by one.

## The story so far

Until now, every WebSocket client connected to an Agent had the same level of access. If any one of them called `setState()` or hit a `@callable()` method, the Agent's state would get modified right then and there. Even someone who just wanted to watch a dashboard ended up holding the same power to accidentally mutate state.

The MCP side had a similar gap: OAuth relied entirely on the default provider, so if you wanted an authentication strategy other than dynamic client registration (like pre-registered client credentials or mTLS), there was no way to customize it. The x402 payment protocol was also still on its older package structure.

## What changes

The headline feature is read-only connections. Three new hooks, `shouldConnectionBeReadonly`, `setConnectionReadonly`, and `isConnectionReadonly`, let you assign "view-only" access on a per-connection basis. A connection flagged as readonly can't call `setState()` or any `@callable()` method, and that flag survives hibernation too. This is a great fit for dashboards or spectator views where clients only need to watch, not change, agent state.

On the MCP OAuth side, a new `createMcpOAuthProvider` method has been added to the `Agent` class. Override it in your subclass and you can swap in your own authentication logic instead of the default OAuth provider, enabling strategies like pre-registered client credentials or mTLS-based auth.

## Dive Deep

Here's roughly how you'd implement read-only connections:

```js
class MyAgent extends Agent {
  shouldConnectionBeReadonly(connection) {
    return connection.url.includes("spectator");
  }
}
```

You can write whatever logic you like here, for example marking a connection readonly whenever its URL contains "spectator".

A custom OAuth provider gets wired in like this:

```js
class MyAgent extends Agent {
  createMcpOAuthProvider(callbackUrl) {
    return new MyCustomOAuthProvider(this.ctx.storage, this.name, callbackUrl);
  }
}
```

There are more MCP security improvements too:

- MCP SDK has moved to 1.26.0, and stateless MCP servers now need to create a fresh `McpServer` instance per request (sharing an instance via a global variable is no longer allowed)
- `addMcpServer` gained a `callbackPath` option, which avoids the problem of the default callback URL leaking the instance name

The x402 payment protocol has also moved to v2:

- The package split from `x402` into `@x402/core` and `@x402/evm`
- The `PaymentRequirements` type changed, with amounts now represented by an `amount` field
- `X402ClientConfig.account` now expects a `ClientEvmSigner`
- Network identifiers support both legacy names like `base-sepolia` and CAIP-2 format like `eip155:84532` (CAIP-2 is recommended)
- `X402ClientConfig.network` is now optional; if you omit it, the client picks automatically from the available payment requirements

On top of that, this release also fixes a crash when routing with `basePath` in `useAgent` and `AgentClient`, delegates CORS handling to partyserver's native support, and adds an `onStateUpdateError` callback for handling rejected state updates.

## Wrap-up

- Three new hooks let you create read-only WebSocket connections: `shouldConnectionBeReadonly`, `setConnectionReadonly`, and `isConnectionReadonly`
- `createMcpOAuthProvider` lets you customize MCP OAuth authentication for things like pre-registered credentials or mTLS
- MCP security got a boost from the MCP SDK 1.26.0 migration and callback URL improvements
- The x402 payment protocol has moved to a v2 setup built on `@x402/core` and `@x402/evm`

If you're building agent apps on Cloudflare's Agents SDK, wiring up MCP tools, or using x402 for payments, this is one worth checking out directly.
