{"record":{"id":"237f3ebb372b81d4","repo":"can1357/oh-my-pi","slug":"server-connection-succeeded-without-oauth-reautho","errorCode":null,"errorMessage":"Server connection succeeded without OAuth; reauthorization is not required.","messagePattern":"Server connection succeeded without OAuth; reauthorization is not required\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/coding-agent/src/modes/controllers/mcp-command-controller.ts","lineNumber":1237,"sourceCode":"\t\ttry {\n\t\t\tawait this.#handleTestConnection(this.#stripOAuthAuth(config), { oauth: false });\n\t\t\tconnectionSucceeded = true;\n\t\t} catch (error) {\n\t\t\tconnectionError = error as Error;\n\t\t}\n\n\t\t// Server connected fine without auth. A tool-level challenge overrides\n\t\t// this: servers may allow the anonymous handshake yet protect individual\n\t\t// tool calls with `_meta[\"mcp/www_authenticate\"]`. Even without such a\n\t\t// challenge, a clean `initialize` is only weak evidence — per the MCP\n\t\t// spec a server MAY permit unauthenticated `initialize` while requiring a\n\t\t// bearer token for `tools/call`. The user explicitly asked to reauth, so\n\t\t// honor it when the server advertises OAuth discovery metadata; only\n\t\t// refuse when there is genuinely no OAuth endpoint to acquire.\n\t\tif (connectionSucceeded && !authChallenge) {\n\t\t\tconst discovered = \"url\" in config && config.url ? await discoverOAuthEndpoints(config.url) : null;\n\t\t\tif (!discovered) {\n\t\t\t\tthrow new Error(\"Server connection succeeded without OAuth; reauthorization is not required.\");\n\t\t\t}\n\t\t\treturn discovered;\n\t\t}\n\n\t\t// Tool calls can carry richer RFC 6750/RFC 9728 hints than the original\n\t\t// connection error. Feed those hints through the same analyzer so\n\t\t// resource_metadata and scope reach protected-resource discovery.\n\t\tconst authError = authChallenge\n\t\t\t? new Error(`${connectionError?.message ?? \"HTTP 401\"}\\n${authChallenge.wwwAuthenticate.join(\"\\n\")}`)\n\t\t\t: connectionError!;\n\t\tconst authResult = analyzeAuthError(authError, \"url\" in config ? config.url : undefined);\n\t\tlet oauth = authResult.authType === \"oauth\" ? (authResult.oauth ?? null) : null;\n\n\t\tif (!oauth && (config.type === \"http\" || config.type === \"sse\") && config.url) {\n\t\t\toauth = await discoverOAuthEndpoints(config.url, authResult.authServerUrl, authResult.resourceMetadataUrl, {\n\t\t\t\tprotectedScopes: authResult.scopes,\n\t\t\t});\n\t\t}","sourceCodeStart":1219,"sourceCodeEnd":1255,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/modes/controllers/mcp-command-controller.ts#L1219-L1255","documentation":"Thrown during /mcp reauth when the server connects successfully without any credentials and no tool-level auth challenge was observed, AND OAuth discovery metadata (.well-known/oauth-protected-resource / oauth-authorization-server) is not advertised at the server URL. Since the user asked to re-authorize but there is genuinely no OAuth endpoint to acquire tokens from, the controller refuses the reauthorization as unnecessary rather than starting a pointless flow.","triggerScenarios":"Running /mcp reauth <name> against an http/sse server that (a) accepts unauthenticated initialize/handshake, (b) produced no RFC 6750/9728 auth challenge, and (c) publishes no OAuth discovery metadata at its URL.","commonSituations":"Reauth issued against a server that needs no auth at all; a server that protects only individual tools but does not advertise metadata and did not raise a challenge this session; a stale belief that the server requires OAuth after it was reconfigured to be open; pointing at the wrong URL/port (e.g. a dev instance without auth).","solutions":["Nothing to fix if the server truly needs no auth — the credentials are already valid; skip reauth.","Verify you are targeting the correct server URL — an open dev/staging endpoint would explain the anonymous success.","If tool calls DO require auth but no metadata is advertised, invoke a protected tool to produce an auth challenge, or configure static credentials (bearer token auth block) instead of OAuth.","Confirm the server publishes .well-known/oauth-protected-resource; if it doesn't, OAuth discovery cannot work and static auth is the only option."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const res = await fetch(serverUrl, { method: \"POST\", headers: { \"content-type\": \"application/json\" }, body: JSON.stringify({ jsonrpc: \"2.0\", id: 1, method: \"initialize\", params: {} }) });\nconst needsAuth = res.status === 401;\nconst hasMeta = (await fetch(`${origin}/.well-known/oauth-protected-resource`)).ok;\nif (!needsAuth && !hasMeta) console.log(\"Server needs no OAuth; skip /mcp reauth\");","typeGuard":"function isReauthNotRequiredError(err: unknown): err is Error {\n  return err instanceof Error && err.message.includes(\"reauthorization is not required\");\n}","tryCatchPattern":"try {\n  await reauthServer(name);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"reauthorization is not required\")) {\n    showInfo(\"Server is already accessible without OAuth — no action needed.\");\n  } else throw err;\n}","preventionTips":["Confirm the server actually advertises .well-known/oauth-protected-resource before attempting reauth.","Make sure the configured URL points at the intended (auth-protected) environment, not an open dev instance.","If only some tools are protected, trigger the protected tool once so a challenge is captured, then reauth."],"tags":["oauth","mcp","reauth","discovery"],"backgroundTag":"oauth-not-required","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}