summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2025-06-22 21:10:05 -0400
committerDax Raad <[email protected]>2025-06-22 21:10:05 -0400
commit100d6212be5b1475692116397aa9bef05da79cbf (patch)
tree3caaa94015fe941a0bf3cf45a36d0d2175c80dd9
parentf0e19a6542d3e3aa7b68e4ec430a7c8bb9b22537 (diff)
downloadopencode-100d6212be5b1475692116397aa9bef05da79cbf.tar.gz
opencode-100d6212be5b1475692116397aa9bef05da79cbf.zip
more graceful mcp failures
-rw-r--r--opencode.json8
-rw-r--r--packages/opencode/src/cli/error.ts3
-rw-r--r--packages/opencode/src/index.ts6
-rw-r--r--packages/opencode/src/mcp/index.ts53
4 files changed, 64 insertions, 6 deletions
diff --git a/opencode.json b/opencode.json
index 720ece5c1..090aed596 100644
--- a/opencode.json
+++ b/opencode.json
@@ -1,3 +1,9 @@
{
- "$schema": "https://opencode.ai/config.json"
+ "$schema": "https://opencode.ai/config.json",
+ "mcp": {
+ "sentry": {
+ "type": "remote",
+ "url": "https://mcp.sentry.dev/sse"
+ }
+ }
}
diff --git a/packages/opencode/src/cli/error.ts b/packages/opencode/src/cli/error.ts
index 21df94a62..bb7186e88 100644
--- a/packages/opencode/src/cli/error.ts
+++ b/packages/opencode/src/cli/error.ts
@@ -1,6 +1,9 @@
import { Config } from "../config/config"
+import { MCP } from "../mcp"
export function FormatError(input: unknown) {
+ if (MCP.Failed.isInstance(input))
+ return `MCP server "${input.data.name}" failed. Note, opencode does not support MCP authentication yet.`
if (Config.JsonError.isInstance(input))
return `Config file at ${input.data.path} is not valid JSON`
if (Config.InvalidError.isInstance(input))
diff --git a/packages/opencode/src/index.ts b/packages/opencode/src/index.ts
index ffe4dcc79..559f45091 100644
--- a/packages/opencode/src/index.ts
+++ b/packages/opencode/src/index.ts
@@ -20,6 +20,9 @@ import { Bus } from "./bus"
import { Config } from "./config/config"
import { NamedError } from "./util/error"
import { FormatError } from "./cli/error"
+import { MCP } from "./mcp"
+
+const cancel = new AbortController()
const cli = yargs(hideBin(process.argv))
.scriptName("opencode")
@@ -72,6 +75,7 @@ const cli = yargs(hideBin(process.argv))
}
const proc = Bun.spawn({
cmd: [...cmd, ...process.argv.slice(2)],
+ signal: cancel.signal,
cwd,
stdout: "inherit",
stderr: "inherit",
@@ -157,3 +161,5 @@ try {
"Unexpected error, check log file at " + Log.file() + " for more details",
)
}
+
+cancel.abort()
diff --git a/packages/opencode/src/mcp/index.ts b/packages/opencode/src/mcp/index.ts
index af52c91a8..154c5464b 100644
--- a/packages/opencode/src/mcp/index.ts
+++ b/packages/opencode/src/mcp/index.ts
@@ -2,8 +2,22 @@ import { experimental_createMCPClient, type Tool } from "ai"
import { Experimental_StdioMCPTransport } from "ai/mcp-stdio"
import { App } from "../app/app"
import { Config } from "../config/config"
+import { Log } from "../util/log"
+import { NamedError } from "../util/error"
+import { z } from "zod"
+import { Session } from "../session"
+import { Bus } from "../bus"
export namespace MCP {
+ const log = Log.create({ service: "mcp" })
+
+ export const Failed = NamedError.create(
+ "MCPFailed",
+ z.object({
+ name: z.string(),
+ }),
+ )
+
const state = App.state(
"mcp",
async () => {
@@ -12,27 +26,56 @@ export namespace MCP {
[name: string]: Awaited<ReturnType<typeof experimental_createMCPClient>>
} = {}
for (const [key, mcp] of Object.entries(cfg.mcp ?? {})) {
+ log.info("found", { key, type: mcp.type })
if (mcp.type === "remote") {
- clients[key] = await experimental_createMCPClient({
+ const client = await experimental_createMCPClient({
name: key,
transport: {
type: "sse",
url: mcp.url,
},
- })
+ }).catch(() => {})
+ if (!client) {
+ Bus.publish(Session.Event.Error, {
+ error: {
+ name: "UnknownError",
+ data: {
+ message: `MCP server ${key} failed to start`,
+ },
+ },
+ })
+ continue
+ }
+ clients[key] = client
}
if (mcp.type === "local") {
const [cmd, ...args] = mcp.command
- clients[key] = await experimental_createMCPClient({
+ const client = await experimental_createMCPClient({
name: key,
transport: new Experimental_StdioMCPTransport({
stderr: "ignore",
command: cmd,
args,
- env: mcp.environment,
+ env: {
+ ...process.env,
+ ...(cmd === "opencode" ? { BUN_BE_BUN: "1" } : {}),
+ ...mcp.environment,
+ },
}),
- })
+ }).catch(() => {})
+ if (!client) {
+ Bus.publish(Session.Event.Error, {
+ error: {
+ name: "UnknownError",
+ data: {
+ message: `MCP server ${key} failed to start`,
+ },
+ },
+ })
+ continue
+ }
+ clients[key] = client
}
}