Skip to content

window.openai.callTool does not trigger OAuth flow for auth-protected tools in mixed auth mode #202

@ansonwcy-rifo

Description

@ansonwcy-rifo

Problem

When using mixed auth (some tools noauth, some tools oauth2), calling an OAuth-protected tool via window.openai.callTool() from a widget fails with HTTP 400 and an empty response body {}. The same tool works correctly when initiated by the chat (LLM-initiated).

Environment

  • MCP server: Python, using mcp SDK
  • Auth: OAuth2 (Auth0)
  • Connector auth mode: Mixed (noauth + oauth2)
  • Browser: Chrome 145 on macOS

Setup

Two tools on the same MCP server:

  1. Tool AsecuritySchemes: [{"type":"noauth"}, {"type":"oauth2"}] — renders a widget
  2. Tool BsecuritySchemes: [{"type":"oauth2"}] — requires authentication

The widget rendered by Tool A contains a button that calls:

window.openai.callTool('tool_b', {})

Steps to Reproduce

  1. Add the MCP connector in ChatGPT. Because the server supports mixed auth, ChatGPT allows connecting without triggering OAuth
  2. Ask ChatGPT something that triggers Tool A. This tool supports noauth, so it succeeds without a token.
  3. Widget renders successfully.
  4. Click a button in the widget that calls window.openai.callTool('tool_b', {}).

Expected Behavior

ChatGPT detects that Tool B requires OAuth, triggers the OAuth flow (login popup), obtains an access token, then forwards the tools/call request to the MCP server — same as when the LLM initiates the call via chat.

Actual Behavior

  • Browser console shows: POST https://chatgpt.com/backend-api/ecosystem/call_mcp 400 (Bad Request)
  • Response body: {}
  • No OAuth flow is triggered
  • The widget's catch block receives an empty object
  • In some attempts, the request reaches the MCP server (without a token); in others, ChatGPT's backend rejects it before forwarding

Comparison: Chat-Initiated Works

When the same OAuth-protected tool is called by the LLM via chat (not from a widget) in the same mixed auth mode with no prior authentication, ChatGPT does trigger the OAuth flow, obtains a token, and the call succeeds.

Comparison: Full OAuth Mode Works

When the connector is configured with full OAuth (not mixed), the user authenticates at connection time. After that, window.openai.callTool('tool_b', {}) from the widget works because the token is already available and attached to all requests.

Conclusion

window.openai.callTool() does not support triggering OAuth for auth-protected tools when no token exists yet. This only affects widget-initiated calls — chat-initiated calls to the same tool in the same mixed auth configuration work correctly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions