Skip to content

Oauth for http MCP servers allowing unauthenticated listTools#159

Open
Spacefish wants to merge 1 commit intoopenclaw:mainfrom
Spacefish:fix-oauth-for-google-workspace
Open

Oauth for http MCP servers allowing unauthenticated listTools#159
Spacefish wants to merge 1 commit intoopenclaw:mainfrom
Spacefish:fix-oauth-for-google-workspace

Conversation

@Spacefish
Copy link
Copy Markdown

@Spacefish Spacefish commented May 7, 2026

Some OAuth-configured MCP servers (e.g. Google Calendar) allow unauthenticated
initialize and listTools and only return 401 for callTool. The auth
command relied on listTools triggering the OAuth handshake, so the login URL
was never shown.
Fix: In connectWithAuth, after the initial connection succeeds without an
auth challenge, proactively start the OAuth flow via the SDK's auth()
orchestrator if the server is configured for OAuth. This obtains tokens during
connect, before any tool listing or calling.
Additionally fix the OAuth callback HTTP server shutdown: server.close()
hangs when the browser keeps the HTTP/1.1 connection alive after the auth
redirect. Call server.closeAllConnections() first to forcefully tear down
idle connections so the close callback fires immediately.
Changes:

  • src/runtime/oauth.ts: new completeProactiveOAuth() function; proactive
    OAuth call in connectWithAuth; close session in both proactive and
    existing 401-triggered completion paths; serverUrl/fetchFn options

  • src/runtime/transport.ts: pass serverUrl to connectWithAuth callers

  • src/oauth.ts: call closeAllConnections() before server.close() to
    prevent hang on browser keep-alive connections

    This issues happens for 2026 MCP Servers like: https://calendarmcp.googleapis.com/mcp/v1 / all the google workspace tools!

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 902662cb06

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/runtime/oauth.ts
Comment on lines +204 to +206
// The OAuth handshake is complete; close the callback server so the event loop
// doesn't keep the process alive.
await session.close().catch(() => {});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep OAuth session open across authorization retries

connectWithAuth still supports multiple authorization retries (e.g., when the first token is not yet accepted and the next client.connect() returns another 401), but this new session.close() call tears down the callback server immediately after the first finishAuth. On a subsequent retry, waitForAuthorizationCodeWithTimeout() waits on a closed session that can no longer receive callbacks, so the flow times out instead of completing the second challenge.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really relevant.. This is a process that is started by a user in a shell, if he click "abort" in the permission grant dialog in his browser he just has to restart the shell command.

Comment thread src/runtime/oauth.ts
Comment on lines +289 to +293
// Proactive OAuth is best-effort: the connection is already established, so
// server may not require auth. Log a warning and continue.
const message = error instanceof Error ? error.message : String(error);
logger.warn(`Proactive OAuth flow for '${displayName}' did not complete: ${message}`);
} finally {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Surface proactive OAuth failures instead of continuing

This catch block downgrades most proactive OAuth errors to warnings and allows connectWithAuth to return success even when authorization actually failed (for example, waitForAuthorizationCode() rejection, denied consent, or finishAuth() failure). In the auth flow this can report success after listTools while leaving the server unauthenticated, causing the first callTool to fail with 401 and hiding the real auth failure from users.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the existing behaviour, this PR just improves on this, but does not handle additional errors that might occur otherwise and just falls back to the previous behaviour in that case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant