@agent-native/dispatch 0.8.5 → 0.8.6

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 (78) hide show
  1. package/dist/actions/ask_app.d.ts +3 -0
  2. package/dist/actions/ask_app.d.ts.map +1 -0
  3. package/dist/actions/ask_app.js +12 -0
  4. package/dist/actions/ask_app.js.map +1 -0
  5. package/dist/actions/create_embed_session.d.ts +3 -0
  6. package/dist/actions/create_embed_session.d.ts.map +1 -0
  7. package/dist/actions/create_embed_session.js +28 -0
  8. package/dist/actions/create_embed_session.js.map +1 -0
  9. package/dist/actions/index.d.ts.map +1 -1
  10. package/dist/actions/index.js +12 -0
  11. package/dist/actions/index.js.map +1 -1
  12. package/dist/actions/list-mcp-app-access.d.ts +3 -0
  13. package/dist/actions/list-mcp-app-access.d.ts.map +1 -0
  14. package/dist/actions/list-mcp-app-access.js +25 -0
  15. package/dist/actions/list-mcp-app-access.js.map +1 -0
  16. package/dist/actions/list_apps.d.ts +3 -0
  17. package/dist/actions/list_apps.d.ts.map +1 -0
  18. package/dist/actions/list_apps.js +26 -0
  19. package/dist/actions/list_apps.js.map +1 -0
  20. package/dist/actions/open_app.d.ts +3 -0
  21. package/dist/actions/open_app.d.ts.map +1 -0
  22. package/dist/actions/open_app.js +59 -0
  23. package/dist/actions/open_app.js.map +1 -0
  24. package/dist/actions/set-mcp-app-access.d.ts +3 -0
  25. package/dist/actions/set-mcp-app-access.d.ts.map +1 -0
  26. package/dist/actions/set-mcp-app-access.js +46 -0
  27. package/dist/actions/set-mcp-app-access.js.map +1 -0
  28. package/dist/actions/start-workspace-app-creation.js +1 -1
  29. package/dist/actions/start-workspace-app-creation.js.map +1 -1
  30. package/dist/actions/view-screen.d.ts.map +1 -1
  31. package/dist/actions/view-screen.js +8 -0
  32. package/dist/actions/view-screen.js.map +1 -1
  33. package/dist/components/create-app-popover.d.ts.map +1 -1
  34. package/dist/components/create-app-popover.js +1 -0
  35. package/dist/components/create-app-popover.js.map +1 -1
  36. package/dist/routes/pages/agents.d.ts.map +1 -1
  37. package/dist/routes/pages/agents.js +74 -3
  38. package/dist/routes/pages/agents.js.map +1 -1
  39. package/dist/routes/pages/apps.d.ts.map +1 -1
  40. package/dist/routes/pages/apps.js +23 -8
  41. package/dist/routes/pages/apps.js.map +1 -1
  42. package/dist/routes/pages/overview.d.ts.map +1 -1
  43. package/dist/routes/pages/overview.js +1 -3
  44. package/dist/routes/pages/overview.js.map +1 -1
  45. package/dist/server/lib/mcp-access-store.d.ts +16 -0
  46. package/dist/server/lib/mcp-access-store.d.ts.map +1 -0
  47. package/dist/server/lib/mcp-access-store.js +64 -0
  48. package/dist/server/lib/mcp-access-store.js.map +1 -0
  49. package/dist/server/lib/mcp-gateway.d.ts +47 -0
  50. package/dist/server/lib/mcp-gateway.d.ts.map +1 -0
  51. package/dist/server/lib/mcp-gateway.js +237 -0
  52. package/dist/server/lib/mcp-gateway.js.map +1 -0
  53. package/dist/server/plugins/agent-chat.d.ts.map +1 -1
  54. package/dist/server/plugins/agent-chat.js +1 -0
  55. package/dist/server/plugins/agent-chat.js.map +1 -1
  56. package/dist/server/plugins/integrations.d.ts.map +1 -1
  57. package/dist/server/plugins/integrations.js +2 -1
  58. package/dist/server/plugins/integrations.js.map +1 -1
  59. package/package.json +1 -1
  60. package/src/actions/ask_app.ts +13 -0
  61. package/src/actions/create_embed_session.ts +29 -0
  62. package/src/actions/index.spec.ts +6 -0
  63. package/src/actions/index.ts +12 -0
  64. package/src/actions/list-mcp-app-access.ts +26 -0
  65. package/src/actions/list_apps.ts +27 -0
  66. package/src/actions/open_app.ts +61 -0
  67. package/src/actions/set-mcp-app-access.ts +59 -0
  68. package/src/actions/start-workspace-app-creation.ts +1 -1
  69. package/src/actions/view-screen.ts +8 -0
  70. package/src/components/create-app-popover.tsx +1 -0
  71. package/src/routes/pages/agents.tsx +187 -5
  72. package/src/routes/pages/apps.tsx +209 -67
  73. package/src/routes/pages/overview.tsx +16 -10
  74. package/src/server/lib/mcp-access-store.spec.ts +58 -0
  75. package/src/server/lib/mcp-access-store.ts +104 -0
  76. package/src/server/lib/mcp-gateway.ts +333 -0
  77. package/src/server/plugins/agent-chat.ts +1 -0
  78. package/src/server/plugins/integrations.ts +2 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-gateway.js","sourceRoot":"","sources":["../../../src/server/lib/mcp-gateway.ts"],"names":[],"mappings":"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","sourcesContent":["import { callAgent, signA2AToken } from \"@agent-native/core/a2a\";\nimport {\n buildMcpToolName,\n McpClientManager,\n} from \"@agent-native/core/mcp-client\";\nimport { buildDeepLink } from \"@agent-native/core/server\";\nimport {\n discoverAgents,\n type DiscoveredAgent,\n} from \"@agent-native/core/server/agent-discovery\";\nimport {\n getRequestOrgId,\n getRequestUserEmail,\n} from \"@agent-native/core/server\";\nimport { getOrgA2ASecret, getOrgDomain } from \"@agent-native/core/org\";\nimport {\n getDispatchMcpAppAccessSettings,\n isAppAllowedByMcpAccess,\n type DispatchMcpAppAccessSettings,\n} from \"./mcp-access-store.js\";\n\nexport interface DispatchMcpAccessibleApp {\n id: string;\n name: string;\n description: string;\n url: string;\n color: string;\n granted: boolean;\n}\n\nfunction normalizeAppId(value: string): string {\n return value.trim().toLowerCase();\n}\n\nconst CONTROL_CHARS = new RegExp(\"[\\\\u0000-\\\\u001f\\\\u007f]\");\n\nfunction safeAppPath(raw: unknown): string | null {\n if (typeof raw !== \"string\" || !raw.trim()) return null;\n const value = raw.trim();\n if (CONTROL_CHARS.test(value)) return null;\n if (!value.startsWith(\"/\")) return null;\n if (value.startsWith(\"//\") || value.startsWith(\"/\\\\\")) return null;\n if (/^\\/[a-z][a-z0-9+.-]*:/i.test(value)) return null;\n return value;\n}\n\nfunction appendParamsToPath(\n path: string,\n params: Record<string, string | number | boolean> | undefined,\n): string {\n if (!params || Object.keys(params).length === 0) return path;\n const url = new URL(path, \"http://agent-native.invalid\");\n for (const [key, value] of Object.entries(params)) {\n url.searchParams.set(key, String(value));\n }\n return `${url.pathname}${url.search}${url.hash}`;\n}\n\nfunction appOrigin(app: DispatchMcpAccessibleApp): string {\n return new URL(app.url).origin;\n}\n\nfunction appBaseUrl(app: DispatchMcpAccessibleApp): string {\n return app.url.replace(/\\/+$/, \"\");\n}\n\nfunction toAccessibleApp(\n agent: DiscoveredAgent,\n settings: DispatchMcpAppAccessSettings,\n): DispatchMcpAccessibleApp {\n return {\n id: agent.id,\n name: agent.name,\n description: agent.description,\n url: agent.url,\n color: agent.color,\n granted: isAppAllowedByMcpAccess(agent.id, settings),\n };\n}\n\nexport async function listDispatchMcpApps(): Promise<{\n settings: DispatchMcpAppAccessSettings;\n apps: DispatchMcpAccessibleApp[];\n}> {\n const [settings, agents] = await Promise.all([\n getDispatchMcpAppAccessSettings(),\n discoverAgents(\"dispatch\"),\n ]);\n return {\n settings,\n apps: agents.map((agent) => toAccessibleApp(agent, settings)),\n };\n}\n\nexport async function listGrantedDispatchMcpApps(): Promise<\n DispatchMcpAccessibleApp[]\n> {\n const { apps } = await listDispatchMcpApps();\n return apps.filter((app) => app.granted);\n}\n\nexport async function resolveGrantedDispatchMcpApp(\n app: string,\n): Promise<DispatchMcpAccessibleApp> {\n const target = normalizeAppId(app);\n if (!target) throw new Error(\"app is required\");\n const { apps } = await listDispatchMcpApps();\n const match = apps.find(\n (candidate) =>\n candidate.id === target || candidate.name.toLowerCase() === target,\n );\n if (!match) {\n throw new Error(\n `Unknown app \"${app}\". Call list_apps to see apps available through Dispatch MCP.`,\n );\n }\n if (!match.granted) {\n throw new Error(\n `Dispatch MCP access to \"${match.id}\" is not granted. Open Dispatch > Agents to change MCP app access.`,\n );\n }\n return match;\n}\n\nexport async function askGrantedDispatchMcpApp(\n app: string,\n message: string,\n): Promise<{ app: string; routedVia: \"a2a\"; response: string }> {\n const trimmedMessage = message.trim();\n if (!trimmedMessage) throw new Error(\"message is required\");\n const target = await resolveGrantedDispatchMcpApp(app);\n const userEmail = getRequestUserEmail();\n if (!userEmail) throw new Error(\"no authenticated user\");\n\n const orgId = getRequestOrgId();\n const [orgDomain, orgSecret] = orgId\n ? await Promise.all([\n getOrgDomain(orgId).catch(() => null),\n getOrgA2ASecret(orgId).catch(() => null),\n ])\n : [null, null];\n\n const response = await callAgent(target.url, trimmedMessage, {\n userEmail,\n orgDomain: orgDomain ?? undefined,\n orgSecret: orgSecret ?? undefined,\n timeoutMs: 5 * 60_000,\n });\n return { app: target.id, routedVia: \"a2a\", response };\n}\n\nexport async function openGrantedDispatchMcpApp(input: {\n app: string;\n view?: string;\n path?: string;\n params?: Record<string, string | number | boolean>;\n embed?: boolean;\n chrome?: \"full\" | \"minimal\";\n}): Promise<{\n app: string;\n view?: string;\n path?: string;\n url: string;\n embed?: boolean;\n chrome?: \"full\" | \"minimal\";\n}> {\n const view = input.view?.trim() ?? \"\";\n const path = safeAppPath(input.path);\n if (!view && !path) throw new Error(\"open_app requires view or path\");\n const target = await resolveGrantedDispatchMcpApp(input.app);\n const relUrl = path\n ? appendParamsToPath(path, input.params)\n : buildDeepLink({\n app: target.id,\n view,\n params: input.params,\n });\n return {\n app: target.id,\n ...(view ? { view } : {}),\n ...(path ? { path } : {}),\n url: `${appBaseUrl(target)}${relUrl}`,\n ...(input.embed === true ? { embed: true } : {}),\n ...(input.chrome ? { chrome: input.chrome } : {}),\n };\n}\n\nfunction parseMcpToolTextResult(result: unknown): Record<string, unknown> {\n if (result && typeof result === \"object\") {\n const structured = (result as any).structuredContent;\n if (structured && typeof structured === \"object\") return structured;\n const parts = Array.isArray((result as any).content)\n ? ((result as any).content as Array<Record<string, unknown>>)\n : [];\n const text = parts.find(\n (part) => part?.type === \"text\" && typeof part.text === \"string\",\n )?.text;\n if (typeof text === \"string\" && text.trim()) {\n const parsed = JSON.parse(text);\n if (parsed && typeof parsed === \"object\") return parsed;\n }\n }\n throw new Error(\"Target app did not return an embed session.\");\n}\n\nasync function resolveDispatchEmbedTarget(input: {\n app?: string;\n url?: string;\n path?: string;\n}): Promise<{ app: DispatchMcpAccessibleApp; path: string; url: string }> {\n const explicitApp = input.app?.trim()\n ? await resolveGrantedDispatchMcpApp(input.app)\n : null;\n if (explicitApp && input.path) {\n const path = safeAppPath(input.path);\n if (!path) throw new Error(\"path must be a safe app-relative route\");\n return {\n app: explicitApp,\n path,\n url: `${appBaseUrl(explicitApp)}${path}`,\n };\n }\n\n if (!input.url) {\n throw new Error(\"create_embed_session requires a url or app + path.\");\n }\n\n let parsed: URL;\n try {\n parsed = new URL(input.url);\n } catch {\n if (!explicitApp) {\n throw new Error(\"Relative embed paths require an app id.\");\n }\n const path = safeAppPath(input.url);\n if (!path) throw new Error(\"url must be a safe app route.\");\n return {\n app: explicitApp,\n path,\n url: `${appBaseUrl(explicitApp)}${path}`,\n };\n }\n\n const apps = explicitApp ? [explicitApp] : await listGrantedDispatchMcpApps();\n const target = apps.find((app) => parsed.origin === appOrigin(app));\n if (!target) {\n throw new Error(\n \"Embed URL must belong to an app granted through Dispatch.\",\n );\n }\n const path = safeAppPath(`${parsed.pathname}${parsed.search}${parsed.hash}`);\n if (!path) throw new Error(\"Embed URL path is not safe.\");\n return { app: target, path, url: `${appBaseUrl(target)}${path}` };\n}\n\nexport async function createGrantedDispatchMcpEmbedSession(input: {\n app?: string;\n url?: string;\n path?: string;\n chrome?: \"full\" | \"minimal\";\n}): Promise<{\n startUrl: string;\n targetPath?: string;\n expiresAt?: number;\n app: string;\n}> {\n const userEmail = getRequestUserEmail();\n if (!userEmail) throw new Error(\"no authenticated user\");\n const target = await resolveDispatchEmbedTarget(input);\n\n const orgId = getRequestOrgId();\n const [orgDomain, orgSecret] = orgId\n ? await Promise.all([\n getOrgDomain(orgId).catch(() => null),\n getOrgA2ASecret(orgId).catch(() => null),\n ])\n : [null, null];\n const token = await signA2AToken(\n userEmail,\n orgDomain ?? undefined,\n orgSecret ?? undefined,\n {\n expiresIn: \"5m\",\n preferGlobalSecret: !orgSecret,\n },\n );\n\n const serverId = \"target\";\n const manager = new McpClientManager({\n servers: {\n [serverId]: {\n type: \"http\",\n url: `${appBaseUrl(target.app)}/_agent-native/mcp`,\n headers: {\n Authorization: `Bearer ${token}`,\n },\n },\n },\n });\n await manager.start();\n try {\n const result = await manager.callTool(\n buildMcpToolName(serverId, \"create_embed_session\"),\n {\n url: target.url,\n chrome: input.chrome ?? \"full\",\n },\n );\n const parsed = parseMcpToolTextResult(result) as {\n startUrl?: string;\n targetPath?: string;\n expiresAt?: number;\n };\n if (!parsed.startUrl) {\n throw new Error(\"Target app did not return an embed start URL.\");\n }\n const output: {\n startUrl: string;\n targetPath?: string;\n expiresAt?: number;\n app: string;\n } = {\n startUrl: parsed.startUrl,\n app: target.app.id,\n };\n if (parsed.targetPath) output.targetPath = parsed.targetPath;\n if (typeof parsed.expiresAt === \"number\")\n output.expiresAt = parsed.expiresAt;\n return output;\n } finally {\n await manager.stop();\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"agent-chat.d.ts","sourceRoot":"","sources":["../../../src/server/plugins/agent-chat.ts"],"names":[],"mappings":";AAIA,wBAkCG"}
1
+ {"version":3,"file":"agent-chat.d.ts","sourceRoot":"","sources":["../../../src/server/plugins/agent-chat.ts"],"names":[],"mappings":";AAIA,wBAmCG"}
@@ -29,6 +29,7 @@ Use the standard workspace primitives:
29
29
  - You receive a compact available-apps block with sibling workspace app names and descriptions. Use it to pick the right A2A target, and call list-connected-agents or tool-search only when you need fresh details.
30
30
  - When answering whether workspace apps expose agent cards or A2A endpoints, call list-workspace-apps with includeAgentCards=true. If you have not requested that probe, absence of agent-card fields means unchecked, not unavailable.
31
31
  - When creating a new workspace app, create a separate app under apps/<app-id> with apps/<app-id>/package.json including a concise generated description, mount it at /<app-id>, use relative /<app-id> links, never hardcode localhost or dev ports, use shadcn/ui with @tabler/icons-react rather than lucide-react, and ensure the React Router client entry preserves APP_BASE_PATH/VITE_APP_BASE_PATH via appBasePath(). There is no separate workspace app registry to edit.
32
+ - If the starter template is used, treat it as scaffolding only: the finished app must be branded as the requested app with its own home screen/navigation/package metadata/manifest, and must not leave visible "Starter", "Blank app", or "New app" UI behind.
32
33
  - Treat first-party apps such as Mail, Calendar, Analytics, Brain, and Dispatch as existing hosted/connected neighbors available through links and A2A/default connected agents. Do not create wrapper apps, child apps, nested routes, or cloned template copies just to give a new app access to them; build only the genuinely new workflow and delegate cross-app work to those existing apps.
33
34
 
34
35
  When a user asks for something like a digest, reminder, routing rule, or saved behavior:
@@ -1 +1 @@
1
- {"version":3,"file":"agent-chat.js","sourceRoot":"","sources":["../../../src/server/plugins/agent-chat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,eAAe,qBAAqB,CAAC;IACnC,KAAK,EAAE,UAAU;IACjB,0EAA0E;IAC1E,2EAA2E;IAC3E,2EAA2E;IAC3E,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAC5B,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC;QACvC,OAAO,GAAG,CAAC,KAAK,CAAC;IACnB,CAAC;IACD,2EAA2E;IAC3E,2EAA2E;IAC3E,wEAAwE;IACxE,OAAO,EAAE,eAAe;IACxB,YAAY,EAAE;;;;;;;;;;;;;;;;;;;;4EAoB4D;CAC3E,CAAC,CAAC","sourcesContent":["import { createAgentChatPlugin } from \"@agent-native/core/server\";\nimport { getOrgContext } from \"@agent-native/core/org\";\nimport { dispatchActions } from \"../../actions/index.js\";\n\nexport default createAgentChatPlugin({\n appId: \"dispatch\",\n // Without this, AGENT_ORG_ID is never set on agent action calls and every\n // row written through the frontend (vault secrets, destinations, workspace\n // resources) lands with org_id=NULL — breaking data isolation across orgs.\n resolveOrgId: async (event) => {\n const ctx = await getOrgContext(event);\n return ctx.orgId;\n },\n // Read actions directly from the package's own action map rather than from\n // a build-time-generated `.generated/actions-registry.ts` (the latter is a\n // template-only construct that the Vite plugin emits next to actions/).\n actions: dispatchActions,\n systemPrompt: `You are the central dispatch for this workspace.\n\nDefault posture:\n- Treat Slack and Telegram as shared entrypoints into the workspace.\n- Heavily delegate domain work to specialized agents through A2A when another app owns the job.\n- Keep durable memory and operating instructions in resources rather than ephemeral chat.\n- Prefer replying in the current external thread unless the user explicitly asks you to send to a saved destination.\n\nUse the standard workspace primitives:\n- Read and update resources like AGENTS.md, LEARNINGS.md, jobs/*.md, agents/*.md, and remote-agents/*.json when appropriate.\n- Use recurring jobs for scheduled behavior.\n- Use custom agent profiles in agents/*.md for local spawned work and remote-agents/*.json for remote A2A apps.\n- You receive a compact available-apps block with sibling workspace app names and descriptions. Use it to pick the right A2A target, and call list-connected-agents or tool-search only when you need fresh details.\n- When answering whether workspace apps expose agent cards or A2A endpoints, call list-workspace-apps with includeAgentCards=true. If you have not requested that probe, absence of agent-card fields means unchecked, not unavailable.\n- When creating a new workspace app, create a separate app under apps/<app-id> with apps/<app-id>/package.json including a concise generated description, mount it at /<app-id>, use relative /<app-id> links, never hardcode localhost or dev ports, use shadcn/ui with @tabler/icons-react rather than lucide-react, and ensure the React Router client entry preserves APP_BASE_PATH/VITE_APP_BASE_PATH via appBasePath(). There is no separate workspace app registry to edit.\n- Treat first-party apps such as Mail, Calendar, Analytics, Brain, and Dispatch as existing hosted/connected neighbors available through links and A2A/default connected agents. Do not create wrapper apps, child apps, nested routes, or cloned template copies just to give a new app access to them; build only the genuinely new workflow and delegate cross-app work to those existing apps.\n\nWhen a user asks for something like a digest, reminder, routing rule, or saved behavior:\n- First decide whether it should be a resource, a recurring job, a destination, or a delegated task.\n- Keep responses concise and operational.\n- Avoid inventing integrations or destinations that are not configured yet.`,\n});\n"]}
1
+ {"version":3,"file":"agent-chat.js","sourceRoot":"","sources":["../../../src/server/plugins/agent-chat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,eAAe,qBAAqB,CAAC;IACnC,KAAK,EAAE,UAAU;IACjB,0EAA0E;IAC1E,2EAA2E;IAC3E,2EAA2E;IAC3E,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAC5B,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC;QACvC,OAAO,GAAG,CAAC,KAAK,CAAC;IACnB,CAAC;IACD,2EAA2E;IAC3E,2EAA2E;IAC3E,wEAAwE;IACxE,OAAO,EAAE,eAAe;IACxB,YAAY,EAAE;;;;;;;;;;;;;;;;;;;;;4EAqB4D;CAC3E,CAAC,CAAC","sourcesContent":["import { createAgentChatPlugin } from \"@agent-native/core/server\";\nimport { getOrgContext } from \"@agent-native/core/org\";\nimport { dispatchActions } from \"../../actions/index.js\";\n\nexport default createAgentChatPlugin({\n appId: \"dispatch\",\n // Without this, AGENT_ORG_ID is never set on agent action calls and every\n // row written through the frontend (vault secrets, destinations, workspace\n // resources) lands with org_id=NULL — breaking data isolation across orgs.\n resolveOrgId: async (event) => {\n const ctx = await getOrgContext(event);\n return ctx.orgId;\n },\n // Read actions directly from the package's own action map rather than from\n // a build-time-generated `.generated/actions-registry.ts` (the latter is a\n // template-only construct that the Vite plugin emits next to actions/).\n actions: dispatchActions,\n systemPrompt: `You are the central dispatch for this workspace.\n\nDefault posture:\n- Treat Slack and Telegram as shared entrypoints into the workspace.\n- Heavily delegate domain work to specialized agents through A2A when another app owns the job.\n- Keep durable memory and operating instructions in resources rather than ephemeral chat.\n- Prefer replying in the current external thread unless the user explicitly asks you to send to a saved destination.\n\nUse the standard workspace primitives:\n- Read and update resources like AGENTS.md, LEARNINGS.md, jobs/*.md, agents/*.md, and remote-agents/*.json when appropriate.\n- Use recurring jobs for scheduled behavior.\n- Use custom agent profiles in agents/*.md for local spawned work and remote-agents/*.json for remote A2A apps.\n- You receive a compact available-apps block with sibling workspace app names and descriptions. Use it to pick the right A2A target, and call list-connected-agents or tool-search only when you need fresh details.\n- When answering whether workspace apps expose agent cards or A2A endpoints, call list-workspace-apps with includeAgentCards=true. If you have not requested that probe, absence of agent-card fields means unchecked, not unavailable.\n- When creating a new workspace app, create a separate app under apps/<app-id> with apps/<app-id>/package.json including a concise generated description, mount it at /<app-id>, use relative /<app-id> links, never hardcode localhost or dev ports, use shadcn/ui with @tabler/icons-react rather than lucide-react, and ensure the React Router client entry preserves APP_BASE_PATH/VITE_APP_BASE_PATH via appBasePath(). There is no separate workspace app registry to edit.\n- If the starter template is used, treat it as scaffolding only: the finished app must be branded as the requested app with its own home screen/navigation/package metadata/manifest, and must not leave visible \"Starter\", \"Blank app\", or \"New app\" UI behind.\n- Treat first-party apps such as Mail, Calendar, Analytics, Brain, and Dispatch as existing hosted/connected neighbors available through links and A2A/default connected agents. Do not create wrapper apps, child apps, nested routes, or cloned template copies just to give a new app access to them; build only the genuinely new workflow and delegate cross-app work to those existing apps.\n\nWhen a user asks for something like a digest, reminder, routing rule, or saved behavior:\n- First decide whether it should be a resource, a recurring job, a destination, or a delegated task.\n- Keep responses concise and operational.\n- Avoid inventing integrations or destinations that are not configured yet.`,\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"integrations.d.ts","sourceRoot":"","sources":["../../../src/server/plugins/integrations.ts"],"names":[],"mappings":"AA+BA;;;;GAIG;AACH,QAAA,MAAM,0BAA0B,GAAU,UAAU,GAAG,kBAuBtD,CAAC;AAEF,eAAe,0BAA0B,CAAC"}
1
+ {"version":3,"file":"integrations.d.ts","sourceRoot":"","sources":["../../../src/server/plugins/integrations.ts"],"names":[],"mappings":"AAgCA;;;;GAIG;AACH,QAAA,MAAM,0BAA0B,GAAU,UAAU,GAAG,kBAuBtD,CAAC;AAEF,eAAe,0BAA0B,CAAC"}
@@ -19,7 +19,8 @@ When a user asks for something:
19
19
  - Exception: if the downstream agent reports a missing model/provider credential, do not name exact env vars, Vault keys, tokens, or secrets. Say the target app needs an LLM connection and recommend connecting Builder/managed LLM for that app; keep bring-your-own provider keys as a secondary option only if the user asks.
20
20
  - If the user asks to create, build, make, scaffold, or generate an "agent" from Dispatch chat or by tagging @agent-native in Slack, email, or Telegram, first classify the ask. If it is a simple Dispatch-native behavior like a reminder, digest, monitor, routing rule, saved instruction, or recurring workflow, create or update the recurring job/resource/destination in Dispatch. If it is a robust unique product or teammate that needs its own UI, data model, actions, integrations, or domain workflow, treat it as a new workspace app and call start-workspace-app-creation.
21
21
  - If a new-app prompt asks for access to Mail, Calendar, Analytics, Brain, or similar first-party app data/agents, keep using the existing hosted/connected app and A2A path. Do not ask Builder to scaffold those apps as children of the new app unless the user explicitly asks for a customized fork/copy.
22
- - If the user explicitly asks for a new app or workspace app, call start-workspace-app-creation with their prompt and include a concise generated description when possible. Do not satisfy a new-app request by adding a route, page, component, or file inside apps/starter or another existing app unless the user explicitly asks to modify that existing app. If the request is too vague to classify, ask one concise follow-up. If the action returns mode "builder", reply with the Builder branch URL; Builder is responsible for creating the separate workspace app under apps/<app-id>, mounting it at /<app-id>, ensuring apps/<app-id>/package.json exists with name/displayName and description so Dispatch discovers it, using relative /<app-id> links instead of hardcoded localhost/dev ports, and preserving APP_BASE_PATH/VITE_APP_BASE_PATH via appBasePath() in the React Router client entry. The new app lives at the workspace root /<app-id>, NOT under /dispatch/<app-id>, /apps/<app-id>, or any other Dispatch tab — when telling the user where to find it, link to /<app-id> only. There is no separate workspace app registry to edit. If it returns mode "local-agent", tell the user it is ready for the local code agent and include the returned app path/prompt summary. If it returns mode "coming-soon" or "builder-unavailable", explain the missing Builder setup and ask them to connect/configure Builder.
22
+ - If the starter template is used, treat it as scaffolding only: the finished app must be branded as the requested app with its own home screen/navigation/package metadata/manifest, and must not leave visible "Starter", "Blank app", or "New app" UI behind.
23
+ - If the user explicitly asks for a new app or workspace app, call start-workspace-app-creation with their prompt and include a concise generated description by default. Do not satisfy a new-app request by adding a route, page, component, or file inside apps/starter or another existing app unless the user explicitly asks to modify that existing app. If the request is too vague to classify, ask one concise follow-up. If the action returns mode "builder", reply with the Builder branch URL; Builder is responsible for creating the separate workspace app under apps/<app-id>, mounting it at /<app-id>, ensuring apps/<app-id>/package.json exists with name/displayName and description so Dispatch discovers it, using relative /<app-id> links instead of hardcoded localhost/dev ports, and preserving APP_BASE_PATH/VITE_APP_BASE_PATH via appBasePath() in the React Router client entry. The new app lives at the workspace root /<app-id>, NOT under /dispatch/<app-id>, /apps/<app-id>, or any other Dispatch tab — when telling the user where to find it, link to /<app-id> only. There is no separate workspace app registry to edit. If it returns mode "local-agent", tell the user it is ready for the local code agent and include the returned app path/prompt summary. If it returns mode "coming-soon" or "builder-unavailable", explain the missing Builder setup and ask them to connect/configure Builder.
23
24
  - For digests, reminders, or saved behavior, prefer recurring jobs, resources, or destinations over chat replies.
24
25
  - Keep responses concise and operational — messaging platforms have character limits.
25
26
  - Use markdown sparingly (bold and lists are fine, avoid complex formatting).
@@ -1 +1 @@
1
- {"version":3,"file":"integrations.js","sourceRoot":"","sources":["../../../src/server/plugins/integrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EACL,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,kCAAkC,GAAG;;;;;;;;;;;;;;;;;;;;;4FAqBiD,CAAC;AAE7F;;;;GAIG;AACH,MAAM,0BAA0B,GAAG,KAAK,EAAE,QAAa,EAAE,EAAE;IACzD,MAAM,EAAE,YAAY,GAAG,EAAE,EAAE,GAAG,iBAAiB,EAAE,CAAC;IAClD,MAAM,cAAc,GAAG,YAAY,CAAC,YAAY,CAAC;IACjD,MAAM,YAAY,GAChB,OAAO,cAAc,KAAK,QAAQ;QAChC,CAAC,CAAC,cAAc;QAChB,CAAC,CAAC,OAAO,cAAc,KAAK,UAAU;YACpC,CAAC,CAAC,cAAc,CAAC,kCAAkC,CAAC;YACpD,CAAC,CAAC,kCAAkC,CAAC;IAE3C,MAAM,MAAM,GAAG,wBAAwB,CAAC;QACtC,KAAK,EAAE,UAAU;QACjB,OAAO,EAAE,eAAe;QACxB,YAAY,EAAE,oBAAoB;QAClC,aAAa,EAAE,qBAAqB;QACpC,YAAY;QACZ,wDAAwD;QACxD,yEAAyE;QACzE,+DAA+D;QAC/D,6EAA6E;KAC9E,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC1B,CAAC,CAAC;AAEF,eAAe,0BAA0B,CAAC","sourcesContent":["import { createIntegrationsPlugin } from \"@agent-native/core/server\";\nimport {\n beforeDispatchProcess,\n resolveDispatchOwner,\n} from \"../lib/dispatch-integrations.js\";\nimport { getDispatchConfig } from \"../index.js\";\nimport { dispatchActions } from \"../../actions/index.js\";\n\nconst DISPATCH_INTEGRATION_SYSTEM_PROMPT = `You are the central dispatch for this workspace, responding via a messaging platform integration (Slack, Telegram, email, etc.).\n\nDefault posture:\n- Treat Slack, Telegram, and email as shared entrypoints into the workspace.\n- Heavily delegate domain work to specialized agents through A2A (call-agent) when another app owns the job. Apps you can delegate to include slides (decks/presentations), analytics (data/dashboards), content (docs/articles), videos (Remotion compositions), forms (form builder), clips (screen recordings), design (visual designs), and images (brand image libraries and generated raster imagery).\n- Use the available-apps prompt context first, then list-connected-agents when you need fresh details, to see what agents are available before assuming a request must be handled locally.\n- When asked whether workspace apps expose agent cards or A2A endpoints, call list-workspace-apps with includeAgentCards=true. Without that probe, missing agent-card fields mean unchecked, not unavailable.\n- Treat first-party apps such as Mail, Calendar, Analytics, Brain, and Dispatch as existing hosted/connected neighbors available through links and A2A/default connected agents. Do not create wrapper apps, child apps, nested routes, or cloned template copies just to give a new app access to them; build only the genuinely new workflow and delegate cross-app work to those existing apps.\n- Keep durable memory and operating instructions in resources rather than ephemeral chat.\n- Reply in the originating thread unless the user explicitly asks you to send to a saved destination.\n\nWhen a user asks for something:\n- If it belongs to analytics, content, slides, videos, images, etc., delegate via call-agent — do not re-implement the domain logic in dispatch.\n- After call-agent returns an answer, RELAY IT DIRECTLY to the user with at most a one-line preface — do not rephrase, summarize, or add commentary. The downstream agent already crafted the answer; your job is delivery, not editing. This minimizes round-trips and keeps the user-visible reply fast.\n- Exception: if the downstream agent reports a missing model/provider credential, do not name exact env vars, Vault keys, tokens, or secrets. Say the target app needs an LLM connection and recommend connecting Builder/managed LLM for that app; keep bring-your-own provider keys as a secondary option only if the user asks.\n- If the user asks to create, build, make, scaffold, or generate an \"agent\" from Dispatch chat or by tagging @agent-native in Slack, email, or Telegram, first classify the ask. If it is a simple Dispatch-native behavior like a reminder, digest, monitor, routing rule, saved instruction, or recurring workflow, create or update the recurring job/resource/destination in Dispatch. If it is a robust unique product or teammate that needs its own UI, data model, actions, integrations, or domain workflow, treat it as a new workspace app and call start-workspace-app-creation.\n- If a new-app prompt asks for access to Mail, Calendar, Analytics, Brain, or similar first-party app data/agents, keep using the existing hosted/connected app and A2A path. Do not ask Builder to scaffold those apps as children of the new app unless the user explicitly asks for a customized fork/copy.\n- If the user explicitly asks for a new app or workspace app, call start-workspace-app-creation with their prompt and include a concise generated description when possible. Do not satisfy a new-app request by adding a route, page, component, or file inside apps/starter or another existing app unless the user explicitly asks to modify that existing app. If the request is too vague to classify, ask one concise follow-up. If the action returns mode \"builder\", reply with the Builder branch URL; Builder is responsible for creating the separate workspace app under apps/<app-id>, mounting it at /<app-id>, ensuring apps/<app-id>/package.json exists with name/displayName and description so Dispatch discovers it, using relative /<app-id> links instead of hardcoded localhost/dev ports, and preserving APP_BASE_PATH/VITE_APP_BASE_PATH via appBasePath() in the React Router client entry. The new app lives at the workspace root /<app-id>, NOT under /dispatch/<app-id>, /apps/<app-id>, or any other Dispatch tab — when telling the user where to find it, link to /<app-id> only. There is no separate workspace app registry to edit. If it returns mode \"local-agent\", tell the user it is ready for the local code agent and include the returned app path/prompt summary. If it returns mode \"coming-soon\" or \"builder-unavailable\", explain the missing Builder setup and ask them to connect/configure Builder.\n- For digests, reminders, or saved behavior, prefer recurring jobs, resources, or destinations over chat replies.\n- Keep responses concise and operational — messaging platforms have character limits.\n- Use markdown sparingly (bold and lists are fine, avoid complex formatting).\n- If a task requires many steps, summarize what you did rather than streaming every detail.`;\n\n/**\n * Defer plugin construction until the Nitro plugin actually fires so the\n * config-aware system prompt resolves AFTER `setupDispatch(config)` has\n * stamped the active config (plugin module load order is not guaranteed).\n */\nconst dispatchIntegrationsPlugin = async (nitroApp: any) => {\n const { integrations = {} } = getDispatchConfig();\n const promptOverride = integrations.systemPrompt;\n const systemPrompt =\n typeof promptOverride === \"string\"\n ? promptOverride\n : typeof promptOverride === \"function\"\n ? promptOverride(DISPATCH_INTEGRATION_SYSTEM_PROMPT)\n : DISPATCH_INTEGRATION_SYSTEM_PROMPT;\n\n const plugin = createIntegrationsPlugin({\n appId: \"dispatch\",\n actions: dispatchActions,\n resolveOwner: resolveDispatchOwner,\n beforeProcess: beforeDispatchProcess,\n systemPrompt,\n // Inherit the framework default (claude-sonnet-4-6 from\n // packages/core/src/integrations/plugin.ts). Haiku was tried for latency\n // but hallucinated URLs/IDs after delegated call-agent results\n // (e.g. inventing `https://slides.workspace.com/deck/builder-io-deck-2024`).\n });\n\n return plugin(nitroApp);\n};\n\nexport default dispatchIntegrationsPlugin;\n"]}
1
+ {"version":3,"file":"integrations.js","sourceRoot":"","sources":["../../../src/server/plugins/integrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EACL,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,kCAAkC,GAAG;;;;;;;;;;;;;;;;;;;;;;4FAsBiD,CAAC;AAE7F;;;;GAIG;AACH,MAAM,0BAA0B,GAAG,KAAK,EAAE,QAAa,EAAE,EAAE;IACzD,MAAM,EAAE,YAAY,GAAG,EAAE,EAAE,GAAG,iBAAiB,EAAE,CAAC;IAClD,MAAM,cAAc,GAAG,YAAY,CAAC,YAAY,CAAC;IACjD,MAAM,YAAY,GAChB,OAAO,cAAc,KAAK,QAAQ;QAChC,CAAC,CAAC,cAAc;QAChB,CAAC,CAAC,OAAO,cAAc,KAAK,UAAU;YACpC,CAAC,CAAC,cAAc,CAAC,kCAAkC,CAAC;YACpD,CAAC,CAAC,kCAAkC,CAAC;IAE3C,MAAM,MAAM,GAAG,wBAAwB,CAAC;QACtC,KAAK,EAAE,UAAU;QACjB,OAAO,EAAE,eAAe;QACxB,YAAY,EAAE,oBAAoB;QAClC,aAAa,EAAE,qBAAqB;QACpC,YAAY;QACZ,wDAAwD;QACxD,yEAAyE;QACzE,+DAA+D;QAC/D,6EAA6E;KAC9E,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC1B,CAAC,CAAC;AAEF,eAAe,0BAA0B,CAAC","sourcesContent":["import { createIntegrationsPlugin } from \"@agent-native/core/server\";\nimport {\n beforeDispatchProcess,\n resolveDispatchOwner,\n} from \"../lib/dispatch-integrations.js\";\nimport { getDispatchConfig } from \"../index.js\";\nimport { dispatchActions } from \"../../actions/index.js\";\n\nconst DISPATCH_INTEGRATION_SYSTEM_PROMPT = `You are the central dispatch for this workspace, responding via a messaging platform integration (Slack, Telegram, email, etc.).\n\nDefault posture:\n- Treat Slack, Telegram, and email as shared entrypoints into the workspace.\n- Heavily delegate domain work to specialized agents through A2A (call-agent) when another app owns the job. Apps you can delegate to include slides (decks/presentations), analytics (data/dashboards), content (docs/articles), videos (Remotion compositions), forms (form builder), clips (screen recordings), design (visual designs), and images (brand image libraries and generated raster imagery).\n- Use the available-apps prompt context first, then list-connected-agents when you need fresh details, to see what agents are available before assuming a request must be handled locally.\n- When asked whether workspace apps expose agent cards or A2A endpoints, call list-workspace-apps with includeAgentCards=true. Without that probe, missing agent-card fields mean unchecked, not unavailable.\n- Treat first-party apps such as Mail, Calendar, Analytics, Brain, and Dispatch as existing hosted/connected neighbors available through links and A2A/default connected agents. Do not create wrapper apps, child apps, nested routes, or cloned template copies just to give a new app access to them; build only the genuinely new workflow and delegate cross-app work to those existing apps.\n- Keep durable memory and operating instructions in resources rather than ephemeral chat.\n- Reply in the originating thread unless the user explicitly asks you to send to a saved destination.\n\nWhen a user asks for something:\n- If it belongs to analytics, content, slides, videos, images, etc., delegate via call-agent — do not re-implement the domain logic in dispatch.\n- After call-agent returns an answer, RELAY IT DIRECTLY to the user with at most a one-line preface — do not rephrase, summarize, or add commentary. The downstream agent already crafted the answer; your job is delivery, not editing. This minimizes round-trips and keeps the user-visible reply fast.\n- Exception: if the downstream agent reports a missing model/provider credential, do not name exact env vars, Vault keys, tokens, or secrets. Say the target app needs an LLM connection and recommend connecting Builder/managed LLM for that app; keep bring-your-own provider keys as a secondary option only if the user asks.\n- If the user asks to create, build, make, scaffold, or generate an \"agent\" from Dispatch chat or by tagging @agent-native in Slack, email, or Telegram, first classify the ask. If it is a simple Dispatch-native behavior like a reminder, digest, monitor, routing rule, saved instruction, or recurring workflow, create or update the recurring job/resource/destination in Dispatch. If it is a robust unique product or teammate that needs its own UI, data model, actions, integrations, or domain workflow, treat it as a new workspace app and call start-workspace-app-creation.\n- If a new-app prompt asks for access to Mail, Calendar, Analytics, Brain, or similar first-party app data/agents, keep using the existing hosted/connected app and A2A path. Do not ask Builder to scaffold those apps as children of the new app unless the user explicitly asks for a customized fork/copy.\n- If the starter template is used, treat it as scaffolding only: the finished app must be branded as the requested app with its own home screen/navigation/package metadata/manifest, and must not leave visible \"Starter\", \"Blank app\", or \"New app\" UI behind.\n- If the user explicitly asks for a new app or workspace app, call start-workspace-app-creation with their prompt and include a concise generated description by default. Do not satisfy a new-app request by adding a route, page, component, or file inside apps/starter or another existing app unless the user explicitly asks to modify that existing app. If the request is too vague to classify, ask one concise follow-up. If the action returns mode \"builder\", reply with the Builder branch URL; Builder is responsible for creating the separate workspace app under apps/<app-id>, mounting it at /<app-id>, ensuring apps/<app-id>/package.json exists with name/displayName and description so Dispatch discovers it, using relative /<app-id> links instead of hardcoded localhost/dev ports, and preserving APP_BASE_PATH/VITE_APP_BASE_PATH via appBasePath() in the React Router client entry. The new app lives at the workspace root /<app-id>, NOT under /dispatch/<app-id>, /apps/<app-id>, or any other Dispatch tab — when telling the user where to find it, link to /<app-id> only. There is no separate workspace app registry to edit. If it returns mode \"local-agent\", tell the user it is ready for the local code agent and include the returned app path/prompt summary. If it returns mode \"coming-soon\" or \"builder-unavailable\", explain the missing Builder setup and ask them to connect/configure Builder.\n- For digests, reminders, or saved behavior, prefer recurring jobs, resources, or destinations over chat replies.\n- Keep responses concise and operational — messaging platforms have character limits.\n- Use markdown sparingly (bold and lists are fine, avoid complex formatting).\n- If a task requires many steps, summarize what you did rather than streaming every detail.`;\n\n/**\n * Defer plugin construction until the Nitro plugin actually fires so the\n * config-aware system prompt resolves AFTER `setupDispatch(config)` has\n * stamped the active config (plugin module load order is not guaranteed).\n */\nconst dispatchIntegrationsPlugin = async (nitroApp: any) => {\n const { integrations = {} } = getDispatchConfig();\n const promptOverride = integrations.systemPrompt;\n const systemPrompt =\n typeof promptOverride === \"string\"\n ? promptOverride\n : typeof promptOverride === \"function\"\n ? promptOverride(DISPATCH_INTEGRATION_SYSTEM_PROMPT)\n : DISPATCH_INTEGRATION_SYSTEM_PROMPT;\n\n const plugin = createIntegrationsPlugin({\n appId: \"dispatch\",\n actions: dispatchActions,\n resolveOwner: resolveDispatchOwner,\n beforeProcess: beforeDispatchProcess,\n systemPrompt,\n // Inherit the framework default (claude-sonnet-4-6 from\n // packages/core/src/integrations/plugin.ts). Haiku was tried for latency\n // but hallucinated URLs/IDs after delegated call-agent results\n // (e.g. inventing `https://slides.workspace.com/deck/builder-io-deck-2024`).\n });\n\n return plugin(nitroApp);\n};\n\nexport default dispatchIntegrationsPlugin;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/dispatch",
3
- "version": "0.8.5",
3
+ "version": "0.8.6",
4
4
  "type": "module",
5
5
  "description": "Dispatch — workspace control plane for agent-native apps. Vault, integrations, destinations, scheduled jobs, and cross-app delegation, shipped as a single drop-in package.",
6
6
  "license": "MIT",
@@ -0,0 +1,13 @@
1
+ import { defineAction } from "@agent-native/core";
2
+ import { z } from "zod";
3
+ import { askGrantedDispatchMcpApp } from "../server/lib/mcp-gateway.js";
4
+
5
+ export default defineAction({
6
+ description:
7
+ "Send a natural-language request to an app available through Dispatch MCP. Use list_apps first to see which apps are granted.",
8
+ schema: z.object({
9
+ app: z.string().describe("Granted app id, e.g. mail or calendar."),
10
+ message: z.string().describe("The request to send to that app's agent."),
11
+ }),
12
+ run: async ({ app, message }) => askGrantedDispatchMcpApp(app, message),
13
+ });
@@ -0,0 +1,29 @@
1
+ import { defineAction } from "@agent-native/core";
2
+ import { z } from "zod";
3
+ import { createGrantedDispatchMcpEmbedSession } from "../server/lib/mcp-gateway.js";
4
+
5
+ export default defineAction({
6
+ description:
7
+ "MCP Apps helper: create a browser embed session for a Dispatch-granted app URL. Usually called by an MCP App iframe, not directly by the model.",
8
+ schema: z.object({
9
+ app: z
10
+ .string()
11
+ .optional()
12
+ .describe("Optional granted app id when path is app-relative."),
13
+ url: z
14
+ .string()
15
+ .optional()
16
+ .describe("Absolute URL returned by open_app, or app-relative path."),
17
+ path: z
18
+ .string()
19
+ .optional()
20
+ .describe("App-relative path. Requires app when url is not provided."),
21
+ chrome: z
22
+ .enum(["full", "minimal"])
23
+ .optional()
24
+ .describe("Embed chrome preference. Defaults to full."),
25
+ }),
26
+ readOnly: false,
27
+ parallelSafe: true,
28
+ run: async (args) => createGrantedDispatchMcpEmbedSession(args),
29
+ });
@@ -5,6 +5,12 @@ import { dispatchActions } from "./index.js";
5
5
  describe("dispatch action registry", () => {
6
6
  it("keeps workspace resources runtime-inherited instead of exposing sync actions", () => {
7
7
  expect(dispatchActions).toHaveProperty("list-workspace-resources-for-app");
8
+ expect(dispatchActions).toHaveProperty("list-mcp-app-access");
9
+ expect(dispatchActions).toHaveProperty("set-mcp-app-access");
10
+ expect(dispatchActions).toHaveProperty("list_apps");
11
+ expect(dispatchActions).toHaveProperty("ask_app");
12
+ expect(dispatchActions).toHaveProperty("open_app");
13
+ expect(dispatchActions).toHaveProperty("create_embed_session");
8
14
  expect(dispatchActions).toHaveProperty(
9
15
  "get-workspace-resource-effective-context",
10
16
  );
@@ -2,6 +2,7 @@ import type { ActionEntry } from "@agent-native/core/server";
2
2
  import approveDispatchChange from "./approve-dispatch-change.js";
3
3
  import approveVaultRequest from "./approve-vault-request.js";
4
4
  import archiveWorkspaceApp from "./archive-workspace-app.js";
5
+ import askApp from "./ask_app.js";
5
6
  import createLinkToken from "./create-link-token.js";
6
7
  import createPylonTicket from "./create-pylon-ticket.js";
7
8
  import createVaultGrant from "./create-vault-grant.js";
@@ -9,6 +10,7 @@ import createVaultSecret from "./create-vault-secret.js";
9
10
  import createWorkspaceResourceGrant from "./create-workspace-resource-grant.js";
10
11
  import createWorkspaceResource from "./create-workspace-resource.js";
11
12
  import createDreamReport from "./create-dream-report.js";
13
+ import createEmbedSession from "./create_embed_session.js";
12
14
  import deleteDestination from "./delete-destination.js";
13
15
  import deleteVaultSecret from "./delete-vault-secret.js";
14
16
  import deleteWorkspaceResource from "./delete-workspace-resource.js";
@@ -36,6 +38,8 @@ import listDreamCandidates from "./list-dream-candidates.js";
36
38
  import listDreams from "./list-dreams.js";
37
39
  import listIntegrationsCatalog from "./list-integrations-catalog.js";
38
40
  import listLinkedIdentities from "./list-linked-identities.js";
41
+ import listMcpAppAccess from "./list-mcp-app-access.js";
42
+ import listApps from "./list_apps.js";
39
43
  import listVaultAudit from "./list-vault-audit.js";
40
44
  import listVaultGrants from "./list-vault-grants.js";
41
45
  import listVaultRequests from "./list-vault-requests.js";
@@ -47,6 +51,7 @@ import listWorkspaceResourceGrants from "./list-workspace-resource-grants.js";
47
51
  import listWorkspaceResourcesForApp from "./list-workspace-resources-for-app.js";
48
52
  import listWorkspaceResources from "./list-workspace-resources.js";
49
53
  import navigate from "./navigate.js";
54
+ import openApp from "./open_app.js";
50
55
  import applyDreamProposal from "./apply-dream-proposal.js";
51
56
  import previewDreamProposal from "./preview-dream-proposal.js";
52
57
  import previewWorkspaceResourceChange from "./preview-workspace-resource-change.js";
@@ -64,6 +69,7 @@ import sendPlatformMessage from "./send-platform-message.js";
64
69
  import setAppCreationSettings from "./set-app-creation-settings.js";
65
70
  import setDispatchApprovalPolicy from "./set-dispatch-approval-policy.js";
66
71
  import setDreamSettings from "./set-dream-settings.js";
72
+ import setMcpAppAccess from "./set-mcp-app-access.js";
67
73
  import setVaultAccessSettings from "./set-vault-access-settings.js";
68
74
  import startWorkspaceAppCreation from "./start-workspace-app-creation.js";
69
75
  import syncVaultToApp from "./sync-vault-to-app.js";
@@ -84,6 +90,7 @@ export const dispatchActions: Record<string, ActionEntry> = {
84
90
  "approve-dispatch-change": approveDispatchChange,
85
91
  "approve-vault-request": approveVaultRequest,
86
92
  "archive-workspace-app": archiveWorkspaceApp,
93
+ ask_app: askApp,
87
94
  "create-link-token": createLinkToken,
88
95
  "create-pylon-ticket": createPylonTicket,
89
96
  "create-vault-grant": createVaultGrant,
@@ -91,6 +98,7 @@ export const dispatchActions: Record<string, ActionEntry> = {
91
98
  "create-workspace-resource-grant": createWorkspaceResourceGrant,
92
99
  "create-workspace-resource": createWorkspaceResource,
93
100
  "create-dream-report": createDreamReport,
101
+ create_embed_session: createEmbedSession,
94
102
  "delete-destination": deleteDestination,
95
103
  "delete-vault-secret": deleteVaultSecret,
96
104
  "delete-workspace-resource": deleteWorkspaceResource,
@@ -119,6 +127,8 @@ export const dispatchActions: Record<string, ActionEntry> = {
119
127
  "list-dreams": listDreams,
120
128
  "list-integrations-catalog": listIntegrationsCatalog,
121
129
  "list-linked-identities": listLinkedIdentities,
130
+ "list-mcp-app-access": listMcpAppAccess,
131
+ list_apps: listApps,
122
132
  "list-vault-audit": listVaultAudit,
123
133
  "list-vault-grants": listVaultGrants,
124
134
  "list-vault-requests": listVaultRequests,
@@ -130,6 +140,7 @@ export const dispatchActions: Record<string, ActionEntry> = {
130
140
  "list-workspace-resources-for-app": listWorkspaceResourcesForApp,
131
141
  "list-workspace-resources": listWorkspaceResources,
132
142
  navigate: navigate,
143
+ open_app: openApp,
133
144
  "apply-dream-proposal": applyDreamProposal,
134
145
  "preview-dream-proposal": previewDreamProposal,
135
146
  "preview-workspace-resource-change": previewWorkspaceResourceChange,
@@ -147,6 +158,7 @@ export const dispatchActions: Record<string, ActionEntry> = {
147
158
  "set-app-creation-settings": setAppCreationSettings,
148
159
  "set-dispatch-approval-policy": setDispatchApprovalPolicy,
149
160
  "set-dream-settings": setDreamSettings,
161
+ "set-mcp-app-access": setMcpAppAccess,
150
162
  "set-vault-access-settings": setVaultAccessSettings,
151
163
  "start-workspace-app-creation": startWorkspaceAppCreation,
152
164
  "sync-vault-to-app": syncVaultToApp,
@@ -0,0 +1,26 @@
1
+ import { defineAction } from "@agent-native/core";
2
+ import { z } from "zod";
3
+ import { listDispatchMcpApps } from "../server/lib/mcp-gateway.js";
4
+
5
+ export default defineAction({
6
+ description:
7
+ "List the apps exposed through Dispatch's unified MCP gateway and the current app access policy.",
8
+ schema: z.object({}),
9
+ http: { method: "GET" },
10
+ readOnly: true,
11
+ run: async () => {
12
+ const { settings, apps } = await listDispatchMcpApps();
13
+ return {
14
+ mode: settings.mode,
15
+ selectedAppIds: settings.selectedAppIds,
16
+ updatedAt: settings.updatedAt,
17
+ updatedBy: settings.updatedBy,
18
+ apps,
19
+ grantedApps: apps.filter((app) => app.granted),
20
+ counts: {
21
+ apps: apps.length,
22
+ granted: apps.filter((app) => app.granted).length,
23
+ },
24
+ };
25
+ },
26
+ });
@@ -0,0 +1,27 @@
1
+ import { defineAction } from "@agent-native/core";
2
+ import { z } from "zod";
3
+ import { listGrantedDispatchMcpApps } from "../server/lib/mcp-gateway.js";
4
+
5
+ export default defineAction({
6
+ description:
7
+ "List the apps this Dispatch MCP gateway can route to. The result is filtered by Dispatch's MCP app access policy.",
8
+ schema: z.object({}),
9
+ http: { method: "GET" },
10
+ readOnly: true,
11
+ parallelSafe: true,
12
+ run: async () => {
13
+ const apps = await listGrantedDispatchMcpApps();
14
+ return {
15
+ workspace: true,
16
+ gateway: "dispatch",
17
+ apps: apps.map((app) => ({
18
+ id: app.id,
19
+ name: app.name,
20
+ description: app.description,
21
+ url: app.url,
22
+ running: true,
23
+ source: "dispatch-mcp-grant",
24
+ })),
25
+ };
26
+ },
27
+ });
@@ -0,0 +1,61 @@
1
+ import { defineAction, embedApp } from "@agent-native/core";
2
+ import { z } from "zod";
3
+ import { openGrantedDispatchMcpApp } from "../server/lib/mcp-gateway.js";
4
+
5
+ const deepLinkParam = z.union([z.string(), z.number(), z.boolean()]);
6
+ const openAppSchema = z
7
+ .object({
8
+ app: z.string().describe("Granted app id, e.g. mail or calendar."),
9
+ view: z.string().optional().describe("Target view in the app, e.g. inbox."),
10
+ path: z
11
+ .string()
12
+ .optional()
13
+ .describe(
14
+ "Optional same-origin app route to open directly, e.g. /dashboards/q2.",
15
+ ),
16
+ params: z
17
+ .record(z.string(), deepLinkParam)
18
+ .optional()
19
+ .describe("Optional record-focus or filter params."),
20
+ embed: z
21
+ .boolean()
22
+ .optional()
23
+ .describe("Render the app inline in MCP Apps when supported."),
24
+ chrome: z
25
+ .enum(["full", "minimal"])
26
+ .optional()
27
+ .describe("Embed chrome preference for compatible app routes."),
28
+ })
29
+ .refine((input) => input.view?.trim() || input.path?.trim(), {
30
+ message: "open_app requires either view or path",
31
+ path: ["view"],
32
+ });
33
+
34
+ export default defineAction({
35
+ description:
36
+ "Build a deep link or embeddable app route for an app available through Dispatch MCP. No side effects; surface the returned Open link to the user.",
37
+ schema: openAppSchema,
38
+ http: { method: "GET" },
39
+ readOnly: true,
40
+ parallelSafe: true,
41
+ run: async (args) => openGrantedDispatchMcpApp(args),
42
+ link: ({ result }) => {
43
+ if (!result || typeof result !== "object") return null;
44
+ const r = result as { url?: string; app?: string; view?: string };
45
+ if (!r.url) return null;
46
+ return {
47
+ url: r.url,
48
+ label: `Open ${r.app ?? "app"}`,
49
+ view: r.view,
50
+ };
51
+ },
52
+ mcpApp: {
53
+ resource: embedApp({
54
+ title: "Open app",
55
+ description: "Render the requested granted app route inline.",
56
+ iframeTitle: "Dispatch MCP app",
57
+ openLabel: "Open app",
58
+ frameDomains: ["https:", "http://localhost:*", "http://127.0.0.1:*"],
59
+ }),
60
+ },
61
+ });
@@ -0,0 +1,59 @@
1
+ import { defineAction } from "@agent-native/core";
2
+ import { z } from "zod";
3
+ import { discoverAgents } from "@agent-native/core/server/agent-discovery";
4
+ import { setDispatchMcpAppAccessSettings } from "../server/lib/mcp-access-store.js";
5
+ import { recordAudit } from "../server/lib/dispatch-store.js";
6
+ import listMcpAppAccess from "./list-mcp-app-access.js";
7
+
8
+ const modeSchema = z.enum(["all-apps", "selected-apps"]);
9
+
10
+ export default defineAction({
11
+ description:
12
+ "Set which apps are available through Dispatch's unified MCP gateway.",
13
+ schema: z.object({
14
+ mode: modeSchema.describe(
15
+ "Use all-apps to expose every discovered app, or selected-apps to allow only selectedAppIds.",
16
+ ),
17
+ selectedAppIds: z
18
+ .array(z.string())
19
+ .default([])
20
+ .describe("App IDs to expose when mode is selected-apps."),
21
+ }),
22
+ run: async (args) => {
23
+ const agents = await discoverAgents("dispatch");
24
+ const knownIds = new Set(agents.map((agent) => agent.id));
25
+ const selectedAppIds = Array.from(
26
+ new Set(
27
+ args.selectedAppIds
28
+ .map((id) => id.trim().toLowerCase())
29
+ .filter(Boolean),
30
+ ),
31
+ );
32
+ const unknown = selectedAppIds.filter((id) => !knownIds.has(id));
33
+ if (unknown.length > 0) {
34
+ throw new Error(
35
+ `Unknown app(s): ${unknown.join(", ")}. Use list-mcp-app-access to see available app IDs.`,
36
+ );
37
+ }
38
+ if (args.mode === "selected-apps" && selectedAppIds.length === 0) {
39
+ throw new Error("selected-apps mode requires at least one app ID.");
40
+ }
41
+
42
+ await setDispatchMcpAppAccessSettings({
43
+ mode: args.mode,
44
+ selectedAppIds,
45
+ });
46
+ await recordAudit({
47
+ action: "mcp-access.updated",
48
+ targetType: "dispatch-mcp-access",
49
+ targetId: "unified-mcp",
50
+ summary:
51
+ args.mode === "all-apps"
52
+ ? "Allowed Dispatch MCP access to all apps"
53
+ : `Allowed Dispatch MCP access to ${selectedAppIds.length} selected app(s)`,
54
+ metadata: { mode: args.mode, selectedAppIds },
55
+ }).catch(() => {});
56
+
57
+ return listMcpAppAccess.run({});
58
+ },
59
+ });
@@ -5,7 +5,7 @@ import { startWorkspaceAppCreation } from "../server/lib/app-creation-store.js";
5
5
 
6
6
  export default defineAction({
7
7
  description:
8
- "Start creating a new workspace app from Dispatch when the request truly needs its own app. In local dev this returns a code-agent prompt; in production it creates a Builder branch when a Builder project is configured. The result must be a separate workspace app under apps/<app-id>, not a new route or file in apps/starter. If the request needs Mail, Calendar, Analytics, Brain, or another first-party app, use the existing hosted/connected app via links or A2A; do not clone, wrap, or nest those templates inside the new app unless the user explicitly asks for a customized copy.",
8
+ 'Start creating a new workspace app from Dispatch when the request truly needs its own app. Callers should include a concise generated description by default; Dispatch generates one from the prompt when omitted. In local dev this returns a code-agent prompt; in production it creates a Builder branch when a Builder project is configured. The result must be a separate workspace app under apps/<app-id>, not a new route or file in apps/starter. If starter is used as the source template, the finished app must be branded as the requested app and must not leave visible "Starter", "Blank app", or "New app" UI behind. If the request needs Mail, Calendar, Analytics, Brain, or another first-party app, use the existing hosted/connected app via links or A2A; do not clone, wrap, or nest those templates inside the new app unless the user explicitly asks for a customized copy.',
9
9
  schema: z.object({
10
10
  prompt: z.string().min(1).describe("The user's app creation request"),
11
11
  appId: z
@@ -74,6 +74,14 @@ export default defineAction({
74
74
  if (navigation?.view === "destinations") {
75
75
  screen.recentDestinations = overview.recentDestinations;
76
76
  }
77
+ if (navigation?.view === "agents") {
78
+ const [connectedAgents, mcpAccess] = await Promise.all([
79
+ runLocalDispatchAction("list-connected-agents", {}),
80
+ runLocalDispatchAction("list-mcp-app-access", {}),
81
+ ]);
82
+ screen.connectedAgents = connectedAgents;
83
+ screen.mcpAppAccess = mcpAccess;
84
+ }
77
85
  if (
78
86
  navigation?.view === "overview" ||
79
87
  navigation?.view === "metrics" ||
@@ -111,6 +111,7 @@ function buildAppCreationPrompt(input: {
111
111
  `Dispatch workspace resources with scope=all are inherited workspace context. Do not copy or sync them into the new app; every workspace app reads them at runtime and may override with app shared or personal resources.`,
112
112
  ``,
113
113
  `Pick a starter template that fits the user's prompt — analytics, brain, calendar, content, design, dispatch, forms, mail, slides, clips, or starter when none of the others fit.`,
114
+ `If you use the starter template, treat it as scaffolding only: the finished app must use the requested app's real name, home screen, navigation, package metadata, and manifest, and it must not leave visible "Starter", "Blank app", or "New app" UI behind.`,
114
115
  `Use the workspace app layout: create it under apps/${input.appId}, mount it at /${input.appId}, keep it on the shared workspace database/hosting model, and avoid table-name collisions by namespacing any new domain tables to the app.`,
115
116
  `Important routing rule: from outside the app, link to /${input.appId}; inside apps/${input.appId}, React Router routes are app-local. Use <Link to="/review"> and navigate("/review"), not "/${input.appId}/review"; APP_BASE_PATH supplies the mounted prefix, and hardcoding it causes doubled URLs like /${input.appId}/${input.appId}/review.`,
116
117
  `Prefer useActionQuery/useActionMutation for actions. If you must raw-fetch framework endpoints, wrap them with agentNativePath("/_agent-native/actions/<name>") so mounted apps call the right URL.`,