|
2 | 2 | title: 'Agent-Native Devframe' |
3 | 3 | navigation: |
4 | 4 | icon: i-lucide-bot |
5 | | -description: 'Devframe exposes its browser-side API (RPC functions, resources, shared state) to coding agents over MCP, opt-in per function.' |
| 5 | +description: 'Devframe exposes its API (RPC functions, resources, shared state) to agents, over MCP on the node side and WebMCP on the browser side, opt-in per function.' |
6 | 6 | --- |
7 | 7 |
|
8 | | -Devframe exposes its browser-side API (RPC functions, resources, shared state) to coding agents over MCP, opt-in per function. |
| 8 | +Devframe exposes its API (RPC functions, resources, shared state) to agents, over MCP on the node side and [WebMCP](#browser-side-tools-over-webmcp) on the browser side, opt-in per function. |
9 | 9 |
|
10 | 10 | ## How it works |
11 | 11 |
|
12 | | -Three pieces: the **`agent` field** on `defineRpcFunction`, **`ctx.agent`** (non-RPC tools + resources), and the **MCP adapter** (`devframe/adapters/mcp`) serving an [MCP](https://modelcontextprotocol.io) server. |
| 12 | +Three pieces: the **`agent` field** on `defineRpcFunction`, **`ctx.agent`** (non-RPC tools + resources), and the **MCP adapter** (`devframe/adapters/mcp`) serving an [MCP](https://modelcontextprotocol.io) server. The same `agent` field on a *client* RPC function surfaces it [over WebMCP](#browser-side-tools-over-webmcp) instead. |
13 | 13 |
|
14 | 14 | ## Exposing an RPC function |
15 | 15 |
|
@@ -137,6 +137,29 @@ In `claude_desktop_config.json`: |
137 | 137 |
|
138 | 138 | Restart; tools appear in the drawer, resources as `devframe://resource/<id>` / `devframe://state/<key>` URIs. |
139 | 139 |
|
| 140 | +## Browser-side tools over WebMCP |
| 141 | + |
| 142 | +The same `agent` signature works on the browser side: a client RPC function (a function the node side calls on the browser, registered on `rpc.client` or through a scoped `client.scope('my-plugin').rpc.register(...)`) carrying an `agent` field is mirrored onto the page's [WebMCP](https://github.com/webmachinelearning/webmcp) model context (`document.modelContext` / `navigator.modelContext`) as a callable tool, so in-page and browser-integrated agents can drive browser-side functionality directly. Wire names, `arg0`/`arg1`/… input schemas, and safety annotations match the MCP projection above. |
| 143 | + |
| 144 | +```ts |
| 145 | +const rpc = await connectDevframe() |
| 146 | + |
| 147 | +rpc.client.register({ |
| 148 | + name: 'my-plugin:highlight-node', |
| 149 | + type: 'action', |
| 150 | + jsonSerializable: true, |
| 151 | + agent: { |
| 152 | + description: 'Highlight a node in the open inspector view. Use it to point the user at a finding.', |
| 153 | + }, |
| 154 | + handler: (id: string) => highlightNode(id), |
| 155 | +}) |
| 156 | +``` |
| 157 | + |
| 158 | +`connectDevframe()` wires this on its own when the browser provides a model context; `webmcp: false` keeps the browser side off the WebMCP surface. `registerWebMcpTools(collector)` (from `devframe/client`) applies the same projection to a hand-built collector and returns a dispose that unregisters every tool. |
| 159 | + |
| 160 | +> [!WARNING] |
| 161 | +> WebMCP is an experimental proposal; `registerWebMcpTools` tracks the current draft (`AbortSignal`-based unregistration) and earlier handle-returning drafts, but the browser API may still change. |
| 162 | +
|
140 | 163 | ## Writing descriptions agents act on |
141 | 164 |
|
142 | 165 | Describe *when* to use a tool, not just its return: |
|
0 commit comments