From 5ef0daddca73be0728207d89ddc6dc5a2e87edd2 Mon Sep 17 00:00:00 2001 From: Fizza-Mukhtar Date: Tue, 10 Mar 2026 23:53:40 -0700 Subject: [PATCH 1/5] fix(mcp): pass OAuthClientProvider to call_mcp_tool for automatic token refresh --- backend/onyx/tools/tool_constructor.py | 1 + .../tool_implementations/mcp/mcp_tool.py | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/backend/onyx/tools/tool_constructor.py b/backend/onyx/tools/tool_constructor.py index 47caaebae8a..2b940dfab38 100644 --- a/backend/onyx/tools/tool_constructor.py +++ b/backend/onyx/tools/tool_constructor.py @@ -396,6 +396,7 @@ def construct_tools( tool_definition=saved_tool.mcp_input_schema or {}, connection_config=connection_config, user_email=user_email, + user_id=str(user.id), user_oauth_token=mcp_user_oauth_token, additional_headers=additional_mcp_headers, ) diff --git a/backend/onyx/tools/tool_implementations/mcp/mcp_tool.py b/backend/onyx/tools/tool_implementations/mcp/mcp_tool.py index 183db731191..88366333476 100644 --- a/backend/onyx/tools/tool_implementations/mcp/mcp_tool.py +++ b/backend/onyx/tools/tool_implementations/mcp/mcp_tool.py @@ -47,6 +47,7 @@ def __init__( tool_definition: dict[str, Any], connection_config: MCPConnectionConfig | None = None, user_email: str = "", + user_id: str = "", user_oauth_token: str | None = None, additional_headers: dict[str, str] | None = None, ) -> None: @@ -56,6 +57,7 @@ def __init__( self.mcp_server = mcp_server self.connection_config = connection_config self.user_email = user_email + self._user_id = user_id self._user_oauth_token = user_oauth_token self._additional_headers = additional_headers or {} @@ -199,12 +201,32 @@ def run( llm_facing_response=llm_facing_response, ) + # For OAuth servers, construct OAuthClientProvider so the MCP SDK + # can refresh expired tokens automatically + auth = None + if ( + self.mcp_server.auth_type == MCPAuthenticationType.OAUTH + and self.connection_config is not None + and self._user_id + ): + from onyx.server.features.mcp.api import UNUSED_RETURN_PATH + from onyx.server.features.mcp.api import make_oauth_provider + + auth = make_oauth_provider( + self.mcp_server, + self._user_id, + UNUSED_RETURN_PATH, + self.connection_config.id, + None, + ) + tool_result = call_mcp_tool( self.mcp_server.server_url, self._name, llm_kwargs, connection_headers=headers, transport=self.mcp_server.transport or MCPTransport.STREAMABLE_HTTP, + auth=auth, ) logger.info(f"MCP tool '{self._name}' executed successfully") From d4c09058276cfff3de50709bad38086a61876d7a Mon Sep 17 00:00:00 2001 From: Fizza-Mukhtar Date: Wed, 11 Mar 2026 00:06:52 -0700 Subject: [PATCH 2/5] fix(mcp): remove trailing whitespace and add reconnect to auth error indicators --- backend/onyx/tools/tool_implementations/mcp/mcp_tool.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/onyx/tools/tool_implementations/mcp/mcp_tool.py b/backend/onyx/tools/tool_implementations/mcp/mcp_tool.py index 88366333476..478dbc46dba 100644 --- a/backend/onyx/tools/tool_implementations/mcp/mcp_tool.py +++ b/backend/onyx/tools/tool_implementations/mcp/mcp_tool.py @@ -202,7 +202,7 @@ def run( ) # For OAuth servers, construct OAuthClientProvider so the MCP SDK - # can refresh expired tokens automatically + # can refresh expired tokens automatically auth = None if ( self.mcp_server.auth_type == MCPAuthenticationType.OAUTH @@ -271,6 +271,7 @@ def run( "invalid token", "invalid api key", "invalid credentials", + "reconnect", ] is_auth_error = any( From 498a14d1ca720e4e30fecb3e4a48ea8d1e291d7b Mon Sep 17 00:00:00 2001 From: Fizza-Mukhtar Date: Wed, 11 Mar 2026 00:20:11 -0700 Subject: [PATCH 3/5] fix(mcp): add SSE warning log and use exact reconnect error string --- .../tool_implementations/mcp/mcp_tool.py | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/backend/onyx/tools/tool_implementations/mcp/mcp_tool.py b/backend/onyx/tools/tool_implementations/mcp/mcp_tool.py index 478dbc46dba..13058f17202 100644 --- a/backend/onyx/tools/tool_implementations/mcp/mcp_tool.py +++ b/backend/onyx/tools/tool_implementations/mcp/mcp_tool.py @@ -209,16 +209,23 @@ def run( and self.connection_config is not None and self._user_id ): - from onyx.server.features.mcp.api import UNUSED_RETURN_PATH - from onyx.server.features.mcp.api import make_oauth_provider - - auth = make_oauth_provider( - self.mcp_server, - self._user_id, - UNUSED_RETURN_PATH, - self.connection_config.id, - None, - ) + if self.mcp_server.transport == MCPTransport.SSE: + logger.warning( + f"MCP tool '{self._name}': OAuth token refresh is not supported " + f"for SSE transport — auth provider will be ignored. " + f"Re-authentication may be required after token expiry." + ) + else: + from onyx.server.features.mcp.api import UNUSED_RETURN_PATH + from onyx.server.features.mcp.api import make_oauth_provider + + auth = make_oauth_provider( + self.mcp_server, + self._user_id, + UNUSED_RETURN_PATH, + self.connection_config.id, + None, + ) tool_result = call_mcp_tool( self.mcp_server.server_url, @@ -271,7 +278,7 @@ def run( "invalid token", "invalid api key", "invalid credentials", - "reconnect", + "please reconnect to the server", ] is_auth_error = any( From 58047d96b0102fdd384eee9bbca4eb6338209332 Mon Sep 17 00:00:00 2001 From: Fizza-Mukhtar Date: Wed, 11 Mar 2026 00:32:04 -0700 Subject: [PATCH 4/5] style(mcp): add OAuthClientProvider import for explicit type annotation --- backend/onyx/tools/tool_implementations/mcp/mcp_tool.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/onyx/tools/tool_implementations/mcp/mcp_tool.py b/backend/onyx/tools/tool_implementations/mcp/mcp_tool.py index 13058f17202..43b87dcd811 100644 --- a/backend/onyx/tools/tool_implementations/mcp/mcp_tool.py +++ b/backend/onyx/tools/tool_implementations/mcp/mcp_tool.py @@ -1,6 +1,7 @@ import json from typing import Any +from mcp.client.auth import OAuthClientProvider from onyx.chat.emitter import Emitter from onyx.db.enums import MCPAuthenticationType from onyx.db.enums import MCPTransport @@ -203,7 +204,7 @@ def run( # For OAuth servers, construct OAuthClientProvider so the MCP SDK # can refresh expired tokens automatically - auth = None + auth: OAuthClientProvider | None = None if ( self.mcp_server.auth_type == MCPAuthenticationType.OAUTH and self.connection_config is not None From 75b24ff1903dfdcbf115f7c7e2747edb58483f79 Mon Sep 17 00:00:00 2001 From: Fizza-Mukhtar Date: Wed, 11 Mar 2026 00:49:46 -0700 Subject: [PATCH 5/5] style: fix import ordering for OAuthClientProvider --- backend/onyx/tools/tool_implementations/mcp/mcp_tool.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/onyx/tools/tool_implementations/mcp/mcp_tool.py b/backend/onyx/tools/tool_implementations/mcp/mcp_tool.py index 43b87dcd811..cf21bbc0be6 100644 --- a/backend/onyx/tools/tool_implementations/mcp/mcp_tool.py +++ b/backend/onyx/tools/tool_implementations/mcp/mcp_tool.py @@ -2,6 +2,7 @@ from typing import Any from mcp.client.auth import OAuthClientProvider + from onyx.chat.emitter import Emitter from onyx.db.enums import MCPAuthenticationType from onyx.db.enums import MCPTransport @@ -220,6 +221,9 @@ def run( from onyx.server.features.mcp.api import UNUSED_RETURN_PATH from onyx.server.features.mcp.api import make_oauth_provider + # user_id is the requesting user's UUID; safe here because + # UNUSED_RETURN_PATH ensures redirect_handler raises immediately + # and user_id is never consulted for Redis state lookups. auth = make_oauth_provider( self.mcp_server, self._user_id,