fix(app): show MCP connection failures as toasts (#45522)

This commit is contained in:
Luke Parker
2026-08-27 18:46:54 +10:00
committed by GitHub
parent 53a4829672
commit ed95fdaa27
2 changed files with 94 additions and 0 deletions
@@ -85,3 +85,94 @@ for (const shared of [true, false]) {
expect(requests.every((request) => request.directory === workspace)).toBe(true)
})
}
for (const surface of ["popover", "dialog"] as const) {
test(`shows connection failures from the MCP ${surface} and allows reconnecting`, async ({ page }, testInfo) => {
const error = "Streamable HTTP error: Error POSTing to endpoint: 404 Not Found"
const state = { fail: true, status: surface === "popover" ? "failed" : "disabled" }
const requests: { path: string; directory: string }[] = []
await page.addInitScript(() => {
localStorage.setItem("settings.v3", JSON.stringify({ general: { showStatus: true } }))
})
await mockOpenCodeServer(page, {
directory,
project: {
id: projectID,
worktree: directory,
vcs: "git",
name: "mcp-workspace",
time: { created: 1700000000000, updated: 1700000000000 },
sandboxes: [workspace],
},
provider: { all: [], connected: [], default: {} },
sessions: [{ id: sessionID, projectID, directory: workspace, title }],
pageMessages: () => ({ items: [] }),
})
await page.route("**/api/mcp**", async (route) => {
if (route.request().method() === "OPTIONS") return route.fallback()
const url = new URL(route.request().url())
const target = url.searchParams.get("location[directory]") ?? directory
requests.push({ path: url.pathname, directory: target })
if (url.pathname === "/api/mcp/figma-desktop/connect") {
state.status = state.fail ? "failed" : "connected"
// Connection failures are reported by the refreshed status, not the HTTP response.
return route.fulfill({ status: 204 })
}
return route.fulfill({
json: {
location: { directory: target },
data:
url.pathname === "/api/mcp/resource"
? { resources: [], templates: [] }
: [
{
name: "figma-desktop",
status: { status: target === workspace ? state.status : "connected", error },
},
],
},
})
})
await page.goto(`/server/${base64Encode(server)}/session/${sessionID}`)
await expectSessionTitle(page, title)
await expect(page.getByRole("textbox", { name: "Prompt", exact: true })).toBeEditable()
if (surface === "popover") await page.getByRole("button", { name: "Status", exact: true }).click()
if (surface === "dialog") await page.keyboard.press("ControlOrMeta+;")
const panel =
surface === "popover" ? page.getByRole("tabpanel") : page.getByRole("dialog", { name: "MCPs", exact: true })
const toggle = panel.getByRole("switch")
await expect(panel.getByText("figma-desktop", { exact: true })).toBeVisible()
await expect(toggle).not.toBeChecked()
await expect(toggle).toBeEnabled()
requests.length = 0
await panel.locator('[data-slot="switch-control"]').click()
const toast = page
.getByRole("listitem", { includeHidden: true })
.filter({ has: page.getByText("Request failed", { exact: true }) })
await expect(toast.getByText(`figma-desktop: ${error}`, { exact: true })).toBeVisible()
await expect(toggle).not.toBeChecked()
await expect(toggle).toBeEnabled()
expect(requests.filter((request) => request.path.endsWith("/connect"))).toEqual([
{ path: "/api/mcp/figma-desktop/connect", directory: workspace },
])
expect(requests.every((request) => request.directory === workspace)).toBe(true)
await expect(toast).toHaveCSS("opacity", "1")
await testInfo.attach("mcp-connection-error", { body: await page.screenshot(), contentType: "image/png" })
if (surface === "popover") await page.keyboard.press("Escape")
if (surface === "dialog") await panel.getByRole("button", { name: "Close", exact: true }).click()
await expect(panel).toBeHidden()
await toast.getByRole("button", { name: "Dismiss", exact: true }).click()
await expect(toast).toBeHidden()
state.fail = false
if (surface === "popover") await page.getByRole("button", { name: "Status", exact: true }).click()
if (surface === "dialog") await page.keyboard.press("ControlOrMeta+;")
await expect(toggle).toBeEnabled()
await panel.locator('[data-slot="switch-control"]').click()
await expect(toggle).toBeChecked()
await expect(toggle).toBeEnabled()
await expect(toast).toBeHidden()
})
}
@@ -40,6 +40,9 @@ export function useMcpToggle(directory?: Accessor<string | undefined>, onSuccess
data.location.mcp.server.invalidate(ref)
data.location.mcp.resource.invalidate(ref)
await Promise.all([data.location.mcp.server.sync(ref), data.location.mcp.resource.sync(ref), onSuccess?.()])
// A successful HTTP response can still leave the MCP connection in a failed state.
const status = data.location.mcp.server.list(ref)?.find((item) => item.name === name)?.status
if (status?.status === "failed") throw new Error(`${name}: ${status.error}`)
},
onError: (error) =>
showToast({