|
@@ -19,7 +19,7 @@ import { NamedError } from "@opencode-ai/core/util/error"
|
|
|
import { InstallationVersion } from "@opencode-ai/core/installation/version"
|
|
import { InstallationVersion } from "@opencode-ai/core/installation/version"
|
|
|
import { withTimeout } from "@/util/timeout"
|
|
import { withTimeout } from "@/util/timeout"
|
|
|
import { AppFileSystem } from "@opencode-ai/core/filesystem"
|
|
import { AppFileSystem } from "@opencode-ai/core/filesystem"
|
|
|
-import { McpOAuthProvider } from "./oauth-provider"
|
|
|
|
|
|
|
+import { McpOAuthProvider, OAUTH_CALLBACK_PATH } from "./oauth-provider"
|
|
|
import { McpOAuthCallback } from "./oauth-callback"
|
|
import { McpOAuthCallback } from "./oauth-callback"
|
|
|
import { McpAuth } from "./auth"
|
|
import { McpAuth } from "./auth"
|
|
|
import { BusEvent } from "../bus/bus-event"
|
|
import { BusEvent } from "../bus/bus-event"
|
|
@@ -318,6 +318,7 @@ export const layer = Layer.effect(
|
|
|
clientId: oauthConfig?.clientId,
|
|
clientId: oauthConfig?.clientId,
|
|
|
clientSecret: oauthConfig?.clientSecret,
|
|
clientSecret: oauthConfig?.clientSecret,
|
|
|
scope: oauthConfig?.scope,
|
|
scope: oauthConfig?.scope,
|
|
|
|
|
+ callbackPort: oauthConfig?.callbackPort,
|
|
|
redirectUri: oauthConfig?.redirectUri,
|
|
redirectUri: oauthConfig?.redirectUri,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
@@ -769,8 +770,15 @@ export const layer = Layer.effect(
|
|
|
// OAuth config is optional - if not provided, we'll use auto-discovery
|
|
// OAuth config is optional - if not provided, we'll use auto-discovery
|
|
|
const oauthConfig = typeof mcpConfig.oauth === "object" ? mcpConfig.oauth : undefined
|
|
const oauthConfig = typeof mcpConfig.oauth === "object" ? mcpConfig.oauth : undefined
|
|
|
|
|
|
|
|
|
|
+ // Resolve effective redirect URI: explicit redirectUri > callbackPort shorthand > default
|
|
|
|
|
+ const effectiveRedirectUri =
|
|
|
|
|
+ oauthConfig?.redirectUri ??
|
|
|
|
|
+ (oauthConfig?.callbackPort
|
|
|
|
|
+ ? `http://127.0.0.1:${oauthConfig.callbackPort}${OAUTH_CALLBACK_PATH}`
|
|
|
|
|
+ : undefined)
|
|
|
|
|
+
|
|
|
// Start the callback server with custom redirectUri if configured
|
|
// Start the callback server with custom redirectUri if configured
|
|
|
- yield* Effect.promise(() => McpOAuthCallback.ensureRunning(oauthConfig?.redirectUri))
|
|
|
|
|
|
|
+ yield* Effect.promise(() => McpOAuthCallback.ensureRunning(effectiveRedirectUri))
|
|
|
|
|
|
|
|
const oauthState = Array.from(crypto.getRandomValues(new Uint8Array(32)))
|
|
const oauthState = Array.from(crypto.getRandomValues(new Uint8Array(32)))
|
|
|
.map((b) => b.toString(16).padStart(2, "0"))
|
|
.map((b) => b.toString(16).padStart(2, "0"))
|
|
@@ -784,7 +792,7 @@ export const layer = Layer.effect(
|
|
|
clientId: oauthConfig?.clientId,
|
|
clientId: oauthConfig?.clientId,
|
|
|
clientSecret: oauthConfig?.clientSecret,
|
|
clientSecret: oauthConfig?.clientSecret,
|
|
|
scope: oauthConfig?.scope,
|
|
scope: oauthConfig?.scope,
|
|
|
- redirectUri: oauthConfig?.redirectUri,
|
|
|
|
|
|
|
+ redirectUri: effectiveRedirectUri,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
onRedirect: async (url) => {
|
|
onRedirect: async (url) => {
|