{"record":{"id":"14972cec5b2aa559","repo":"nexu-io/open-design","slug":"the-mcp-apps-bridge-is-unavailable","errorCode":null,"errorMessage":"The MCP Apps bridge is unavailable.","messagePattern":"The MCP Apps bridge is unavailable\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/mcp-apps/brief-resource.ts","lineNumber":383,"sourceCode":"        function selections() {\n          const answers = {};\n          if (!draft || !draft.questionForm) return answers;\n          for (const item of draft.questionForm.questions || []) {\n            const selected = form.elements.namedItem(item.id);\n            const value = selected && selected.value;\n            if (value) answers[item.id] = [value];\n          }\n          return answers;\n        }\n\n        async function callConfirm(argumentsValue) {\n          if (standardBridgeReady && hostSupports(\"serverTools\")) {\n            return request(\"tools/call\", { name: \"confirm_brief\", arguments: argumentsValue });\n          }\n          if (window.openai && typeof window.openai.callTool === \"function\") {\n            return window.openai.callTool(\"confirm_brief\", argumentsValue);\n          }\n          throw new Error(copy().bridgeUnavailable);\n        }\n\n        async function publishConfirmation(payload) {\n          const activeLocale = effectiveLocale();\n          const prompt = copy().confirmed + \"\\\\n\\\\n\" + payload.summary + \"\\\\n\\\\n\"\n            + (activeLocale === \"zh-CN\"\n              ? \"请根据这份需求继续。\"\n              : activeLocale === \"zh-TW\"\n                ? \"請依照這份需求繼續。\"\n                : activeLocale === \"ja\"\n                  ? \"このブリーフに沿って続行してください。\"\n                  : \"Continue with this brief.\");\n          // Codex exposes its host-native follow-up bridge alongside MCP Apps.\n          // Prefer it when present so the confirmed brief becomes readable user\n          // text instead of a context-only turn rendered as \"(No content)\".\n          if (window.openai && typeof window.openai.sendFollowUpMessage === \"function\") {\n            await window.openai.sendFollowUpMessage({ prompt, scrollToBottom: true });\n            return clearModelContext();","sourceCodeStart":365,"sourceCodeEnd":401,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/mcp-apps/brief-resource.ts#L365-L401","documentation":"Browser-side error from the MCP Apps brief UI's callConfirm(). The function tries two bridges to invoke the confirm_brief tool: first the standard MCP Apps bridge (when standardBridgeReady AND host capability 'serverTools'), then the legacy `window.openai.callTool` API. If neither is available, it throws — meaning the brief form is being rendered in a context that cannot call host tools at all.","triggerScenarios":"Opening the brief resource HTML in a plain browser tab (no MCP host); running inside a host that does not implement the standard bridge and does not expose window.openai.callTool; the standard bridge failed to initialize (standardBridgeReady is false) and the legacy API is absent.","commonSituations":"Developer previews the brief HTML standalone during testing; host is an older MCP client without Apps support; an ACP-style host that exposes a different bridge not yet wired in; browser extension blocking window.openai.","solutions":["Render the brief inside an MCP Apps-capable host (the Open Design daemon's MCP server, or Claude Desktop with MCP Apps support).","If you control the host, implement either the standard bridge (respond to initialize capabilities with serverTools) or expose window.openai.callTool.","For local preview, drive the brief through the daemon's HTTP API instead of the embedded UI.","Check the browser console — standardBridgeInitialization failing is the usual root cause."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Inside the brief UI host capability detection (run on load)\nfunction canCallConfirm(): boolean {\n  return (standardBridgeReady && hostSupports('serverTools'))\n    || (typeof window !== 'undefined' && !!window.openai && typeof window.openai.callTool === 'function');\n}\n\nif (!canCallConfirm()) {\n  // Show a banner instead of letting the user reach the submit that would throw.\n  showBanner('This host cannot confirm briefs. Run inside an MCP Apps-capable host.');\n}","typeGuard":null,"tryCatchPattern":"// Already handled in-source: callConfirm() throws; the submit handler catches and re-applies 'ready' phase.\ntry {\n  await callConfirm(args);\n} catch (error) {\n  applyPhase('ready', publicErrorMessage(error, copy().confirmFailed));\n  return;\n}","preventionTips":["Detect host capabilities on load and disable submit if neither bridge is present.","Run the brief UI only inside MCP Apps-capable hosts.","If you maintain a host, declare serverTools and implement tools/call."],"tags":["mcp-apps","brief","browser","bridge","host-capability"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}