@agent-native/core 0.106.2 → 0.107.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 (240) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +19 -0
  3. package/corpus/core/docs/content/external-agents.mdx +8 -0
  4. package/corpus/core/docs/content/integrations.mdx +597 -0
  5. package/corpus/core/docs/content/locales/ar-SA/external-agents.mdx +7 -0
  6. package/corpus/core/docs/content/locales/ar-SA/mcp-clients.mdx +19 -1
  7. package/corpus/core/docs/content/locales/ar-SA/mcp-protocol.mdx +7 -0
  8. package/corpus/core/docs/content/locales/de-DE/external-agents.mdx +9 -0
  9. package/corpus/core/docs/content/locales/de-DE/mcp-clients.mdx +22 -1
  10. package/corpus/core/docs/content/locales/de-DE/mcp-protocol.mdx +9 -0
  11. package/corpus/core/docs/content/locales/es-ES/external-agents.mdx +9 -0
  12. package/corpus/core/docs/content/locales/es-ES/mcp-clients.mdx +23 -1
  13. package/corpus/core/docs/content/locales/es-ES/mcp-protocol.mdx +9 -0
  14. package/corpus/core/docs/content/locales/fr-FR/external-agents.mdx +9 -0
  15. package/corpus/core/docs/content/locales/fr-FR/mcp-clients.mdx +23 -1
  16. package/corpus/core/docs/content/locales/fr-FR/mcp-protocol.mdx +9 -0
  17. package/corpus/core/docs/content/locales/hi-IN/external-agents.mdx +8 -0
  18. package/corpus/core/docs/content/locales/hi-IN/mcp-clients.mdx +22 -1
  19. package/corpus/core/docs/content/locales/hi-IN/mcp-protocol.mdx +8 -0
  20. package/corpus/core/docs/content/locales/ja-JP/external-agents.mdx +8 -0
  21. package/corpus/core/docs/content/locales/ja-JP/mcp-clients.mdx +21 -1
  22. package/corpus/core/docs/content/locales/ja-JP/mcp-protocol.mdx +8 -0
  23. package/corpus/core/docs/content/locales/ko-KR/external-agents.mdx +8 -0
  24. package/corpus/core/docs/content/locales/ko-KR/mcp-clients.mdx +20 -1
  25. package/corpus/core/docs/content/locales/ko-KR/mcp-protocol.mdx +8 -0
  26. package/corpus/core/docs/content/locales/pt-BR/external-agents.mdx +9 -0
  27. package/corpus/core/docs/content/locales/pt-BR/mcp-clients.mdx +22 -1
  28. package/corpus/core/docs/content/locales/pt-BR/mcp-protocol.mdx +9 -0
  29. package/corpus/core/docs/content/locales/zh-CN/external-agents.mdx +6 -0
  30. package/corpus/core/docs/content/locales/zh-CN/mcp-clients.mdx +17 -1
  31. package/corpus/core/docs/content/locales/zh-CN/mcp-protocol.mdx +6 -0
  32. package/corpus/core/docs/content/locales/zh-TW/external-agents.mdx +6 -0
  33. package/corpus/core/docs/content/locales/zh-TW/mcp-clients.mdx +17 -1
  34. package/corpus/core/docs/content/locales/zh-TW/mcp-protocol.mdx +6 -0
  35. package/corpus/core/docs/content/mcp-clients.mdx +51 -1
  36. package/corpus/core/docs/content/mcp-protocol.mdx +8 -0
  37. package/corpus/core/docs/content/organizations-teams-permissions.mdx +413 -0
  38. package/corpus/core/package.json +1 -1
  39. package/corpus/core/src/client/AssistantChat.tsx +13 -1
  40. package/corpus/core/src/client/chat/message-components.tsx +41 -0
  41. package/corpus/core/src/client/composer/TiptapComposer.tsx +45 -8
  42. package/corpus/core/src/client/integrations/IntegrationsPanel.tsx +30 -11
  43. package/corpus/core/src/client/resources/McpConnectionSuggestion.tsx +240 -0
  44. package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +159 -40
  45. package/corpus/core/src/client/resources/mcp-integration-catalog.ts +433 -4
  46. package/corpus/core/src/client/resources/mcp-integration-logos.ts +108 -0
  47. package/corpus/core/src/deploy/build.ts +32 -0
  48. package/corpus/core/src/extensions/html-shell.ts +33 -1
  49. package/corpus/core/src/ingestion/office.ts +1 -2
  50. package/corpus/core/src/ingestion/pptx.ts +2 -4
  51. package/corpus/core/src/localization/default-messages.ts +126 -1
  52. package/corpus/core/src/mcp/actions/call-mcp-tool.ts +1 -0
  53. package/corpus/core/src/mcp/builtin-tools.ts +115 -10
  54. package/corpus/core/src/server/index.ts +4 -0
  55. package/corpus/core/src/server/org-admin.ts +28 -0
  56. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +9 -0
  57. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/references/api.md +31 -0
  58. package/corpus/core/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +9 -0
  59. package/corpus/templates/analytics/.agents/skills/creative-context/SKILL.md +64 -0
  60. package/corpus/templates/analytics/AGENTS.md +5 -0
  61. package/corpus/templates/analytics/actions/clone-creative-context-dashboard.ts +86 -0
  62. package/corpus/templates/analytics/app/components/layout/Layout.tsx +2 -0
  63. package/corpus/templates/analytics/app/i18n/zh-TW.ts +1 -0
  64. package/corpus/templates/analytics/app/i18n-data.ts +1 -0
  65. package/corpus/templates/analytics/app/pages/Ask.tsx +8 -4
  66. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +59 -0
  67. package/corpus/templates/analytics/app/routes/agent.tsx +7 -1
  68. package/corpus/templates/analytics/changelog/2026-07-17-library-now-flags-published-dashboards-with-newer-versions-a.md +6 -0
  69. package/corpus/templates/analytics/changelog/2026-07-17-resources-can-be-added-to-creative-context-from-their-action.md +6 -0
  70. package/corpus/templates/analytics/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
  71. package/corpus/templates/analytics/package.json +1 -0
  72. package/corpus/templates/analytics/server/lib/native-creative-context.ts +158 -0
  73. package/corpus/templates/analytics/server/plugins/creative-context.ts +10 -0
  74. package/corpus/templates/assets/.agents/skills/creative-context/SKILL.md +12 -3
  75. package/corpus/templates/assets/AGENTS.md +5 -0
  76. package/corpus/templates/assets/actions/clone-creative-context-asset.ts +74 -0
  77. package/corpus/templates/assets/app/hooks/use-navigation-state.ts +2 -1
  78. package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +308 -178
  79. package/corpus/templates/assets/app/routes/library.tsx +5 -11
  80. package/corpus/templates/assets/changelog/2026-07-17-library-now-flags-published-assets-with-newer-versions-and-l.md +6 -0
  81. package/corpus/templates/assets/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
  82. package/corpus/templates/assets/server/lib/native-creative-context.ts +198 -0
  83. package/corpus/templates/assets/server/plugins/creative-context.ts +4 -0
  84. package/corpus/templates/brain/actions/provider-api-request.ts +1 -0
  85. package/corpus/templates/calendar/actions/provider-api-request.ts +1 -0
  86. package/corpus/templates/clips/actions/get-recording-insights.ts +7 -4
  87. package/corpus/templates/clips/actions/list-recordings.ts +48 -0
  88. package/corpus/templates/clips/actions/list-viewers.ts +2 -1
  89. package/corpus/templates/clips/app/components/editor/stitch-manager.tsx +3 -1
  90. package/corpus/templates/clips/app/components/player/share-dialog.tsx +1 -3
  91. package/corpus/templates/clips/app/hooks/use-desktop-promo.ts +11 -6
  92. package/corpus/templates/clips/app/hooks/use-view-tracking.ts +6 -1
  93. package/corpus/templates/clips/app/lib/ffmpeg-export.ts +4 -2
  94. package/corpus/templates/clips/app/routes/share.$shareId.tsx +21 -3
  95. package/corpus/templates/clips/changelog/2026-07-17-dictation-keeps-sentence-spacing-and-no-longer-crashes-when-.md +6 -0
  96. package/corpus/templates/clips/changelog/2026-07-17-shared-clips-now-preserve-editor-access-and-show-editor-insi.md +6 -0
  97. package/corpus/templates/clips/changelog/2026-07-17-stitching-clips-no-longer-fails-when-editor-media-metadata-i.md +6 -0
  98. package/corpus/templates/clips/server/routes/api/public-recording.get.ts +14 -8
  99. package/corpus/templates/clips/shared/view-analytics.ts +4 -0
  100. package/corpus/templates/content/.agents/skills/creative-context/SKILL.md +12 -3
  101. package/corpus/templates/content/AGENTS.md +5 -0
  102. package/corpus/templates/content/actions/clone-creative-context-document.ts +61 -0
  103. package/corpus/templates/content/actions/provider-api-request.ts +1 -0
  104. package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +21 -0
  105. package/corpus/templates/content/app/components/sidebar/DocumentTreeItem.tsx +29 -0
  106. package/corpus/templates/content/changelog/2026-07-17-library-now-flags-published-documents-with-newer-versions-an.md +6 -0
  107. package/corpus/templates/content/changelog/2026-07-17-resources-can-be-added-to-creative-context-from-their-action.md +6 -0
  108. package/corpus/templates/content/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
  109. package/corpus/templates/content/parity/matrix.md +1 -1
  110. package/corpus/templates/content/parity/matrix.ts +1 -0
  111. package/corpus/templates/content/server/lib/native-creative-context.ts +191 -0
  112. package/corpus/templates/content/server/plugins/creative-context.ts +8 -1
  113. package/corpus/templates/design/.agents/skills/creative-context/SKILL.md +11 -3
  114. package/corpus/templates/design/AGENTS.md +5 -0
  115. package/corpus/templates/design/actions/clone-creative-context-design-native.ts +111 -0
  116. package/corpus/templates/design/actions/provider-api-request.ts +1 -0
  117. package/corpus/templates/design/app/pages/Index.tsx +44 -0
  118. package/corpus/templates/design/app/pages/design-editor/types.ts +1 -0
  119. package/corpus/templates/design/changelog/2026-07-17-library-now-flags-published-designs-with-newer-versions-and-.md +6 -0
  120. package/corpus/templates/design/changelog/2026-07-17-resources-can-be-added-to-creative-context-from-their-action.md +6 -0
  121. package/corpus/templates/design/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
  122. package/corpus/templates/design/server/lib/native-creative-context.ts +265 -0
  123. package/corpus/templates/design/server/plugins/creative-context.ts +8 -1
  124. package/corpus/templates/dispatch/actions/provider-api-request.ts +1 -0
  125. package/corpus/templates/mail/actions/provider-api-request.ts +1 -0
  126. package/corpus/templates/slides/.agents/skills/creative-context/SKILL.md +11 -3
  127. package/corpus/templates/slides/AGENTS.md +5 -0
  128. package/corpus/templates/slides/actions/clone-creative-context-deck.ts +96 -0
  129. package/corpus/templates/slides/actions/extract-pdf.ts +3 -2
  130. package/corpus/templates/slides/actions/import-file.ts +3 -2
  131. package/corpus/templates/slides/actions/provider-api-request.ts +1 -0
  132. package/corpus/templates/slides/app/components/deck/DeckCard.tsx +27 -0
  133. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +21 -0
  134. package/corpus/templates/slides/changelog/2026-07-17-library-now-flags-published-decks-with-newer-versions-and-le.md +6 -0
  135. package/corpus/templates/slides/changelog/2026-07-17-pdf-and-powerpoint-imports-now-work-reliably-in-hosted-decks.md +6 -0
  136. package/corpus/templates/slides/changelog/2026-07-17-resources-can-be-added-to-creative-context-from-their-action.md +6 -0
  137. package/corpus/templates/slides/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
  138. package/corpus/templates/slides/server/lib/native-creative-context.ts +288 -0
  139. package/corpus/templates/slides/server/plugins/creative-context.ts +4 -0
  140. package/dist/client/AssistantChat.d.ts.map +1 -1
  141. package/dist/client/AssistantChat.js +8 -2
  142. package/dist/client/AssistantChat.js.map +1 -1
  143. package/dist/client/chat/message-components.d.ts.map +1 -1
  144. package/dist/client/chat/message-components.js +35 -1
  145. package/dist/client/chat/message-components.js.map +1 -1
  146. package/dist/client/composer/TiptapComposer.d.ts +7 -0
  147. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  148. package/dist/client/composer/TiptapComposer.js +37 -8
  149. package/dist/client/composer/TiptapComposer.js.map +1 -1
  150. package/dist/client/integrations/IntegrationsPanel.d.ts.map +1 -1
  151. package/dist/client/integrations/IntegrationsPanel.js +3 -2
  152. package/dist/client/integrations/IntegrationsPanel.js.map +1 -1
  153. package/dist/client/resources/McpConnectionSuggestion.d.ts +9 -0
  154. package/dist/client/resources/McpConnectionSuggestion.d.ts.map +1 -0
  155. package/dist/client/resources/McpConnectionSuggestion.js +115 -0
  156. package/dist/client/resources/McpConnectionSuggestion.js.map +1 -0
  157. package/dist/client/resources/McpIntegrationDialog.d.ts +2 -1
  158. package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
  159. package/dist/client/resources/McpIntegrationDialog.js +48 -20
  160. package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
  161. package/dist/client/resources/mcp-integration-catalog.d.ts +9 -0
  162. package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
  163. package/dist/client/resources/mcp-integration-catalog.js +387 -4
  164. package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
  165. package/dist/client/resources/mcp-integration-logos.d.ts +2 -0
  166. package/dist/client/resources/mcp-integration-logos.d.ts.map +1 -0
  167. package/dist/client/resources/mcp-integration-logos.js +109 -0
  168. package/dist/client/resources/mcp-integration-logos.js.map +1 -0
  169. package/dist/deploy/build.d.ts.map +1 -1
  170. package/dist/deploy/build.js +23 -0
  171. package/dist/deploy/build.js.map +1 -1
  172. package/dist/extensions/html-shell.d.ts.map +1 -1
  173. package/dist/extensions/html-shell.js +33 -1
  174. package/dist/extensions/html-shell.js.map +1 -1
  175. package/dist/ingestion/office.d.ts.map +1 -1
  176. package/dist/ingestion/office.js +1 -2
  177. package/dist/ingestion/office.js.map +1 -1
  178. package/dist/ingestion/pptx.js +2 -4
  179. package/dist/ingestion/pptx.js.map +1 -1
  180. package/dist/localization/default-messages.d.ts +98 -0
  181. package/dist/localization/default-messages.d.ts.map +1 -1
  182. package/dist/localization/default-messages.js +99 -1
  183. package/dist/localization/default-messages.js.map +1 -1
  184. package/dist/mcp/actions/call-mcp-tool.js +1 -0
  185. package/dist/mcp/actions/call-mcp-tool.js.map +1 -1
  186. package/dist/mcp/builtin-tools.d.ts.map +1 -1
  187. package/dist/mcp/builtin-tools.js +87 -6
  188. package/dist/mcp/builtin-tools.js.map +1 -1
  189. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  190. package/dist/server/index.d.ts +1 -0
  191. package/dist/server/index.d.ts.map +1 -1
  192. package/dist/server/index.js +1 -0
  193. package/dist/server/index.js.map +1 -1
  194. package/dist/server/org-admin.d.ts +3 -0
  195. package/dist/server/org-admin.d.ts.map +1 -0
  196. package/dist/server/org-admin.js +24 -0
  197. package/dist/server/org-admin.js.map +1 -0
  198. package/dist/server/transcribe-voice.d.ts +1 -1
  199. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +9 -0
  200. package/dist/templates/workspace-core/.agents/skills/extensions/references/api.md +31 -0
  201. package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +9 -0
  202. package/docs/content/external-agents.mdx +8 -0
  203. package/docs/content/integrations.mdx +597 -0
  204. package/docs/content/locales/ar-SA/external-agents.mdx +7 -0
  205. package/docs/content/locales/ar-SA/mcp-clients.mdx +19 -1
  206. package/docs/content/locales/ar-SA/mcp-protocol.mdx +7 -0
  207. package/docs/content/locales/de-DE/external-agents.mdx +9 -0
  208. package/docs/content/locales/de-DE/mcp-clients.mdx +22 -1
  209. package/docs/content/locales/de-DE/mcp-protocol.mdx +9 -0
  210. package/docs/content/locales/es-ES/external-agents.mdx +9 -0
  211. package/docs/content/locales/es-ES/mcp-clients.mdx +23 -1
  212. package/docs/content/locales/es-ES/mcp-protocol.mdx +9 -0
  213. package/docs/content/locales/fr-FR/external-agents.mdx +9 -0
  214. package/docs/content/locales/fr-FR/mcp-clients.mdx +23 -1
  215. package/docs/content/locales/fr-FR/mcp-protocol.mdx +9 -0
  216. package/docs/content/locales/hi-IN/external-agents.mdx +8 -0
  217. package/docs/content/locales/hi-IN/mcp-clients.mdx +22 -1
  218. package/docs/content/locales/hi-IN/mcp-protocol.mdx +8 -0
  219. package/docs/content/locales/ja-JP/external-agents.mdx +8 -0
  220. package/docs/content/locales/ja-JP/mcp-clients.mdx +21 -1
  221. package/docs/content/locales/ja-JP/mcp-protocol.mdx +8 -0
  222. package/docs/content/locales/ko-KR/external-agents.mdx +8 -0
  223. package/docs/content/locales/ko-KR/mcp-clients.mdx +20 -1
  224. package/docs/content/locales/ko-KR/mcp-protocol.mdx +8 -0
  225. package/docs/content/locales/pt-BR/external-agents.mdx +9 -0
  226. package/docs/content/locales/pt-BR/mcp-clients.mdx +22 -1
  227. package/docs/content/locales/pt-BR/mcp-protocol.mdx +9 -0
  228. package/docs/content/locales/zh-CN/external-agents.mdx +6 -0
  229. package/docs/content/locales/zh-CN/mcp-clients.mdx +17 -1
  230. package/docs/content/locales/zh-CN/mcp-protocol.mdx +6 -0
  231. package/docs/content/locales/zh-TW/external-agents.mdx +6 -0
  232. package/docs/content/locales/zh-TW/mcp-clients.mdx +17 -1
  233. package/docs/content/locales/zh-TW/mcp-protocol.mdx +6 -0
  234. package/docs/content/mcp-clients.mdx +51 -1
  235. package/docs/content/mcp-protocol.mdx +8 -0
  236. package/docs/content/organizations-teams-permissions.mdx +413 -0
  237. package/package.json +1 -1
  238. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +9 -0
  239. package/src/templates/workspace-core/.agents/skills/extensions/references/api.md +31 -0
  240. package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +9 -0
@@ -232,6 +232,12 @@ Auto-mounted on every app. Speaks the standard MCP handshake (`initialize` → `
232
232
  請使用這些引數呼叫 `ask_app_status`,直到任務進入終止狀態。Dispatch 應用程式自有的
233
233
  `ask_app` 使用相同的持久任務與狀態合約,並在提交與輪詢時都會檢查所選應用程式的授權。
234
234
 
235
+ 若有界的暫時狀態讀取無法使用,`ask_app_status` 可傳回
236
+ `status: "unknown"`、`statusRead: "unavailable"`、`retryable: true`、原始的
237
+ `app` 與 `taskId`,以及 `pollAfterMs` / `poll`。這表示狀態讀取無法使用,並不表示
238
+ 持久任務失敗。請以完全相同的 `app` 與 `taskId` 重試 `ask_app_status`;切勿為了復原而
239
+ 重新提交 `ask_app`,因為提交可能重複工作。永久性的驗證、找不到與通訊協定錯誤仍然是錯誤。
240
+
235
241
  ## 驗證 {#authentication}
236
242
 
237
243
  MCP 端點支援標準遠端 MCP OAuth 以及現有的不記名權杖後備:
@@ -7,6 +7,10 @@ description: "Connect your agent-native app to local MCP servers (claude-in-chro
7
7
 
8
8
  **This page: give your agent more tools.** Point an agent-native app at MCP servers — local or remote — so their tools show up in the agent chat. This is the _client_ direction, the mirror image of [MCP Server](/docs/mcp-protocol) (which makes your app an MCP _server_). Note the dual use of "client" here: this page is about your app acting as an MCP client of _other_ servers — a different sense from an "MCP host" like Claude or Cursor connecting to your app (see [MCP Server](/docs/mcp-protocol) for that direction).
9
9
 
10
+ **Looking for the provider list first?** See the [Integrations Directory](/docs/integrations)
11
+ for the self-hosted catalog wall, connection modes, setup links, and current
12
+ restricted-provider notes.
13
+
10
14
  | If you want to… | Read |
11
15
  | ------------------------------------------------------------ | ---------------------------------------- |
12
16
  | Connect an external agent/host to your app | [External Agents](/docs/external-agents) |
@@ -272,7 +276,16 @@ export default {
272
276
  ```
273
277
 
274
278
  Preset ids are `context7`, `sentry`, `notion`, `semgrep`, `linear`,
275
- `atlassian`, `supabase`, `neon`, and `stripe`.
279
+ `atlassian`, `supabase`, `neon`, `stripe`, `cloudflare`, `gitlab`, `figma`,
280
+ `vercel`, `github`, `slack`, `asana`, `hubspot`, `intercom`, `monday`,
281
+ `webflow`, `paypal`, `box`, `netlify`, and `zapier`.
282
+
283
+ The directory distinguishes endpoints that support the framework's generic
284
+ OAuth flow from providers that require a vendor-approved client or a
285
+ pre-registered OAuth application. The latter stay visible for discovery and
286
+ link to their official setup instructions, but do not show a misleading
287
+ one-click connect button. Provider restrictions change over time, so verify
288
+ the vendor setup note before enabling one in a production catalog.
276
289
 
277
290
  ### Atlassian / Jira
278
291
 
@@ -319,6 +332,43 @@ Adds and removes hot-reload into the running MCP manager — no process restart,
319
332
 
320
333
  HTTPS URLs are accepted everywhere; plain `http://` is only allowed for `localhost` during development. Optional auth goes in as a Bearer token that's sent via `Authorization: Bearer …` on every request. OAuth-only providers, including Atlassian Rovo MCP, require the provider's OAuth flow instead of a static header.
321
334
 
335
+ ### Use connected MCP and OAuth provider data in extensions
336
+
337
+ Extensions run in a sandboxed iframe and never receive connector URLs, OAuth
338
+ client secrets, access tokens, or refresh tokens. They can call the same
339
+ request-scoped action surface as the host app through the injected helpers:
340
+
341
+ ```html
342
+ <div
343
+ x-data="{ tools: [] }"
344
+ x-init="
345
+ agentNative.mcp.listTools().then(result => tools = result)
346
+ "
347
+ >
348
+ <template x-for="tool in tools" :key="tool.serverId + ':' + tool.name">
349
+ <p x-text="tool.title || tool.name"></p>
350
+ </template>
351
+ </div>
352
+ ```
353
+
354
+ To invoke a tool after inspecting its contract, use
355
+ `agentNative.mcp.callTool(serverId, toolName, arguments)`. For regular OAuth
356
+ provider connectors used by Analytics, Dispatch, Mail, Content, Calendar, and
357
+ other templates, use `agentNative.providerApi.catalog(...)` and
358
+ `agentNative.providerApi.docs(...)` to discover the granted provider API. Raw
359
+ `provider-api-request` is intentionally host/agent-only: exposing arbitrary
360
+ method/path requests to shared extensions would make an extension an
361
+ authenticated write proxy. Extensions should use `agentNative.mcp.callTool(...)`
362
+ or a purpose-built app action for bounded provider operations. The discovery
363
+ helpers are also available under `agentNative.connectors.mcp` and
364
+ `agentNative.connectors.providerApi`.
365
+
366
+ Local-file extensions must explicitly allow `list-mcp-tools`,
367
+ `call-mcp-tool`, and any explicitly supported provider action they use in
368
+ `extension.json`.
369
+ Database-backed extensions use the existing extension role and action gates.
370
+ Never pass a raw bearer token or arbitrary provider URL from extension code.
371
+
322
372
  Under the hood these servers are persisted in the framework's `settings` table under the key `u:<email>:mcp-servers-remote` (Personal) or `o:<orgId>:mcp-servers-remote` (Team) and merged with `mcp.config.json` on startup.
323
373
 
324
374
  ### HTTP endpoints
@@ -244,6 +244,14 @@ Call `ask_app_status` with those arguments until the task reaches a terminal
244
244
  state. Dispatch's app-owned `ask_app` uses the same durable task and status
245
245
  contract, with the selected-app grant checked on both submission and polling.
246
246
 
247
+ If a bounded transient status read is unavailable, `ask_app_status` can return
248
+ `status: "unknown"`, `statusRead: "unavailable"`, `retryable: true`, the
249
+ original `app` and `taskId`, and `pollAfterMs` / `poll`. This means the status
250
+ read is unavailable—not that the durable task failed. Retry `ask_app_status`
251
+ with that exact `app` and `taskId`; never resubmit `ask_app` to recover, because
252
+ submission can duplicate work. Permanent authentication, not-found, and
253
+ protocol failures remain errors.
254
+
247
255
  ## Authentication {#authentication}
248
256
 
249
257
  The MCP endpoint supports standard remote MCP OAuth plus the existing bearer-token fallback:
@@ -0,0 +1,413 @@
1
+ ---
2
+ title: "Organizations, Teams & Permissions"
3
+ description: "A practical guide to organization context, team roles, resource sharing, RBAC, and the environment variables used by Agent Native apps."
4
+ ---
5
+
6
+ # Organizations, Teams & Permissions
7
+
8
+ If you are building an app for more than one person, start here. Agent Native
9
+ has several scopes that are easy to conflate:
10
+
11
+ | Scope | What it identifies | Where it appears |
12
+ | ---------------- | -------------------------------------------------------------------- | ------------------------------------------------------- |
13
+ | **User** | The signed-in person | `session.email`, `ctx.userEmail` |
14
+ | **Organization** | The team or tenant the person is currently using | `session.orgId`, `session.orgRole`, `ctx.orgId` |
15
+ | **Resource** | A document, dashboard, design, or other app row | `owner_email`, `org_id`, `visibility`, and share grants |
16
+ | **Workspace** | A deployment shape containing multiple apps and shared configuration | `AGENT_NATIVE_WORKSPACE`, shared `.env`, app base paths |
17
+
18
+ An organization is the team boundary for application data. A workspace is a
19
+ deployment and customization concept; it is not a replacement for an
20
+ organization and it does not grant access to application rows by itself.
21
+
22
+ ## The access model in one minute
23
+
24
+ The framework resolves a request in this order:
25
+
26
+ 1. Authentication identifies the user.
27
+ 2. The org module resolves the user's active organization and membership role.
28
+ 3. SQL and resource access helpers scope reads and writes to that identity.
29
+
30
+ ```text
31
+ Better Auth session
32
+ -> active organization: orgId + orgRole
33
+ -> request context: userEmail + orgId
34
+ -> scoped SQL / resource access
35
+ ```
36
+
37
+ The same context is used by the UI, actions, custom server routes, and the
38
+ agent. Hiding a button in React is useful UX, but it is not authorization. The
39
+ server-side action or access guard must enforce the rule.
40
+
41
+ ## Organizations and teams
42
+
43
+ Every scaffold includes the framework's own `org/` module. It is backed by
44
+ `organizations`, `org_members`, and `org_invitations`; it is not Better Auth's
45
+ organization plugin. The built-in flow supports:
46
+
47
+ - Creating an organization. The creator becomes the `owner`.
48
+ - Inviting people as `member` or `admin` and accepting invitations.
49
+ - Switching the active organization when a user belongs to more than one.
50
+ - Joining by an allowed email domain when the organization enables that policy.
51
+ - Renaming an organization, managing members, and managing cross-app A2A
52
+ settings from the team surface.
53
+
54
+ The framework mounts the server surface under `/_agent-native/org/*`. The main
55
+ routes are:
56
+
57
+ | Route | Purpose |
58
+ | ------------------------------------------------ | ------------------------------------------------------------ |
59
+ | `GET /_agent-native/org/me` | Active org, memberships, pending invites, and domain matches |
60
+ | `POST /_agent-native/org` | Create an organization |
61
+ | `PATCH /_agent-native/org` | Rename the active organization |
62
+ | `PUT /_agent-native/org/switch` | Switch the active organization |
63
+ | `GET /_agent-native/org/members` | List members in the active organization |
64
+ | `DELETE /_agent-native/org/members/:email` | Remove a member |
65
+ | `PUT /_agent-native/org/members/:email/role` | Change a member's role |
66
+ | `POST /_agent-native/org/invitations` | Invite one or more people |
67
+ | `POST /_agent-native/org/invitations/:id/accept` | Accept an invitation |
68
+ | `POST /_agent-native/org/join-by-domain` | Join an organization matched by email domain |
69
+ | `PUT /_agent-native/org/domain` | Set or clear the allowed email domain |
70
+ | `PUT /_agent-native/org/a2a-secret` | Set or regenerate the active org's A2A secret |
71
+
72
+ Use the shared UI and hooks instead of recreating this flow in each app:
73
+
74
+ ```tsx
75
+ import {
76
+ OrgSwitcher,
77
+ RequireActiveOrg,
78
+ TeamPage,
79
+ useOrgRole,
80
+ } from "@agent-native/core/client/org-team";
81
+
82
+ export function AppShell() {
83
+ return <OrgSwitcher />;
84
+ }
85
+
86
+ export function TeamSettings() {
87
+ return (
88
+ <RequireActiveOrg>
89
+ <TeamPage />
90
+ </RequireActiveOrg>
91
+ );
92
+ }
93
+
94
+ export function InviteButton() {
95
+ const { canInviteMembers } = useOrgRole();
96
+ return canInviteMembers ? <button>Invite members</button> : null;
97
+ }
98
+ ```
99
+
100
+ On the server, import the org helpers from `@agent-native/core/org-team`.
101
+ `getOrgContext(event)` returns the resolved `{ email, orgId, orgName, role }`.
102
+ For actions, the second `run` argument is the simpler path for the identity
103
+ needed by most app code:
104
+
105
+ ```ts
106
+ export default defineAction({
107
+ description: "Create a project in the active organization.",
108
+ schema: z.object({ name: z.string().min(1) }),
109
+ run: async ({ name }, ctx) => {
110
+ if (!ctx?.userEmail) throw new Error("Authentication required");
111
+
112
+ await db.insert(projects).values({
113
+ id: crypto.randomUUID(),
114
+ name,
115
+ ownerEmail: ctx.userEmail,
116
+ orgId: ctx.orgId,
117
+ });
118
+
119
+ return { ok: true };
120
+ },
121
+ });
122
+ ```
123
+
124
+ The active organization is selected from the user's memberships. For a user
125
+ with several memberships, the framework honors the `active-org-id` user
126
+ setting. If a signed-in user has no membership, the framework creates a
127
+ personal organization by default. Set `AUTO_CREATE_DEFAULT_ORG=0` when an app
128
+ must require an explicit invite or organization-creation step.
129
+
130
+ ## Organization roles (membership RBAC)
131
+
132
+ Organization roles answer: **what may this person do to the team itself?**
133
+
134
+ | Role | Meaning | Typical capabilities |
135
+ | -------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
136
+ | `owner` | Full control of the organization | Manage the organization, members, admins, domain policy, and org-level A2A settings |
137
+ | `admin` | Team administrator | Invite/remove members and manage ordinary member roles; admins cannot change the owner's role, only the owner manages admin-to-admin transitions, and the shared client domain helper is owner-only |
138
+ | `member` | Regular team member | Use resources that the app shares with the organization; cannot manage membership |
139
+
140
+ The shared role helpers are deliberately small and composable:
141
+
142
+ ```ts
143
+ import {
144
+ canInviteOrgMembers,
145
+ canManageOrg,
146
+ canManageOrgDomain,
147
+ orgRoleAtLeast,
148
+ } from "@agent-native/core/org-team";
149
+
150
+ if (!orgRoleAtLeast(role, "admin")) {
151
+ throw new Error("Organization admin role required");
152
+ }
153
+ ```
154
+
155
+ The same helpers are available from
156
+ `@agent-native/core/client/org-team` for presentation logic. Treat those
157
+ client checks as progressive disclosure only; repeat the authorization check
158
+ in the server action or route that changes org state.
159
+
160
+ ## Resource permissions (sharing RBAC)
161
+
162
+ Organization roles and resource roles are different systems:
163
+
164
+ - **Organization role** controls team administration.
165
+ - **Resource role** controls access to one document, dashboard, or other
166
+ shareable row.
167
+
168
+ Shareable resources use three layers together:
169
+
170
+ 1. `owner_email` identifies the creator.
171
+ 2. `org_id` and `visibility` define the resource's tenant and coarse visibility.
172
+ 3. A companion shares table grants a user or organization `viewer`, `editor`,
173
+ or `admin` access.
174
+
175
+ | Resource role | Access |
176
+ | ------------- | ------------------------------ |
177
+ | `viewer` | Read |
178
+ | `editor` | Read and write |
179
+ | `admin` | Read, write, and manage shares |
180
+
181
+ `admin` on a resource does not transfer ownership. The resource owner remains
182
+ separate from every share grant.
183
+
184
+ For new tenant-aware tables, use `ownableColumns()` and the access helpers:
185
+
186
+ ```ts
187
+ import { table, text, ownableColumns } from "@agent-native/core/db/schema";
188
+ import { accessFilter, assertAccess } from "@agent-native/core/sharing";
189
+
190
+ export const projects = table("projects", {
191
+ id: text("id").primaryKey(),
192
+ name: text("name").notNull(),
193
+ ...ownableColumns(), // owner_email + org_id + visibility
194
+ });
195
+
196
+ const visibleProjects = await db
197
+ .select()
198
+ .from(projects)
199
+ .where(accessFilter(projects, projectShares));
200
+
201
+ await assertAccess("project", projectId, "editor");
202
+ ```
203
+
204
+ Use these helpers consistently:
205
+
206
+ - `accessFilter(table, sharesTable)` for list/read queries.
207
+ - `resolveAccess(resourceType, resourceId)` when the action needs to inspect
208
+ the effective access role.
209
+ - `assertAccess(resourceType, resourceId, minRole)` at the top of a write or
210
+ single-record action.
211
+
212
+ The framework's SQL agent tools are scoped as well, but direct Drizzle queries
213
+ in actions and custom routes still need the access helpers. Run
214
+ `pnpm action db-check-scoping` and `pnpm guards` while developing to catch
215
+ missing ownership or unscoped query paths.
216
+
217
+ ## Environment variables: what belongs where
218
+
219
+ Environment variables configure the deployment. They are not a database for
220
+ user or team state.
221
+
222
+ | Store | Use it for | Do not use it for |
223
+ | ------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
224
+ | Server/deploy environment | One value shared by the whole app instance, such as `DATABASE_URL`, auth signing keys, or an A2A secret | A user's API key or a team's mutable setting |
225
+ | `VITE_*` build-time environment | Non-secret values that must be embedded in browser code | Secrets; anything with `VITE_` can be public |
226
+ | Encrypted credential/vault APIs | Per-user and per-organization provider keys, OAuth tokens, and app secrets | Deployment bootstrapping that must exist before the database is available |
227
+ | SQL application state/settings | App state, preferences, and references | Raw credentials, tokens, or large file payloads |
228
+
229
+ For local development, put deploy-level values in a gitignored `.env`. In a
230
+ workspace, the root `.env` is shared by apps and `apps/<name>/.env` overrides it
231
+ for that app. Never commit real values.
232
+
233
+ ## How environment files are loaded {#env-loading}
234
+
235
+ There is not one central environment schema. The effective contract is split
236
+ between dotenv loading, Vite's browser exposure, secret registration, and the
237
+ feature that consumes each value. For the framework's dotenv loader, the
238
+ effective precedence is:
239
+
240
+ 1. Values already present in the shell.
241
+ 2. The app's `.env.local`.
242
+ 3. The app's `.env`.
243
+ 4. The workspace root `.env.local`.
244
+ 5. The workspace root `.env`.
245
+
246
+ Workspace files only fill keys the app has not already defined. This lets a
247
+ workspace keep shared defaults in one place while an app or shell overrides a
248
+ value deliberately. `VITE_*` values are an additional build-time contract:
249
+ Vite embeds them in browser code, so treat every `VITE_*` value as public even
250
+ when it came from a private `.env` file.
251
+
252
+ ## Framework environment variables
253
+
254
+ There is no single useful list of every environment variable in an app: each
255
+ template and provider adds its own integration settings. The table below is the
256
+ framework-level set developers most often need. Feature-specific variables stay
257
+ on the page for the feature that owns them.
258
+
259
+ ### Database and public URL
260
+
261
+ | Variable | What it does |
262
+ | --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
263
+ | `APP_NAME` | Names the current app and enables prefixed lookups such as `MAIL_DATABASE_URL` when the app name is `mail`. |
264
+ | `DATABASE_URL` | Persistent SQL connection. Unset uses local SQLite; `pglite:./data/pglite` opts into local Postgres semantics. |
265
+ | `DATABASE_AUTH_TOKEN` | Separate auth token for providers such as Turso/libSQL. |
266
+ | `<APP_NAME>_DATABASE_URL` | Per-app database override in a multi-app workspace; it wins over `DATABASE_URL` and `NETLIFY_DATABASE_URL`. |
267
+ | `<APP_NAME>_DATABASE_AUTH_TOKEN` | Per-app auth-token override; it wins over `DATABASE_AUTH_TOKEN` and `NETLIFY_DATABASE_AUTH_TOKEN`. |
268
+ | `NETLIFY_DATABASE_URL` | Netlify-managed database fallback when no app-prefixed or generic `DATABASE_URL` is set. |
269
+ | `NETLIFY_DATABASE_AUTH_TOKEN` | Netlify-managed database auth-token fallback. |
270
+ | `<APP_NAME>_DATABASE_URL_UNPOOLED` | Per-app direct connection used for migrations where the provider exposes a pooled and unpooled endpoint. |
271
+ | `DATABASE_URL_UNPOOLED` / `NETLIFY_DATABASE_URL_UNPOOLED` | Generic or Netlify direct migration connection fallback. The app-prefixed value wins when present. |
272
+ | `ALLOW_DRIZZLE_PUSH_ON_NEON` | Set to `1` only for an intentional local schema push against Neon. Do not set it in CI or production. |
273
+ | `APP_URL` | Canonical app/workspace origin used for generated links and callbacks. |
274
+ | `WORKSPACE_OAUTH_ORIGIN` / `VITE_WORKSPACE_OAUTH_ORIGIN` | Workspace OAuth origin, used when the workspace gateway and app origin differ. |
275
+ | `BETTER_AUTH_URL` / `VITE_BETTER_AUTH_URL` | Explicit public auth origin for session and OAuth URL construction; `APP_URL` and request/platform origins can provide fallbacks. |
276
+ | `WEBHOOK_BASE_URL` | Optional callback origin when webhook self-callbacks should use a stable custom domain instead of the deploy preview URL. |
277
+ | `URL` / `DEPLOY_URL` / `DEPLOY_PRIME_URL` | Platform-provided public URL fallbacks, especially for Netlify previews and deploys. |
278
+ | `VERCEL_PROJECT_PRODUCTION_URL` / `VERCEL_URL` | Vercel's production and deployment-hostname fallbacks. |
279
+ | `PORT` | Node server port. |
280
+ | `APP_BASE_PATH` / `VITE_APP_BASE_PATH` | Mounts an app under a path such as `/mail`; the `VITE_*` form preserves that path in browser code. |
281
+ | `NITRO_PRESET` | Selects the deployment/build target, such as `netlify`, `vercel`, or `cloudflare_pages`. |
282
+
283
+ ### Authentication, cookies, and org defaults
284
+
285
+ | Variable | What it does |
286
+ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
287
+ | `BETTER_AUTH_SECRET` | Production session-signing secret and fallback key material. Generate a fresh 32+ character value. |
288
+ | `OAUTH_STATE_SECRET` | Dedicated HMAC key for OAuth state envelopes; falls back to `BETTER_AUTH_SECRET` when unset. |
289
+ | `SECRETS_ENCRYPTION_KEY` | AES-256-GCM key for encrypted credentials and vault rows; falls back to `BETTER_AUTH_SECRET`. |
290
+ | `AUTH_DISABLED` | Local/demo escape hatch that makes every request one shared user. Never use it with real production users. |
291
+ | `AUTH_SKIP_EMAIL_VERIFICATION` | Set to `1` for QA/preview signup without email verification. |
292
+ | `AGENT_NATIVE_DISABLE_AUTO_DEV_ACCOUNT` | Set to `1` to disable localhost's automatic throwaway account. |
293
+ | `AUTH_MODE` | Controls CLI/agent identity resolution such as `pnpm action`; it is not a browser login bypass. |
294
+ | `COOKIE_DOMAIN` | Shares cookies across same-database subdomains when explicitly configured. |
295
+ | `AGENT_NATIVE_SHARE_COOKIE_DOMAIN` | Set to `1` with `COOKIE_DOMAIN` when intentionally sharing one auth database across first-party subdomains. |
296
+ | `AGENT_NATIVE_WORKSPACE` | Enables the shared workspace session realm for a multi-app workspace. |
297
+ | `VITE_AGENT_NATIVE_WORKSPACE` | Build-time/browser equivalent of `AGENT_NATIVE_WORKSPACE`. |
298
+ | `AUTO_CREATE_DEFAULT_ORG` | Defaults to enabled; set to `0` to stop creating a personal organization for users with no membership. |
299
+
300
+ ### OAuth providers
301
+
302
+ | Variable | What it does |
303
+ | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
304
+ | `GOOGLE_SIGN_IN_CLIENT_ID` / `GOOGLE_SIGN_IN_CLIENT_SECRET` | Preferred low-scope Google OAuth client for signing users in. |
305
+ | `GOOGLE_CLIENT_ID` / `GOOGLE_CLIENT_SECRET` | Google OAuth fallback and client credentials for Google API integrations such as Calendar. |
306
+ | `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET` | Enable GitHub sign-in. |
307
+ | `GOOGLE_AUTH_MODE` | Chooses Google sign-in UX: `auto`, `popup`, or `redirect`; defaults to `auto`. |
308
+
309
+ ### Agent providers and runtime
310
+
311
+ | Variable | What it does |
312
+ | ------------------------------ | -------------------------------------------------------------------------------------------------------- |
313
+ | `AGENT_ENGINE` | Explicitly selects the agent engine, for example a built-in provider or `codex-cli`. |
314
+ | `AGENT_ENGINE_PREFER_BYO_KEY` | Set to `true` to prefer a user's stored provider key over the managed Builder engine. |
315
+ | `ANTHROPIC_API_KEY` | Deploy-level Anthropic fallback for the agent. In multi-tenant hosted apps, prefer per-user credentials. |
316
+ | `OPENAI_API_KEY` | Deploy-level OpenAI provider key. |
317
+ | `GOOGLE_GENERATIVE_AI_API_KEY` | Deploy-level Google Gemini provider key. |
318
+ | `OPENROUTER_API_KEY` | Deploy-level OpenRouter provider key. |
319
+ | `GROQ_API_KEY` | Deploy-level Groq provider key. |
320
+ | `MISTRAL_API_KEY` | Deploy-level Mistral provider key. |
321
+ | `COHERE_API_KEY` | Deploy-level Cohere provider key. |
322
+ | `AGENT_MAX_ITERATIONS` | Default maximum agent loop iterations; app settings can override it where supported. |
323
+ | `AGENT_MAX_OUTPUT_TOKENS` | Default output-token limit for the agent. |
324
+ | `AGENT_PROD_CODE_EXECUTION` | Production code execution mode: `off`, `sandboxed`, or `trusted`. The default is `off`. |
325
+
326
+ ### Optional framework integrations
327
+
328
+ These values enable optional capabilities. When a user or organization has a
329
+ scoped credential in the app's secret or credential settings, that scoped value
330
+ can take precedence over the deploy environment.
331
+
332
+ | Variable | What it does |
333
+ | ------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
334
+ | `BRAVE_SEARCH_API_KEY` / `TAVILY_API_KEY` / `EXA_API_KEY` / `FIRECRAWL_API_KEY` | Enable the corresponding web-search BYOK provider. The search tool tries configured providers before the managed Builder fallback. |
335
+ | `GITHUB_TOKEN` | Workspace-level GitHub API fallback for repository and PR operations. |
336
+ | `RESEND_API_KEY` | Enables Resend email delivery. |
337
+ | `SENDGRID_API_KEY` / `EMAIL_FROM` | Enables SendGrid email delivery and supplies its sender address. Production email requires Resend or SendGrid; SendGrid also requires a sender. |
338
+ | `SENTRY_SERVER_DSN` / `SENTRY_CLIENT_DSN` / `SENTRY_DSN` | Optional Sentry error reporting for Nitro, browser, or both. No DSN means that surface is disabled. |
339
+ | `VITE_SENTRY_CLIENT_DSN` | Build-time browser Sentry DSN; runtime `SENTRY_CLIENT_DSN` or shared `SENTRY_DSN` can also configure SSR apps. |
340
+ | `SENTRY_ENVIRONMENT` / `SENTRY_SERVER_TRACES_SAMPLE_RATE` | Label Sentry events and opt into server performance traces (`0`–`1`; default `0`). |
341
+ | `POSTHOG_API_KEY` / `POSTHOG_HOST` | Configure PostHog tracking and its optional host. |
342
+ | `MIXPANEL_TOKEN` / `AMPLITUDE_API_KEY` | Configure Mixpanel or Amplitude tracking. |
343
+ | `AGENT_NATIVE_ANALYTICS_PUBLIC_KEY` / `VITE_AGENT_NATIVE_ANALYTICS_PUBLIC_KEY` | Public write key for first-party analytics ingestion; the `VITE_*` form is for browser builds. |
344
+ | `AGENT_NATIVE_ANALYTICS_ENDPOINT` / `VITE_AGENT_NATIVE_ANALYTICS_ENDPOINT` | Override the first-party analytics ingestion endpoint for server or browser events. |
345
+ | `TRACKING_WEBHOOK_URL` / `TRACKING_WEBHOOK_AUTH` | Send tracking events to a webhook and optionally provide its `Authorization` header value. |
346
+ | `AGENT_NATIVE_ALLOW_UNVERIFIED_WEBHOOKS` | Set to `1` only for local development while configuring webhook signing secrets. Never set it in production. |
347
+
348
+ Template-specific variables belong with the template that owns the feature and
349
+ its `.env.example` or feature docs. Start with [Messaging](/docs/messaging),
350
+ [Tracking](/docs/tracking), [Observability](/docs/observability), or the
351
+ template's development guide when a variable is not in this framework-level
352
+ map.
353
+
354
+ ### MCP, A2A, and CLI identity
355
+
356
+ | Variable | What it does |
357
+ | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
358
+ | `A2A_SECRET` | Shared signing secret for production cross-app A2A and queued integration dispatch. Use the same value across sibling apps. |
359
+ | `ACCESS_TOKEN` | One static bearer fallback for MCP clients that cannot use OAuth. It is not browser authentication. |
360
+ | `ACCESS_TOKENS` | Comma-separated static bearer fallbacks for MCP clients. |
361
+ | `MCP_OAUTH_ACCESS_TOKEN_TTL` | Lifetime for MCP OAuth access tokens; defaults to `30d`. |
362
+ | `AGENT_USER_EMAIL` | CLI-only user identity fallback when no request context exists. It does not impersonate browser requests. |
363
+ | `AGENT_USER_NAME` | CLI-only display-name fallback. |
364
+ | `AGENT_ORG_ID` | CLI-only active-org fallback when no request context exists. It does not override a browser session. |
365
+ | `AGENT_USER_TIMEZONE` | CLI/agent timezone fallback. |
366
+
367
+ `A2A_SECRET` is deployment-wide signing material. The organization-level
368
+ `organizations.a2a_secret` is a separate, UI-managed secret used when an org
369
+ delegates between separately deployed apps by organization domain. Do not copy
370
+ the org-level secret into `.env`; manage it from the organization settings
371
+ surface.
372
+
373
+ ### Workspace route visibility
374
+
375
+ These are generated automatically by the workspace deploy/dev commands in most
376
+ projects. Configure them directly only when you are building the workspace
377
+ runtime yourself:
378
+
379
+ | Variable | What it does |
380
+ | -------------------------------------------- | ------------------------------------------------------------------ |
381
+ | `AGENT_NATIVE_WORKSPACE_APP_ID` | Identifies the current app inside a multi-app workspace. |
382
+ | `AGENT_NATIVE_WORKSPACE_APP_AUDIENCE` | Sets the app audience, usually `internal` or `public`. |
383
+ | `AGENT_NATIVE_WORKSPACE_APP_PUBLIC_PATHS` | JSON array of public route prefixes. |
384
+ | `AGENT_NATIVE_WORKSPACE_APP_PROTECTED_PATHS` | JSON array of route prefixes that remain authenticated. |
385
+ | `WORKSPACE_ORG_NAME` | Optional organization name used by workspace bootstrap tooling. |
386
+ | `WORKSPACE_ORG_DOMAIN` | Optional allowed email domain used by workspace bootstrap tooling. |
387
+ | `WORKSPACE_OWNER_EMAIL` | Optional owner identity used by workspace bootstrap tooling. |
388
+
389
+ ## A practical setup sequence
390
+
391
+ For a new team app, configure in this order:
392
+
393
+ 1. Set `DATABASE_URL` if the app will be shared or deployed.
394
+ 2. Set `BETTER_AUTH_SECRET` and an explicit public URL such as `APP_URL` or
395
+ `BETTER_AUTH_URL` before production.
396
+ 3. Render `OrgSwitcher` and `TeamPage` from the shared org/team kit.
397
+ 4. Add `...ownableColumns()` to tenant-aware tables.
398
+ 5. Use `ctx.orgId` when creating rows and `accessFilter` / `assertAccess` when
399
+ reading or mutating them.
400
+ 6. Put provider credentials in the encrypted credential/vault surface when
401
+ they vary by user or organization; keep env keys for deploy-level defaults.
402
+ 7. Add `A2A_SECRET` to every production app that delegates to a sibling app or
403
+ processes signed integration tasks.
404
+
405
+ ## Related docs
406
+
407
+ - [**Authentication**](/docs/authentication) — sessions, OAuth, cookies, and auth flags
408
+ - [**Multi-Tenancy**](/docs/multi-tenancy) — org switching and tenant isolation
409
+ - [**Security — Data Scoping**](/docs/security#data-scoping) — SQL scoping and access guards
410
+ - [**Sharing & Privacy**](/docs/sharing) — resource visibility and share roles
411
+ - [**Database**](/docs/database) — schema and connection details
412
+ - [**Deployment**](/docs/deployment#environment-variables) — production and provider environment
413
+ - [**Org & Team Kit**](/docs/toolkit-org-team) — reusable UI components and hooks
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.106.2",
3
+ "version": "0.107.0",
4
4
  "description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -172,6 +172,7 @@ import {
172
172
  useGuidedQuestionFlow,
173
173
  } from "./guided-questions.js";
174
174
  import { useT } from "./i18n.js";
175
+ import { McpConnectionSuggestion } from "./resources/McpConnectionSuggestion.js";
175
176
  import {
176
177
  AgentAutoContinueSignal,
177
178
  type ContentPart,
@@ -2239,6 +2240,14 @@ const AssistantChatInner = forwardRef<
2239
2240
  // (unsupported format, size cap, body-size rejection, drop errors).
2240
2241
  // Cleared on the next message send.
2241
2242
  const [composerError, setComposerError] = useState<string | null>(null);
2243
+ const [composerText, setComposerText] = useState("");
2244
+ const handleComposerTextChange = useCallback(
2245
+ (text: string) => {
2246
+ setComposerText(text);
2247
+ onComposerTextChange?.(text);
2248
+ },
2249
+ [onComposerTextChange],
2250
+ );
2242
2251
  const dropDepthRef = useRef(0);
2243
2252
  const handleChatDragEnter = useCallback((e: React.DragEvent) => {
2244
2253
  if (!Array.from(e.dataTransfer?.types ?? []).includes("Files")) return;
@@ -5382,6 +5391,9 @@ const AssistantChatInner = forwardRef<
5382
5391
  </MessageScrollerProvider>
5383
5392
 
5384
5393
  {showComposerSlot ? composerSlot : null}
5394
+ {isActiveComposer && (
5395
+ <McpConnectionSuggestion text={composerText} />
5396
+ )}
5385
5397
  {showCenteredEmptyThreadFooterSlot ? (
5386
5398
  <div className="agent-thread-footer-slot agent-thread-footer-slot--centered-empty">
5387
5399
  {resolvedThreadFooterSlot}
@@ -5488,7 +5500,7 @@ const AssistantChatInner = forwardRef<
5488
5500
  focusRef={tiptapRef}
5489
5501
  onTextChange={
5490
5502
  isActiveComposer
5491
- ? onComposerTextChange
5503
+ ? handleComposerTextChange
5492
5504
  : undefined
5493
5505
  }
5494
5506
  disabled={isComposerDisabled}
@@ -62,6 +62,7 @@ import {
62
62
  import { isPastedTextAttachmentName } from "../composer/pasted-text.js";
63
63
  import { PastedTextChip } from "../composer/PastedTextChip.js";
64
64
  import { ThumbsFeedback } from "../observability/ThumbsFeedback.js";
65
+ import { McpConnectionSuggestion } from "../resources/McpConnectionSuggestion.js";
65
66
  import type { ContentPart } from "../sse-event-processor.js";
66
67
  import { cn } from "../utils.js";
67
68
  import {
@@ -819,6 +820,37 @@ function assistantMessageStatusIsTerminal(message: {
819
820
  return statusType === "complete" || statusType === "incomplete";
820
821
  }
821
822
 
823
+ function messageTextFromContent(content: unknown): string {
824
+ if (typeof content === "string") return content;
825
+ if (!Array.isArray(content)) return "";
826
+ return content
827
+ .flatMap((part) => {
828
+ if (!part || typeof part !== "object") return [];
829
+ const record = part as {
830
+ type?: unknown;
831
+ text?: unknown;
832
+ result?: unknown;
833
+ };
834
+ const values: string[] = [];
835
+ if (typeof record.text === "string") values.push(record.text);
836
+ if (record.type === "tool-call" && typeof record.result === "string") {
837
+ values.push(record.result);
838
+ }
839
+ return values;
840
+ })
841
+ .join("\n");
842
+ }
843
+
844
+ function latestUserMessageText(messages: readonly unknown[]): string {
845
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
846
+ const message = messages[index];
847
+ if (!message || typeof message !== "object") continue;
848
+ const record = message as { role?: unknown; content?: unknown };
849
+ if (record.role === "user") return messageTextFromContent(record.content);
850
+ }
851
+ return "";
852
+ }
853
+
822
854
  export function assistantMessageHasUnresolvedTool(content: unknown): boolean {
823
855
  if (!Array.isArray(content)) return false;
824
856
  return content.some((part): boolean => {
@@ -946,6 +978,8 @@ export function AssistantMessage() {
946
978
  thread.messages[thread.messages.length - 1].id === msg.id;
947
979
  const hasRenderableContent = assistantMessageHasRenderableContent(msg);
948
980
  const hasUnresolvedTool = assistantMessageHasUnresolvedTool(msg.content);
981
+ const responseConnectionText = messageTextFromContent(msg.content);
982
+ const responseConnectionContext = latestUserMessageText(thread.messages);
949
983
  const isComplete = shouldShowAssistantMessageFooter({
950
984
  isLast,
951
985
  chatRunning,
@@ -1104,6 +1138,13 @@ export function AssistantMessage() {
1104
1138
  {isComplete && hasCodeAgentTools && msgContent && (
1105
1139
  <FilesChangedSummary parts={msgContent} />
1106
1140
  )}
1141
+ {isComplete && isLast && (
1142
+ <McpConnectionSuggestion
1143
+ text={responseConnectionText}
1144
+ contextText={responseConnectionContext}
1145
+ variant="response"
1146
+ />
1147
+ )}
1107
1148
  {isLast && hasUnresolvedTool && !chatRunning && (
1108
1149
  <RunningActivityStatus label="Thinking" />
1109
1150
  )}