@agent-native/core 0.20.9 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/action.d.ts +61 -0
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js +14 -0
- package/dist/action.js.map +1 -1
- package/dist/agent/production-agent.d.ts +4 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +19 -7
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/types.d.ts +2 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/cli/code-agent-executor.d.ts.map +1 -1
- package/dist/cli/code-agent-executor.js +1 -0
- package/dist/cli/code-agent-executor.js.map +1 -1
- package/dist/cli/connect.d.ts +18 -3
- package/dist/cli/connect.d.ts.map +1 -1
- package/dist/cli/connect.js +619 -19
- package/dist/cli/connect.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +6 -2
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +13 -6
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/NewWorkspaceAppFlow.js +1 -1
- package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +13 -8
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/agent-sidebar-state.d.ts +2 -0
- package/dist/client/agent-sidebar-state.d.ts.map +1 -1
- package/dist/client/agent-sidebar-state.js +40 -0
- package/dist/client/agent-sidebar-state.js.map +1 -1
- package/dist/client/code-agent-chat-adapter.js +1 -0
- package/dist/client/code-agent-chat-adapter.js.map +1 -1
- package/dist/client/conversation/AgentConversation.d.ts.map +1 -1
- package/dist/client/conversation/AgentConversation.js +3 -2
- package/dist/client/conversation/AgentConversation.js.map +1 -1
- package/dist/client/conversation/code-agent-transcript.js +1 -0
- package/dist/client/conversation/code-agent-transcript.js.map +1 -1
- package/dist/client/conversation/types.d.ts +2 -0
- package/dist/client/conversation/types.d.ts.map +1 -1
- package/dist/client/conversation/types.js.map +1 -1
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/mcp-apps/McpAppRenderer.d.ts +10 -0
- package/dist/client/mcp-apps/McpAppRenderer.d.ts.map +1 -0
- package/dist/client/mcp-apps/McpAppRenderer.js +301 -0
- package/dist/client/mcp-apps/McpAppRenderer.js.map +1 -0
- package/dist/client/sse-event-processor.d.ts +3 -0
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +2 -0
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/client/use-db-sync.d.ts +5 -5
- package/dist/client/use-db-sync.d.ts.map +1 -1
- package/dist/client/use-db-sync.js +15 -5
- package/dist/client/use-db-sync.js.map +1 -1
- package/dist/client/use-db-sync.spec.d.ts +2 -0
- package/dist/client/use-db-sync.spec.d.ts.map +1 -0
- package/dist/client/use-db-sync.spec.js +80 -0
- package/dist/client/use-db-sync.spec.js.map +1 -0
- package/dist/code-agents/transcript-normalizer.d.ts +2 -0
- package/dist/code-agents/transcript-normalizer.d.ts.map +1 -1
- package/dist/code-agents/transcript-normalizer.js +17 -0
- package/dist/code-agents/transcript-normalizer.js.map +1 -1
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +29 -21
- package/dist/db/client.js.map +1 -1
- package/dist/extensions/actions.d.ts.map +1 -1
- package/dist/extensions/actions.js +62 -3
- package/dist/extensions/actions.js.map +1 -1
- package/dist/extensions/content-patch.d.ts +71 -0
- package/dist/extensions/content-patch.d.ts.map +1 -0
- package/dist/extensions/content-patch.js +251 -0
- package/dist/extensions/content-patch.js.map +1 -0
- package/dist/extensions/routes.js +6 -1
- package/dist/extensions/routes.js.map +1 -1
- package/dist/extensions/store.d.ts +4 -4
- package/dist/extensions/store.d.ts.map +1 -1
- package/dist/extensions/store.js +14 -18
- package/dist/extensions/store.js.map +1 -1
- package/dist/index.browser.d.ts +1 -1
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +1 -1
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/build-server.d.ts +3 -0
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js +207 -8
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/mcp/oauth-route.d.ts +22 -0
- package/dist/mcp/oauth-route.d.ts.map +1 -0
- package/dist/mcp/oauth-route.js +618 -0
- package/dist/mcp/oauth-route.js.map +1 -0
- package/dist/mcp/oauth-store.d.ts +89 -0
- package/dist/mcp/oauth-store.d.ts.map +1 -0
- package/dist/mcp/oauth-store.js +391 -0
- package/dist/mcp/oauth-store.js.map +1 -0
- package/dist/mcp/oauth-token.d.ts +28 -0
- package/dist/mcp/oauth-token.d.ts.map +1 -0
- package/dist/mcp/oauth-token.js +83 -0
- package/dist/mcp/oauth-token.js.map +1 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +5 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/stdio.d.ts +2 -2
- package/dist/mcp/stdio.d.ts.map +1 -1
- package/dist/mcp/stdio.js +26 -8
- package/dist/mcp/stdio.js.map +1 -1
- package/dist/mcp-client/app-result.d.ts +40 -0
- package/dist/mcp-client/app-result.d.ts.map +1 -0
- package/dist/mcp-client/app-result.js +19 -0
- package/dist/mcp-client/app-result.js.map +1 -0
- package/dist/mcp-client/index.d.ts +5 -2
- package/dist/mcp-client/index.d.ts.map +1 -1
- package/dist/mcp-client/index.js +201 -25
- package/dist/mcp-client/index.js.map +1 -1
- package/dist/mcp-client/manager.d.ts +16 -0
- package/dist/mcp-client/manager.d.ts.map +1 -1
- package/dist/mcp-client/manager.js +58 -1
- package/dist/mcp-client/manager.js.map +1 -1
- package/dist/mcp-client/routes.d.ts +4 -1
- package/dist/mcp-client/routes.d.ts.map +1 -1
- package/dist/mcp-client/routes.js +159 -0
- package/dist/mcp-client/routes.js.map +1 -1
- package/dist/scripts/dev/shell.d.ts.map +1 -1
- package/dist/scripts/dev/shell.js +24 -1
- package/dist/scripts/dev/shell.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +3 -2
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +14 -8
- package/dist/server/auth.js.map +1 -1
- package/dist/server/builder-browser.d.ts +6 -0
- package/dist/server/builder-browser.d.ts.map +1 -1
- package/dist/server/builder-browser.js +15 -0
- package/dist/server/builder-browser.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts +5 -4
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +17 -2
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/styles/agent-conversation.css +53 -0
- package/dist/templates/default/.agents/skills/actions/SKILL.md +193 -72
- package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +88 -38
- package/dist/templates/default/AGENTS.md +3 -3
- package/dist/templates/default/actions/hello.ts +13 -20
- package/dist/templates/default/actions/navigate.ts +19 -51
- package/dist/templates/default/actions/view-screen.ts +16 -33
- package/dist/templates/default/app/hooks/use-navigation-state.ts +13 -3
- package/dist/templates/default/app/lib/tab-id.ts +1 -0
- package/dist/templates/default/app/root.tsx +2 -1
- package/dist/templates/default/app/routes/_index.tsx +11 -0
- package/dist/templates/default/package.json +2 -1
- package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +9 -1
- package/dist/templates/workspace-core/AGENTS.md +8 -0
- package/dist/templates/workspace-root/AGENTS.md +7 -0
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +2 -2
- package/dist/vite/client.js.map +1 -1
- package/docs/content/actions.md +26 -3
- package/docs/content/authentication.md +16 -1
- package/docs/content/client.md +11 -8
- package/docs/content/context-awareness.md +2 -3
- package/docs/content/creating-templates.md +2 -2
- package/docs/content/external-agents.md +106 -19
- package/docs/content/faq.md +2 -2
- package/docs/content/key-concepts.md +31 -23
- package/docs/content/mcp-clients.md +1 -1
- package/docs/content/mcp-protocol.md +65 -27
- package/docs/content/template-starter.md +3 -3
- package/docs/content/what-is-agent-native.md +4 -2
- package/package.json +3 -1
- package/src/templates/default/.agents/skills/actions/SKILL.md +193 -72
- package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +88 -38
- package/src/templates/default/AGENTS.md +3 -3
- package/src/templates/default/actions/hello.ts +13 -20
- package/src/templates/default/actions/navigate.ts +19 -51
- package/src/templates/default/actions/view-screen.ts +16 -33
- package/src/templates/default/app/hooks/use-navigation-state.ts +13 -3
- package/src/templates/default/app/lib/tab-id.ts +1 -0
- package/src/templates/default/app/root.tsx +2 -1
- package/src/templates/default/app/routes/_index.tsx +11 -0
- package/src/templates/default/package.json +2 -1
- package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +9 -1
- package/src/templates/workspace-core/AGENTS.md +8 -0
- package/src/templates/workspace-root/AGENTS.md +7 -0
- package/dist/templates/default/server/routes/api/hello.get.ts +0 -5
- package/dist/templates/default/shared/api.ts +0 -6
- package/src/templates/default/server/routes/api/hello.get.ts +0 -5
- package/src/templates/default/shared/api.ts +0 -6
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "External Agents: Claude
|
|
3
|
-
description: "Connect
|
|
4
|
-
search: "Claude Code Codex Cursor Claude Cowork agent-native connect
|
|
2
|
+
title: "External Agents: Claude, ChatGPT, Codex, Cursor, Cowork"
|
|
3
|
+
description: "Connect Claude, ChatGPT, Codex, Cursor, Claude Cowork, or any MCP-compatible host to a hosted agent-native app — then round-trip artifacts back into the running UI with MCP Apps and deep links."
|
|
4
|
+
search: "Claude ChatGPT Claude Code Codex Cursor Claude Cowork MCP Apps agent-native connect local agent tools external agents"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# External Agents
|
|
8
8
|
|
|
9
|
-
An agent-native app is reachable by any
|
|
9
|
+
An agent-native app is reachable by any MCP-compatible host — Claude, Claude Desktop, Claude Code, ChatGPT custom MCP apps, Codex, Cursor, Claude Cowork, VS Code GitHub Copilot, Goose, Postman, MCPJam, and future clients that implement the standard. External agents are great at producing artifacts (a draft, an event, a dashboard) but they often live in a terminal or another app. Without a bridge, the user gets a wall of JSON and has to go find the thing.
|
|
10
10
|
|
|
11
|
-
The external-agent bridge closes the loop. First you connect your own agent to a **hosted** app — one command,
|
|
11
|
+
The external-agent bridge closes the loop. First you connect your own agent to a **hosted** app — one command writes the local client config, using standard remote MCP OAuth for clients that support it and a browser-authorized bearer fallback for older clients. Then the agent does the work over MCP and hands the user either an inline **MCP App** UI in compatible hosts or a single **"Open in <app> →"** link that opens the real app focused on exactly what was produced. It reuses the existing `navigate` / `application_state` contract the UI already drains every 2s (see [Context Awareness](/docs/context-awareness)) — there is no second navigation mechanism.
|
|
12
12
|
|
|
13
13
|
## Connect Claude Code, Codex, Cursor, and Cowork {#connect}
|
|
14
14
|
|
|
@@ -26,15 +26,19 @@ Or run the same command through npm without installing anything globally:
|
|
|
26
26
|
npx @agent-native/core connect https://mail.agent-native.com
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
The command asks which local agent clients should receive MCP config. All clients are preselected the first time; after you choose, the selection is saved to `~/.agent-native/connect.json` so the next run can reuse it with Enter, or you can edit the checked items.
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
| ----------------------------- | ----------------------------------------------------------- |
|
|
33
|
-
| Claude Code / Claude Code CLI | `.mcp.json` or `~/.claude.json`, depending on `--scope` |
|
|
34
|
-
| Codex | `~/.codex/config.toml` under `[mcp_servers.<app>]` |
|
|
35
|
-
| Claude Cowork | `~/.cowork/mcp.json` using the Claude Code MCP server shape |
|
|
31
|
+
For Claude Code and Claude Code CLI, `connect` writes a standard remote HTTP MCP entry with no static headers. Restart Claude Code, run `/mcp`, and choose **Authenticate**; Claude completes the OAuth flow and stores its own tokens. For Codex and Claude Cowork, `connect` uses the compatibility device-code flow: it opens your browser at the app, you click **Authorize** once, and the command writes a scoped bearer-token entry. If you choose a mix of clients, it does both.
|
|
36
32
|
|
|
37
|
-
|
|
33
|
+
If you previously connected Claude Code through the old bearer-token flow, just run the same `agent-native connect ... --client claude-code` command again. The CLI replaces the legacy `Authorization` headers with the URL-only OAuth entry and tells you to re-authenticate from `/mcp`.
|
|
34
|
+
|
|
35
|
+
| Local client | Config written by `connect` | Auth flow |
|
|
36
|
+
| ----------------------------- | ------------------------------------------------------- | ----------------------------------------------- |
|
|
37
|
+
| Claude Code / Claude Code CLI | `.mcp.json` or `~/.claude.json`, depending on `--scope` | Standard remote MCP OAuth in Claude's `/mcp` UI |
|
|
38
|
+
| Codex | `~/.codex/config.toml` under `[mcp_servers.<app>]` | Browser-authorized bearer fallback |
|
|
39
|
+
| Claude Cowork | `~/.cowork/mcp.json` using the Claude Code MCP shape | Browser-authorized bearer fallback |
|
|
40
|
+
|
|
41
|
+
There is no token to copy and no local server to run. Restart the agent client after connecting so it picks up the new MCP server; OAuth-native clients may then prompt you to authenticate from their MCP UI.
|
|
38
42
|
|
|
39
43
|
Use `--client codex` (or `--client claude-code`, `--client claude-code-cli`, `--client cowork`, `--client all`) to skip the picker for scripts or one-off installs.
|
|
40
44
|
|
|
@@ -46,7 +50,7 @@ npx @agent-native/core connect --all
|
|
|
46
50
|
|
|
47
51
|
The client picker appears once and the same selection is used for every hosted app.
|
|
48
52
|
|
|
49
|
-
The connection is **per-user, scoped, and revocable**.
|
|
53
|
+
The connection is **per-user, scoped, and revocable**. In the OAuth path, the host stores the tokens after `/mcp` authentication; in the fallback path, the browser session you authorized with is the identity the agent acts as. Nothing exposes the deployment's shared secret.
|
|
50
54
|
|
|
51
55
|
### No-CLI alternative {#no-cli}
|
|
52
56
|
|
|
@@ -57,7 +61,7 @@ If you'd rather not run a command, open the app in your browser and use its **Co
|
|
|
57
61
|
{
|
|
58
62
|
"mcpServers": {
|
|
59
63
|
"mail": {
|
|
60
|
-
"type": "
|
|
64
|
+
"type": "http",
|
|
61
65
|
"url": "https://mail.agent-native.com/_agent-native/mcp",
|
|
62
66
|
"headers": { "Authorization": "Bearer <minted-token>" },
|
|
63
67
|
},
|
|
@@ -67,7 +71,34 @@ If you'd rather not run a command, open the app in your browser and use its **Co
|
|
|
67
71
|
|
|
68
72
|
Restart the agent client after connecting so it picks up the new MCP server.
|
|
69
73
|
|
|
70
|
-
Use this manual block for MCP clients that
|
|
74
|
+
Use this manual bearer block for MCP clients that cannot complete the standard remote MCP OAuth flow, or for one-off debugging when you explicitly want to paste a token.
|
|
75
|
+
|
|
76
|
+
### Standard remote MCP OAuth {#standard-oauth}
|
|
77
|
+
|
|
78
|
+
Hosted agent-native apps also support the standard remote MCP OAuth flow. For clients that implement MCP OAuth, add the remote HTTP server URL with no static headers:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
claude mcp add --transport http agent-native-mail \
|
|
82
|
+
https://mail.agent-native.com/_agent-native/mcp
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
This is the same URL-only entry that `agent-native connect https://mail.agent-native.com --client claude-code` writes for you. Then run `/mcp` in Claude Code and choose **Authenticate**. The client discovers auth from the MCP server's `401 WWW-Authenticate` challenge, fetches `/.well-known/oauth-protected-resource` and `/.well-known/oauth-authorization-server`, dynamically registers a public OAuth client, opens the app's authorization page, and stores the resulting token securely. ChatGPT developer-mode connectors use the same server URL:
|
|
86
|
+
|
|
87
|
+
```text
|
|
88
|
+
https://mail.agent-native.com/_agent-native/mcp
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The OAuth flow is authorization-code + PKCE with refresh-token rotation. Access tokens are audience-bound to the exact MCP resource URL and carry the signed user/org identity, so tool calls, `resources/read`, and MCP App iframe-initiated `tools/call` all run through the same `runWithRequestContext` tenant scoping as the existing connect-minted JWT path. The iframe never receives raw OAuth tokens; the host mediates calls through the authenticated MCP connection.
|
|
92
|
+
|
|
93
|
+
Current scopes are:
|
|
94
|
+
|
|
95
|
+
| Scope | Allows |
|
|
96
|
+
| ----------- | ------------------------------------------------------------------------- |
|
|
97
|
+
| `mcp:read` | read-only MCP actions and ordinary tool/resource discovery |
|
|
98
|
+
| `mcp:write` | mutating actions and the `ask-agent` meta-tool |
|
|
99
|
+
| `mcp:apps` | MCP Apps resource listing/reading and inline UI rendering where supported |
|
|
100
|
+
|
|
101
|
+
When the client requests no explicit scope, the app grants all three so the connector behaves like the browser-authorized Connect flow. Keep the bearer-token Connect page and `agent-native connect --token <token>` fallback around for local dev, fallback hosts, and clients where you need a ready-to-paste config block.
|
|
71
102
|
|
|
72
103
|
## What you can do once connected {#what-you-can-do}
|
|
73
104
|
|
|
@@ -82,6 +113,14 @@ Claude Code calls: manage-draft(to: "john@example.com", subject: "Q3 Report", bo
|
|
|
82
113
|
|
|
83
114
|
Click that link and Mail opens with the draft restored — focused exactly where you, the logged-in user, are. The agent never had to know your session; it just produced the artifact.
|
|
84
115
|
|
|
116
|
+
### MCP Apps compatibility {#mcp-apps-compatibility}
|
|
117
|
+
|
|
118
|
+
Agent-native apps also speak the official MCP Apps extension. When any action declares `mcpApp`, the server advertises `extensions["io.modelcontextprotocol/ui"]`, includes both `_meta.ui.resourceUri` and the legacy-compatible `_meta["ui/resourceUri"]` in `tools/list`, and serves the HTML UI through `resources/list` + `resources/read` as `text/html;profile=mcp-app`.
|
|
119
|
+
|
|
120
|
+
That makes the same app surface available to every compatible host rather than building per-client shims. The current official MCP Apps client list includes Claude, Claude Desktop, VS Code GitHub Copilot, Goose, Postman, MCPJam, ChatGPT, and Cursor; host support still varies by plan, release channel, and client version, so check the [MCP extension support matrix](https://modelcontextprotocol.io/extensions/client-matrix). ChatGPT custom MCP apps are available through developer mode for Business and Enterprise/Edu workspaces on ChatGPT web; see OpenAI's [developer mode and MCP apps](https://help.openai.com/en/articles/12584461-developer-mode-and-full-mcp-apps-in-chatgpt-beta) notes.
|
|
121
|
+
|
|
122
|
+
Claude Code and other CLI-first clients still receive the same resources and metadata when they support MCP Apps, but the deep link remains the reliable fallback when a host chooses not to render an iframe. In practice, every agent-native app should be authored with both: MCP Apps for inline review/edit in capable hosts, and `link` for universal round-tripping back to the full app.
|
|
123
|
+
|
|
85
124
|
### Generic cross-app verbs {#cross-app}
|
|
86
125
|
|
|
87
126
|
On top of the per-action tools the MCP server exposes a stable verb set, so an external agent has a predictable surface without guessing per-app action names:
|
|
@@ -101,7 +140,7 @@ On top of the per-action tools the MCP server exposes a stable verb set, so an e
|
|
|
101
140
|
Every allow-listed template that produces or lists a navigable resource ships a `link` builder, and the ingest-heavy ones ship a GET + `publicAgent` action so a connected agent can pull live state:
|
|
102
141
|
|
|
103
142
|
- **Mail** — `manage-draft` returns a `compose`-encoded deep link; clicking it opens the inbox with the draft restored into a `compose-<id>`. `list-emails` / `search-emails` point at a filtered inbox view.
|
|
104
|
-
- **Calendar** — `create-event` returns `buildDeepLink({ app: "calendar", view: "calendar", params: { eventId, date } })`; the click lands on the calendar with that event focused on its date.
|
|
143
|
+
- **Calendar** — `manage-event-draft` returns a `calendarDraft` + `eventDraftId` deep link; clicking it opens a visible draft placeholder on the calendar with the native event editor for review/send. `create-event` still returns `buildDeepLink({ app: "calendar", view: "calendar", params: { eventId, date } })`; the click lands on the calendar with that event focused on its date.
|
|
105
144
|
- **Analytics** — `update-dashboard` / `save-analysis` return `buildDeepLink({ app: "analytics", view: "adhoc", params: { dashboardId } })`; the agent builds a dashboard over MCP and hands back "Open dashboard in Analytics".
|
|
106
145
|
- **Design** — `get-design-snapshot` is the GET + `publicAgent` ingest action: it returns the **live** Yjs file contents plus the resolved tweak values so the agent continues from the tuned design, not the original tokens. `apply-tweaks` round-trips back with an "Open design" editor link.
|
|
107
146
|
- **Content** — `pull-document` is the GET + `publicAgent` ingest action: it flushes any open live collaborative session to SQL first so the external agent ingests exactly what the user sees, then surfaces a deep link to the document.
|
|
@@ -142,7 +181,33 @@ export default defineAction({
|
|
|
142
181
|
});
|
|
143
182
|
```
|
|
144
183
|
|
|
145
|
-
List/search actions point at a record-focused view the same way — e.g. calendar's `create-event` returns `buildDeepLink({ app: "calendar", view: "calendar", params: { eventId, date } })` with label `"Open event in Calendar"`.
|
|
184
|
+
List/search actions point at a record-focused view the same way — e.g. calendar's `create-event` returns `buildDeepLink({ app: "calendar", view: "calendar", params: { eventId, date } })` with label `"Open event in Calendar"`. Calendar draft actions use the same pattern: `manage-event-draft` returns `buildDeepLink({ app: "calendar", view: "calendar", to: "/", params: { eventDraftId, calendarDraft, date } })` with label `"Review invite in Calendar"`, so external agents can hand back a direct draft-review link without creating the event first.
|
|
185
|
+
|
|
186
|
+
## Authoring: optional MCP Apps UI {#mcp-apps}
|
|
187
|
+
|
|
188
|
+
For hosts that support the MCP Apps extension, an action can also advertise an inline HTML UI resource with `mcpApp`. This is a progressive enhancement for flows where the external agent should hand the user an interactive surface instead of only text — for example reviewing an email draft, editing a calendar invite, or choosing between generated dashboard variants.
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
export default defineAction({
|
|
192
|
+
// ...description, schema, run, link...
|
|
193
|
+
mcpApp: {
|
|
194
|
+
resource: {
|
|
195
|
+
title: "Review draft",
|
|
196
|
+
description: "Review and send the generated email draft.",
|
|
197
|
+
html: ({ actionName, requestOrigin }) => `<!doctype html>
|
|
198
|
+
<html><body data-action="${actionName}" data-origin="${requestOrigin}">
|
|
199
|
+
<main id="app"></main>
|
|
200
|
+
</body></html>`,
|
|
201
|
+
csp: { connectDomains: ["https://mail.agent-native.com"] },
|
|
202
|
+
prefersBorder: true,
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
The MCP server advertises extension `io.modelcontextprotocol/ui`, adds `_meta.ui.resourceUri` plus `_meta["ui/resourceUri"]` to `tools/list`, and exposes the HTML through `resources/list` + `resources/read` using MIME `text/html;profile=mcp-app`. The stdio proxy forwards those resource handlers from the live app, so desktop and CLI clients see the same resources as HTTP clients.
|
|
209
|
+
|
|
210
|
+
Keep the existing `link` builder even when adding `mcpApp`. CLI-only clients, older hosts, and any host that does not render MCP Apps will ignore the UI metadata and still need the `"Open in … →"` link. Treat `mcpApp.resource.html` like `link`: synchronous, deterministic, and self-contained; declare external origins in `csp`. Use the full app deep link for heavyweight authenticated workflows that do not fit cleanly in an embedded iframe.
|
|
146
211
|
|
|
147
212
|
### The `link` contract {#link-contract}
|
|
148
213
|
|
|
@@ -226,7 +291,7 @@ You can also write the MCP client config by hand against any deployed endpoint w
|
|
|
226
291
|
{
|
|
227
292
|
"mcpServers": {
|
|
228
293
|
"analytics": {
|
|
229
|
-
"type": "
|
|
294
|
+
"type": "http",
|
|
230
295
|
"url": "https://analytics.agent-native.com/_agent-native/mcp",
|
|
231
296
|
"headers": { "Authorization": "Bearer <ACCESS_TOKEN-or-JWT>" },
|
|
232
297
|
},
|
|
@@ -240,9 +305,31 @@ This is the unmanaged equivalent of what `connect` writes for you. See [MCP Prot
|
|
|
240
305
|
|
|
241
306
|
In plain local dev (`NODE_ENV=development` and `AGENT_MODE !== "production"`) the MCP `tools/list` deliberately exposes only the generic builtins plus actions with `publicAgent.requiresAuth === false` — the per-app ingest actions (`requiresAuth: true`) and mutating actions (no `publicAgent`) are filtered out (`filterPublicAgentActions`). The full per-app surface appears when the request is authenticated as a real caller: a deployed / `AGENT_MODE=production` app, or a local app reached through `connect` / `agent-native mcp install` (which provisions a token so the caller has an identity). So if `tools/list` looks sparse, you are hitting an unauthenticated dev endpoint — connect (or present a token) rather than assuming the action is missing.
|
|
242
307
|
|
|
308
|
+
### Switching first-party apps between prod and dev {#dev-switch}
|
|
309
|
+
|
|
310
|
+
When you already have first-party hosted apps connected and want to test local framework changes through `pnpm dev:lazy`, use the developer switcher:
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
pnpm dev:lazy -- --apps mail,calendar,analytics
|
|
314
|
+
|
|
315
|
+
agent-native connect dev --apps mail,calendar,analytics --client codex
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
`connect dev` rewrites the same stable MCP server names (`agent-native-mail`, `agent-native-calendar`, etc.) to the local dev-lazy gateway, so tool names do not change. It backs up the current production entries in `~/.agent-native/connect-profiles.json` before writing dev entries. The default gateway is `http://127.0.0.1:8080`; use `--gateway <url>` or `--port <n>` if your gateway moved.
|
|
319
|
+
|
|
320
|
+
Switch back with:
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
agent-native connect prod --apps mail,calendar,analytics --client codex
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
If `connect dev` cannot infer your local owner identity from an existing connected JWT, pass `--owner-email you@example.com`; this keeps local dev tools on the full authenticated MCP surface instead of the sparse unauthenticated dev surface.
|
|
327
|
+
|
|
243
328
|
## How it works & security {#how-it-works}
|
|
244
329
|
|
|
245
|
-
The
|
|
330
|
+
The standard OAuth path never exposes tokens to MCP Apps: the host stores OAuth access/refresh tokens and mediates tool calls and `resources/read` over the authenticated MCP connection. Embedded iframes receive app data and tool results, not bearer secrets.
|
|
331
|
+
|
|
332
|
+
The fallback hosted `connect` flow never copies the deployment's shared secret. Instead:
|
|
246
333
|
|
|
247
334
|
- A logged-in browser session mints a **per-user, scoped, revocable** token — an `A2A_SECRET`-signed JWT carrying the caller's `sub` + `org_domain` and a unique `jti`, so every tool run stays tenant-scoped via `runWithRequestContext`.
|
|
248
335
|
- The existing `/_agent-native/mcp` endpoint accepts that token like any other bearer (see [MCP Protocol](/docs/mcp-protocol)) — no new endpoint, no new transport.
|
package/docs/content/faq.md
CHANGED
|
@@ -121,9 +121,9 @@ Anywhere. The server runs on Nitro, which compiles to any deployment target: Nod
|
|
|
121
121
|
|
|
122
122
|
## Architecture {#architecture}
|
|
123
123
|
|
|
124
|
-
### Why polling instead of WebSockets? {#why-polling-not-websockets}
|
|
124
|
+
### Why SSE plus polling instead of WebSockets? {#why-polling-not-websockets}
|
|
125
125
|
|
|
126
|
-
Polling works in every deployment environment — including serverless, edge, and container platforms where persistent connections
|
|
126
|
+
SSE gives same-process writes an immediate path to the browser without requiring a bidirectional socket server. Polling remains the fallback because it works in every deployment environment — including serverless, edge, and container platforms where persistent connections may not be available. The fallback uses a lightweight version counter; when changes are detected, React Query caches are invalidated and components re-render.
|
|
127
127
|
|
|
128
128
|
### Why can't the UI call an LLM directly? {#why-no-inline-llm-calls}
|
|
129
129
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Key Concepts"
|
|
3
|
-
description: "How agent-native apps work: the four-area checklist, SQL database, agent chat bridge, polling sync, actions, context awareness, and portability."
|
|
3
|
+
description: "How agent-native apps work: the four-area checklist, SQL database, agent chat bridge, polling sync, actions, external-agent entry points, context awareness, and portability."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Key Concepts
|
|
@@ -37,7 +37,7 @@ Six rules govern the architecture:
|
|
|
37
37
|
1. **Data lives in SQL** — all app state lives in the database via Drizzle ORM
|
|
38
38
|
2. **All AI goes through the agent** — no inline LLM calls
|
|
39
39
|
3. **Actions for agent operations** — complex work runs as actions
|
|
40
|
-
4. **
|
|
40
|
+
4. **Live sync keeps the UI in sync** — database changes stream over SSE with polling as the universal fallback
|
|
41
41
|
5. **The agent can modify code** — the app evolves as you use it
|
|
42
42
|
6. **Application state in SQL** — ephemeral UI state lives in the database, readable by both agent and UI
|
|
43
43
|
|
|
@@ -45,10 +45,10 @@ Six rules govern the architecture:
|
|
|
45
45
|
|
|
46
46
|
Adopting the framework is valuable mostly because of what you stop having to build. The moment your app follows the six rules, you inherit:
|
|
47
47
|
|
|
48
|
-
- **One action =
|
|
48
|
+
- **One action = every surface.** Every action defined with `defineAction()` is simultaneously an agent tool, a typesafe frontend mutation (`useActionMutation("name")`), an HTTP endpoint at `/_agent-native/actions/:name`, a CLI command, an MCP tool for external clients, and an A2A tool for other agent-native apps. Optional `link` and `mcpApp` metadata add deep links and MCP Apps UI without a second implementation.
|
|
49
49
|
- **A full workspace per user.** Skills, shared `LEARNINGS.md`, personal `memory/MEMORY.md`, `AGENTS.md`, custom sub-agents, scheduled jobs, connected MCP servers — all SQL-backed, no dev-box required. See [Workspace](/docs/workspace).
|
|
50
50
|
- **Drop-in React components.** `<AgentPanel />` and `<AgentSidebar />` render chat + workspace anywhere in your app. See [Drop-in Agent](/docs/drop-in-agent).
|
|
51
|
-
- **Live sync between agent and UI.**
|
|
51
|
+
- **Live sync between agent and UI.** Same-process writes stream immediately over `/_agent-native/events`; a lightweight poll keeps serverless, cron, and cross-process writes convergent. Mutating actions invalidate action-backed queries automatically, so agent-created records appear without a manual refresh. See [Live Sync](#polling-sync) below.
|
|
52
52
|
- **Auth, orgs, RBAC.** Better Auth with orgs/members/roles is wired in for every template. See [Authentication](/docs/authentication).
|
|
53
53
|
- **Context awareness.** The agent always knows what the user is looking at through the `navigation` app-state key. See [Context Awareness](/docs/context-awareness).
|
|
54
54
|
- **MCP client + server, both directions.** The app ingests MCP servers (local, remote, hub-shared) _and_ exposes its own actions as an MCP server. See [MCP Clients](/docs/mcp-clients) and [MCP Protocol](/docs/mcp-protocol).
|
|
@@ -158,27 +158,24 @@ One `defineAction()` call gives you:
|
|
|
158
158
|
|
|
159
159
|
Same logic, one definition, wired to every consumer automatically. See [Actions](/docs/actions) for the full reference.
|
|
160
160
|
|
|
161
|
-
##
|
|
161
|
+
## Live sync {#polling-sync}
|
|
162
162
|
|
|
163
|
-
Database changes are synced to the UI
|
|
163
|
+
Database changes are synced to the UI through `useDbSync()`. Same-process writes stream over `/_agent-native/events`; `/_agent-native/poll` remains the cross-process and serverless fallback. When the agent writes to the database (application state, settings, or domain data), a version counter increments and the client invalidates the relevant React Query caches.
|
|
164
164
|
|
|
165
165
|
```ts
|
|
166
|
-
// Client:
|
|
166
|
+
// Client: subscribe to agent/UI data changes once near the app shell
|
|
167
167
|
import { useDbSync } from "@agent-native/core";
|
|
168
168
|
|
|
169
|
-
useDbSync({
|
|
170
|
-
queryClient,
|
|
171
|
-
queryKeys: ["app-state", "settings", "forms"],
|
|
172
|
-
});
|
|
169
|
+
useDbSync({ queryClient });
|
|
173
170
|
```
|
|
174
171
|
|
|
175
172
|
The flow is:
|
|
176
173
|
|
|
177
174
|
1. Agent runs an action that writes to the database
|
|
178
|
-
2.
|
|
179
|
-
3. `useDbSync`
|
|
180
|
-
4.
|
|
181
|
-
5. Components
|
|
175
|
+
2. The server emits a change event with a source such as `"action"` or `"settings"`
|
|
176
|
+
3. `useDbSync` receives it over SSE or the polling fallback
|
|
177
|
+
4. `useActionQuery` hooks and source-versioned `useQuery` hooks refetch
|
|
178
|
+
5. Components render the new data without a page reload
|
|
182
179
|
|
|
183
180
|
This works in all deployment environments — including serverless and edge — because it uses the database, not in-memory state or file system watchers.
|
|
184
181
|
|
|
@@ -196,14 +193,25 @@ The agent always knows what the user is looking at. The UI writes a `navigation`
|
|
|
196
193
|
|
|
197
194
|
See [Context Awareness](/docs/context-awareness) for the full pattern: navigation state, view-screen, navigate commands, and jitter prevention.
|
|
198
195
|
|
|
199
|
-
##
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
196
|
+
## One action, many protocols {#protocols}
|
|
197
|
+
|
|
198
|
+
Agent-native supports a lot of agent-facing protocols because different hosts standardize different pieces of the same workflow. App authors should not have to choose among them or rebuild the same operation for each client. The center of gravity stays the action system.
|
|
199
|
+
|
|
200
|
+
| Surface | What agent-native provides | What you write |
|
|
201
|
+
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------- | --------------------------------------- |
|
|
202
|
+
| Agent tool calling | The in-app agent sees actions as function tools with zod-derived JSON Schema. | `defineAction()` |
|
|
203
|
+
| UI actions | React calls the same action through `useActionMutation()` / `useActionQuery()`. | The same action |
|
|
204
|
+
| HTTP and CLI | Actions auto-mount at `/_agent-native/actions/:name` and run via `pnpm action <name>`. | The same action |
|
|
205
|
+
| MCP server | External MCP hosts get Streamable HTTP tools, the `ask-agent` meta-tool, and optional MCP Apps resources. | The same action, plus optional `mcpApp` |
|
|
206
|
+
| MCP Auth | Remote MCP OAuth, PKCE, dynamic client registration, refresh tokens, and `mcp:read` / `mcp:write` / `mcp:apps` scopes. | Nothing per action |
|
|
207
|
+
| A2A | Other agents discover the agent card and call the app over JSON-RPC tasks. | The same actions and agent config |
|
|
208
|
+
| Deep links | Action results can round-trip users into the running UI through `/_agent-native/open` and `agentnative://open`. | Optional `link` metadata |
|
|
209
|
+
| MCP clients | The app can also consume local, remote, or hub-shared MCP servers as `mcp__...` tools. | `mcp.config.json` or settings |
|
|
210
|
+
| Instructions and skills | `AGENTS.md`, skills, memory, slash commands, sub-agents, jobs, and automations live in the SQL-backed workspace. | Workspace resources, not protocol glue |
|
|
211
|
+
| Agent Web | Public pages can publish `robots.txt`, `sitemap.xml`, `llms.txt`, markdown mirrors, and structured metadata. | Route access plus `agentWeb` config |
|
|
212
|
+
| Extensions | Sandboxed mini-apps call app actions, persist extension data, and use proxied fetch helpers. | Extension HTML using `appAction()` |
|
|
213
|
+
|
|
214
|
+
The practical rule is simple: implement domain operations as actions, add `readOnly`, `publicAgent`, `link`, or `mcpApp` metadata only when the surface needs it, and use skills/instructions for behavior. MCP, A2A, MCP Apps, MCP Auth, UI mutations, CLI commands, and deep-link handoffs are adapters around that same core.
|
|
207
215
|
|
|
208
216
|
## Agent modifies code {#agent-modifies-code}
|
|
209
217
|
|
|
@@ -7,7 +7,7 @@ description: "Connect your agent-native app to local MCP servers (claude-in-chro
|
|
|
7
7
|
|
|
8
8
|
Agent-native apps can also act as MCP **clients** — connecting to locally installed MCP servers and exposing their tools to the agent chat. This is the symmetric counterpart to the [MCP Protocol](./mcp-protocol.md) (which makes your app an MCP server).
|
|
9
9
|
|
|
10
|
-
Looking for the other direction — connecting Claude Code, Codex, Cursor, or Claude Cowork to an agent-native app? Use [External Agents](/docs/external-agents).
|
|
10
|
+
Looking for the other direction — connecting Claude, ChatGPT, Claude Code, Codex, Cursor, or Claude Cowork to an agent-native app? Use [External Agents](/docs/external-agents).
|
|
11
11
|
|
|
12
12
|
With one config file, every agent-native app in your workspace gains access to tools provided by MCP servers on your machine: `claude-in-chrome` for browser automation, `@modelcontextprotocol/server-filesystem` for reading files, `@playwright/mcp` for browser testing, and anything else that speaks MCP.
|
|
13
13
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "MCP Protocol"
|
|
3
|
-
description: "Expose your agent-native app as a remote MCP server so Claude Code, Cursor, and other AI tools can call your app's actions directly."
|
|
3
|
+
description: "Expose your agent-native app as a remote MCP server so Claude, ChatGPT, Claude Code, Cursor, and other AI tools can call your app's actions directly."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# MCP Protocol
|
|
7
7
|
|
|
8
|
-
Every agent-native app automatically exposes a remote MCP (Model Context Protocol) server. This lets external AI tools like Claude Code, Cursor, and Windsurf discover and call your app's actions directly — no extra code needed.
|
|
8
|
+
Every agent-native app automatically exposes a remote MCP (Model Context Protocol) server. This lets external AI tools like Claude, ChatGPT custom MCP apps, Claude Code, Cursor, Codex, VS Code GitHub Copilot, and Windsurf discover and call your app's actions directly — no extra code needed.
|
|
9
9
|
|
|
10
|
-
If your goal is to connect Claude Code, Codex, Cursor, or Claude Cowork to a hosted agent-native app, start with [External Agents](/docs/external-agents). It documents the one-command `agent-native connect https://mail.agent-native.com` flow,
|
|
10
|
+
If your goal is to connect Claude, ChatGPT, Claude Code, Codex, Cursor, or Claude Cowork to a hosted agent-native app, start with [External Agents](/docs/external-agents). It documents the one-command `agent-native connect https://mail.agent-native.com` flow, standard remote MCP OAuth for Claude Code, bearer fallback config for older clients, manual remote MCP setup for hosts we do not write directly, MCP Apps inline UIs, and deep links back into the UI. This page is the lower-level MCP server reference.
|
|
11
11
|
|
|
12
12
|
## Overview {#overview}
|
|
13
13
|
|
|
@@ -19,40 +19,41 @@ Key concepts:
|
|
|
19
19
|
- **Streamable HTTP** — uses the modern MCP transport over standard HTTP (POST + SSE)
|
|
20
20
|
- **Same actions** — the exact same action registry that powers agent chat and A2A
|
|
21
21
|
- **`ask-agent` tool** — a meta-tool that delegates to the full agent loop for complex tasks
|
|
22
|
-
- **
|
|
22
|
+
- **MCP Apps** — actions can advertise inline HTML UIs through the official `io.modelcontextprotocol/ui` extension
|
|
23
|
+
- **Standard remote MCP OAuth** — OAuth 2.1 discovery, dynamic client registration, authorization-code + PKCE, refresh-token rotation
|
|
24
|
+
- **Bearer auth fallback** — uses `ACCESS_TOKEN`, `ACCESS_TOKENS`, or connect-minted JWTs for clients that cannot run OAuth
|
|
23
25
|
|
|
24
26
|
## MCP vs A2A {#mcp-vs-a2a}
|
|
25
27
|
|
|
26
28
|
Both protocols are auto-mounted. Use whichever fits your use case:
|
|
27
29
|
|
|
28
|
-
| | MCP
|
|
29
|
-
| ------------------ |
|
|
30
|
-
| **Best for** | External tools calling your app
|
|
31
|
-
| **Protocol** | MCP Streamable HTTP
|
|
32
|
-
| **Tool discovery** | `tools/list`
|
|
33
|
-
| **Endpoint** | `/_agent-native/mcp`
|
|
34
|
-
| **Supported by** | Claude Code, Cursor,
|
|
35
|
-
| **Execution** | Direct tool calls (no extra LLM)
|
|
30
|
+
| | MCP | A2A |
|
|
31
|
+
| ------------------ | ------------------------------------------------------------------------ | -------------------------------------------- |
|
|
32
|
+
| **Best for** | External tools calling your app | Agent-to-agent communication |
|
|
33
|
+
| **Protocol** | MCP Streamable HTTP | JSON-RPC 2.0 |
|
|
34
|
+
| **Tool discovery** | `tools/list` | Agent card at `/.well-known/agent-card.json` |
|
|
35
|
+
| **Endpoint** | `/_agent-native/mcp` | `/_agent-native/a2a` |
|
|
36
|
+
| **Supported by** | Claude, ChatGPT, Claude Code, Cursor, Codex, Cowork, and other MCP hosts | Other agent-native apps |
|
|
37
|
+
| **Execution** | Direct tool calls (no extra LLM) | Full agent loop (LLM reasoning) |
|
|
36
38
|
|
|
37
39
|
You can also use the `ask-agent` MCP tool to get the best of both worlds — call it from Claude Code and let your app's agent reason through complex tasks.
|
|
38
40
|
|
|
39
41
|
## Manual MCP client config {#claude-code}
|
|
40
42
|
|
|
41
|
-
For the recommended one-command setup, use [External Agents](/docs/external-agents). If you are hand-writing MCP config, add your app as a remote MCP server
|
|
43
|
+
For the recommended one-command setup, use [External Agents](/docs/external-agents). If you are hand-writing MCP config for an OAuth-capable client, add your app as a remote MCP server with no static headers:
|
|
42
44
|
|
|
43
45
|
```jsonc
|
|
44
46
|
// ~/.claude/mcp_servers.json
|
|
45
47
|
{
|
|
46
48
|
"mail": {
|
|
47
|
-
"type": "
|
|
49
|
+
"type": "http",
|
|
48
50
|
"url": "https://mail.example.com/_agent-native/mcp",
|
|
49
|
-
"headers": {
|
|
50
|
-
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
|
|
51
|
-
},
|
|
52
51
|
},
|
|
53
52
|
}
|
|
54
53
|
```
|
|
55
54
|
|
|
55
|
+
Then run `/mcp` in Claude Code and choose **Authenticate**. For clients that cannot perform remote MCP OAuth, use the Connect page or a static bearer-token entry with `headers.Authorization`.
|
|
56
|
+
|
|
56
57
|
Then in Claude Code, you can use your app's tools naturally:
|
|
57
58
|
|
|
58
59
|
```
|
|
@@ -71,6 +72,8 @@ POST https://your-app.example.com/_agent-native/mcp
|
|
|
71
72
|
|
|
72
73
|
The server supports the standard MCP handshake: `initialize` → `initialized` → `tools/list` → `tools/call`.
|
|
73
74
|
|
|
75
|
+
If an action declares `mcpApp`, the server also advertises the official MCP Apps extension (`io.modelcontextprotocol/ui`) and supports `resources/list`, `resources/templates/list`, and `resources/read` for the app HTML. Hosts that render MCP Apps can show the UI inline; hosts that do not can still call the tool and use the deep-link fallback. The current official extension matrix includes Claude, Claude Desktop, VS Code GitHub Copilot, Goose, Postman, MCPJam, ChatGPT, and Cursor; host support varies by version and plan, so use the [External Agents MCP Apps notes](/docs/external-agents#mcp-apps-compatibility) for the user-facing guidance.
|
|
76
|
+
|
|
74
77
|
## Tools {#tools}
|
|
75
78
|
|
|
76
79
|
All actions registered in your app are exposed as MCP tools. The mapping is direct:
|
|
@@ -81,6 +84,8 @@ All actions registered in your app are exposed as MCP tools. The mapping is dire
|
|
|
81
84
|
| `tool.parameters` | `inputSchema` |
|
|
82
85
|
| Action name | Tool name |
|
|
83
86
|
|
|
87
|
+
When `mcpApp` is present, the tool entry also includes `_meta.ui.resourceUri` and `_meta["ui/resourceUri"]`, and the corresponding `ui://` resource is returned as `text/html;profile=mcp-app`.
|
|
88
|
+
|
|
84
89
|
### The `ask-agent` tool {#ask-agent}
|
|
85
90
|
|
|
86
91
|
In addition to individual action tools, every MCP server includes an `ask-agent` meta-tool. This sends a natural-language message to the app's AI agent and returns the response.
|
|
@@ -100,16 +105,50 @@ The agent runs the same loop as the interactive chat — it can call multiple to
|
|
|
100
105
|
|
|
101
106
|
## Authentication {#authentication}
|
|
102
107
|
|
|
103
|
-
The MCP endpoint
|
|
108
|
+
The MCP endpoint supports standard remote MCP OAuth plus the existing bearer-token fallback:
|
|
109
|
+
|
|
110
|
+
| Mode | How it works |
|
|
111
|
+
| --------------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
112
|
+
| Standard MCP OAuth | Client discovers auth from `WWW-Authenticate`, registers, runs PKCE, and sends `Authorization: Bearer <access-token>` |
|
|
113
|
+
| Connect-minted JWT | `agent-native connect` / the Connect page mints a per-user, revocable JWT |
|
|
114
|
+
| `ACCESS_TOKEN` | Static bearer token — client sends `Authorization: Bearer <token>` |
|
|
115
|
+
| `ACCESS_TOKENS` | Comma-separated list of valid static bearer tokens |
|
|
116
|
+
| `A2A_SECRET` | JWT-based auth — tokens are verified cryptographically |
|
|
117
|
+
| _(none set, loopback only)_ | No auth required for local dev probes |
|
|
118
|
+
|
|
119
|
+
For OAuth-capable MCP hosts, configure the remote server URL with no static headers:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
claude mcp add --transport http agent-native-mail https://mail.agent-native.com/_agent-native/mcp
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The first unauthenticated MCP request receives:
|
|
126
|
+
|
|
127
|
+
```http
|
|
128
|
+
HTTP/1.1 401 Unauthorized
|
|
129
|
+
WWW-Authenticate: Bearer resource_metadata="https://mail.agent-native.com/.well-known/oauth-protected-resource", scope="mcp:read mcp:write mcp:apps"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Discovery endpoints:
|
|
133
|
+
|
|
134
|
+
| Endpoint | Purpose |
|
|
135
|
+
| ----------------------------------------- | ------------------------------------------- |
|
|
136
|
+
| `/.well-known/oauth-protected-resource` | RFC 9728 protected-resource metadata |
|
|
137
|
+
| `/.well-known/oauth-authorization-server` | OAuth authorization server metadata |
|
|
138
|
+
| `/.well-known/openid-configuration` | OIDC-compatible metadata alias |
|
|
139
|
+
| `/_agent-native/mcp/oauth/register` | Dynamic public-client registration |
|
|
140
|
+
| `/_agent-native/mcp/oauth/authorize` | Browser authorization + consent |
|
|
141
|
+
| `/_agent-native/mcp/oauth/token` | Authorization-code and refresh-token grants |
|
|
142
|
+
|
|
143
|
+
Access tokens are signed JWTs whose audience is the exact MCP resource URL. The server accepts only tokens issued for itself and applies scopes before listing/calling tools:
|
|
104
144
|
|
|
105
|
-
|
|
|
106
|
-
|
|
|
107
|
-
| `
|
|
108
|
-
| `
|
|
109
|
-
| `
|
|
110
|
-
| _(none set)_ | No auth required (dev mode) |
|
|
145
|
+
| Scope | Allows |
|
|
146
|
+
| ----------- | ------------------------------------------- |
|
|
147
|
+
| `mcp:read` | read-only actions |
|
|
148
|
+
| `mcp:write` | mutating actions and `ask-agent` |
|
|
149
|
+
| `mcp:apps` | MCP Apps resources (`ui://` HTML resources) |
|
|
111
150
|
|
|
112
|
-
|
|
151
|
+
Refresh tokens are stored only as hashes and are rotated on every refresh. `agent-native connect` writes this URL-only OAuth entry for Claude Code clients by default; keep the Connect page, `agent-native connect --token <token>`, and static bearer config for local stdio proxying, older clients, and emergency/debug flows.
|
|
113
152
|
|
|
114
153
|
## Custom MCP setup {#custom-setup}
|
|
115
154
|
|
|
@@ -144,9 +183,8 @@ You have a deployed analytics app at `analytics.example.com`. From Claude Code:
|
|
|
144
183
|
// ~/.claude/mcp_servers.json
|
|
145
184
|
{
|
|
146
185
|
"analytics": {
|
|
147
|
-
"type": "
|
|
186
|
+
"type": "http",
|
|
148
187
|
"url": "https://analytics.example.com/_agent-native/mcp",
|
|
149
|
-
"headers": { "Authorization": "Bearer sk-analytics-token" },
|
|
150
188
|
},
|
|
151
189
|
}
|
|
152
190
|
```
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Starter Template"
|
|
3
|
-
description: "The minimal agent-native scaffold — agent chat, actions, application state,
|
|
3
|
+
description: "The minimal agent-native scaffold — agent chat, actions, application state, live sync, auth — wired up, with no domain code. Build from scratch."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Starter
|
|
7
7
|
|
|
8
|
-
Starter is the minimum viable agent-native app. You get the six-rules architecture, the agent sidebar, the workspace tab,
|
|
8
|
+
Starter is the minimum viable agent-native app. You get the six-rules architecture, the agent sidebar, the workspace tab, live sync, auth, and exactly one example action. Nothing else. Build from there.
|
|
9
9
|
|
|
10
10
|
<!-- screenshot:
|
|
11
11
|
app: starter
|
|
@@ -26,7 +26,7 @@ Pick Starter when you're not sure which domain template fits, or when you want t
|
|
|
26
26
|
- **Auth** via Better Auth — login, signup, sessions, organizations. The same flow runs locally and in production; in development email verification is skipped so signup is just an email + password.
|
|
27
27
|
- **Actions directory** with one example (`actions/hello-world.ts`) and the `view-screen` / `navigate` standard actions wired up.
|
|
28
28
|
- **Drizzle schema** with the framework's core tables (application_state, settings, oauth_tokens, sessions, resources).
|
|
29
|
-
- **
|
|
29
|
+
- **Live sync** (`useDbSync`) already wired so UI auto-refreshes when the agent writes to the database.
|
|
30
30
|
- **AGENTS.md** with the framework-wide rules the agent reads on every turn.
|
|
31
31
|
- **One route** at `/` that says hi and renders the sidebar toggle. That's it.
|
|
32
32
|
|
|
@@ -45,10 +45,12 @@ Three things change when you reach rung 3:
|
|
|
45
45
|
|
|
46
46
|
- **You stopped adding buttons to a chatbot. You added an agent to an app.** That's a much higher-quality product on both sides.
|
|
47
47
|
- **The agent has real context.** It sees what you're looking at, what you've selected, what you just did. It writes to the same database the UI reads from, so its work shows up immediately.
|
|
48
|
-
- **External agents can use it too.** Other agent-native apps can call this one's actions over the [A2A protocol](/docs/a2a-protocol).
|
|
48
|
+
- **External agents can use it too.** Other agent-native apps can call this one's actions over the [A2A protocol](/docs/a2a-protocol). Claude Code, Codex, ChatGPT custom MCP apps, Cursor, and other MCP hosts can drive it as an [MCP server](/docs/mcp-protocol). One app, many entry points.
|
|
49
49
|
|
|
50
50
|
That's rung 3. That's agent-native.
|
|
51
51
|
|
|
52
|
+
It also explains why agent-native can support so many protocols without making every app author become a protocol expert. MCP tools, MCP Apps, remote MCP OAuth, A2A, typed React mutations, HTTP action endpoints, CLI actions, deep links, instructions, skills, memory, jobs, and connected MCP servers all hang off the same action and workspace model. Build the domain operation once as an action; the framework projects it into the surfaces each host understands.
|
|
53
|
+
|
|
52
54
|
## Why every agent needs a UI {#why-every-agent-needs-a-ui}
|
|
53
55
|
|
|
54
56
|
The hot take in 2026 is "apps are dead, agents will replace UIs, everyone will just text an agent in Telegram." That's wrong.
|
|
@@ -170,7 +172,7 @@ import { AgentSidebar } from "@agent-native/core/client";
|
|
|
170
172
|
<AgentSidebar />;
|
|
171
173
|
```
|
|
172
174
|
|
|
173
|
-
One action,
|
|
175
|
+
One action, many surfaces: the agent calls it as a tool, the UI calls it as a typesafe mutation, external agents reach it over [A2A](/docs/a2a-protocol), and MCP hosts call it through the app's [MCP server](/docs/mcp-protocol), optionally with MCP Apps UI resources and standard remote MCP OAuth handled by the framework. See [Actions](/docs/actions) for the full reference.
|
|
174
176
|
|
|
175
177
|
## What's next {#whats-next}
|
|
176
178
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Framework for agent-native application development — where AI agents and UI share state via files",
|
|
6
6
|
"license": "MIT",
|
|
@@ -114,6 +114,7 @@
|
|
|
114
114
|
"@assistant-ui/react-markdown": "^0.12.6",
|
|
115
115
|
"@clack/prompts": "^1.4.0",
|
|
116
116
|
"@libsql/client": "^0.15.0",
|
|
117
|
+
"@modelcontextprotocol/ext-apps": "1.7.2",
|
|
117
118
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
118
119
|
"@neondatabase/serverless": "^1.1.0",
|
|
119
120
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
@@ -149,6 +150,7 @@
|
|
|
149
150
|
"nanoid": "^5.1.9",
|
|
150
151
|
"nitro": "3.0.260415-beta",
|
|
151
152
|
"p-limit": "^7.3.0",
|
|
153
|
+
"prettier": "^3.8.3",
|
|
152
154
|
"react-markdown": "^10.1.0",
|
|
153
155
|
"react-router": "^7.13.1",
|
|
154
156
|
"remark-gfm": "^4.0.1",
|