From bf3ae45439ccd97f2991c87457081648e75cff71 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Fri, 3 Jul 2026 13:43:21 -0500 Subject: [PATCH] fix(core): clean up mcp event surface (#35221) --- packages/core/src/mcp/client.ts | 6 +++- packages/core/src/mcp/index.ts | 6 +++- packages/core/test/mcp.test.ts | 14 +++++++++ packages/schema/src/mcp-event.ts | 2 +- packages/schema/test/event-manifest.test.ts | 3 ++ packages/sdk/js/src/v2/gen/types.gen.ts | 33 --------------------- 6 files changed, 28 insertions(+), 36 deletions(-) create mode 100644 packages/core/test/mcp.test.ts diff --git a/packages/core/src/mcp/client.ts b/packages/core/src/mcp/client.ts index fcd0814fb8c..84ccbd70bbe 100644 --- a/packages/core/src/mcp/client.ts +++ b/packages/core/src/mcp/client.ts @@ -46,7 +46,11 @@ const TolerantListPromptsResult = ListPromptsResultSchema.extend({ export class NeedsAuthError extends Schema.TaggedErrorClass()("MCP.NeedsAuthError", { server: Schema.String, -}) {} +}) { + override get message() { + return `MCP server requires authentication: ${this.server}` + } +} export class ConnectError extends Schema.TaggedErrorClass()("MCP.ConnectError", { server: Schema.String, diff --git a/packages/core/src/mcp/index.ts b/packages/core/src/mcp/index.ts index 2075c8dd19a..d4935dc5129 100644 --- a/packages/core/src/mcp/index.ts +++ b/packages/core/src/mcp/index.ts @@ -127,7 +127,11 @@ export class ResourceContent extends Schema.Class("MCP.Resource export class NotFoundError extends Schema.TaggedErrorClass()("MCP.NotFoundError", { server: ServerName, -}) {} +}) { + override get message() { + return `MCP server not found: ${this.server}` + } +} export class ToolCallError extends Schema.TaggedErrorClass()("MCP.ToolCallError", { server: ServerName, diff --git a/packages/core/test/mcp.test.ts b/packages/core/test/mcp.test.ts new file mode 100644 index 00000000000..15ff95a28ff --- /dev/null +++ b/packages/core/test/mcp.test.ts @@ -0,0 +1,14 @@ +import { describe, expect, test } from "bun:test" +import { MCP } from "@opencode-ai/core/mcp/index" +import { MCPClient } from "@opencode-ai/core/mcp/client" + +describe("MCP errors", () => { + test("expose useful messages", () => { + expect(new MCP.NotFoundError({ server: MCP.ServerName.make("demo") }).message).toBe("MCP server not found: demo") + expect(new MCP.ToolCallError({ server: MCP.ServerName.make("demo"), tool: "search", message: "failed" }).message).toBe( + "failed", + ) + expect(new MCPClient.NeedsAuthError({ server: "demo" }).message).toBe("MCP server requires authentication: demo") + expect(new MCPClient.ConnectError({ server: "demo", message: "offline" }).message).toBe("offline") + }) +}) diff --git a/packages/schema/src/mcp-event.ts b/packages/schema/src/mcp-event.ts index f4221335e95..ae1e82656d0 100644 --- a/packages/schema/src/mcp-event.ts +++ b/packages/schema/src/mcp-event.ts @@ -27,4 +27,4 @@ export const StatusChanged = Event.ephemeral({ }, }) -export const Definitions = Event.inventory(ToolsChanged, BrowserOpenFailed, StatusChanged) +export const Definitions = Event.inventory(ToolsChanged, StatusChanged) diff --git a/packages/schema/test/event-manifest.test.ts b/packages/schema/test/event-manifest.test.ts index 9cdf3a787a9..4fa23e75f77 100644 --- a/packages/schema/test/event-manifest.test.ts +++ b/packages/schema/test/event-manifest.test.ts @@ -12,6 +12,7 @@ import { } from "../src/index.js" import { EventManifest } from "../src/event-manifest.js" import { IdeEvent } from "../src/ide-event.js" +import { McpEvent } from "../src/mcp-event.js" import { SessionEvent } from "../src/session-event.js" import { SessionTodo } from "../src/session-todo.js" import { SessionV1 } from "../src/session-v1.js" @@ -63,6 +64,8 @@ describe("public event manifest", () => { expect(Permission.Event.Definitions).toEqual([Permission.Event.Asked, Permission.Event.Replied]) expect(Form.Event.Definitions).toEqual([Form.Event.Created, Form.Event.Replied, Form.Event.Cancelled]) expect(Reference.Event.Definitions).toEqual([Reference.Event.Updated]) + expect(McpEvent.Definitions).toEqual([McpEvent.ToolsChanged, McpEvent.StatusChanged]) + expect(EventManifest.Latest.has("mcp.browser.open.failed")).toBe(false) expect(EventManifest.Latest.has("ide.installed")).toBe(false) expect(IdeEvent.Definitions).toEqual([IdeEvent.Installed]) const sessionV1TailStart = EventManifest.Definitions.indexOf(SessionV1.Event.PartDelta) diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index d97eb59298f..56cdccf087d 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -89,7 +89,6 @@ export type Event = | EventTuiToastShow2 | EventTuiSessionSelect2 | EventMcpToolsChanged - | EventMcpBrowserOpenFailed | EventMcpStatusChanged | EventCommandExecuted | EventProjectUpdated @@ -1556,14 +1555,6 @@ export type GlobalEvent = { server: string } } - | { - id: string - type: "mcp.browser.open.failed" - properties: { - mcpName: string - url: string - } - } | { id: string type: "mcp.status.changed" @@ -3177,7 +3168,6 @@ export type V2Event = | TuiToastShow | TuiSessionSelect | McpToolsChanged - | McpBrowserOpenFailed | McpStatusChanged | CommandExecuted | ProjectUpdated @@ -6373,20 +6363,6 @@ export type McpToolsChanged = { } } -export type McpBrowserOpenFailed = { - id: string - created: number - metadata?: { - [key: string]: unknown - } - type: "mcp.browser.open.failed" - location?: LocationRef - data: { - mcpName: string - url: string - } -} - export type McpStatusChanged = { id: string created: number @@ -7493,15 +7469,6 @@ export type EventMcpToolsChanged = { } } -export type EventMcpBrowserOpenFailed = { - id: string - type: "mcp.browser.open.failed" - properties: { - mcpName: string - url: string - } -} - export type EventMcpStatusChanged = { id: string type: "mcp.status.changed"