Skip to content

Commit 33290c5

Browse files
committed
Revert "feat(mcp): add OAuth redirect URI configuration for MCP servers (anomalyco#7379)"
This reverts commit 40b275d.
1 parent 5d613a0 commit 33290c5

6 files changed

Lines changed: 19 additions & 151 deletions

File tree

packages/opencode/src/cli/cmd/mcp.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import * as prompts from "@clack/prompts"
66
import { UI } from "../ui"
77
import { MCP } from "../../mcp"
88
import { McpAuth } from "../../mcp/auth"
9-
import { McpOAuthCallback } from "../../mcp/oauth-callback"
109
import { McpOAuthProvider } from "../../mcp/oauth-provider"
1110
import { Config } from "../../config/config"
1211
import { Instance } from "../../project/instance"
@@ -683,18 +682,13 @@ export const McpDebugCommand = cmd({
683682

684683
// Try to discover OAuth metadata
685684
const oauthConfig = typeof serverConfig.oauth === "object" ? serverConfig.oauth : undefined
686-
687-
// Start callback server
688-
await McpOAuthCallback.ensureRunning(oauthConfig?.redirectUri)
689-
690685
const authProvider = new McpOAuthProvider(
691686
serverName,
692687
serverConfig.url,
693688
{
694689
clientId: oauthConfig?.clientId,
695690
clientSecret: oauthConfig?.clientSecret,
696691
scope: oauthConfig?.scope,
697-
redirectUri: oauthConfig?.redirectUri,
698692
},
699693
{
700694
onRedirect: async () => {},

packages/opencode/src/config/config.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -435,10 +435,6 @@ export namespace Config {
435435
.describe("OAuth client ID. If not provided, dynamic client registration (RFC 7591) will be attempted."),
436436
clientSecret: z.string().optional().describe("OAuth client secret (if required by the authorization server)"),
437437
scope: z.string().optional().describe("OAuth scopes to request during authorization"),
438-
redirectUri: z
439-
.string()
440-
.optional()
441-
.describe("OAuth redirect URI (default: http://127.0.0.1:19876/mcp/oauth/callback)."),
442438
})
443439
.strict()
444440
.meta({

packages/opencode/src/mcp/index.ts

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -308,16 +308,13 @@ export namespace MCP {
308308
let authProvider: McpOAuthProvider | undefined
309309

310310
if (!oauthDisabled) {
311-
await McpOAuthCallback.ensureRunning(oauthConfig?.redirectUri)
312-
313311
authProvider = new McpOAuthProvider(
314312
key,
315313
mcp.url,
316314
{
317315
clientId: oauthConfig?.clientId,
318316
clientSecret: oauthConfig?.clientSecret,
319317
scope: oauthConfig?.scope,
320-
redirectUri: oauthConfig?.redirectUri,
321318
},
322319
{
323320
onRedirect: async (url) => {
@@ -347,7 +344,6 @@ export namespace MCP {
347344

348345
let lastError: Error | undefined
349346
const connectTimeout = mcp.timeout ?? DEFAULT_TIMEOUT
350-
351347
for (const { name, transport } of transports) {
352348
try {
353349
const client = new Client({
@@ -574,8 +570,7 @@ export namespace MCP {
574570

575571
for (const [clientName, client] of Object.entries(clientsSnapshot)) {
576572
// Only include tools from connected MCPs (skip disabled ones)
577-
const clientStatus = s.status[clientName]?.status
578-
if (clientStatus !== "connected") {
573+
if (s.status[clientName]?.status !== "connected") {
579574
continue
580575
}
581576

@@ -725,10 +720,8 @@ export namespace MCP {
725720
throw new Error(`MCP server ${mcpName} has OAuth explicitly disabled`)
726721
}
727722

728-
// OAuth config is optional - if not provided, we'll use auto-discovery
729-
const oauthConfig = typeof mcpConfig.oauth === "object" ? mcpConfig.oauth : undefined
730-
731-
await McpOAuthCallback.ensureRunning(oauthConfig?.redirectUri)
723+
// Start the callback server
724+
await McpOAuthCallback.ensureRunning()
732725

733726
// Generate and store a cryptographically secure state parameter BEFORE creating the provider
734727
// The SDK will call provider.state() to read this value
@@ -738,6 +731,8 @@ export namespace MCP {
738731
await McpAuth.updateOAuthState(mcpName, oauthState)
739732

740733
// Create a new auth provider for this flow
734+
// OAuth config is optional - if not provided, we'll use auto-discovery
735+
const oauthConfig = typeof mcpConfig.oauth === "object" ? mcpConfig.oauth : undefined
741736
let capturedUrl: URL | undefined
742737
const authProvider = new McpOAuthProvider(
743738
mcpName,
@@ -746,7 +741,6 @@ export namespace MCP {
746741
clientId: oauthConfig?.clientId,
747742
clientSecret: oauthConfig?.clientSecret,
748743
scope: oauthConfig?.scope,
749-
redirectUri: oauthConfig?.redirectUri,
750744
},
751745
{
752746
onRedirect: async (url) => {
@@ -775,7 +769,6 @@ export namespace MCP {
775769
pendingOAuthTransports.set(mcpName, transport)
776770
return { authorizationUrl: capturedUrl.toString() }
777771
}
778-
779772
throw error
780773
}
781774
}
@@ -785,9 +778,9 @@ export namespace MCP {
785778
* Opens the browser and waits for callback.
786779
*/
787780
export async function authenticate(mcpName: string): Promise<Status> {
788-
const result = await startAuth(mcpName)
781+
const { authorizationUrl } = await startAuth(mcpName)
789782

790-
if (!result.authorizationUrl) {
783+
if (!authorizationUrl) {
791784
// Already authenticated
792785
const s = await state()
793786
return s.status[mcpName] ?? { status: "connected" }
@@ -801,9 +794,9 @@ export namespace MCP {
801794

802795
// The SDK has already added the state parameter to the authorization URL
803796
// We just need to open the browser
804-
log.info("opening browser for oauth", { mcpName, url: result.authorizationUrl, state: oauthState })
797+
log.info("opening browser for oauth", { mcpName, url: authorizationUrl, state: oauthState })
805798
try {
806-
const subprocess = await open(result.authorizationUrl)
799+
const subprocess = await open(authorizationUrl)
807800
// The open package spawns a detached process and returns immediately.
808801
// We need to listen for errors which fire asynchronously:
809802
// - "error" event: command not found (ENOENT)
@@ -826,7 +819,7 @@ export namespace MCP {
826819
// Browser opening failed (e.g., in remote/headless sessions like SSH, devcontainers)
827820
// Emit event so CLI can display the URL for manual opening
828821
log.warn("failed to open browser, user must open URL manually", { mcpName, error })
829-
Bus.publish(BrowserOpenFailed, { mcpName, url: result.authorizationUrl })
822+
Bus.publish(BrowserOpenFailed, { mcpName, url: authorizationUrl })
830823
}
831824

832825
// Wait for callback using the OAuth state parameter

packages/opencode/src/mcp/oauth-callback.ts

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
import { Log } from "../util/log"
2-
import { OAUTH_CALLBACK_PORT, OAUTH_CALLBACK_PATH, parseRedirectUri } from "./oauth-provider"
2+
import { OAUTH_CALLBACK_PORT, OAUTH_CALLBACK_PATH } from "./oauth-provider"
33

44
const log = Log.create({ service: "mcp.oauth-callback" })
55

6-
// Current callback server configuration (may differ from defaults if custom redirectUri is used)
7-
let currentPort = OAUTH_CALLBACK_PORT
8-
let currentPath = OAUTH_CALLBACK_PATH
9-
106
const HTML_SUCCESS = `<!DOCTYPE html>
117
<html>
128
<head>
@@ -60,33 +56,21 @@ export namespace McpOAuthCallback {
6056

6157
const CALLBACK_TIMEOUT_MS = 5 * 60 * 1000 // 5 minutes
6258

63-
export async function ensureRunning(redirectUri?: string): Promise<void> {
64-
// Parse the redirect URI to get port and path (uses defaults if not provided)
65-
const { port, path } = parseRedirectUri(redirectUri)
66-
67-
// If server is running on a different port/path, stop it first
68-
if (server && (currentPort !== port || currentPath !== path)) {
69-
log.info("stopping oauth callback server to reconfigure", { oldPort: currentPort, newPort: port })
70-
await stop()
71-
}
72-
59+
export async function ensureRunning(): Promise<void> {
7360
if (server) return
7461

75-
const running = await isPortInUse(port)
62+
const running = await isPortInUse()
7663
if (running) {
77-
log.info("oauth callback server already running on another instance", { port })
64+
log.info("oauth callback server already running on another instance", { port: OAUTH_CALLBACK_PORT })
7865
return
7966
}
8067

81-
currentPort = port
82-
currentPath = path
83-
8468
server = Bun.serve({
85-
port: currentPort,
69+
port: OAUTH_CALLBACK_PORT,
8670
fetch(req) {
8771
const url = new URL(req.url)
8872

89-
if (url.pathname !== currentPath) {
73+
if (url.pathname !== OAUTH_CALLBACK_PATH) {
9074
return new Response("Not found", { status: 404 })
9175
}
9276

@@ -149,7 +133,7 @@ export namespace McpOAuthCallback {
149133
},
150134
})
151135

152-
log.info("oauth callback server started", { port: currentPort, path: currentPath })
136+
log.info("oauth callback server started", { port: OAUTH_CALLBACK_PORT })
153137
}
154138

155139
export function waitForCallback(oauthState: string): Promise<string> {
@@ -174,11 +158,11 @@ export namespace McpOAuthCallback {
174158
}
175159
}
176160

177-
export async function isPortInUse(port: number = OAUTH_CALLBACK_PORT): Promise<boolean> {
161+
export async function isPortInUse(): Promise<boolean> {
178162
return new Promise((resolve) => {
179163
Bun.connect({
180164
hostname: "127.0.0.1",
181-
port,
165+
port: OAUTH_CALLBACK_PORT,
182166
socket: {
183167
open(socket) {
184168
socket.end()

packages/opencode/src/mcp/oauth-provider.ts

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ export interface McpOAuthConfig {
1717
clientId?: string
1818
clientSecret?: string
1919
scope?: string
20-
redirectUri?: string
2120
}
2221

2322
export interface McpOAuthCallbacks {
@@ -33,10 +32,6 @@ export class McpOAuthProvider implements OAuthClientProvider {
3332
) {}
3433

3534
get redirectUrl(): string {
36-
// Use configured redirectUri if provided, otherwise use OpenCode defaults
37-
if (this.config.redirectUri) {
38-
return this.config.redirectUri
39-
}
4035
return `http://127.0.0.1:${OAUTH_CALLBACK_PORT}${OAUTH_CALLBACK_PATH}`
4136
}
4237

@@ -157,22 +152,3 @@ export class McpOAuthProvider implements OAuthClientProvider {
157152
}
158153

159154
export { OAUTH_CALLBACK_PORT, OAUTH_CALLBACK_PATH }
160-
161-
/**
162-
* Parse a redirect URI to extract port and path for the callback server.
163-
* Returns defaults if the URI can't be parsed.
164-
*/
165-
export function parseRedirectUri(redirectUri?: string): { port: number; path: string } {
166-
if (!redirectUri) {
167-
return { port: OAUTH_CALLBACK_PORT, path: OAUTH_CALLBACK_PATH }
168-
}
169-
170-
try {
171-
const url = new URL(redirectUri)
172-
const port = url.port ? parseInt(url.port, 10) : url.protocol === "https:" ? 443 : 80
173-
const path = url.pathname || OAUTH_CALLBACK_PATH
174-
return { port, path }
175-
} catch {
176-
return { port: OAUTH_CALLBACK_PORT, path: OAUTH_CALLBACK_PATH }
177-
}
178-
}

packages/opencode/test/mcp/oauth-callback.test.ts

Lines changed: 0 additions & 75 deletions
This file was deleted.

0 commit comments

Comments
 (0)