@agent-native/core 0.21.0 → 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.
Files changed (134) hide show
  1. package/dist/cli/connect.d.ts +5 -3
  2. package/dist/cli/connect.d.ts.map +1 -1
  3. package/dist/cli/connect.js +127 -15
  4. package/dist/cli/connect.js.map +1 -1
  5. package/dist/client/AgentPanel.d.ts.map +1 -1
  6. package/dist/client/AgentPanel.js +6 -2
  7. package/dist/client/AgentPanel.js.map +1 -1
  8. package/dist/client/AssistantChat.d.ts.map +1 -1
  9. package/dist/client/AssistantChat.js +7 -1
  10. package/dist/client/AssistantChat.js.map +1 -1
  11. package/dist/client/NewWorkspaceAppFlow.js +1 -1
  12. package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
  13. package/dist/client/agent-chat.d.ts.map +1 -1
  14. package/dist/client/agent-chat.js +13 -8
  15. package/dist/client/agent-chat.js.map +1 -1
  16. package/dist/client/agent-sidebar-state.d.ts +2 -0
  17. package/dist/client/agent-sidebar-state.d.ts.map +1 -1
  18. package/dist/client/agent-sidebar-state.js +40 -0
  19. package/dist/client/agent-sidebar-state.js.map +1 -1
  20. package/dist/client/mcp-apps/McpAppRenderer.d.ts.map +1 -1
  21. package/dist/client/mcp-apps/McpAppRenderer.js +9 -4
  22. package/dist/client/mcp-apps/McpAppRenderer.js.map +1 -1
  23. package/dist/client/use-db-sync.d.ts +5 -5
  24. package/dist/client/use-db-sync.d.ts.map +1 -1
  25. package/dist/client/use-db-sync.js +15 -5
  26. package/dist/client/use-db-sync.js.map +1 -1
  27. package/dist/client/use-db-sync.spec.d.ts +2 -0
  28. package/dist/client/use-db-sync.spec.d.ts.map +1 -0
  29. package/dist/client/use-db-sync.spec.js +80 -0
  30. package/dist/client/use-db-sync.spec.js.map +1 -0
  31. package/dist/db/client.d.ts.map +1 -1
  32. package/dist/db/client.js +14 -8
  33. package/dist/db/client.js.map +1 -1
  34. package/dist/extensions/actions.d.ts.map +1 -1
  35. package/dist/extensions/actions.js +62 -3
  36. package/dist/extensions/actions.js.map +1 -1
  37. package/dist/extensions/content-patch.d.ts +71 -0
  38. package/dist/extensions/content-patch.d.ts.map +1 -0
  39. package/dist/extensions/content-patch.js +251 -0
  40. package/dist/extensions/content-patch.js.map +1 -0
  41. package/dist/extensions/routes.js +6 -1
  42. package/dist/extensions/routes.js.map +1 -1
  43. package/dist/extensions/store.d.ts +4 -4
  44. package/dist/extensions/store.d.ts.map +1 -1
  45. package/dist/extensions/store.js +14 -18
  46. package/dist/extensions/store.js.map +1 -1
  47. package/dist/mcp/build-server.d.ts +3 -0
  48. package/dist/mcp/build-server.d.ts.map +1 -1
  49. package/dist/mcp/build-server.js +55 -6
  50. package/dist/mcp/build-server.js.map +1 -1
  51. package/dist/mcp/oauth-route.d.ts +22 -0
  52. package/dist/mcp/oauth-route.d.ts.map +1 -0
  53. package/dist/mcp/oauth-route.js +618 -0
  54. package/dist/mcp/oauth-route.js.map +1 -0
  55. package/dist/mcp/oauth-store.d.ts +89 -0
  56. package/dist/mcp/oauth-store.d.ts.map +1 -0
  57. package/dist/mcp/oauth-store.js +391 -0
  58. package/dist/mcp/oauth-store.js.map +1 -0
  59. package/dist/mcp/oauth-token.d.ts +28 -0
  60. package/dist/mcp/oauth-token.d.ts.map +1 -0
  61. package/dist/mcp/oauth-token.js +83 -0
  62. package/dist/mcp/oauth-token.js.map +1 -0
  63. package/dist/mcp/server.d.ts.map +1 -1
  64. package/dist/mcp/server.js +5 -2
  65. package/dist/mcp/server.js.map +1 -1
  66. package/dist/mcp-client/index.d.ts.map +1 -1
  67. package/dist/mcp-client/index.js +16 -2
  68. package/dist/mcp-client/index.js.map +1 -1
  69. package/dist/mcp-client/routes.js +18 -5
  70. package/dist/mcp-client/routes.js.map +1 -1
  71. package/dist/scripts/dev/shell.d.ts.map +1 -1
  72. package/dist/scripts/dev/shell.js +24 -1
  73. package/dist/scripts/dev/shell.js.map +1 -1
  74. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  75. package/dist/server/agent-chat-plugin.js +3 -2
  76. package/dist/server/agent-chat-plugin.js.map +1 -1
  77. package/dist/server/auth.d.ts.map +1 -1
  78. package/dist/server/auth.js +14 -8
  79. package/dist/server/auth.js.map +1 -1
  80. package/dist/server/builder-browser.d.ts +6 -0
  81. package/dist/server/builder-browser.d.ts.map +1 -1
  82. package/dist/server/builder-browser.js +15 -0
  83. package/dist/server/builder-browser.js.map +1 -1
  84. package/dist/server/core-routes-plugin.d.ts +5 -4
  85. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  86. package/dist/server/core-routes-plugin.js +17 -2
  87. package/dist/server/core-routes-plugin.js.map +1 -1
  88. package/dist/templates/default/.agents/skills/actions/SKILL.md +193 -72
  89. package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +88 -38
  90. package/dist/templates/default/AGENTS.md +3 -3
  91. package/dist/templates/default/actions/hello.ts +13 -20
  92. package/dist/templates/default/actions/navigate.ts +19 -51
  93. package/dist/templates/default/actions/view-screen.ts +16 -33
  94. package/dist/templates/default/app/hooks/use-navigation-state.ts +13 -3
  95. package/dist/templates/default/app/lib/tab-id.ts +1 -0
  96. package/dist/templates/default/app/root.tsx +2 -1
  97. package/dist/templates/default/app/routes/_index.tsx +11 -0
  98. package/dist/templates/default/package.json +2 -1
  99. package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +9 -1
  100. package/dist/templates/workspace-core/AGENTS.md +8 -0
  101. package/dist/templates/workspace-root/AGENTS.md +7 -0
  102. package/dist/vite/client.d.ts.map +1 -1
  103. package/dist/vite/client.js +2 -2
  104. package/dist/vite/client.js.map +1 -1
  105. package/docs/content/actions.md +1 -1
  106. package/docs/content/authentication.md +16 -1
  107. package/docs/content/client.md +11 -8
  108. package/docs/content/context-awareness.md +2 -3
  109. package/docs/content/creating-templates.md +2 -2
  110. package/docs/content/external-agents.md +47 -14
  111. package/docs/content/faq.md +2 -2
  112. package/docs/content/key-concepts.md +31 -23
  113. package/docs/content/mcp-protocol.md +50 -17
  114. package/docs/content/template-starter.md +3 -3
  115. package/docs/content/what-is-agent-native.md +4 -2
  116. package/package.json +2 -1
  117. package/src/templates/default/.agents/skills/actions/SKILL.md +193 -72
  118. package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +88 -38
  119. package/src/templates/default/AGENTS.md +3 -3
  120. package/src/templates/default/actions/hello.ts +13 -20
  121. package/src/templates/default/actions/navigate.ts +19 -51
  122. package/src/templates/default/actions/view-screen.ts +16 -33
  123. package/src/templates/default/app/hooks/use-navigation-state.ts +13 -3
  124. package/src/templates/default/app/lib/tab-id.ts +1 -0
  125. package/src/templates/default/app/root.tsx +2 -1
  126. package/src/templates/default/app/routes/_index.tsx +11 -0
  127. package/src/templates/default/package.json +2 -1
  128. package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +9 -1
  129. package/src/templates/workspace-core/AGENTS.md +8 -0
  130. package/src/templates/workspace-root/AGENTS.md +7 -0
  131. package/dist/templates/default/server/routes/api/hello.get.ts +0 -5
  132. package/dist/templates/default/shared/api.ts +0 -6
  133. package/src/templates/default/server/routes/api/hello.get.ts +0 -5
  134. package/src/templates/default/shared/api.ts +0 -6
@@ -8,7 +8,7 @@ search: "Claude ChatGPT Claude Code Codex Cursor Claude Cowork MCP Apps agent-na
8
8
 
9
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, no token copying where we can write the client config, or a standard remote MCP endpoint everywhere else. 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.
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
- This opens your browser at the app. You are already logged in, so you just click **Authorize** once. The command then 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.
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
- | Local client | Config written by `connect` |
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
- 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.
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**. The browser session you authorized with is the identity the agent acts as; nothing exposes the deployment's shared secret.
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": "url",
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 are not yet written by `agent-native connect`, including Cursor, Claude web/Desktop connector setup, ChatGPT developer-mode custom MCP apps, VS Code GitHub Copilot, Goose, Postman, MCPJam, and any other host that accepts a remote Streamable HTTP MCP endpoint.
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
 
@@ -109,7 +140,7 @@ On top of the per-action tools the MCP server exposes a stable verb set, so an e
109
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:
110
141
 
111
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.
112
- - **Calendar** — `manage-event-draft` returns a `calendarDraft` + `eventDraftId` deep link; clicking it opens the New Event form prefilled 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.
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.
113
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".
114
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.
115
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.
@@ -260,7 +291,7 @@ You can also write the MCP client config by hand against any deployed endpoint w
260
291
  {
261
292
  "mcpServers": {
262
293
  "analytics": {
263
- "type": "url",
294
+ "type": "http",
264
295
  "url": "https://analytics.agent-native.com/_agent-native/mcp",
265
296
  "headers": { "Authorization": "Bearer <ACCESS_TOKEN-or-JWT>" },
266
297
  },
@@ -296,7 +327,9 @@ If `connect dev` cannot infer your local owner identity from an existing connect
296
327
 
297
328
  ## How it works & security {#how-it-works}
298
329
 
299
- The hosted `connect` flow never copies the deployment's shared secret. Instead:
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:
300
333
 
301
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`.
302
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.
@@ -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 aren't available. The framework polls every 2 seconds using a lightweight version counter. When changes are detected, React Query caches are invalidated and components re-render. It's simple, reliable, and universal.
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. **Polling keeps the UI in sync** — database changes sync via lightweight polling
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 = four surfaces.** Every action defined with `defineAction()` is simultaneously an agent tool, a typesafe frontend mutation (`useActionMutation("name")`), an HTTP endpoint at `/_agent-native/actions/:name`, and an MCP tool (when MCP is enabled). External agents can call it over [A2A](/docs/a2a-protocol) too. One implementation, four consumers.
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.** A 2-second poll invalidates React Query caches whenever the agent writes to the DB. No WebSockets, no serverless-unfriendly long-lived connections. See [Polling Sync](#polling-sync) below.
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
- ## Polling sync {#polling-sync}
161
+ ## Live sync {#polling-sync}
162
162
 
163
- Database changes are synced to the UI via lightweight polling. When the agent writes to the database (application state, settings, or domain data), a version counter increments. The client `useDbSync()` hook (formerly `useFileWatcher`) polls `/_agent-native/poll` every 2 seconds and invalidates React Query caches when changes are detected.
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: invalidate caches on database changes
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. Version counter increments
179
- 3. `useDbSync` detects the new version on next poll
180
- 4. React Query caches are invalidated
181
- 5. Components re-fetch and render the new data
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
- ## Actions, MCP, and A2A — one surface, many protocols {#protocols}
200
-
201
- Every action you define automatically becomes available over multiple protocols you don't pick one. The framework runs both an MCP server and an A2A peer for your app, with actions feeding both.
202
-
203
- - **Actions first.** Write the logic once as an action. Use `fetch()` and any SDK you want inside — no wrapper layer.
204
- - **MCP for the outside world.** Your actions show up as MCP tools to Claude, ChatGPT custom MCP apps, Claude Desktop/Code, Cursor, Codex, and any other MCP client. Actions can also expose MCP Apps UI resources so compatible hosts render inline review/edit surfaces, with deep links back to the full app as the universal fallback. Your app also _consumes_ MCP servers — local, remote, or from a workspace hub. See [External Agents](/docs/external-agents), [MCP Clients](/docs/mcp-clients), and [MCP Protocol](/docs/mcp-protocol).
205
- - **A2A for other agents.** Other agent-native apps discover and call your actions over [A2A](/docs/a2a-protocol) same-origin deploys skip JWT entirely.
206
- - **CLIs still work.** `pnpm action <name>` and direct shell tools (`ffmpeg`, `gh`, `aws`) remain available whenever they're the simplest path.
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: "Expose your agent-native app as a remote MCP server so Claude, Cha
7
7
 
8
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, 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, token minting, local client config writes, 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.
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
 
@@ -20,7 +20,8 @@ Key concepts:
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
- - **Bearer auth** — uses `ACCESS_TOKEN` or `A2A_SECRET` for authentication
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
24
25
 
25
26
  ## MCP vs A2A {#mcp-vs-a2a}
26
27
 
@@ -39,21 +40,20 @@ You can also use the `ask-agent` MCP tool to get the best of both worlds — cal
39
40
 
40
41
  ## Manual MCP client config {#claude-code}
41
42
 
42
- 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 in Claude Code's config:
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:
43
44
 
44
45
  ```jsonc
45
46
  // ~/.claude/mcp_servers.json
46
47
  {
47
48
  "mail": {
48
- "type": "url",
49
+ "type": "http",
49
50
  "url": "https://mail.example.com/_agent-native/mcp",
50
- "headers": {
51
- "Authorization": "Bearer YOUR_ACCESS_TOKEN",
52
- },
53
51
  },
54
52
  }
55
53
  ```
56
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
+
57
57
  Then in Claude Code, you can use your app's tools naturally:
58
58
 
59
59
  ```
@@ -105,16 +105,50 @@ The agent runs the same loop as the interactive chat — it can call multiple to
105
105
 
106
106
  ## Authentication {#authentication}
107
107
 
108
- The MCP endpoint uses the same auth as the rest of the app:
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:
109
144
 
110
- | Env var | How it works |
111
- | --------------- | ----------------------------------------------------------- |
112
- | `ACCESS_TOKEN` | Bearer token — client sends `Authorization: Bearer <token>` |
113
- | `ACCESS_TOKENS` | Comma-separated list of valid tokens |
114
- | `A2A_SECRET` | JWT-based auth tokens are verified cryptographically |
115
- | _(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) |
116
150
 
117
- In production, set `ACCESS_TOKEN` or `A2A_SECRET` to secure the endpoint. In development (no auth env vars configured), all requests are allowed.
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.
118
152
 
119
153
  ## Custom MCP setup {#custom-setup}
120
154
 
@@ -149,9 +183,8 @@ You have a deployed analytics app at `analytics.example.com`. From Claude Code:
149
183
  // ~/.claude/mcp_servers.json
150
184
  {
151
185
  "analytics": {
152
- "type": "url",
186
+ "type": "http",
153
187
  "url": "https://analytics.example.com/_agent-native/mcp",
154
- "headers": { "Authorization": "Bearer sk-analytics-token" },
155
188
  },
156
189
  }
157
190
  ```
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  title: "Starter Template"
3
- description: "The minimal agent-native scaffold — agent chat, actions, application state, polling, auth — wired up, with no domain code. Build from scratch."
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, polling sync, auth, and exactly one example action. Nothing else. Build from there.
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
- - **Polling sync** (`useDbSync`) already wired so UI auto-refreshes when the agent writes to the database.
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). Tools like Claude Desktop can drive it as an [MCP server](/docs/mcp-protocol). One app, many entry points.
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, four 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 tools like Claude Desktop talk to it as an [MCP server](/docs/mcp-protocol). See [Actions](/docs/actions) for the full reference.
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.21.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",
@@ -150,6 +150,7 @@
150
150
  "nanoid": "^5.1.9",
151
151
  "nitro": "3.0.260415-beta",
152
152
  "p-limit": "^7.3.0",
153
+ "prettier": "^3.8.3",
153
154
  "react-markdown": "^10.1.0",
154
155
  "react-router": "^7.13.1",
155
156
  "remark-gfm": "^4.0.1",