You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit b53a08d
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: docs/adapters/mcp.md
+27Lines changed: 27 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -46,4 +46,31 @@ defineDevframe({
46
46
})
47
47
```
48
48
49
+
### Hosted bridges
50
+
51
+
Both hosted bridges forward the same option to their side-car dev server and advertise the endpoint (with its port) in the `__connection.json` they serve:
`createMcpFetchHandler(ctx, options)` returns the endpoint as a web-standard `Request → Response` handler plus a `dispose()` for session teardown — mount it on any fetch-shaped server (a Next.js App Router route, a custom Node server). The h3 `mountMcpHttp` used by the dev server is a thin wrapper over it.
> Command "`{id}`" declares agent exposure but has no handler
10
+
11
+
## Cause
12
+
13
+
`ctx.commands.register(command)` or a command handle `update()` received a command carrying an `agent` field but no `handler`. Agent-exposed commands are projected into `ctx.agent` as callable tools (reaching MCP clients through the devframe MCP adapter), so they must be executable server-side — a handler-less command is a palette group and cannot run.
14
+
15
+
## Example
16
+
17
+
```ts
18
+
// ✗ Bad: group-only command opting into the agent surface
19
+
ctx.commands.register({
20
+
id: 'my-tool:group',
21
+
title: 'My tool',
22
+
agent: { description: 'Run my tool.' },
23
+
children: [/* … */],
24
+
})
25
+
26
+
// ✓ Good: the executable child carries the agent field
27
+
ctx.commands.register({
28
+
id: 'my-tool:group',
29
+
title: 'My tool',
30
+
children: [
31
+
{
32
+
id: 'my-tool:reload',
33
+
title: 'Reload',
34
+
agent: { description: 'Reload my tool\'s state. Call after changing its config.' },
35
+
handler: () =>reload(),
36
+
},
37
+
],
38
+
})
39
+
```
40
+
41
+
## Fix
42
+
43
+
- Add a `handler` to the command carrying the `agent` field.
44
+
- Or move the `agent` field to an executable child command.
45
+
46
+
## Source
47
+
48
+
-[`packages/hub/src/node/host-commands.ts`](https://github.com/devframes/devframe/blob/main/packages/hub/src/node/host-commands.ts) — `DevframeCommandsHost.register()` and command handle `update()` validate agent exposure across the command tree.
Copy file name to clipboardExpand all lines: docs/guide/agent-native.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -79,6 +79,8 @@ ctx.agent.registerResource({
79
79
80
80
Every `ctx.rpc.sharedState` key is also automatically exposed to MCP as `devframe://state/<key>`. Pass `exposeSharedState: false` (or a filter function) to `createMcpServer` to opt out.
81
81
82
+
Shared state is additionally reachable through the built-in **`read_state` tool** — call it without arguments for the key list, with a `key` for that value — since many MCP clients only consume tools. It honors the same `exposeSharedState` filter as the resource projection.
Copy file name to clipboardExpand all lines: docs/guide/hub.md
+18Lines changed: 18 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -30,6 +30,24 @@ Every hub context auto-registers these RPC functions so framework kits don't rei
30
30
31
31
Host-specific capabilities (open in editor, reveal in finder, …) ship as kit-registered RPC functions rather than as part of the hub surface.
32
32
33
+
## Commands as agent tools
34
+
35
+
A server command opts into the [agent surface](./agent-native) with an `agent` field — the same default-deny convention as `defineRpcFunction`. Agent-flagged, handler-bearing commands are projected into `ctx.agent` as callable tools and reach MCP clients through the devframe MCP adapter:
36
+
37
+
```ts
38
+
ctx.commands.register({
39
+
id: 'app:build',
40
+
title: 'Run build',
41
+
agent: {
42
+
description: 'Run the production build. Call after config or dependency changes to verify the app still builds.',
`args` takes positional valibot schemas (a single `v.object(...)` is unwrapped into the tool's input object); omit it for a zero-argument tool. `safety` defaults to `'action'`. `when` clauses evaluate client-side only and are not enforced for agent calls — opt in a `when`-gated command only if running it outside its UI context is safe.
50
+
33
51
## Cross-iframe dock activation
34
52
35
53
The viewer's active dock is client-local state — which dock is on screen lives in the shell page, not in shared state. A mounted devframe runs in its own iframe on its own RPC client, so it can't reach that selection directly. `hub:docks:activate` bridges the gap: any connected client asks the hub to switch the active dock, and the hub relays the request to the shell.
description: 'Read this devtool\'s live shared state. Call without arguments to list the available keys, then with a key to get that value as JSON. Safe to call freely.',
173
+
inputSchema: {
174
+
type: 'object',
175
+
properties: {
176
+
key: {
177
+
type: 'string',
178
+
description: 'A shared-state key from the key list. Omit to list all keys.',
0 commit comments