@agent-native/core 0.20.8 → 0.21.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 (142) hide show
  1. package/dist/action.d.ts +61 -0
  2. package/dist/action.d.ts.map +1 -1
  3. package/dist/action.js +14 -0
  4. package/dist/action.js.map +1 -1
  5. package/dist/agent/production-agent.d.ts +4 -0
  6. package/dist/agent/production-agent.d.ts.map +1 -1
  7. package/dist/agent/production-agent.js +19 -7
  8. package/dist/agent/production-agent.js.map +1 -1
  9. package/dist/agent/types.d.ts +2 -0
  10. package/dist/agent/types.d.ts.map +1 -1
  11. package/dist/agent/types.js.map +1 -1
  12. package/dist/cli/code-agent-executor.d.ts.map +1 -1
  13. package/dist/cli/code-agent-executor.js +1 -0
  14. package/dist/cli/code-agent-executor.js.map +1 -1
  15. package/dist/cli/connect.d.ts +26 -4
  16. package/dist/cli/connect.d.ts.map +1 -1
  17. package/dist/cli/connect.js +578 -10
  18. package/dist/cli/connect.js.map +1 -1
  19. package/dist/cli/templates-meta.d.ts.map +1 -1
  20. package/dist/cli/templates-meta.js +1 -0
  21. package/dist/cli/templates-meta.js.map +1 -1
  22. package/dist/client/AssistantChat.d.ts.map +1 -1
  23. package/dist/client/AssistantChat.js +6 -5
  24. package/dist/client/AssistantChat.js.map +1 -1
  25. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  26. package/dist/client/agent-chat-adapter.js +25 -4
  27. package/dist/client/agent-chat-adapter.js.map +1 -1
  28. package/dist/client/code-agent-chat-adapter.js +1 -0
  29. package/dist/client/code-agent-chat-adapter.js.map +1 -1
  30. package/dist/client/composer/TiptapComposer.js +1 -1
  31. package/dist/client/composer/TiptapComposer.js.map +1 -1
  32. package/dist/client/conversation/AgentConversation.d.ts.map +1 -1
  33. package/dist/client/conversation/AgentConversation.js +3 -2
  34. package/dist/client/conversation/AgentConversation.js.map +1 -1
  35. package/dist/client/conversation/code-agent-transcript.js +1 -0
  36. package/dist/client/conversation/code-agent-transcript.js.map +1 -1
  37. package/dist/client/conversation/types.d.ts +2 -0
  38. package/dist/client/conversation/types.d.ts.map +1 -1
  39. package/dist/client/conversation/types.js.map +1 -1
  40. package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
  41. package/dist/client/extensions/EmbeddedExtension.js +2 -1
  42. package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
  43. package/dist/client/extensions/ExtensionEditor.d.ts.map +1 -1
  44. package/dist/client/extensions/ExtensionEditor.js +6 -3
  45. package/dist/client/extensions/ExtensionEditor.js.map +1 -1
  46. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  47. package/dist/client/extensions/ExtensionViewer.js +66 -2
  48. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  49. package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -1
  50. package/dist/client/extensions/ExtensionsListPage.js +2 -1
  51. package/dist/client/extensions/ExtensionsListPage.js.map +1 -1
  52. package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -1
  53. package/dist/client/extensions/ExtensionsSidebarSection.js +5 -7
  54. package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
  55. package/dist/client/extensions/index.d.ts +1 -0
  56. package/dist/client/extensions/index.d.ts.map +1 -1
  57. package/dist/client/extensions/index.js +1 -0
  58. package/dist/client/extensions/index.js.map +1 -1
  59. package/dist/client/index.d.ts +1 -0
  60. package/dist/client/index.d.ts.map +1 -1
  61. package/dist/client/index.js +1 -0
  62. package/dist/client/index.js.map +1 -1
  63. package/dist/client/mcp-apps/McpAppRenderer.d.ts +10 -0
  64. package/dist/client/mcp-apps/McpAppRenderer.d.ts.map +1 -0
  65. package/dist/client/mcp-apps/McpAppRenderer.js +296 -0
  66. package/dist/client/mcp-apps/McpAppRenderer.js.map +1 -0
  67. package/dist/client/sse-event-processor.d.ts +3 -0
  68. package/dist/client/sse-event-processor.d.ts.map +1 -1
  69. package/dist/client/sse-event-processor.js +2 -0
  70. package/dist/client/sse-event-processor.js.map +1 -1
  71. package/dist/code-agents/transcript-normalizer.d.ts +2 -0
  72. package/dist/code-agents/transcript-normalizer.d.ts.map +1 -1
  73. package/dist/code-agents/transcript-normalizer.js +17 -0
  74. package/dist/code-agents/transcript-normalizer.js.map +1 -1
  75. package/dist/db/client.d.ts +19 -0
  76. package/dist/db/client.d.ts.map +1 -1
  77. package/dist/db/client.js +139 -6
  78. package/dist/db/client.js.map +1 -1
  79. package/dist/extensions/actions.d.ts.map +1 -1
  80. package/dist/extensions/actions.js +6 -2
  81. package/dist/extensions/actions.js.map +1 -1
  82. package/dist/extensions/path.d.ts +6 -0
  83. package/dist/extensions/path.d.ts.map +1 -0
  84. package/dist/extensions/path.js +38 -0
  85. package/dist/extensions/path.js.map +1 -0
  86. package/dist/index.browser.d.ts +1 -1
  87. package/dist/index.browser.d.ts.map +1 -1
  88. package/dist/index.browser.js +1 -1
  89. package/dist/index.browser.js.map +1 -1
  90. package/dist/index.d.ts +1 -1
  91. package/dist/index.d.ts.map +1 -1
  92. package/dist/index.js +1 -1
  93. package/dist/index.js.map +1 -1
  94. package/dist/mcp/build-server.d.ts.map +1 -1
  95. package/dist/mcp/build-server.js +154 -4
  96. package/dist/mcp/build-server.js.map +1 -1
  97. package/dist/mcp/connect-store.d.ts +1 -1
  98. package/dist/mcp/connect-store.d.ts.map +1 -1
  99. package/dist/mcp/connect-store.js +1 -1
  100. package/dist/mcp/connect-store.js.map +1 -1
  101. package/dist/mcp/stdio.d.ts +2 -2
  102. package/dist/mcp/stdio.d.ts.map +1 -1
  103. package/dist/mcp/stdio.js +26 -8
  104. package/dist/mcp/stdio.js.map +1 -1
  105. package/dist/mcp-client/app-result.d.ts +40 -0
  106. package/dist/mcp-client/app-result.d.ts.map +1 -0
  107. package/dist/mcp-client/app-result.js +19 -0
  108. package/dist/mcp-client/app-result.js.map +1 -0
  109. package/dist/mcp-client/index.d.ts +5 -2
  110. package/dist/mcp-client/index.d.ts.map +1 -1
  111. package/dist/mcp-client/index.js +185 -23
  112. package/dist/mcp-client/index.js.map +1 -1
  113. package/dist/mcp-client/manager.d.ts +16 -0
  114. package/dist/mcp-client/manager.d.ts.map +1 -1
  115. package/dist/mcp-client/manager.js +58 -1
  116. package/dist/mcp-client/manager.js.map +1 -1
  117. package/dist/mcp-client/routes.d.ts +4 -1
  118. package/dist/mcp-client/routes.d.ts.map +1 -1
  119. package/dist/mcp-client/routes.js +146 -0
  120. package/dist/mcp-client/routes.js.map +1 -1
  121. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  122. package/dist/server/agent-chat-plugin.js +8 -1
  123. package/dist/server/agent-chat-plugin.js.map +1 -1
  124. package/dist/server/auth.d.ts +2 -0
  125. package/dist/server/auth.d.ts.map +1 -1
  126. package/dist/server/auth.js +2 -2
  127. package/dist/server/auth.js.map +1 -1
  128. package/dist/server/framework-request-handler.d.ts +4 -2
  129. package/dist/server/framework-request-handler.d.ts.map +1 -1
  130. package/dist/server/framework-request-handler.js +25 -11
  131. package/dist/server/framework-request-handler.js.map +1 -1
  132. package/dist/server/index.d.ts +1 -1
  133. package/dist/server/index.d.ts.map +1 -1
  134. package/dist/server/index.js +1 -1
  135. package/dist/server/index.js.map +1 -1
  136. package/dist/styles/agent-conversation.css +53 -0
  137. package/docs/content/actions.md +25 -2
  138. package/docs/content/external-agents.md +62 -8
  139. package/docs/content/key-concepts.md +1 -1
  140. package/docs/content/mcp-clients.md +1 -1
  141. package/docs/content/mcp-protocol.md +16 -11
  142. package/package.json +2 -1
@@ -1 +1 @@
1
- {"version":3,"file":"build-server.js","sourceRoot":"","sources":["../../src/mcp/build-server.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared MCP server builder.\n *\n * Extracted from `server.ts` so the stateless Streamable-HTTP mount\n * (`mountMCP`) and the stdio transport (`runMCPStdio --standalone`) build the\n * *same* MCP server from the *same* `ActionEntry` registry. Both surfaces:\n *\n * - expose every action as an MCP tool (+ the `ask-agent` meta-tool),\n * - append the framework deep-link block / `_meta` to every tool result,\n * - wrap `run()` / `askAgent()` in `runWithRequestContext` so per-user /\n * per-org scoping (accessFilter, resolveCredential, MCP visibility) is\n * honoured.\n *\n * `server.ts` re-exports `createMCPServerForRequest` and the auth helpers so\n * any (future) external importer of `@agent-native/core/mcp` keeps resolving.\n *\n * Node-only at the SDK level, but this module itself has no Node-only imports\n * — it can be bundled into the serverless function alongside `mountMCP`.\n */\n\nimport type { ActionEntry } from \"../agent/production-agent.js\";\nimport { runWithRequestContext } from \"../server/request-context.js\";\nimport { toAbsoluteOpenUrl, toDesktopOpenUrl } from \"../server/deep-link.js\";\nimport {\n isAgentNativeOpenDeepLink,\n withCollapsedAgentSidebarParam,\n} from \"../shared/agent-sidebar-url.js\";\nimport { getBuiltinCrossAppTools } from \"./builtin-tools.js\";\nimport { MCP_CONNECT_SCOPE } from \"./connect-store.js\";\n\nexport interface MCPConfig {\n /** App name shown in MCP server info */\n name: string;\n /**\n * Canonical app id (directory under `apps/`, e.g. `mail`) this MCP server\n * is mounted for. Optional & back-compat: when omitted the builtin\n * cross-app tools fall back to lowercasing `name`. Used by `open_app` /\n * `ask_app` / `create_workspace_app` to tell \"this app\" from a cross-app\n * target so they resolve the *target* app's origin rather than echoing the\n * current request origin.\n */\n appId?: string;\n /** App description */\n description: string;\n /** Version string (default \"1.0.0\") */\n version?: string;\n /** Action registry — same as agent chat and A2A */\n actions: Record<string, ActionEntry>;\n /**\n * Full (\"production\") action surface served to an **authenticated real\n * caller** — a connect-minted token, an `agent-native mcp install` stdio\n * proxy (owner-email header / `AGENT_NATIVE_OWNER_EMAIL`), or a deployed /\n * `AGENT_MODE=production` app. In local dev `actions` is intentionally the\n * sparse, dev-toggled surface (builtins + read-only public-agent actions)\n * so the local agent chat and unauthenticated dev probes don't see every\n * mutating tool; but per the external-agents contract a real caller that\n * connected with a token MUST get the full surface even in dev. When unset\n * (production, where `actions` already IS the full set) the swap is a\n * no-op. See `external-agents` skill, \"Dev vs production tool surface\".\n */\n productionActions?: Record<string, ActionEntry>;\n /** Handler for the ask-agent meta-tool — runs the full agent loop */\n askAgent?: (message: string) => Promise<string>;\n /**\n * Disable the generic cross-app builtin tools (`list_apps`, `open_app`,\n * `ask_app`, `create_workspace_app`, `list_templates`). They are merged in\n * by default so external agents get a stable verb set; a template action of\n * the same name always wins (template precedence). Set to `false` only for\n * a constrained / locked-down mount.\n */\n builtinCrossAppTools?: boolean;\n}\n\n/**\n * Identity extracted from a verified MCP bearer token / JWT. Used to wrap\n * `entry.run()` and `config.askAgent()` calls in `runWithRequestContext`\n * so downstream tools (db-query, accessFilter, resolveCredential) honour\n * per-user / per-org scoping. Without this wrap the MCP endpoint would\n * silently bypass tenant isolation. See finding #6 in\n * /tmp/security-audit/12-mcp-a2a-agent.md.\n */\nexport interface MCPCallerIdentity {\n userEmail: string | undefined;\n orgDomain: string | undefined;\n}\n\n/** Per-request context used to turn an action's relative deep link into the\n * absolute web URL (and desktop `agentnative://` URL) the external agent\n * surfaces. Derived from the inbound request headers in `mountMCP`, or from\n * the resolved local app origin in the stdio standalone path. */\nexport interface MCPRequestMeta {\n /** Origin of the running app, e.g. `http://localhost:8100`. */\n origin?: string;\n /** Optional client preference for which URL the *markdown* link uses. */\n target?: \"browser\" | \"desktop\" | \"terminal\";\n /**\n * The caller authenticated with a real credential (verified A2A/connect\n * JWT, matching ACCESS_TOKEN, or a forwarded owner-email header from\n * `agent-native mcp install`) — not the unauthenticated local dev-open\n * path. When true, `createMCPServerForRequest` serves\n * `config.productionActions` (the full surface) instead of the sparse dev\n * `config.actions`. Set by `mountMCP` from `verifyAuth`.\n */\n fullSurface?: boolean;\n}\n\n/**\n * Build the deep-link content block + structured `_meta` for a tool result.\n * Best-effort: any throw / nullish link is swallowed so a bad `link` builder\n * never fails the tool call.\n */\nexport function buildLinkArtifacts(\n entry: ActionEntry,\n args: Record<string, any>,\n result: any,\n meta: MCPRequestMeta | undefined,\n): {\n block?: { type: \"text\"; text: string };\n _meta?: Record<string, unknown>;\n} {\n if (typeof entry.link !== \"function\") return {};\n try {\n const lk = entry.link({ args: args ?? {}, result });\n if (!lk?.url) return {};\n const linkUrl = isAgentNativeOpenDeepLink(lk.url)\n ? withCollapsedAgentSidebarParam(lk.url)\n : lk.url;\n const webUrl = toAbsoluteOpenUrl(linkUrl, meta?.origin);\n const desktopUrl = toDesktopOpenUrl(linkUrl);\n const markdownUrl = meta?.target === \"desktop\" ? desktopUrl : webUrl;\n return {\n block: { type: \"text\", text: `\\n\\n[${lk.label} →](${markdownUrl})` },\n _meta: {\n \"agent-native/openLink\": {\n label: lk.label,\n view: lk.view,\n webUrl,\n desktopUrl,\n },\n },\n };\n } catch {\n return {};\n }\n}\n\n/**\n * Merge the generic cross-app builtin tools into the config's action\n * registry. **Template actions take precedence**: if a template defines an\n * action with the same name as a builtin (e.g. its own `list_apps`), the\n * template entry wins and the builtin is dropped. This mirrors the\n * template-over-workspace-core precedence in `autoDiscoverActions`.\n *\n * The builtins are pure-ish navigators / scaffolders; they call back into the\n * same `config.actions` / `config.askAgent` so there is no second agent loop.\n */\nfunction mergeBuiltinTools(\n config: MCPConfig,\n baseActions: Record<string, ActionEntry>,\n requestMeta?: MCPRequestMeta,\n): Record<string, ActionEntry> {\n if (config.builtinCrossAppTools === false) return baseActions;\n const builtins = getBuiltinCrossAppTools(config, requestMeta);\n const merged: Record<string, ActionEntry> = { ...builtins };\n // Template / app actions overwrite same-named builtins.\n for (const [name, entry] of Object.entries(baseActions)) {\n merged[name] = entry;\n }\n return merged;\n}\n\n// ---------------------------------------------------------------------------\n// MCP Server creation — converts ActionEntry registry to MCP tools\n// ---------------------------------------------------------------------------\n\n/**\n * Build a fully-wired MCP `Server` for a single request / session.\n *\n * Shared by the stateless Streamable-HTTP mount (`mountMCP`) and the stdio\n * standalone transport. The HTTP mount passes the per-request origin via\n * `requestMeta`; the stdio standalone path passes the resolved local app\n * origin so deep links still become absolute URLs.\n */\nexport async function createMCPServerForRequest(\n config: MCPConfig,\n identity: MCPCallerIdentity | undefined,\n requestMeta?: MCPRequestMeta,\n) {\n const { Server } = await import(\"@modelcontextprotocol/sdk/server/index.js\");\n const { ListToolsRequestSchema, CallToolRequestSchema } =\n await import(\"@modelcontextprotocol/sdk/types.js\");\n\n const server = new Server(\n { name: config.name, version: config.version ?? \"1.0.0\" },\n { capabilities: { tools: {} } },\n );\n\n // Resolve the effective caller identity. JWT / header-derived identity\n // (passed by `mountMCP` via `verifyAuth`) wins. When the caller passed no\n // identity — the stdio **standalone** path — fall back to the\n // `AGENT_NATIVE_OWNER_EMAIL` env the `agent-native mcp install` flow writes\n // into the `agent-native mcp serve` process env, so standalone tool runs are\n // tenant-scoped to the configured owner instead of running unscoped. Stays\n // undefined for true dev-open (no token, no secret, no owner) — behavior\n // there is unchanged.\n const ownerFromEnv = process.env.AGENT_NATIVE_OWNER_EMAIL?.trim();\n const effectiveIdentity: MCPCallerIdentity | undefined =\n identity ??\n (ownerFromEnv\n ? { userEmail: ownerFromEnv, orgDomain: undefined }\n : undefined);\n\n // The action set the request handlers operate on = base actions + generic\n // cross-app builtins (template wins on name collision). An authenticated\n // real caller (connect-minted token / `mcp install` owner / production —\n // `requestMeta.fullSurface`, or the stdio standalone path identified by\n // `AGENT_NATIVE_OWNER_EMAIL`) gets the full `productionActions` surface\n // even in local dev; the unauthenticated dev-open path keeps the sparse\n // `config.actions`. See `external-agents` skill, \"Dev vs production tool\n // surface\".\n const useFullSurface = requestMeta?.fullSurface === true || !!ownerFromEnv;\n const baseActions =\n useFullSurface && config.productionActions\n ? config.productionActions\n : config.actions;\n const actions = mergeBuiltinTools(config, baseActions, requestMeta);\n\n // Resolve orgId once per request (DB lookup) so subsequent wraps are\n // synchronous. The caller identity may be undefined for true dev-open —\n // in that case we run with no userEmail/orgId, which makes downstream\n // tools that require per-user scope return empty results rather than\n // cross-tenant data (the safe default).\n const orgIdPromise = resolveOrgIdFromDomain(effectiveIdentity?.orgDomain);\n\n /**\n * Wrap a callback in\n * `runWithRequestContext({ userEmail, orgId, requestOrigin }, fn)`.\n * Both the tools/list and tools/call handlers go through this so\n * downstream `accessFilter`, `resolveCredential`, and per-user MCP\n * visibility checks see the verified caller's identity. `requestOrigin`\n * is the live server origin derived from the inbound request (same value\n * used to absolutize deep links) so actions that build fetchable URLs\n * (e.g. design `export-coding-handoff`'s signed raw-code URL) resolve the\n * correct local-workspace origin instead of a prod/localhost fallback.\n */\n async function withCallerContext<T>(fn: () => Promise<T>): Promise<T> {\n const orgId = await orgIdPromise;\n return runWithRequestContext(\n {\n userEmail: effectiveIdentity?.userEmail,\n orgId,\n ...(requestMeta?.origin ? { requestOrigin: requestMeta.origin } : {}),\n },\n fn,\n ) as Promise<T>;\n }\n\n // tools/list — return all actions + ask-agent meta-tool. Wrapped in the\n // request context so per-user MCP visibility (mcp-client/visibility.ts)\n // applies to the listing too.\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return withCallerContext(async () => {\n const tools = Object.entries(actions).map(([name, entry]) => {\n const hasLink = typeof entry.link === \"function\";\n const baseDescription = entry.tool.description ?? name;\n return {\n name,\n description: hasLink\n ? `${baseDescription} After calling, surface the returned \"Open in … →\" link to the user.`\n : baseDescription,\n inputSchema: entry.tool.parameters ?? {\n type: \"object\" as const,\n properties: {},\n },\n ...(hasLink\n ? { annotations: { \"agent-native/producesOpenLink\": true } }\n : {}),\n };\n });\n\n if (config.askAgent) {\n tools.push({\n name: \"ask-agent\",\n description:\n \"Send a natural-language message to the app's AI agent and get a response. \" +\n \"Use this for complex, multi-step tasks that require the agent's reasoning \" +\n \"and full context about the app.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n message: {\n type: \"string\",\n description: \"The message to send to the agent\",\n },\n },\n required: [\"message\"],\n },\n });\n }\n\n return { tools };\n });\n });\n\n // tools/call — dispatch to action registry or ask-agent. Wrapped in the\n // request context so the action's `run(args)` and `askAgent()` execute\n // with the verified caller's identity, not the platform default.\n server.setRequestHandler(CallToolRequestSchema, async (request: any) => {\n return withCallerContext(async () => {\n const { name, arguments: args } = request.params;\n\n if (name === \"ask-agent\" && config.askAgent) {\n const message = args?.message ?? \"\";\n try {\n const result = await config.askAgent(message);\n return { content: [{ type: \"text\", text: result }] };\n } catch (err: any) {\n return {\n content: [{ type: \"text\", text: `Error: ${err.message}` }],\n isError: true,\n };\n }\n }\n\n const entry = actions[name];\n if (!entry) {\n return {\n content: [{ type: \"text\", text: `Unknown tool: ${name}` }],\n isError: true,\n };\n }\n\n try {\n const result = await entry.run((args as Record<string, string>) ?? {});\n const text =\n typeof result === \"string\" ? result : JSON.stringify(result);\n const content: any[] = [{ type: \"text\", text }];\n const { block, _meta } = buildLinkArtifacts(\n entry,\n (args as Record<string, any>) ?? {},\n result,\n requestMeta,\n );\n if (block) content.push(block);\n return { content, ...(_meta ? { _meta } : {}) };\n } catch (err: any) {\n return {\n content: [{ type: \"text\", text: `Error: ${err.message}` }],\n isError: true,\n };\n }\n });\n });\n\n return server;\n}\n\n// ---------------------------------------------------------------------------\n// Auth — reuses the same pattern as A2A (Bearer token or JWT). Shared so the\n// HTTP mount and any stdio-side auth-aware helper resolve identity identically.\n// ---------------------------------------------------------------------------\n\nexport function getAccessTokens(): string[] {\n const single = process.env.ACCESS_TOKEN;\n const multi = process.env.ACCESS_TOKENS;\n const tokens: string[] = [];\n if (single) tokens.push(single);\n if (multi) {\n tokens.push(\n ...multi\n .split(\",\")\n .map((t) => t.trim())\n .filter(Boolean),\n );\n }\n return tokens;\n}\n\n/**\n * Resolve the caller identity for a static-token (or dev-open) auth path.\n *\n * Static `ACCESS_TOKEN` / `ACCESS_TOKENS` auth carries no per-caller claims,\n * so without this the MCP endpoint would run every tool with\n * `userEmail === undefined` and per-user / per-org scoped actions\n * (`accessFilter`, `resolveAccess`, `resolveCredential`) would return\n * empty / wrong data. The `agent-native mcp install` flow writes\n * `AGENT_NATIVE_OWNER_EMAIL` into the client config env and the stdio proxy\n * forwards it as the `X-Agent-Native-Owner-Email` request header (see\n * `mcp/stdio.ts#authHeaders`). We trust that owner hint *only* on the\n * static-token path — JWT auth already carries a cryptographically verified\n * `sub`, so the header is ignored there and never widens JWT scope.\n *\n * Precedence is server-trusted-first: the server process's\n * `AGENT_NATIVE_OWNER_EMAIL` env (set out-of-band by the operator / deploy)\n * ALWAYS wins, and a client-supplied `X-Agent-Native-Owner-Email` header is\n * honored *only as a fallback when that env is unset*. A static `ACCESS_TOKEN`\n * is a shared bearer secret; letting a request header override a\n * server-configured owner would let anyone holding a leaked token act as any\n * user. The header path remains for the single-tenant local-dev install flow\n * where the app server process has no owner env and the token *is* the\n * workspace secret; multi-tenant deployments must use A2A JWT (verified `sub`),\n * not a static token, for per-user scope.\n *\n * Returns `undefined` when no owner email is available (true dev-open: no\n * token, no secret, no owner) so behavior there stays unchanged.\n */\nfunction deriveStaticTokenIdentity(\n ownerEmailHeader: string | undefined,\n): MCPCallerIdentity | undefined {\n const owner =\n process.env.AGENT_NATIVE_OWNER_EMAIL?.trim() ||\n (typeof ownerEmailHeader === \"string\" && ownerEmailHeader.trim()) ||\n \"\";\n if (!owner) return undefined;\n return { userEmail: owner, orgDomain: undefined };\n}\n\n/**\n * Verify the inbound auth header. Returns:\n * - { authed: true, identity } when verified — `identity` is derived from\n * the JWT (`sub` / `org_domain`) for JWT auth, or from the\n * `AGENT_NATIVE_OWNER_EMAIL` env / `X-Agent-Native-Owner-Email` header\n * for static-token auth (the `agent-native mcp install` flow). `identity`\n * is undefined only for true dev-open with no owner hint.\n * - { authed: false } on rejection.\n *\n * When A2A_SECRET is set we extract the JWT's `sub` (caller email) and\n * `org_domain` claims so the MCP endpoint can wrap tool runs in\n * `runWithRequestContext({ userEmail, orgId })`. Without that wrap, the\n * MCP endpoint loses tenant identity and downstream `accessFilter` /\n * `resolveCredential` calls fall back to platform-wide defaults.\n *\n * `ownerEmailHeader` is the forwarded `X-Agent-Native-Owner-Email` value; it\n * is consulted ONLY on the static-token / dev-open path (never to influence\n * verified JWT identity), so the install flow runs tools as the configured\n * owner instead of an unscoped anonymous caller.\n */\nexport async function verifyAuth(\n authHeader: string | undefined,\n ownerEmailHeader?: string | undefined,\n options: { allowDevOpen?: boolean } = {},\n): Promise<{\n authed: boolean;\n identity?: MCPCallerIdentity;\n /**\n * The caller presented a real credential — a verified A2A/connect JWT, a\n * matching ACCESS_TOKEN, or (on the no-auth-configured path) a forwarded\n * owner-email header from `agent-native mcp install`. Drives the full vs\n * sparse MCP tool surface in local dev. The pure unauthenticated dev-open\n * path (no secret, no token, no owner header) is `false`.\n */\n fullSurface?: boolean;\n}> {\n // No auth configured → allow only when the route caller has already\n // established that this is a loopback/local dev request. Still honour an\n // owner hint there so the local install/connect flow stays tenant-scoped.\n const accessTokens = getAccessTokens();\n const hasA2ASecret = !!process.env.A2A_SECRET;\n if (accessTokens.length === 0 && !hasA2ASecret) {\n if (options.allowDevOpen === false) {\n return { authed: false };\n }\n return {\n authed: true,\n identity: deriveStaticTokenIdentity(ownerEmailHeader),\n // `mcp install`'s stdio proxy forwards an owner-email header even when\n // the local app has no secret configured — that is a real, identified\n // caller and gets the full surface. A bare browser/curl dev probe with\n // no owner hint stays on the sparse dev surface.\n fullSurface: !!(ownerEmailHeader && ownerEmailHeader.trim()),\n };\n }\n\n if (!authHeader?.startsWith(\"Bearer \")) return { authed: false };\n const token = authHeader.slice(7);\n\n // Try JWT via A2A_SECRET\n if (hasA2ASecret) {\n try {\n const jose = await import(\"jose\");\n const { payload } = await jose.jwtVerify(\n token,\n new TextEncoder().encode(process.env.A2A_SECRET!),\n );\n\n const tokenScope =\n typeof payload.scope === \"string\" ? payload.scope : undefined;\n if (tokenScope && tokenScope !== MCP_CONNECT_SCOPE) {\n return { authed: false };\n }\n\n // Connect-minted tokens (scope === \"mcp-connect\") carry a random `jti`\n // and are individually revocable. Only these tokens hit the revoke\n // store — ordinary A2A delegation JWTs skip the DB lookup entirely so\n // the hot path is unchanged. The revoke check FAILS OPEN on any\n // store/DB error: a transient Neon WS drop must never lock every\n // connected agent out. The signature was already cryptographically\n // verified above, so failing open here only widens the explicit-revoke\n // gate, never the trust boundary.\n if (tokenScope === MCP_CONNECT_SCOPE) {\n if (typeof payload.jti !== \"string\" || !payload.jti) {\n return { authed: false };\n }\n const jti = payload.jti;\n try {\n const { isJtiRevoked, touchTokenUsed } =\n await import(\"./connect-store.js\");\n if (await isJtiRevoked(jti)) {\n return { authed: false };\n }\n // Best-effort usage telemetry — never blocks / throws.\n void touchTokenUsed(jti);\n } catch {\n // Store import / lookup failed — fail open (see comment above).\n }\n }\n\n return {\n authed: true,\n identity: {\n userEmail: typeof payload.sub === \"string\" ? payload.sub : undefined,\n orgDomain:\n typeof payload.org_domain === \"string\"\n ? (payload.org_domain as string)\n : undefined,\n },\n // Verified JWT (connect-minted or A2A delegation) — a real caller.\n fullSurface: true,\n };\n } catch {\n // Not a valid JWT — fall through to token check\n }\n }\n\n // Try ACCESS_TOKEN / ACCESS_TOKENS exact match. Static tokens carry no\n // per-caller claims, so derive identity from the forwarded owner-email\n // hint (install flow) — otherwise tools would run unscoped.\n if (accessTokens.length > 0 && accessTokens.includes(token)) {\n return {\n authed: true,\n identity: deriveStaticTokenIdentity(ownerEmailHeader),\n // Matched a configured ACCESS_TOKEN — a real caller.\n fullSurface: true,\n };\n }\n\n return { authed: false };\n}\n\nexport async function resolveOrgIdFromDomain(\n orgDomain: string | undefined,\n): Promise<string | undefined> {\n if (!orgDomain) return undefined;\n try {\n const { resolveOrgByDomain } = await import(\"../org/context.js\");\n const org = await resolveOrgByDomain(orgDomain);\n return org?.orgId ?? undefined;\n } catch {\n return undefined;\n }\n}\n"]}
1
+ {"version":3,"file":"build-server.js","sourceRoot":"","sources":["../../src/mcp/build-server.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared MCP server builder.\n *\n * Extracted from `server.ts` so the stateless Streamable-HTTP mount\n * (`mountMCP`) and the stdio transport (`runMCPStdio --standalone`) build the\n * *same* MCP server from the *same* `ActionEntry` registry. Both surfaces:\n *\n * - expose every action as an MCP tool (+ the `ask-agent` meta-tool),\n * - append the framework deep-link block / `_meta` to every tool result,\n * - wrap `run()` / `askAgent()` in `runWithRequestContext` so per-user /\n * per-org scoping (accessFilter, resolveCredential, MCP visibility) is\n * honoured.\n *\n * `server.ts` re-exports `createMCPServerForRequest` and the auth helpers so\n * any (future) external importer of `@agent-native/core/mcp` keeps resolving.\n *\n * Node-only at the SDK level, but this module itself has no Node-only imports\n * — it can be bundled into the serverless function alongside `mountMCP`.\n */\n\nimport type { ActionEntry } from \"../agent/production-agent.js\";\nimport { isMcpActionResult } from \"../mcp-client/app-result.js\";\nimport {\n MCP_APP_EXTENSION_ID,\n MCP_APP_MIME_TYPE,\n MCP_APP_RESOURCE_URI_META_KEY,\n type ActionMcpAppResourceConfig,\n} from \"../action.js\";\nimport { runWithRequestContext } from \"../server/request-context.js\";\nimport { toAbsoluteOpenUrl, toDesktopOpenUrl } from \"../server/deep-link.js\";\nimport {\n isAgentNativeOpenDeepLink,\n withCollapsedAgentSidebarParam,\n} from \"../shared/agent-sidebar-url.js\";\nimport { getBuiltinCrossAppTools } from \"./builtin-tools.js\";\nimport { MCP_CONNECT_SCOPE } from \"./connect-store.js\";\n\nexport interface MCPConfig {\n /** App name shown in MCP server info */\n name: string;\n /**\n * Canonical app id (directory under `apps/`, e.g. `mail`) this MCP server\n * is mounted for. Optional & back-compat: when omitted the builtin\n * cross-app tools fall back to lowercasing `name`. Used by `open_app` /\n * `ask_app` / `create_workspace_app` to tell \"this app\" from a cross-app\n * target so they resolve the *target* app's origin rather than echoing the\n * current request origin.\n */\n appId?: string;\n /** App description */\n description: string;\n /** Version string (default \"1.0.0\") */\n version?: string;\n /** Action registry — same as agent chat and A2A */\n actions: Record<string, ActionEntry>;\n /**\n * Full (\"production\") action surface served to an **authenticated real\n * caller** — a connect-minted token, an `agent-native mcp install` stdio\n * proxy (owner-email header / `AGENT_NATIVE_OWNER_EMAIL`), or a deployed /\n * `AGENT_MODE=production` app. In local dev `actions` is intentionally the\n * sparse, dev-toggled surface (builtins + read-only public-agent actions)\n * so the local agent chat and unauthenticated dev probes don't see every\n * mutating tool; but per the external-agents contract a real caller that\n * connected with a token MUST get the full surface even in dev. When unset\n * (production, where `actions` already IS the full set) the swap is a\n * no-op. See `external-agents` skill, \"Dev vs production tool surface\".\n */\n productionActions?: Record<string, ActionEntry>;\n /** Handler for the ask-agent meta-tool — runs the full agent loop */\n askAgent?: (message: string) => Promise<string>;\n /**\n * Disable the generic cross-app builtin tools (`list_apps`, `open_app`,\n * `ask_app`, `create_workspace_app`, `list_templates`). They are merged in\n * by default so external agents get a stable verb set; a template action of\n * the same name always wins (template precedence). Set to `false` only for\n * a constrained / locked-down mount.\n */\n builtinCrossAppTools?: boolean;\n}\n\n/**\n * Identity extracted from a verified MCP bearer token / JWT. Used to wrap\n * `entry.run()` and `config.askAgent()` calls in `runWithRequestContext`\n * so downstream tools (db-query, accessFilter, resolveCredential) honour\n * per-user / per-org scoping. Without this wrap the MCP endpoint would\n * silently bypass tenant isolation. See finding #6 in\n * /tmp/security-audit/12-mcp-a2a-agent.md.\n */\nexport interface MCPCallerIdentity {\n userEmail: string | undefined;\n orgDomain: string | undefined;\n}\n\n/** Per-request context used to turn an action's relative deep link into the\n * absolute web URL (and desktop `agentnative://` URL) the external agent\n * surfaces. Derived from the inbound request headers in `mountMCP`, or from\n * the resolved local app origin in the stdio standalone path. */\nexport interface MCPRequestMeta {\n /** Origin of the running app, e.g. `http://localhost:8100`. */\n origin?: string;\n /** Optional client preference for which URL the *markdown* link uses. */\n target?: \"browser\" | \"desktop\" | \"terminal\";\n /**\n * The caller authenticated with a real credential (verified A2A/connect\n * JWT, matching ACCESS_TOKEN, or a forwarded owner-email header from\n * `agent-native mcp install`) — not the unauthenticated local dev-open\n * path. When true, `createMCPServerForRequest` serves\n * `config.productionActions` (the full surface) instead of the sparse dev\n * `config.actions`. Set by `mountMCP` from `verifyAuth`.\n */\n fullSurface?: boolean;\n}\n\ninterface ResolvedMcpAppResource {\n uri: string;\n name: string;\n title?: string;\n description?: string;\n html: ActionMcpAppResourceConfig[\"html\"];\n mimeType: typeof MCP_APP_MIME_TYPE;\n _meta?: Record<string, unknown>;\n}\n\n/**\n * Build the deep-link content block + structured `_meta` for a tool result.\n * Best-effort: any throw / nullish link is swallowed so a bad `link` builder\n * never fails the tool call.\n */\nexport function buildLinkArtifacts(\n entry: ActionEntry,\n args: Record<string, any>,\n result: any,\n meta: MCPRequestMeta | undefined,\n): {\n block?: { type: \"text\"; text: string };\n _meta?: Record<string, unknown>;\n} {\n if (typeof entry.link !== \"function\") return {};\n try {\n const lk = entry.link({ args: args ?? {}, result });\n if (!lk?.url) return {};\n const linkUrl = isAgentNativeOpenDeepLink(lk.url)\n ? withCollapsedAgentSidebarParam(lk.url)\n : lk.url;\n const webUrl = toAbsoluteOpenUrl(linkUrl, meta?.origin);\n const desktopUrl = toDesktopOpenUrl(linkUrl);\n const markdownUrl = meta?.target === \"desktop\" ? desktopUrl : webUrl;\n return {\n block: { type: \"text\", text: `\\n\\n[${lk.label} →](${markdownUrl})` },\n _meta: {\n \"agent-native/openLink\": {\n label: lk.label,\n view: lk.view,\n webUrl,\n desktopUrl,\n },\n },\n };\n } catch {\n return {};\n }\n}\n\n/**\n * Merge the generic cross-app builtin tools into the config's action\n * registry. **Template actions take precedence**: if a template defines an\n * action with the same name as a builtin (e.g. its own `list_apps`), the\n * template entry wins and the builtin is dropped. This mirrors the\n * template-over-workspace-core precedence in `autoDiscoverActions`.\n *\n * The builtins are pure-ish navigators / scaffolders; they call back into the\n * same `config.actions` / `config.askAgent` so there is no second agent loop.\n */\nfunction mergeBuiltinTools(\n config: MCPConfig,\n baseActions: Record<string, ActionEntry>,\n requestMeta?: MCPRequestMeta,\n): Record<string, ActionEntry> {\n if (config.builtinCrossAppTools === false) return baseActions;\n const builtins = getBuiltinCrossAppTools(config, requestMeta);\n const merged: Record<string, ActionEntry> = { ...builtins };\n // Template / app actions overwrite same-named builtins.\n for (const [name, entry] of Object.entries(baseActions)) {\n merged[name] = entry;\n }\n return merged;\n}\n\nfunction safeUiSegment(value: string | undefined, fallback: string): string {\n const normalized = (value || fallback)\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9._-]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n return normalized || fallback;\n}\n\nfunction defaultMcpAppUri(config: MCPConfig, actionName: string): string {\n const app = safeUiSegment(config.appId ?? config.name, \"agent-native\");\n const action = safeUiSegment(actionName, \"tool\");\n return `ui://${app}/${action}`;\n}\n\nfunction mcpAppUiMeta(\n resource: ActionMcpAppResourceConfig,\n): Record<string, unknown> | undefined {\n const base =\n resource._meta && typeof resource._meta === \"object\"\n ? { ...resource._meta }\n : {};\n const existingUi =\n base.ui && typeof base.ui === \"object\" && !Array.isArray(base.ui)\n ? (base.ui as Record<string, unknown>)\n : {};\n const ui: Record<string, unknown> = { ...existingUi };\n if (resource.csp) ui.csp = resource.csp;\n if (resource.permissions) ui.permissions = resource.permissions;\n if (resource.domain) ui.domain = resource.domain;\n if (typeof resource.prefersBorder === \"boolean\") {\n ui.prefersBorder = resource.prefersBorder;\n }\n if (Object.keys(ui).length > 0) base.ui = ui;\n return Object.keys(base).length > 0 ? base : undefined;\n}\n\nfunction resolveMcpAppResource(\n config: MCPConfig,\n actionName: string,\n entry: ActionEntry,\n): ResolvedMcpAppResource | null {\n const resource = entry.mcpApp?.resource;\n if (!resource) return null;\n const uri = resource.uri?.trim() || defaultMcpAppUri(config, actionName);\n if (!uri.startsWith(\"ui://\")) return null;\n const resourceMeta = mcpAppUiMeta(resource);\n return {\n uri,\n name: resource.name?.trim() || actionName,\n ...(resource.title ? { title: resource.title } : {}),\n ...((resource.description ?? entry.tool.description)\n ? { description: resource.description ?? entry.tool.description }\n : {}),\n html: resource.html,\n mimeType: resource.mimeType ?? MCP_APP_MIME_TYPE,\n ...(resourceMeta ? { _meta: resourceMeta } : {}),\n };\n}\n\nfunction getMcpAppResources(\n config: MCPConfig,\n actions: Record<string, ActionEntry>,\n): ResolvedMcpAppResource[] {\n return Object.entries(actions).flatMap(([name, entry]) => {\n const resource = resolveMcpAppResource(config, name, entry);\n return resource ? [resource] : [];\n });\n}\n\nfunction renderMcpAppHtml(\n resource: ResolvedMcpAppResource,\n actionName: string,\n config: MCPConfig,\n requestMeta?: MCPRequestMeta,\n): string {\n if (typeof resource.html === \"function\") {\n return resource.html({\n actionName,\n appId: config.appId,\n requestOrigin: requestMeta?.origin,\n });\n }\n return resource.html;\n}\n\n// ---------------------------------------------------------------------------\n// MCP Server creation — converts ActionEntry registry to MCP tools\n// ---------------------------------------------------------------------------\n\n/**\n * Build a fully-wired MCP `Server` for a single request / session.\n *\n * Shared by the stateless Streamable-HTTP mount (`mountMCP`) and the stdio\n * standalone transport. The HTTP mount passes the per-request origin via\n * `requestMeta`; the stdio standalone path passes the resolved local app\n * origin so deep links still become absolute URLs.\n */\nexport async function createMCPServerForRequest(\n config: MCPConfig,\n identity: MCPCallerIdentity | undefined,\n requestMeta?: MCPRequestMeta,\n) {\n const { Server } = await import(\"@modelcontextprotocol/sdk/server/index.js\");\n const {\n ListToolsRequestSchema,\n CallToolRequestSchema,\n ListResourcesRequestSchema,\n ReadResourceRequestSchema,\n ListResourceTemplatesRequestSchema,\n } = await import(\"@modelcontextprotocol/sdk/types.js\");\n\n // Resolve the effective caller identity. JWT / header-derived identity\n // (passed by `mountMCP` via `verifyAuth`) wins. When the caller passed no\n // identity — the stdio **standalone** path — fall back to the\n // `AGENT_NATIVE_OWNER_EMAIL` env the `agent-native mcp install` flow writes\n // into the `agent-native mcp serve` process env, so standalone tool runs are\n // tenant-scoped to the configured owner instead of running unscoped. Stays\n // undefined for true dev-open (no token, no secret, no owner) — behavior\n // there is unchanged.\n const ownerFromEnv = process.env.AGENT_NATIVE_OWNER_EMAIL?.trim();\n const effectiveIdentity: MCPCallerIdentity | undefined =\n identity ??\n (ownerFromEnv\n ? { userEmail: ownerFromEnv, orgDomain: undefined }\n : undefined);\n\n // The action set the request handlers operate on = base actions + generic\n // cross-app builtins (template wins on name collision). An authenticated\n // real caller (connect-minted token / `mcp install` owner / production —\n // `requestMeta.fullSurface`, or the stdio standalone path identified by\n // `AGENT_NATIVE_OWNER_EMAIL`) gets the full `productionActions` surface\n // even in local dev; the unauthenticated dev-open path keeps the sparse\n // `config.actions`. See `external-agents` skill, \"Dev vs production tool\n // surface\".\n const useFullSurface = requestMeta?.fullSurface === true || !!ownerFromEnv;\n const baseActions =\n useFullSurface && config.productionActions\n ? config.productionActions\n : config.actions;\n const actions = mergeBuiltinTools(config, baseActions, requestMeta);\n const mcpAppResources = getMcpAppResources(config, actions);\n const supportsMcpApps = mcpAppResources.length > 0;\n const server = new Server(\n { name: config.name, version: config.version ?? \"1.0.0\" },\n {\n capabilities: {\n tools: {},\n ...(supportsMcpApps\n ? {\n resources: {},\n extensions: {\n [MCP_APP_EXTENSION_ID]: {\n mimeTypes: [MCP_APP_MIME_TYPE],\n },\n },\n }\n : {}),\n },\n },\n );\n\n // Resolve orgId once per request (DB lookup) so subsequent wraps are\n // synchronous. The caller identity may be undefined for true dev-open —\n // in that case we run with no userEmail/orgId, which makes downstream\n // tools that require per-user scope return empty results rather than\n // cross-tenant data (the safe default).\n const orgIdPromise = resolveOrgIdFromDomain(effectiveIdentity?.orgDomain);\n\n /**\n * Wrap a callback in\n * `runWithRequestContext({ userEmail, orgId, requestOrigin }, fn)`.\n * Both the tools/list and tools/call handlers go through this so\n * downstream `accessFilter`, `resolveCredential`, and per-user MCP\n * visibility checks see the verified caller's identity. `requestOrigin`\n * is the live server origin derived from the inbound request (same value\n * used to absolutize deep links) so actions that build fetchable URLs\n * (e.g. design `export-coding-handoff`'s signed raw-code URL) resolve the\n * correct local-workspace origin instead of a prod/localhost fallback.\n */\n async function withCallerContext<T>(fn: () => Promise<T>): Promise<T> {\n const orgId = await orgIdPromise;\n return runWithRequestContext(\n {\n userEmail: effectiveIdentity?.userEmail,\n orgId,\n ...(requestMeta?.origin ? { requestOrigin: requestMeta.origin } : {}),\n },\n fn,\n ) as Promise<T>;\n }\n\n // tools/list — return all actions + ask-agent meta-tool. Wrapped in the\n // request context so per-user MCP visibility (mcp-client/visibility.ts)\n // applies to the listing too.\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return withCallerContext(async () => {\n const tools = Object.entries(actions).map(([name, entry]) => {\n const hasLink = typeof entry.link === \"function\";\n const mcpAppResource = resolveMcpAppResource(config, name, entry);\n const baseDescription = entry.tool.description ?? name;\n return {\n name,\n description: hasLink\n ? `${baseDescription} After calling, surface the returned \"Open in … →\" link to the user.`\n : baseDescription,\n inputSchema: entry.tool.parameters ?? {\n type: \"object\" as const,\n properties: {},\n },\n ...(mcpAppResource\n ? {\n _meta: {\n [MCP_APP_RESOURCE_URI_META_KEY]: mcpAppResource.uri,\n ui: {\n resourceUri: mcpAppResource.uri,\n visibility: entry.mcpApp?.visibility ?? [\"model\", \"app\"],\n },\n },\n }\n : {}),\n ...(hasLink\n ? { annotations: { \"agent-native/producesOpenLink\": true } }\n : {}),\n };\n });\n\n if (config.askAgent) {\n tools.push({\n name: \"ask-agent\",\n description:\n \"Send a natural-language message to the app's AI agent and get a response. \" +\n \"Use this for complex, multi-step tasks that require the agent's reasoning \" +\n \"and full context about the app.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n message: {\n type: \"string\",\n description: \"The message to send to the agent\",\n },\n },\n required: [\"message\"],\n },\n });\n }\n\n return { tools };\n });\n });\n\n // tools/call — dispatch to action registry or ask-agent. Wrapped in the\n // request context so the action's `run(args)` and `askAgent()` execute\n // with the verified caller's identity, not the platform default.\n server.setRequestHandler(CallToolRequestSchema, async (request: any) => {\n return withCallerContext(async () => {\n const { name, arguments: args } = request.params;\n\n if (name === \"ask-agent\" && config.askAgent) {\n const message = args?.message ?? \"\";\n try {\n const result = await config.askAgent(message);\n return { content: [{ type: \"text\", text: result }] };\n } catch (err: any) {\n return {\n content: [{ type: \"text\", text: `Error: ${err.message}` }],\n isError: true,\n };\n }\n }\n\n const entry = actions[name];\n if (!entry) {\n return {\n content: [{ type: \"text\", text: `Unknown tool: ${name}` }],\n isError: true,\n };\n }\n\n try {\n const result = await entry.run((args as Record<string, string>) ?? {});\n const resultForClient = isMcpActionResult(result)\n ? result.text\n : result;\n const text =\n typeof resultForClient === \"string\"\n ? resultForClient\n : JSON.stringify(resultForClient);\n const content: any[] = [{ type: \"text\", text }];\n const { block, _meta } = buildLinkArtifacts(\n entry,\n (args as Record<string, any>) ?? {},\n isMcpActionResult(result) ? result.raw : result,\n requestMeta,\n );\n if (block) content.push(block);\n return { content, ...(_meta ? { _meta } : {}) };\n } catch (err: any) {\n return {\n content: [{ type: \"text\", text: `Error: ${err.message}` }],\n isError: true,\n };\n }\n });\n });\n\n if (supportsMcpApps) {\n server.setRequestHandler(ListResourcesRequestSchema, async () => {\n return withCallerContext(async () => ({\n resources: mcpAppResources.map((resource) => ({\n uri: resource.uri,\n name: resource.name,\n ...(resource.title ? { title: resource.title } : {}),\n ...(resource.description\n ? { description: resource.description }\n : {}),\n mimeType: resource.mimeType,\n ...(resource._meta ? { _meta: resource._meta } : {}),\n })),\n }));\n });\n\n server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => {\n return { resourceTemplates: [] };\n });\n\n server.setRequestHandler(\n ReadResourceRequestSchema,\n async (request: any) => {\n return withCallerContext(async () => {\n const uri = request.params?.uri;\n const found = Object.entries(actions)\n .map(([name, entry]) => ({\n actionName: name,\n resource: resolveMcpAppResource(config, name, entry),\n }))\n .find((candidate) => candidate.resource?.uri === uri);\n if (!found?.resource) {\n throw new Error(`MCP App resource not found: ${uri}`);\n }\n return {\n contents: [\n {\n uri: found.resource.uri,\n mimeType: found.resource.mimeType,\n text: renderMcpAppHtml(\n found.resource,\n found.actionName,\n config,\n requestMeta,\n ),\n ...(found.resource._meta\n ? { _meta: found.resource._meta }\n : {}),\n },\n ],\n };\n });\n },\n );\n }\n\n return server;\n}\n\n// ---------------------------------------------------------------------------\n// Auth — reuses the same pattern as A2A (Bearer token or JWT). Shared so the\n// HTTP mount and any stdio-side auth-aware helper resolve identity identically.\n// ---------------------------------------------------------------------------\n\nexport function getAccessTokens(): string[] {\n const single = process.env.ACCESS_TOKEN;\n const multi = process.env.ACCESS_TOKENS;\n const tokens: string[] = [];\n if (single) tokens.push(single);\n if (multi) {\n tokens.push(\n ...multi\n .split(\",\")\n .map((t) => t.trim())\n .filter(Boolean),\n );\n }\n return tokens;\n}\n\n/**\n * Resolve the caller identity for a static-token (or dev-open) auth path.\n *\n * Static `ACCESS_TOKEN` / `ACCESS_TOKENS` auth carries no per-caller claims,\n * so without this the MCP endpoint would run every tool with\n * `userEmail === undefined` and per-user / per-org scoped actions\n * (`accessFilter`, `resolveAccess`, `resolveCredential`) would return\n * empty / wrong data. The `agent-native mcp install` flow writes\n * `AGENT_NATIVE_OWNER_EMAIL` into the client config env and the stdio proxy\n * forwards it as the `X-Agent-Native-Owner-Email` request header (see\n * `mcp/stdio.ts#authHeaders`). We trust that owner hint *only* on the\n * static-token path — JWT auth already carries a cryptographically verified\n * `sub`, so the header is ignored there and never widens JWT scope.\n *\n * Precedence is server-trusted-first: the server process's\n * `AGENT_NATIVE_OWNER_EMAIL` env (set out-of-band by the operator / deploy)\n * ALWAYS wins, and a client-supplied `X-Agent-Native-Owner-Email` header is\n * honored *only as a fallback when that env is unset*. A static `ACCESS_TOKEN`\n * is a shared bearer secret; letting a request header override a\n * server-configured owner would let anyone holding a leaked token act as any\n * user. The header path remains for the single-tenant local-dev install flow\n * where the app server process has no owner env and the token *is* the\n * workspace secret; multi-tenant deployments must use A2A JWT (verified `sub`),\n * not a static token, for per-user scope.\n *\n * Returns `undefined` when no owner email is available (true dev-open: no\n * token, no secret, no owner) so behavior there stays unchanged.\n */\nfunction deriveStaticTokenIdentity(\n ownerEmailHeader: string | undefined,\n): MCPCallerIdentity | undefined {\n const owner =\n process.env.AGENT_NATIVE_OWNER_EMAIL?.trim() ||\n (typeof ownerEmailHeader === \"string\" && ownerEmailHeader.trim()) ||\n \"\";\n if (!owner) return undefined;\n return { userEmail: owner, orgDomain: undefined };\n}\n\n/**\n * Verify the inbound auth header. Returns:\n * - { authed: true, identity } when verified — `identity` is derived from\n * the JWT (`sub` / `org_domain`) for JWT auth, or from the\n * `AGENT_NATIVE_OWNER_EMAIL` env / `X-Agent-Native-Owner-Email` header\n * for static-token auth (the `agent-native mcp install` flow). `identity`\n * is undefined only for true dev-open with no owner hint.\n * - { authed: false } on rejection.\n *\n * When A2A_SECRET is set we extract the JWT's `sub` (caller email) and\n * `org_domain` claims so the MCP endpoint can wrap tool runs in\n * `runWithRequestContext({ userEmail, orgId })`. Without that wrap, the\n * MCP endpoint loses tenant identity and downstream `accessFilter` /\n * `resolveCredential` calls fall back to platform-wide defaults.\n *\n * `ownerEmailHeader` is the forwarded `X-Agent-Native-Owner-Email` value; it\n * is consulted ONLY on the static-token / dev-open path (never to influence\n * verified JWT identity), so the install flow runs tools as the configured\n * owner instead of an unscoped anonymous caller.\n */\nexport async function verifyAuth(\n authHeader: string | undefined,\n ownerEmailHeader?: string | undefined,\n options: { allowDevOpen?: boolean } = {},\n): Promise<{\n authed: boolean;\n identity?: MCPCallerIdentity;\n /**\n * The caller presented a real credential — a verified A2A/connect JWT, a\n * matching ACCESS_TOKEN, or (on the no-auth-configured path) a forwarded\n * owner-email header from `agent-native mcp install`. Drives the full vs\n * sparse MCP tool surface in local dev. The pure unauthenticated dev-open\n * path (no secret, no token, no owner header) is `false`.\n */\n fullSurface?: boolean;\n}> {\n // No auth configured → allow only when the route caller has already\n // established that this is a loopback/local dev request. Still honour an\n // owner hint there so the local install/connect flow stays tenant-scoped.\n const accessTokens = getAccessTokens();\n const hasA2ASecret = !!process.env.A2A_SECRET;\n if (accessTokens.length === 0 && !hasA2ASecret) {\n if (options.allowDevOpen === false) {\n return { authed: false };\n }\n return {\n authed: true,\n identity: deriveStaticTokenIdentity(ownerEmailHeader),\n // `mcp install`'s stdio proxy forwards an owner-email header even when\n // the local app has no secret configured — that is a real, identified\n // caller and gets the full surface. A bare browser/curl dev probe with\n // no owner hint stays on the sparse dev surface.\n fullSurface: !!(ownerEmailHeader && ownerEmailHeader.trim()),\n };\n }\n\n if (!authHeader?.startsWith(\"Bearer \")) return { authed: false };\n const token = authHeader.slice(7);\n\n // Try JWT via A2A_SECRET\n if (hasA2ASecret) {\n try {\n const jose = await import(\"jose\");\n const { payload } = await jose.jwtVerify(\n token,\n new TextEncoder().encode(process.env.A2A_SECRET!),\n );\n\n const tokenScope =\n typeof payload.scope === \"string\" ? payload.scope : undefined;\n if (tokenScope && tokenScope !== MCP_CONNECT_SCOPE) {\n return { authed: false };\n }\n\n // Connect-minted tokens (scope === \"mcp-connect\") carry a random `jti`\n // and are individually revocable. Only these tokens hit the revoke\n // store — ordinary A2A delegation JWTs skip the DB lookup entirely so\n // the hot path is unchanged. The revoke check FAILS OPEN on any\n // store/DB error: a transient Neon WS drop must never lock every\n // connected agent out. The signature was already cryptographically\n // verified above, so failing open here only widens the explicit-revoke\n // gate, never the trust boundary.\n if (tokenScope === MCP_CONNECT_SCOPE) {\n if (typeof payload.jti !== \"string\" || !payload.jti) {\n return { authed: false };\n }\n const jti = payload.jti;\n try {\n const { isJtiRevoked, touchTokenUsed } =\n await import(\"./connect-store.js\");\n if (await isJtiRevoked(jti)) {\n return { authed: false };\n }\n // Best-effort usage telemetry — never blocks / throws.\n void touchTokenUsed(jti);\n } catch {\n // Store import / lookup failed — fail open (see comment above).\n }\n }\n\n return {\n authed: true,\n identity: {\n userEmail: typeof payload.sub === \"string\" ? payload.sub : undefined,\n orgDomain:\n typeof payload.org_domain === \"string\"\n ? (payload.org_domain as string)\n : undefined,\n },\n // Verified JWT (connect-minted or A2A delegation) — a real caller.\n fullSurface: true,\n };\n } catch {\n // Not a valid JWT — fall through to token check\n }\n }\n\n // Try ACCESS_TOKEN / ACCESS_TOKENS exact match. Static tokens carry no\n // per-caller claims, so derive identity from the forwarded owner-email\n // hint (install flow) — otherwise tools would run unscoped.\n if (accessTokens.length > 0 && accessTokens.includes(token)) {\n return {\n authed: true,\n identity: deriveStaticTokenIdentity(ownerEmailHeader),\n // Matched a configured ACCESS_TOKEN — a real caller.\n fullSurface: true,\n };\n }\n\n return { authed: false };\n}\n\nexport async function resolveOrgIdFromDomain(\n orgDomain: string | undefined,\n): Promise<string | undefined> {\n if (!orgDomain) return undefined;\n try {\n const { resolveOrgByDomain } = await import(\"../org/context.js\");\n const org = await resolveOrgByDomain(orgDomain);\n return org?.orgId ?? undefined;\n } catch {\n return undefined;\n }\n}\n"]}
@@ -26,7 +26,7 @@ export declare const MCP_CONNECT_SCOPE = "mcp-connect";
26
26
  /** Device codes are valid for 10 minutes. */
27
27
  export declare const DEVICE_CODE_TTL_MS: number;
28
28
  /** Default minted-token lifetime. Configurable per-request 1–365 days. */
29
- export declare const DEFAULT_TOKEN_TTL_DAYS = 90;
29
+ export declare const DEFAULT_TOKEN_TTL_DAYS = 365;
30
30
  export declare const MIN_TOKEN_TTL_DAYS = 1;
31
31
  export declare const MAX_TOKEN_TTL_DAYS = 365;
32
32
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"connect-store.d.ts","sourceRoot":"","sources":["../../src/mcp/connect-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"connect-store.d.ts","sourceRoot":"","sources":["../../src/mcp/connect-store.ts"],"names":[],"mappings":"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"}
@@ -29,7 +29,7 @@ export const MCP_CONNECT_SCOPE = "mcp-connect";
29
29
  /** Device codes are valid for 10 minutes. */
30
30
  export const DEVICE_CODE_TTL_MS = 10 * 60_000;
31
31
  /** Default minted-token lifetime. Configurable per-request 1–365 days. */
32
- export const DEFAULT_TOKEN_TTL_DAYS = 90;
32
+ export const DEFAULT_TOKEN_TTL_DAYS = 365;
33
33
  export const MIN_TOKEN_TTL_DAYS = 1;
34
34
  export const MAX_TOKEN_TTL_DAYS = 365;
35
35
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"connect-store.js","sourceRoot":"","sources":["../../src/mcp/connect-store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Framework-table store for the \"connect external agents\" feature.\n *\n * Two additive, dialect-agnostic tables back the browser **Connect** page and\n * the OAuth-style **device-code flow** a CLI drives:\n *\n * - `mcp_connect_tokens` — one row per minted MCP token. We never store the\n * token value (it's a signed JWT); only its `jti` so revocation is a\n * SQL lookup. Revoking sets `revoked_at`; the row is never deleted.\n * - `mcp_device_codes` — short-lived (10 min) device/user code pairs for\n * the OAuth 2.0 device-authorization-style CLI flow. Single-use\n * (`consumed_at`), rate-limited at creation.\n *\n * Mirrors `application-state/store.ts`: lazy `ensureTable()`, `getDbExec()`,\n * `isPostgres()` dialect branching for upserts, `isConnectionError()` swallow\n * so a transient Neon WS drop never 500s. `CREATE TABLE IF NOT EXISTS` only —\n * strictly additive, never DROP / ALTER (shared prod DB rule).\n */\n\nimport {\n getDbExec,\n isConnectionError,\n isPostgres,\n intType,\n} from \"../db/client.js\";\nimport { randomBytes, randomUUID } from \"node:crypto\";\n\nlet _initPromise: Promise<void> | undefined;\n\n/**\n * Scope claim that marks a connect-minted token (vs. an ordinary A2A\n * delegation JWT). Only tokens carrying this scope go through the revoke\n * lookup in `verifyAuth` — defined here so both `connect-route.ts` and\n * `build-server.ts` import it from the leaf store without a cycle.\n */\nexport const MCP_CONNECT_SCOPE = \"mcp-connect\";\n\n/** Device codes are valid for 10 minutes. */\nexport const DEVICE_CODE_TTL_MS = 10 * 60_000;\n\n/** Default minted-token lifetime. Configurable per-request 1–365 days. */\nexport const DEFAULT_TOKEN_TTL_DAYS = 90;\nexport const MIN_TOKEN_TTL_DAYS = 1;\nexport const MAX_TOKEN_TTL_DAYS = 365;\n\n/**\n * Rate limit for `device/start`: at most this many device codes may be created\n * within `DEVICE_START_WINDOW_MS`. Unauthenticated endpoint — keep it tight so\n * a hostile client can't flood the table or brute-force user codes.\n */\nexport const DEVICE_START_MAX = 20;\nexport const DEVICE_START_WINDOW_MS = 60_000;\n\nasync function ensureTable(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n // Additive only. Never DROP / ALTER — this DB is shared across every\n // deploy context (preview/branch/prod) for hosted templates.\n await client.execute(`\n CREATE TABLE IF NOT EXISTS mcp_connect_tokens (\n id TEXT PRIMARY KEY,\n jti TEXT UNIQUE NOT NULL,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n label TEXT,\n created_at ${intType()},\n last_used_at ${intType()},\n revoked_at ${intType()}\n )\n `);\n await client.execute(`\n CREATE TABLE IF NOT EXISTS mcp_device_codes (\n device_code TEXT PRIMARY KEY,\n user_code TEXT NOT NULL,\n owner_email TEXT,\n org_id TEXT,\n status TEXT NOT NULL DEFAULT 'pending',\n token_jti TEXT,\n created_at ${intType()},\n expires_at ${intType()},\n consumed_at ${intType()}\n )\n `);\n })().catch((err) => {\n // Don't cache a rejected init. A transient DB blip should let the next\n // connect/mint/revoke call retry rather than wedging the process.\n _initPromise = undefined;\n throw err;\n });\n }\n return _initPromise;\n}\n\n// ---------------------------------------------------------------------------\n// Minted-token records\n// ---------------------------------------------------------------------------\n\nexport interface MintedTokenRow {\n id: string;\n jti: string;\n ownerEmail: string;\n orgId: string | null;\n label: string | null;\n createdAt: number | null;\n lastUsedAt: number | null;\n revokedAt: number | null;\n}\n\n/**\n * Persist a record of a minted token. The token value itself (a signed JWT)\n * is NEVER stored — only its `jti`, so revocation is a cheap SQL lookup.\n */\nexport async function recordMintedToken(params: {\n jti: string;\n ownerEmail: string;\n orgId?: string | null;\n label?: string | null;\n}): Promise<string> {\n await ensureTable();\n const client = getDbExec();\n const id = randomUUID();\n await client.execute({\n sql: `INSERT INTO mcp_connect_tokens (id, jti, owner_email, org_id, label, created_at, last_used_at, revoked_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n id,\n params.jti,\n params.ownerEmail,\n params.orgId ?? null,\n params.label ?? null,\n Date.now(),\n null,\n null,\n ],\n });\n return id;\n}\n\n/**\n * Returns true when the given `jti` corresponds to a token that has been\n * revoked. Fails OPEN on a store/DB error: a transient Neon WS drop must not\n * lock every connected agent out. Signature verification is unaffected — this\n * is only the post-verify revoke check (see `verifyAuth` in build-server.ts).\n */\nexport async function isJtiRevoked(jti: string): Promise<boolean> {\n try {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT revoked_at FROM mcp_connect_tokens WHERE jti = ?`,\n args: [jti],\n });\n if (rows.length === 0) return false;\n const revokedAt = rows[0].revoked_at ?? rows[0].revokedAt;\n return revokedAt != null;\n } catch (err) {\n // Fail open: a DB blip must not turn every minted token into a 401.\n // (Signature checks already passed; this only gates explicit revokes.)\n if (isConnectionError(err)) return false;\n return false;\n }\n}\n\nexport async function listTokens(\n ownerEmail: string,\n): Promise<MintedTokenRow[]> {\n try {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT id, jti, owner_email, org_id, label, created_at, last_used_at, revoked_at FROM mcp_connect_tokens WHERE owner_email = ? ORDER BY created_at DESC`,\n args: [ownerEmail],\n });\n return rows.map((r: any) => ({\n id: r.id as string,\n jti: r.jti as string,\n ownerEmail: (r.owner_email ?? r.ownerEmail) as string,\n orgId: (r.org_id ?? r.orgId ?? null) as string | null,\n label: (r.label ?? null) as string | null,\n createdAt: numOrNull(r.created_at ?? r.createdAt),\n lastUsedAt: numOrNull(r.last_used_at ?? r.lastUsedAt),\n revokedAt: numOrNull(r.revoked_at ?? r.revokedAt),\n }));\n } catch (err) {\n if (isConnectionError(err)) return [];\n throw err;\n }\n}\n\n/**\n * Revoke a token, but ONLY if it is owned by `ownerEmail` (the caller). The\n * `owner_email = ?` predicate is the access scope — a caller can never revoke\n * another user's token. Idempotent: re-revoking keeps the first timestamp.\n * Returns true when a row was actually transitioned to revoked.\n */\nexport async function revokeToken(\n ownerEmail: string,\n id: string,\n): Promise<boolean> {\n await ensureTable();\n const client = getDbExec();\n const result = await client.execute({\n sql: `UPDATE mcp_connect_tokens SET revoked_at = ? WHERE id = ? AND owner_email = ? AND revoked_at IS NULL`,\n args: [Date.now(), id, ownerEmail],\n });\n return result.rowsAffected > 0;\n}\n\n/**\n * Best-effort: stamp `last_used_at` for a token. Swallows all errors — this is\n * pure telemetry and must never affect the auth path.\n */\nexport async function touchTokenUsed(jti: string): Promise<void> {\n try {\n await ensureTable();\n const client = getDbExec();\n await client.execute({\n sql: `UPDATE mcp_connect_tokens SET last_used_at = ? WHERE jti = ?`,\n args: [Date.now(), jti],\n });\n } catch {\n // last_used_at is informational only — never throw from the hot path.\n }\n}\n\n// ---------------------------------------------------------------------------\n// Device-code flow (OAuth 2.0 device-authorization style)\n// ---------------------------------------------------------------------------\n\nexport interface DeviceCodeRow {\n deviceCode: string;\n userCode: string;\n ownerEmail: string | null;\n orgId: string | null;\n status: \"pending\" | \"approved\" | \"minting\" | \"consumed\" | \"expired\";\n tokenJti: string | null;\n createdAt: number | null;\n expiresAt: number | null;\n consumedAt: number | null;\n}\n\nconst USER_CODE_ALPHABET = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567\"; // Crockford-ish base32, no 0/1/O/I\n\n/** Crypto-random short human-typable code, formatted `XXXX-XXXX`. */\nfunction generateUserCode(): string {\n const bytes = randomBytes(8);\n let out = \"\";\n for (let i = 0; i < 8; i++) {\n out += USER_CODE_ALPHABET[bytes[i] % USER_CODE_ALPHABET.length];\n if (i === 3) out += \"-\";\n }\n return out;\n}\n\nfunction generateDeviceCode(): string {\n return randomBytes(32).toString(\"base64url\");\n}\n\n/**\n * Create a new device+user code pair. Rate-limited: at most\n * `DEVICE_START_MAX` codes within `DEVICE_START_WINDOW_MS`. The window count\n * is a coarse global cap (this endpoint is unauthenticated) — enough to stop\n * table flooding / user-code brute force without per-IP plumbing.\n *\n * Throws `RATE_LIMITED` when the cap is exceeded so the route can map it to a\n * 429.\n */\nexport async function createDeviceCode(): Promise<DeviceCodeRow> {\n await ensureTable();\n const client = getDbExec();\n\n const now = Date.now();\n try {\n const { rows } = await client.execute({\n sql: `SELECT COUNT(*) AS n FROM mcp_device_codes WHERE created_at > ?`,\n args: [now - DEVICE_START_WINDOW_MS],\n });\n const n = Number(rows[0]?.n ?? rows[0]?.[\"COUNT(*)\"] ?? 0);\n if (Number.isFinite(n) && n >= DEVICE_START_MAX) {\n throw new Error(\"RATE_LIMITED\");\n }\n } catch (err: any) {\n if (err?.message === \"RATE_LIMITED\") throw err;\n // A read failure here should not block legitimate device starts — the\n // single-use + short-TTL design is the primary protection. Continue.\n }\n\n const deviceCode = generateDeviceCode();\n const userCode = generateUserCode();\n const expiresAt = now + DEVICE_CODE_TTL_MS;\n await client.execute({\n sql: `INSERT INTO mcp_device_codes (device_code, user_code, owner_email, org_id, status, token_jti, created_at, expires_at, consumed_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n deviceCode,\n userCode,\n null,\n null,\n \"pending\",\n null,\n now,\n expiresAt,\n null,\n ],\n });\n return {\n deviceCode,\n userCode,\n ownerEmail: null,\n orgId: null,\n status: \"pending\",\n tokenJti: null,\n createdAt: now,\n expiresAt,\n consumedAt: null,\n };\n}\n\nfunction mapDeviceRow(r: any): DeviceCodeRow {\n return {\n deviceCode: (r.device_code ?? r.deviceCode) as string,\n userCode: (r.user_code ?? r.userCode) as string,\n ownerEmail: (r.owner_email ?? r.ownerEmail ?? null) as string | null,\n orgId: (r.org_id ?? r.orgId ?? null) as string | null,\n status: (r.status ?? \"pending\") as DeviceCodeRow[\"status\"],\n tokenJti: (r.token_jti ?? r.tokenJti ?? null) as string | null,\n createdAt: numOrNull(r.created_at ?? r.createdAt),\n expiresAt: numOrNull(r.expires_at ?? r.expiresAt),\n consumedAt: numOrNull(r.consumed_at ?? r.consumedAt),\n };\n}\n\nexport async function getDeviceCode(\n deviceCode: string,\n): Promise<DeviceCodeRow | null> {\n try {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT * FROM mcp_device_codes WHERE device_code = ?`,\n args: [deviceCode],\n });\n if (rows.length === 0) return null;\n return mapDeviceRow(rows[0]);\n } catch (err) {\n if (isConnectionError(err)) return null;\n throw err;\n }\n}\n\nexport async function getDeviceCodeByUserCode(\n userCode: string,\n): Promise<DeviceCodeRow | null> {\n try {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT * FROM mcp_device_codes WHERE user_code = ?`,\n args: [userCode],\n });\n if (rows.length === 0) return null;\n return mapDeviceRow(rows[0]);\n } catch (err) {\n if (isConnectionError(err)) return null;\n throw err;\n }\n}\n\n/**\n * Bind the logged-in user (email + org) to a pending device code, identified\n * by its human-typable `user_code`. Only transitions a non-expired, still\n * `pending` row. Returns the bound row, or a string error code:\n * - `not_found` — no such user_code\n * - `expired` — past its TTL\n * - `already` — already approved/consumed (not re-bindable)\n */\nexport async function approveDeviceCode(\n userCode: string,\n ownerEmail: string,\n orgId: string | null,\n): Promise<DeviceCodeRow | \"not_found\" | \"expired\" | \"already\"> {\n await ensureTable();\n const client = getDbExec();\n const row = await getDeviceCodeByUserCode(userCode);\n if (!row) return \"not_found\";\n if ((row.expiresAt ?? 0) < Date.now()) return \"expired\";\n if (row.status !== \"pending\") return \"already\";\n\n const result = await client.execute({\n sql: `UPDATE mcp_device_codes SET status = 'approved', owner_email = ?, org_id = ? WHERE user_code = ? AND status = 'pending'`,\n args: [ownerEmail, orgId, userCode],\n });\n if (result.rowsAffected === 0) {\n // Lost a race with another approve — re-read to report the real state.\n const fresh = await getDeviceCodeByUserCode(userCode);\n return fresh && fresh.status !== \"pending\" ? \"already\" : \"not_found\";\n }\n return {\n ...row,\n status: \"approved\",\n ownerEmail,\n orgId,\n };\n}\n\n/**\n * Atomically transition an approved device code to consumed and stamp the\n * minted token's jti. Single-use: only succeeds when the row is currently\n * `approved` (not already consumed). Returns the pre-consume row on success,\n * or null when it could not be consumed (already consumed / not approved /\n * gone). The caller mints the token only after this returns a row.\n */\nexport async function consumeDeviceCode(\n deviceCode: string,\n tokenJti: string,\n): Promise<DeviceCodeRow | null> {\n await ensureTable();\n const client = getDbExec();\n const row = await getDeviceCode(deviceCode);\n if (!row) return null;\n if (row.status !== \"approved\") return null;\n const result = await client.execute({\n sql: `UPDATE mcp_device_codes SET status = 'consumed', token_jti = ?, consumed_at = ? WHERE device_code = ? AND status = 'approved'`,\n args: [tokenJti, Date.now(), deviceCode],\n });\n if (result.rowsAffected === 0) return null; // lost the single-use race\n return row;\n}\n\n/**\n * Claim an approved device code for token minting without making it terminal.\n * If signing or token recording fails, callers release this back to approved\n * so the CLI can retry the poll instead of being stuck at \"consumed\".\n */\nexport async function claimDeviceCodeForMint(\n deviceCode: string,\n tokenJti: string,\n): Promise<DeviceCodeRow | null> {\n await ensureTable();\n const client = getDbExec();\n const row = await getDeviceCode(deviceCode);\n if (!row || row.status !== \"approved\") return null;\n const result = await client.execute({\n sql: `UPDATE mcp_device_codes SET status = 'minting', token_jti = ?, consumed_at = ? WHERE device_code = ? AND status = 'approved'`,\n args: [tokenJti, Date.now(), deviceCode],\n });\n if (result.rowsAffected === 0) return null;\n return row;\n}\n\nexport async function finishDeviceCodeMint(\n deviceCode: string,\n tokenJti: string,\n): Promise<boolean> {\n await ensureTable();\n const client = getDbExec();\n const result = await client.execute({\n sql: `UPDATE mcp_device_codes SET status = 'consumed' WHERE device_code = ? AND status = 'minting' AND token_jti = ?`,\n args: [deviceCode, tokenJti],\n });\n return result.rowsAffected > 0;\n}\n\nexport async function releaseDeviceCodeMint(\n deviceCode: string,\n tokenJti: string,\n): Promise<void> {\n try {\n await ensureTable();\n const client = getDbExec();\n await client.execute({\n sql: `UPDATE mcp_device_codes SET status = 'approved', token_jti = NULL, consumed_at = NULL WHERE device_code = ? AND status = 'minting' AND token_jti = ?`,\n args: [deviceCode, tokenJti],\n });\n } catch {\n // The next poll will keep returning pending for a minting row until a\n // later cleanup/retry path can observe or repair it. Do not throw here.\n }\n}\n\n/**\n * Best-effort: flip an expired, still-pending/approved row to `expired` so\n * the poll endpoint can report a clean terminal state. Swallows errors.\n */\nexport async function expireDeviceCode(deviceCode: string): Promise<void> {\n try {\n await ensureTable();\n const client = getDbExec();\n await client.execute({\n sql: `UPDATE mcp_device_codes SET status = 'expired' WHERE device_code = ? AND status IN ('pending','approved')`,\n args: [deviceCode],\n });\n } catch {\n // The poll handler already treats past-TTL rows as expired regardless of\n // whether this housekeeping write lands.\n }\n}\n\nfunction numOrNull(v: unknown): number | null {\n if (v == null) return null;\n const n = Number(v);\n return Number.isFinite(n) ? n : null;\n}\n"]}
1
+ {"version":3,"file":"connect-store.js","sourceRoot":"","sources":["../../src/mcp/connect-store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Framework-table store for the \"connect external agents\" feature.\n *\n * Two additive, dialect-agnostic tables back the browser **Connect** page and\n * the OAuth-style **device-code flow** a CLI drives:\n *\n * - `mcp_connect_tokens` — one row per minted MCP token. We never store the\n * token value (it's a signed JWT); only its `jti` so revocation is a\n * SQL lookup. Revoking sets `revoked_at`; the row is never deleted.\n * - `mcp_device_codes` — short-lived (10 min) device/user code pairs for\n * the OAuth 2.0 device-authorization-style CLI flow. Single-use\n * (`consumed_at`), rate-limited at creation.\n *\n * Mirrors `application-state/store.ts`: lazy `ensureTable()`, `getDbExec()`,\n * `isPostgres()` dialect branching for upserts, `isConnectionError()` swallow\n * so a transient Neon WS drop never 500s. `CREATE TABLE IF NOT EXISTS` only —\n * strictly additive, never DROP / ALTER (shared prod DB rule).\n */\n\nimport {\n getDbExec,\n isConnectionError,\n isPostgres,\n intType,\n} from \"../db/client.js\";\nimport { randomBytes, randomUUID } from \"node:crypto\";\n\nlet _initPromise: Promise<void> | undefined;\n\n/**\n * Scope claim that marks a connect-minted token (vs. an ordinary A2A\n * delegation JWT). Only tokens carrying this scope go through the revoke\n * lookup in `verifyAuth` — defined here so both `connect-route.ts` and\n * `build-server.ts` import it from the leaf store without a cycle.\n */\nexport const MCP_CONNECT_SCOPE = \"mcp-connect\";\n\n/** Device codes are valid for 10 minutes. */\nexport const DEVICE_CODE_TTL_MS = 10 * 60_000;\n\n/** Default minted-token lifetime. Configurable per-request 1–365 days. */\nexport const DEFAULT_TOKEN_TTL_DAYS = 365;\nexport const MIN_TOKEN_TTL_DAYS = 1;\nexport const MAX_TOKEN_TTL_DAYS = 365;\n\n/**\n * Rate limit for `device/start`: at most this many device codes may be created\n * within `DEVICE_START_WINDOW_MS`. Unauthenticated endpoint — keep it tight so\n * a hostile client can't flood the table or brute-force user codes.\n */\nexport const DEVICE_START_MAX = 20;\nexport const DEVICE_START_WINDOW_MS = 60_000;\n\nasync function ensureTable(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n // Additive only. Never DROP / ALTER — this DB is shared across every\n // deploy context (preview/branch/prod) for hosted templates.\n await client.execute(`\n CREATE TABLE IF NOT EXISTS mcp_connect_tokens (\n id TEXT PRIMARY KEY,\n jti TEXT UNIQUE NOT NULL,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n label TEXT,\n created_at ${intType()},\n last_used_at ${intType()},\n revoked_at ${intType()}\n )\n `);\n await client.execute(`\n CREATE TABLE IF NOT EXISTS mcp_device_codes (\n device_code TEXT PRIMARY KEY,\n user_code TEXT NOT NULL,\n owner_email TEXT,\n org_id TEXT,\n status TEXT NOT NULL DEFAULT 'pending',\n token_jti TEXT,\n created_at ${intType()},\n expires_at ${intType()},\n consumed_at ${intType()}\n )\n `);\n })().catch((err) => {\n // Don't cache a rejected init. A transient DB blip should let the next\n // connect/mint/revoke call retry rather than wedging the process.\n _initPromise = undefined;\n throw err;\n });\n }\n return _initPromise;\n}\n\n// ---------------------------------------------------------------------------\n// Minted-token records\n// ---------------------------------------------------------------------------\n\nexport interface MintedTokenRow {\n id: string;\n jti: string;\n ownerEmail: string;\n orgId: string | null;\n label: string | null;\n createdAt: number | null;\n lastUsedAt: number | null;\n revokedAt: number | null;\n}\n\n/**\n * Persist a record of a minted token. The token value itself (a signed JWT)\n * is NEVER stored — only its `jti`, so revocation is a cheap SQL lookup.\n */\nexport async function recordMintedToken(params: {\n jti: string;\n ownerEmail: string;\n orgId?: string | null;\n label?: string | null;\n}): Promise<string> {\n await ensureTable();\n const client = getDbExec();\n const id = randomUUID();\n await client.execute({\n sql: `INSERT INTO mcp_connect_tokens (id, jti, owner_email, org_id, label, created_at, last_used_at, revoked_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n id,\n params.jti,\n params.ownerEmail,\n params.orgId ?? null,\n params.label ?? null,\n Date.now(),\n null,\n null,\n ],\n });\n return id;\n}\n\n/**\n * Returns true when the given `jti` corresponds to a token that has been\n * revoked. Fails OPEN on a store/DB error: a transient Neon WS drop must not\n * lock every connected agent out. Signature verification is unaffected — this\n * is only the post-verify revoke check (see `verifyAuth` in build-server.ts).\n */\nexport async function isJtiRevoked(jti: string): Promise<boolean> {\n try {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT revoked_at FROM mcp_connect_tokens WHERE jti = ?`,\n args: [jti],\n });\n if (rows.length === 0) return false;\n const revokedAt = rows[0].revoked_at ?? rows[0].revokedAt;\n return revokedAt != null;\n } catch (err) {\n // Fail open: a DB blip must not turn every minted token into a 401.\n // (Signature checks already passed; this only gates explicit revokes.)\n if (isConnectionError(err)) return false;\n return false;\n }\n}\n\nexport async function listTokens(\n ownerEmail: string,\n): Promise<MintedTokenRow[]> {\n try {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT id, jti, owner_email, org_id, label, created_at, last_used_at, revoked_at FROM mcp_connect_tokens WHERE owner_email = ? ORDER BY created_at DESC`,\n args: [ownerEmail],\n });\n return rows.map((r: any) => ({\n id: r.id as string,\n jti: r.jti as string,\n ownerEmail: (r.owner_email ?? r.ownerEmail) as string,\n orgId: (r.org_id ?? r.orgId ?? null) as string | null,\n label: (r.label ?? null) as string | null,\n createdAt: numOrNull(r.created_at ?? r.createdAt),\n lastUsedAt: numOrNull(r.last_used_at ?? r.lastUsedAt),\n revokedAt: numOrNull(r.revoked_at ?? r.revokedAt),\n }));\n } catch (err) {\n if (isConnectionError(err)) return [];\n throw err;\n }\n}\n\n/**\n * Revoke a token, but ONLY if it is owned by `ownerEmail` (the caller). The\n * `owner_email = ?` predicate is the access scope — a caller can never revoke\n * another user's token. Idempotent: re-revoking keeps the first timestamp.\n * Returns true when a row was actually transitioned to revoked.\n */\nexport async function revokeToken(\n ownerEmail: string,\n id: string,\n): Promise<boolean> {\n await ensureTable();\n const client = getDbExec();\n const result = await client.execute({\n sql: `UPDATE mcp_connect_tokens SET revoked_at = ? WHERE id = ? AND owner_email = ? AND revoked_at IS NULL`,\n args: [Date.now(), id, ownerEmail],\n });\n return result.rowsAffected > 0;\n}\n\n/**\n * Best-effort: stamp `last_used_at` for a token. Swallows all errors — this is\n * pure telemetry and must never affect the auth path.\n */\nexport async function touchTokenUsed(jti: string): Promise<void> {\n try {\n await ensureTable();\n const client = getDbExec();\n await client.execute({\n sql: `UPDATE mcp_connect_tokens SET last_used_at = ? WHERE jti = ?`,\n args: [Date.now(), jti],\n });\n } catch {\n // last_used_at is informational only — never throw from the hot path.\n }\n}\n\n// ---------------------------------------------------------------------------\n// Device-code flow (OAuth 2.0 device-authorization style)\n// ---------------------------------------------------------------------------\n\nexport interface DeviceCodeRow {\n deviceCode: string;\n userCode: string;\n ownerEmail: string | null;\n orgId: string | null;\n status: \"pending\" | \"approved\" | \"minting\" | \"consumed\" | \"expired\";\n tokenJti: string | null;\n createdAt: number | null;\n expiresAt: number | null;\n consumedAt: number | null;\n}\n\nconst USER_CODE_ALPHABET = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567\"; // Crockford-ish base32, no 0/1/O/I\n\n/** Crypto-random short human-typable code, formatted `XXXX-XXXX`. */\nfunction generateUserCode(): string {\n const bytes = randomBytes(8);\n let out = \"\";\n for (let i = 0; i < 8; i++) {\n out += USER_CODE_ALPHABET[bytes[i] % USER_CODE_ALPHABET.length];\n if (i === 3) out += \"-\";\n }\n return out;\n}\n\nfunction generateDeviceCode(): string {\n return randomBytes(32).toString(\"base64url\");\n}\n\n/**\n * Create a new device+user code pair. Rate-limited: at most\n * `DEVICE_START_MAX` codes within `DEVICE_START_WINDOW_MS`. The window count\n * is a coarse global cap (this endpoint is unauthenticated) — enough to stop\n * table flooding / user-code brute force without per-IP plumbing.\n *\n * Throws `RATE_LIMITED` when the cap is exceeded so the route can map it to a\n * 429.\n */\nexport async function createDeviceCode(): Promise<DeviceCodeRow> {\n await ensureTable();\n const client = getDbExec();\n\n const now = Date.now();\n try {\n const { rows } = await client.execute({\n sql: `SELECT COUNT(*) AS n FROM mcp_device_codes WHERE created_at > ?`,\n args: [now - DEVICE_START_WINDOW_MS],\n });\n const n = Number(rows[0]?.n ?? rows[0]?.[\"COUNT(*)\"] ?? 0);\n if (Number.isFinite(n) && n >= DEVICE_START_MAX) {\n throw new Error(\"RATE_LIMITED\");\n }\n } catch (err: any) {\n if (err?.message === \"RATE_LIMITED\") throw err;\n // A read failure here should not block legitimate device starts — the\n // single-use + short-TTL design is the primary protection. Continue.\n }\n\n const deviceCode = generateDeviceCode();\n const userCode = generateUserCode();\n const expiresAt = now + DEVICE_CODE_TTL_MS;\n await client.execute({\n sql: `INSERT INTO mcp_device_codes (device_code, user_code, owner_email, org_id, status, token_jti, created_at, expires_at, consumed_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n deviceCode,\n userCode,\n null,\n null,\n \"pending\",\n null,\n now,\n expiresAt,\n null,\n ],\n });\n return {\n deviceCode,\n userCode,\n ownerEmail: null,\n orgId: null,\n status: \"pending\",\n tokenJti: null,\n createdAt: now,\n expiresAt,\n consumedAt: null,\n };\n}\n\nfunction mapDeviceRow(r: any): DeviceCodeRow {\n return {\n deviceCode: (r.device_code ?? r.deviceCode) as string,\n userCode: (r.user_code ?? r.userCode) as string,\n ownerEmail: (r.owner_email ?? r.ownerEmail ?? null) as string | null,\n orgId: (r.org_id ?? r.orgId ?? null) as string | null,\n status: (r.status ?? \"pending\") as DeviceCodeRow[\"status\"],\n tokenJti: (r.token_jti ?? r.tokenJti ?? null) as string | null,\n createdAt: numOrNull(r.created_at ?? r.createdAt),\n expiresAt: numOrNull(r.expires_at ?? r.expiresAt),\n consumedAt: numOrNull(r.consumed_at ?? r.consumedAt),\n };\n}\n\nexport async function getDeviceCode(\n deviceCode: string,\n): Promise<DeviceCodeRow | null> {\n try {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT * FROM mcp_device_codes WHERE device_code = ?`,\n args: [deviceCode],\n });\n if (rows.length === 0) return null;\n return mapDeviceRow(rows[0]);\n } catch (err) {\n if (isConnectionError(err)) return null;\n throw err;\n }\n}\n\nexport async function getDeviceCodeByUserCode(\n userCode: string,\n): Promise<DeviceCodeRow | null> {\n try {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT * FROM mcp_device_codes WHERE user_code = ?`,\n args: [userCode],\n });\n if (rows.length === 0) return null;\n return mapDeviceRow(rows[0]);\n } catch (err) {\n if (isConnectionError(err)) return null;\n throw err;\n }\n}\n\n/**\n * Bind the logged-in user (email + org) to a pending device code, identified\n * by its human-typable `user_code`. Only transitions a non-expired, still\n * `pending` row. Returns the bound row, or a string error code:\n * - `not_found` — no such user_code\n * - `expired` — past its TTL\n * - `already` — already approved/consumed (not re-bindable)\n */\nexport async function approveDeviceCode(\n userCode: string,\n ownerEmail: string,\n orgId: string | null,\n): Promise<DeviceCodeRow | \"not_found\" | \"expired\" | \"already\"> {\n await ensureTable();\n const client = getDbExec();\n const row = await getDeviceCodeByUserCode(userCode);\n if (!row) return \"not_found\";\n if ((row.expiresAt ?? 0) < Date.now()) return \"expired\";\n if (row.status !== \"pending\") return \"already\";\n\n const result = await client.execute({\n sql: `UPDATE mcp_device_codes SET status = 'approved', owner_email = ?, org_id = ? WHERE user_code = ? AND status = 'pending'`,\n args: [ownerEmail, orgId, userCode],\n });\n if (result.rowsAffected === 0) {\n // Lost a race with another approve — re-read to report the real state.\n const fresh = await getDeviceCodeByUserCode(userCode);\n return fresh && fresh.status !== \"pending\" ? \"already\" : \"not_found\";\n }\n return {\n ...row,\n status: \"approved\",\n ownerEmail,\n orgId,\n };\n}\n\n/**\n * Atomically transition an approved device code to consumed and stamp the\n * minted token's jti. Single-use: only succeeds when the row is currently\n * `approved` (not already consumed). Returns the pre-consume row on success,\n * or null when it could not be consumed (already consumed / not approved /\n * gone). The caller mints the token only after this returns a row.\n */\nexport async function consumeDeviceCode(\n deviceCode: string,\n tokenJti: string,\n): Promise<DeviceCodeRow | null> {\n await ensureTable();\n const client = getDbExec();\n const row = await getDeviceCode(deviceCode);\n if (!row) return null;\n if (row.status !== \"approved\") return null;\n const result = await client.execute({\n sql: `UPDATE mcp_device_codes SET status = 'consumed', token_jti = ?, consumed_at = ? WHERE device_code = ? AND status = 'approved'`,\n args: [tokenJti, Date.now(), deviceCode],\n });\n if (result.rowsAffected === 0) return null; // lost the single-use race\n return row;\n}\n\n/**\n * Claim an approved device code for token minting without making it terminal.\n * If signing or token recording fails, callers release this back to approved\n * so the CLI can retry the poll instead of being stuck at \"consumed\".\n */\nexport async function claimDeviceCodeForMint(\n deviceCode: string,\n tokenJti: string,\n): Promise<DeviceCodeRow | null> {\n await ensureTable();\n const client = getDbExec();\n const row = await getDeviceCode(deviceCode);\n if (!row || row.status !== \"approved\") return null;\n const result = await client.execute({\n sql: `UPDATE mcp_device_codes SET status = 'minting', token_jti = ?, consumed_at = ? WHERE device_code = ? AND status = 'approved'`,\n args: [tokenJti, Date.now(), deviceCode],\n });\n if (result.rowsAffected === 0) return null;\n return row;\n}\n\nexport async function finishDeviceCodeMint(\n deviceCode: string,\n tokenJti: string,\n): Promise<boolean> {\n await ensureTable();\n const client = getDbExec();\n const result = await client.execute({\n sql: `UPDATE mcp_device_codes SET status = 'consumed' WHERE device_code = ? AND status = 'minting' AND token_jti = ?`,\n args: [deviceCode, tokenJti],\n });\n return result.rowsAffected > 0;\n}\n\nexport async function releaseDeviceCodeMint(\n deviceCode: string,\n tokenJti: string,\n): Promise<void> {\n try {\n await ensureTable();\n const client = getDbExec();\n await client.execute({\n sql: `UPDATE mcp_device_codes SET status = 'approved', token_jti = NULL, consumed_at = NULL WHERE device_code = ? AND status = 'minting' AND token_jti = ?`,\n args: [deviceCode, tokenJti],\n });\n } catch {\n // The next poll will keep returning pending for a minting row until a\n // later cleanup/retry path can observe or repair it. Do not throw here.\n }\n}\n\n/**\n * Best-effort: flip an expired, still-pending/approved row to `expired` so\n * the poll endpoint can report a clean terminal state. Swallows errors.\n */\nexport async function expireDeviceCode(deviceCode: string): Promise<void> {\n try {\n await ensureTable();\n const client = getDbExec();\n await client.execute({\n sql: `UPDATE mcp_device_codes SET status = 'expired' WHERE device_code = ? AND status IN ('pending','approved')`,\n args: [deviceCode],\n });\n } catch {\n // The poll handler already treats past-TTL rows as expired regardless of\n // whether this housekeeping write lands.\n }\n}\n\nfunction numOrNull(v: unknown): number | null {\n if (v == null) return null;\n const n = Number(v);\n return Number.isFinite(n) ? n : null;\n}\n"]}
@@ -8,8 +8,8 @@
8
8
  * - **proxy (default)** — connect an MCP `Client` over
9
9
  * `StreamableHTTPClientTransport` to the *already-running* local app's
10
10
  * `http://127.0.0.1:<port>/_agent-native/mcp`, and run a stdio `Server`
11
- * that forwards `tools/list` + `tools/call` to it. The live app is the
12
- * single source of truth: HMR'd actions, the real registry, correct
11
+ * that forwards tools and optional MCP App resources to it. The live app
12
+ * is the single source of truth: HMR'd actions, the real registry, correct
13
13
  * per-request deep links, and tenant scoping all come for free. If the
14
14
  * app isn't running, we wait briefly for it (the workspace gateway boots
15
15
  * it lazily on first request).
@@ -1 +1 @@
1
- {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../src/mcp/stdio.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAqMD;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,IAAI,GAAE,kBAAuB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAef"}
1
+ {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../src/mcp/stdio.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAKH,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAwOD;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,IAAI,GAAE,kBAAuB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAef"}
package/dist/mcp/stdio.js CHANGED
@@ -8,8 +8,8 @@
8
8
  * - **proxy (default)** — connect an MCP `Client` over
9
9
  * `StreamableHTTPClientTransport` to the *already-running* local app's
10
10
  * `http://127.0.0.1:<port>/_agent-native/mcp`, and run a stdio `Server`
11
- * that forwards `tools/list` + `tools/call` to it. The live app is the
12
- * single source of truth: HMR'd actions, the real registry, correct
11
+ * that forwards tools and optional MCP App resources to it. The live app
12
+ * is the single source of truth: HMR'd actions, the real registry, correct
13
13
  * per-request deep links, and tenant scoping all come for free. If the
14
14
  * app isn't running, we wait briefly for it (the workspace gateway boots
15
15
  * it lazily on first request).
@@ -61,10 +61,10 @@ async function probeOrigin(origin, timeoutMs = 800) {
61
61
  /**
62
62
  * Proxy mode: stdio Server ⇄ HTTP Client to the running app.
63
63
  *
64
- * We register the standard `tools/list` and `tools/call` handlers on the
65
- * stdio server and forward them verbatim to the upstream HTTP MCP server via
66
- * the SDK `Client`. The upstream owns tool definitions, results, and the
67
- * appended deep-link block / `_meta`, so nothing is duplicated here.
64
+ * We register the standard handlers on the stdio server and forward them
65
+ * verbatim to the upstream HTTP MCP server via the SDK `Client`. The upstream
66
+ * owns tool definitions, results, MCP App resources, and the appended
67
+ * deep-link block / `_meta`, so nothing is duplicated here.
68
68
  */
69
69
  async function runProxy(opts) {
70
70
  const { origin, appId } = await resolveLocalAppOrigin({
@@ -96,7 +96,7 @@ async function runProxy(opts) {
96
96
  const { StreamableHTTPClientTransport } = await import("@modelcontextprotocol/sdk/client/streamableHttp.js");
97
97
  const { Server } = await import("@modelcontextprotocol/sdk/server/index.js");
98
98
  const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
99
- const { ListToolsRequestSchema, CallToolRequestSchema } = await import("@modelcontextprotocol/sdk/types.js");
99
+ const { ListToolsRequestSchema, CallToolRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListResourceTemplatesRequestSchema, } = await import("@modelcontextprotocol/sdk/types.js");
100
100
  // --- Upstream HTTP client -------------------------------------------------
101
101
  const clientTransport = new StreamableHTTPClientTransport(new URL(target), {
102
102
  requestInit: { headers: authHeaders(env) },
@@ -105,7 +105,14 @@ async function runProxy(opts) {
105
105
  await client.connect(clientTransport);
106
106
  log(`Proxying stdio ⇄ ${target} (app: ${appId})`);
107
107
  // --- Downstream stdio server ---------------------------------------------
108
- const server = new Server({ name: `agent-native-${appId}`, version: "1.0.0" }, { capabilities: { tools: {} } });
108
+ const upstreamCapabilities = client.getServerCapabilities();
109
+ const capabilities = { tools: {} };
110
+ if (upstreamCapabilities?.resources)
111
+ capabilities.resources = {};
112
+ if (upstreamCapabilities?.extensions) {
113
+ capabilities.extensions = upstreamCapabilities.extensions;
114
+ }
115
+ const server = new Server({ name: `agent-native-${appId}`, version: "1.0.0" }, { capabilities });
109
116
  server.setRequestHandler(ListToolsRequestSchema, async (request) => {
110
117
  return client.listTools(request.params);
111
118
  });
@@ -113,6 +120,17 @@ async function runProxy(opts) {
113
120
  // Forward the call verbatim; the upstream appends the deep-link block.
114
121
  return client.callTool(request.params);
115
122
  });
123
+ if (upstreamCapabilities?.resources) {
124
+ server.setRequestHandler(ListResourcesRequestSchema, async (request) => {
125
+ return client.listResources(request.params);
126
+ });
127
+ server.setRequestHandler(ListResourceTemplatesRequestSchema, async (request) => {
128
+ return client.listResourceTemplates(request.params);
129
+ });
130
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
131
+ return client.readResource(request.params);
132
+ });
133
+ }
116
134
  const stdioTransport = new StdioServerTransport();
117
135
  await server.connect(stdioTransport);
118
136
  // Keep the proxy alive until the client/transport closes.
@@ -1 +1 @@
1
- {"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../src/mcp/stdio.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MCP **stdio** transport for the `agent-native mcp serve` command.\n *\n * This is the binary external coding agents (Claude Code, Claude Cowork,\n * Codex) actually launch — they speak MCP over a child process's stdio, not\n * HTTP. We expose the agent-native app's MCP surface over stdio in two modes:\n *\n * - **proxy (default)** — connect an MCP `Client` over\n * `StreamableHTTPClientTransport` to the *already-running* local app's\n * `http://127.0.0.1:<port>/_agent-native/mcp`, and run a stdio `Server`\n * that forwards `tools/list` + `tools/call` to it. The live app is the\n * single source of truth: HMR'd actions, the real registry, correct\n * per-request deep links, and tenant scoping all come for free. If the\n * app isn't running, we wait briefly for it (the workspace gateway boots\n * it lazily on first request).\n *\n * - **standalone (`--standalone`)** — no running server, no HMR. Build the\n * MCP server in-process from `autoDiscoverActions(cwd)` +\n * `createMCPServerForRequest`, connected straight to a\n * `StdioServerTransport`. Useful in CI / when nothing is serving.\n *\n * Node-only: imports `node:*` and the SDK stdio/http transports. Never part\n * of the serverless bundle.\n */\n\nimport { resolveLocalAppOrigin } from \"./workspace-resolve.js\";\n\nexport interface RunMCPStdioOptions {\n /** App id to bridge to (workspace). Optional in a single-app project. */\n appId?: string;\n /** Explicit port of the running app's dev server. Overrides discovery. */\n port?: number;\n /** Skip the HTTP proxy and build the server in-process from disk. */\n standalone?: boolean;\n /** Working directory (defaults to process.cwd()). */\n cwd?: string;\n /** Env (defaults to process.env). */\n env?: NodeJS.ProcessEnv;\n /** Max ms to wait for the running app before failing (proxy mode). */\n waitForAppMs?: number;\n}\n\nconst MCP_SUBPATH = \"/_agent-native/mcp\";\n\nfunction log(msg: string): void {\n // stderr only — stdout is the MCP protocol channel and must stay clean.\n process.stderr.write(`[mcp] ${msg}\\n`);\n}\n\n/**\n * Owner identity the installer wrote into the client config's env. Passed\n * through to the HTTP MCP endpoint as a JWT/identity bearer (when present)\n * so tool runs stay tenant-scoped. For local dev with a static ACCESS_TOKEN\n * the email is informational; for hosted JWT auth the token already carries\n * `sub`, so we only add an `X-Agent-Native-Owner-Email` hint header.\n */\nfunction authHeaders(env: NodeJS.ProcessEnv): Record<string, string> {\n const headers: Record<string, string> = {};\n const token = env.ACCESS_TOKEN || env.AGENT_NATIVE_MCP_TOKEN;\n if (token) headers[\"Authorization\"] = `Bearer ${token}`;\n const owner = env.AGENT_NATIVE_OWNER_EMAIL;\n if (owner) headers[\"X-Agent-Native-Owner-Email\"] = owner;\n return headers;\n}\n\nasync function probeOrigin(origin: string, timeoutMs = 800): Promise<boolean> {\n try {\n const res = await fetch(`${origin}${MCP_SUBPATH}`, {\n method: \"GET\",\n signal: AbortSignal.timeout(timeoutMs),\n });\n // Any HTTP response (even 401/405/406) means the server is up.\n return res.status > 0;\n } catch {\n return false;\n }\n}\n\n/**\n * Proxy mode: stdio Server ⇄ HTTP Client to the running app.\n *\n * We register the standard `tools/list` and `tools/call` handlers on the\n * stdio server and forward them verbatim to the upstream HTTP MCP server via\n * the SDK `Client`. The upstream owns tool definitions, results, and the\n * appended deep-link block / `_meta`, so nothing is duplicated here.\n */\nasync function runProxy(opts: RunMCPStdioOptions): Promise<void> {\n const { origin, appId } = await resolveLocalAppOrigin({\n cwd: opts.cwd,\n env: opts.env,\n appId: opts.appId,\n port: opts.port,\n });\n const env = opts.env ?? process.env;\n const target = `${origin}${MCP_SUBPATH}`;\n\n // Wait for the app to come up. The workspace gateway lazily boots an app's\n // dev server on first request, so a fresh `mcp serve` may briefly race the\n // boot. Hit the gateway path too so the lazy start is triggered.\n const deadline = Date.now() + (opts.waitForAppMs ?? 60_000);\n let up = await probeOrigin(origin);\n if (!up) {\n log(`Waiting for ${appId} at ${origin} …`);\n while (!up && Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, 750));\n up = await probeOrigin(origin);\n }\n }\n if (!up) {\n throw new Error(\n `Timed out waiting for the local app at ${origin}. Start it with ` +\n `\\`agent-native dev\\` (or \\`agent-native workspace-dev\\`), or run ` +\n `\\`agent-native mcp serve --standalone\\` to build the server from disk.`,\n );\n }\n\n const { Client } = await import(\"@modelcontextprotocol/sdk/client/index.js\");\n const { StreamableHTTPClientTransport } =\n await import(\"@modelcontextprotocol/sdk/client/streamableHttp.js\");\n const { Server } = await import(\"@modelcontextprotocol/sdk/server/index.js\");\n const { StdioServerTransport } =\n await import(\"@modelcontextprotocol/sdk/server/stdio.js\");\n const { ListToolsRequestSchema, CallToolRequestSchema } =\n await import(\"@modelcontextprotocol/sdk/types.js\");\n\n // --- Upstream HTTP client -------------------------------------------------\n const clientTransport = new StreamableHTTPClientTransport(new URL(target), {\n requestInit: { headers: authHeaders(env) },\n });\n const client = new Client(\n { name: \"agent-native-mcp-proxy\", version: \"1.0.0\" },\n { capabilities: {} },\n );\n await client.connect(clientTransport);\n log(`Proxying stdio ⇄ ${target} (app: ${appId})`);\n\n // --- Downstream stdio server ---------------------------------------------\n const server = new Server(\n { name: `agent-native-${appId}`, version: \"1.0.0\" },\n { capabilities: { tools: {} } },\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async (request: any) => {\n return client.listTools(request.params);\n });\n\n server.setRequestHandler(CallToolRequestSchema, async (request: any) => {\n // Forward the call verbatim; the upstream appends the deep-link block.\n return client.callTool(request.params);\n });\n\n const stdioTransport = new StdioServerTransport();\n await server.connect(stdioTransport);\n\n // Keep the proxy alive until the client/transport closes.\n await new Promise<void>((resolve) => {\n const done = () => resolve();\n stdioTransport.onclose = done;\n clientTransport.onclose = done;\n process.once(\"SIGINT\", done);\n process.once(\"SIGTERM\", done);\n });\n\n try {\n await client.close();\n } catch {\n // best-effort\n }\n}\n\n/**\n * Standalone mode: build the MCP server in-process from disk.\n *\n * No running server, no HMR — actions are discovered via\n * `autoDiscoverActions(cwd)` and the shared `createMCPServerForRequest`\n * builder is reused so behavior (tools, deep links, builtin cross-app tools)\n * matches the HTTP mount exactly.\n */\nasync function runStandalone(opts: RunMCPStdioOptions): Promise<void> {\n const cwd = opts.cwd ?? process.cwd();\n const env = opts.env ?? process.env;\n\n const { resolveLocalAppOrigin } = await import(\"./workspace-resolve.js\");\n let appId = opts.appId ?? \"app\";\n let origin: string | undefined;\n try {\n const resolved = await resolveLocalAppOrigin({\n cwd,\n env,\n appId: opts.appId,\n port: opts.port,\n });\n appId = resolved.appId;\n // Origin is best-effort here (server may not be running) — still useful\n // so a `link` builder's relative deep link becomes an absolute URL.\n origin = resolved.origin;\n } catch {\n // No workspace / can't resolve — fall back to a bare app id.\n }\n\n const { autoDiscoverActions } = await import(\"../server/action-discovery.js\");\n const { createMCPServerForRequest } = await import(\"./build-server.js\");\n const { StdioServerTransport } =\n await import(\"@modelcontextprotocol/sdk/server/stdio.js\");\n\n const actions = await autoDiscoverActions(cwd);\n log(\n `Standalone: discovered ${Object.keys(actions).length} action(s) in ${cwd}`,\n );\n\n const server = await createMCPServerForRequest(\n {\n name: appId.charAt(0).toUpperCase() + appId.slice(1),\n appId,\n description: `Agent-native ${appId} app (standalone MCP)`,\n actions,\n // No askAgent in standalone — there is no running engine/runtime here.\n // builtin cross-app tools stay on so `list_apps` / `open_app` /\n // `create_workspace_app` / `list_templates` still work from disk.\n },\n // No verified identity in standalone (no inbound auth header). Runs with\n // platform-default scope, same as a tokenless local HTTP mount.\n undefined,\n { origin },\n );\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n await new Promise<void>((resolve) => {\n const done = () => resolve();\n transport.onclose = done;\n process.once(\"SIGINT\", done);\n process.once(\"SIGTERM\", done);\n });\n}\n\n/**\n * Entry point for `agent-native mcp serve`. Defaults to proxy mode; pass\n * `standalone: true` to build the server from disk with no running app.\n */\nexport async function runMCPStdio(\n opts: RunMCPStdioOptions = {},\n): Promise<void> {\n if (opts.standalone) {\n await runStandalone(opts);\n return;\n }\n try {\n await runProxy(opts);\n } catch (err: any) {\n // Proxy couldn't reach a running app — surface a clear, actionable\n // message on stderr. We do NOT silently fall back to standalone: the\n // caller asked for the live registry; auto-falling-back would hide a\n // broken dev server and serve stale tools.\n log(`Proxy mode failed: ${err?.message ?? err}`);\n throw err;\n }\n}\n"]}
1
+ {"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../src/mcp/stdio.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MCP **stdio** transport for the `agent-native mcp serve` command.\n *\n * This is the binary external coding agents (Claude Code, Claude Cowork,\n * Codex) actually launch — they speak MCP over a child process's stdio, not\n * HTTP. We expose the agent-native app's MCP surface over stdio in two modes:\n *\n * - **proxy (default)** — connect an MCP `Client` over\n * `StreamableHTTPClientTransport` to the *already-running* local app's\n * `http://127.0.0.1:<port>/_agent-native/mcp`, and run a stdio `Server`\n * that forwards tools and optional MCP App resources to it. The live app\n * is the single source of truth: HMR'd actions, the real registry, correct\n * per-request deep links, and tenant scoping all come for free. If the\n * app isn't running, we wait briefly for it (the workspace gateway boots\n * it lazily on first request).\n *\n * - **standalone (`--standalone`)** — no running server, no HMR. Build the\n * MCP server in-process from `autoDiscoverActions(cwd)` +\n * `createMCPServerForRequest`, connected straight to a\n * `StdioServerTransport`. Useful in CI / when nothing is serving.\n *\n * Node-only: imports `node:*` and the SDK stdio/http transports. Never part\n * of the serverless bundle.\n */\n\nimport { resolveLocalAppOrigin } from \"./workspace-resolve.js\";\nimport type { ServerCapabilities } from \"@modelcontextprotocol/sdk/types.js\";\n\nexport interface RunMCPStdioOptions {\n /** App id to bridge to (workspace). Optional in a single-app project. */\n appId?: string;\n /** Explicit port of the running app's dev server. Overrides discovery. */\n port?: number;\n /** Skip the HTTP proxy and build the server in-process from disk. */\n standalone?: boolean;\n /** Working directory (defaults to process.cwd()). */\n cwd?: string;\n /** Env (defaults to process.env). */\n env?: NodeJS.ProcessEnv;\n /** Max ms to wait for the running app before failing (proxy mode). */\n waitForAppMs?: number;\n}\n\nconst MCP_SUBPATH = \"/_agent-native/mcp\";\n\nfunction log(msg: string): void {\n // stderr only — stdout is the MCP protocol channel and must stay clean.\n process.stderr.write(`[mcp] ${msg}\\n`);\n}\n\n/**\n * Owner identity the installer wrote into the client config's env. Passed\n * through to the HTTP MCP endpoint as a JWT/identity bearer (when present)\n * so tool runs stay tenant-scoped. For local dev with a static ACCESS_TOKEN\n * the email is informational; for hosted JWT auth the token already carries\n * `sub`, so we only add an `X-Agent-Native-Owner-Email` hint header.\n */\nfunction authHeaders(env: NodeJS.ProcessEnv): Record<string, string> {\n const headers: Record<string, string> = {};\n const token = env.ACCESS_TOKEN || env.AGENT_NATIVE_MCP_TOKEN;\n if (token) headers[\"Authorization\"] = `Bearer ${token}`;\n const owner = env.AGENT_NATIVE_OWNER_EMAIL;\n if (owner) headers[\"X-Agent-Native-Owner-Email\"] = owner;\n return headers;\n}\n\nasync function probeOrigin(origin: string, timeoutMs = 800): Promise<boolean> {\n try {\n const res = await fetch(`${origin}${MCP_SUBPATH}`, {\n method: \"GET\",\n signal: AbortSignal.timeout(timeoutMs),\n });\n // Any HTTP response (even 401/405/406) means the server is up.\n return res.status > 0;\n } catch {\n return false;\n }\n}\n\n/**\n * Proxy mode: stdio Server ⇄ HTTP Client to the running app.\n *\n * We register the standard handlers on the stdio server and forward them\n * verbatim to the upstream HTTP MCP server via the SDK `Client`. The upstream\n * owns tool definitions, results, MCP App resources, and the appended\n * deep-link block / `_meta`, so nothing is duplicated here.\n */\nasync function runProxy(opts: RunMCPStdioOptions): Promise<void> {\n const { origin, appId } = await resolveLocalAppOrigin({\n cwd: opts.cwd,\n env: opts.env,\n appId: opts.appId,\n port: opts.port,\n });\n const env = opts.env ?? process.env;\n const target = `${origin}${MCP_SUBPATH}`;\n\n // Wait for the app to come up. The workspace gateway lazily boots an app's\n // dev server on first request, so a fresh `mcp serve` may briefly race the\n // boot. Hit the gateway path too so the lazy start is triggered.\n const deadline = Date.now() + (opts.waitForAppMs ?? 60_000);\n let up = await probeOrigin(origin);\n if (!up) {\n log(`Waiting for ${appId} at ${origin} …`);\n while (!up && Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, 750));\n up = await probeOrigin(origin);\n }\n }\n if (!up) {\n throw new Error(\n `Timed out waiting for the local app at ${origin}. Start it with ` +\n `\\`agent-native dev\\` (or \\`agent-native workspace-dev\\`), or run ` +\n `\\`agent-native mcp serve --standalone\\` to build the server from disk.`,\n );\n }\n\n const { Client } = await import(\"@modelcontextprotocol/sdk/client/index.js\");\n const { StreamableHTTPClientTransport } =\n await import(\"@modelcontextprotocol/sdk/client/streamableHttp.js\");\n const { Server } = await import(\"@modelcontextprotocol/sdk/server/index.js\");\n const { StdioServerTransport } =\n await import(\"@modelcontextprotocol/sdk/server/stdio.js\");\n const {\n ListToolsRequestSchema,\n CallToolRequestSchema,\n ListResourcesRequestSchema,\n ReadResourceRequestSchema,\n ListResourceTemplatesRequestSchema,\n } = await import(\"@modelcontextprotocol/sdk/types.js\");\n\n // --- Upstream HTTP client -------------------------------------------------\n const clientTransport = new StreamableHTTPClientTransport(new URL(target), {\n requestInit: { headers: authHeaders(env) },\n });\n const client = new Client(\n { name: \"agent-native-mcp-proxy\", version: \"1.0.0\" },\n { capabilities: {} },\n );\n await client.connect(clientTransport);\n log(`Proxying stdio ⇄ ${target} (app: ${appId})`);\n\n // --- Downstream stdio server ---------------------------------------------\n const upstreamCapabilities = client.getServerCapabilities();\n const capabilities: ServerCapabilities = { tools: {} };\n if (upstreamCapabilities?.resources) capabilities.resources = {};\n if (upstreamCapabilities?.extensions) {\n capabilities.extensions = upstreamCapabilities.extensions;\n }\n\n const server = new Server(\n { name: `agent-native-${appId}`, version: \"1.0.0\" },\n { capabilities },\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async (request: any) => {\n return client.listTools(request.params);\n });\n\n server.setRequestHandler(CallToolRequestSchema, async (request: any) => {\n // Forward the call verbatim; the upstream appends the deep-link block.\n return client.callTool(request.params);\n });\n\n if (upstreamCapabilities?.resources) {\n server.setRequestHandler(\n ListResourcesRequestSchema,\n async (request: any) => {\n return client.listResources(request.params);\n },\n );\n\n server.setRequestHandler(\n ListResourceTemplatesRequestSchema,\n async (request: any) => {\n return client.listResourceTemplates(request.params);\n },\n );\n\n server.setRequestHandler(\n ReadResourceRequestSchema,\n async (request: any) => {\n return client.readResource(request.params);\n },\n );\n }\n\n const stdioTransport = new StdioServerTransport();\n await server.connect(stdioTransport);\n\n // Keep the proxy alive until the client/transport closes.\n await new Promise<void>((resolve) => {\n const done = () => resolve();\n stdioTransport.onclose = done;\n clientTransport.onclose = done;\n process.once(\"SIGINT\", done);\n process.once(\"SIGTERM\", done);\n });\n\n try {\n await client.close();\n } catch {\n // best-effort\n }\n}\n\n/**\n * Standalone mode: build the MCP server in-process from disk.\n *\n * No running server, no HMR — actions are discovered via\n * `autoDiscoverActions(cwd)` and the shared `createMCPServerForRequest`\n * builder is reused so behavior (tools, deep links, builtin cross-app tools)\n * matches the HTTP mount exactly.\n */\nasync function runStandalone(opts: RunMCPStdioOptions): Promise<void> {\n const cwd = opts.cwd ?? process.cwd();\n const env = opts.env ?? process.env;\n\n const { resolveLocalAppOrigin } = await import(\"./workspace-resolve.js\");\n let appId = opts.appId ?? \"app\";\n let origin: string | undefined;\n try {\n const resolved = await resolveLocalAppOrigin({\n cwd,\n env,\n appId: opts.appId,\n port: opts.port,\n });\n appId = resolved.appId;\n // Origin is best-effort here (server may not be running) — still useful\n // so a `link` builder's relative deep link becomes an absolute URL.\n origin = resolved.origin;\n } catch {\n // No workspace / can't resolve — fall back to a bare app id.\n }\n\n const { autoDiscoverActions } = await import(\"../server/action-discovery.js\");\n const { createMCPServerForRequest } = await import(\"./build-server.js\");\n const { StdioServerTransport } =\n await import(\"@modelcontextprotocol/sdk/server/stdio.js\");\n\n const actions = await autoDiscoverActions(cwd);\n log(\n `Standalone: discovered ${Object.keys(actions).length} action(s) in ${cwd}`,\n );\n\n const server = await createMCPServerForRequest(\n {\n name: appId.charAt(0).toUpperCase() + appId.slice(1),\n appId,\n description: `Agent-native ${appId} app (standalone MCP)`,\n actions,\n // No askAgent in standalone — there is no running engine/runtime here.\n // builtin cross-app tools stay on so `list_apps` / `open_app` /\n // `create_workspace_app` / `list_templates` still work from disk.\n },\n // No verified identity in standalone (no inbound auth header). Runs with\n // platform-default scope, same as a tokenless local HTTP mount.\n undefined,\n { origin },\n );\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n await new Promise<void>((resolve) => {\n const done = () => resolve();\n transport.onclose = done;\n process.once(\"SIGINT\", done);\n process.once(\"SIGTERM\", done);\n });\n}\n\n/**\n * Entry point for `agent-native mcp serve`. Defaults to proxy mode; pass\n * `standalone: true` to build the server from disk with no running app.\n */\nexport async function runMCPStdio(\n opts: RunMCPStdioOptions = {},\n): Promise<void> {\n if (opts.standalone) {\n await runStandalone(opts);\n return;\n }\n try {\n await runProxy(opts);\n } catch (err: any) {\n // Proxy couldn't reach a running app — surface a clear, actionable\n // message on stderr. We do NOT silently fall back to standalone: the\n // caller asked for the live registry; auto-falling-back would hide a\n // broken dev server and serve stale tools.\n log(`Proxy mode failed: ${err?.message ?? err}`);\n throw err;\n }\n}\n"]}
@@ -0,0 +1,40 @@
1
+ import type { McpTool } from "./manager.js";
2
+ export declare const MCP_ACTION_RESULT_MARKER: "__agentNativeMcpToolResult";
3
+ export interface AgentMcpAppResourceContent {
4
+ uri: string;
5
+ mimeType?: string;
6
+ text?: string;
7
+ blob?: string;
8
+ _meta?: Record<string, unknown>;
9
+ }
10
+ export interface AgentMcpAppPayload {
11
+ serverId: string;
12
+ toolName: string;
13
+ originalToolName: string;
14
+ resourceUri: string;
15
+ toolInput: Record<string, unknown>;
16
+ toolResult: Record<string, unknown>;
17
+ tool?: {
18
+ name: string;
19
+ title?: string;
20
+ description?: string;
21
+ inputSchema?: Record<string, unknown>;
22
+ outputSchema?: Record<string, unknown>;
23
+ annotations?: Record<string, unknown>;
24
+ _meta?: Record<string, unknown>;
25
+ };
26
+ resource?: AgentMcpAppResourceContent;
27
+ }
28
+ export interface McpActionResult {
29
+ [MCP_ACTION_RESULT_MARKER]: true;
30
+ text: string;
31
+ raw: unknown;
32
+ serverId: string;
33
+ toolName: string;
34
+ originalToolName: string;
35
+ input: Record<string, unknown>;
36
+ mcpApp?: AgentMcpAppPayload;
37
+ }
38
+ export declare function isMcpActionResult(value: unknown): value is McpActionResult;
39
+ export declare function toolForMcpAppPayload(tool: McpTool): AgentMcpAppPayload["tool"];
40
+ //# sourceMappingURL=app-result.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-result.d.ts","sourceRoot":"","sources":["../../src/mcp-client/app-result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,eAAO,MAAM,wBAAwB,EAAG,4BAAqC,CAAC;AAE9E,MAAM,WAAW,0BAA0B;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,IAAI,CAAC,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACtC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACvC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACtC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACjC,CAAC;IACF,QAAQ,CAAC,EAAE,0BAA0B,CAAC;CACvC;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,wBAAwB,CAAC,EAAE,IAAI,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,kBAAkB,CAAC;CAC7B;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAO1E;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,OAAO,GACZ,kBAAkB,CAAC,MAAM,CAAC,CAU5B"}
@@ -0,0 +1,19 @@
1
+ export const MCP_ACTION_RESULT_MARKER = "__agentNativeMcpToolResult";
2
+ export function isMcpActionResult(value) {
3
+ return (!!value &&
4
+ typeof value === "object" &&
5
+ value[MCP_ACTION_RESULT_MARKER] === true &&
6
+ typeof value.text === "string");
7
+ }
8
+ export function toolForMcpAppPayload(tool) {
9
+ return {
10
+ name: tool.originalName,
11
+ ...(tool.title ? { title: tool.title } : {}),
12
+ description: tool.description,
13
+ inputSchema: tool.inputSchema,
14
+ ...(tool.outputSchema ? { outputSchema: tool.outputSchema } : {}),
15
+ ...(tool.annotations ? { annotations: tool.annotations } : {}),
16
+ ...(tool._meta ? { _meta: tool._meta } : {}),
17
+ };
18
+ }
19
+ //# sourceMappingURL=app-result.js.map