diff --git a/packages/opencode/src/mcp/index.ts b/packages/opencode/src/mcp/index.ts index 7f6141ca3da2..e5dbaefa418a 100644 --- a/packages/opencode/src/mcp/index.ts +++ b/packages/opencode/src/mcp/index.ts @@ -28,7 +28,7 @@ import { McpAuth } from "./auth" import { EventV2Bridge } from "@/event-v2-bridge" import { TuiEvent } from "@/server/tui-event" import open from "open" -import { Cause, Effect, Exit, Layer, Option, Context, Schema, Stream } from "effect" +import { Cause, Effect, Exit, Layer, Context, Schema, Stream } from "effect" import { EffectBridge } from "@/effect/bridge" import { InstanceState } from "@/effect/instance-state" import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process" @@ -928,16 +928,17 @@ export const layer = Layer.effect( const pending = pendingOAuthTransports.get(mcpName) if (!pending) throw new Error(`No pending OAuth flow for MCP server: ${mcpName}`) - const result = yield* Effect.tryPromise({ - try: () => pending.transport.finishAuth(authorizationCode).then(() => true as const), - catch: (error) => { - return error - }, - }).pipe(Effect.option) + const error = yield* Effect.tryPromise({ + try: () => pending.transport.finishAuth(authorizationCode), + catch: (error) => error, + }).pipe( + Effect.match({ + onFailure: (error) => (error instanceof Error ? error.message : String(error)), + onSuccess: () => undefined, + }), + ) - if (Option.isNone(result)) { - return { status: "failed", error: "OAuth completion failed" } satisfies Status - } + if (error) return { status: "failed", error: `OAuth completion failed: ${error}` } satisfies Status yield* Effect.promise(() => pending.provider?.commit() ?? Promise.resolve()) yield* auth.clearCodeVerifier(mcpName) diff --git a/packages/opencode/test/mcp/oauth-auto-connect.test.ts b/packages/opencode/test/mcp/oauth-auto-connect.test.ts index 43b10929e4bb..866bf829018b 100644 --- a/packages/opencode/test/mcp/oauth-auto-connect.test.ts +++ b/packages/opencode/test/mcp/oauth-auto-connect.test.ts @@ -263,7 +263,7 @@ mcpTest.instance( expect(yield* mcp.finishAuth(name, "invalid-code")).toEqual({ status: "failed", - error: "OAuth completion failed", + error: "OAuth completion failed: Token exchange failed", }) const entry = yield* auth.get(name) expect(entry?.tokens?.accessToken).toBe("working-token")