Repository navigation
MCP Toolset OAuth2 User Interaction Flow Defects #3331
Description
Describe the bug
The current Google ADK Python implementation has critical defects in the MCP (Model Context Protocol) Toolset OAuth2 authentication flow that prevent proper user interaction during the authentication process. MCP Toolset tool discovery occurs during the preprocessing phase using ReadonlyContext, which lacks the request_credential() method necessary for OAuth2 user interaction. This creates a fundamental architectural problem where authentication is required before tools can be discovered, but the authentication mechanism is not available at that stage.
To Reproduce
Steps to reproduce the behavior:
- Install ADK Python with MCP Toolset support
- Create an MCP Toolset that requires OAuth2 authentication:
from google.adk.tools.mcp_tool import MCPToolset from google.adk.auth import AuthScheme, AuthCredential # Configure OAuth2 MCP Toolset toolset = MCPToolset( connection_params=connection_params, auth_scheme=oauth2_scheme, auth_credential=oauth2_credential )
- Attempt to use the agent with the MCP Toolset
- Observe MCP session creation failure during tool discovery phase with the following error stacktrace:
Traceback (most recent call last):
File "/.../google/adk/flows/llm_flows/base_llm_flow.py", line 435, in _preprocess_async
tools = await _convert_tool_union_to_tools(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/.../google/adk/agents/llm_agent.py", line 121, in _convert_tool_union_to_tools
return await tool_union.get_tools_with_prefix(ctx)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/.../google/adk/tools/base_toolset.py", line 114, in get_tools_with_prefix
tools = await self.get_tools(readonly_context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/.../google/adk/tools/mcp_tool/mcp_toolset.py", line 159, in get_tools
session = await self._mcp_session_manager.create_session()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/.../google/adk/tools/mcp_tool/mcp_session_manager.py", line 362, in create_session
await session.initialize()
File "/.../mcp/client/session.py", line 151, in initialize
result = await self.send_request(
^^^^^^^^^^^^^^^^^^^^^^^^
asyncio.exceptions.CancelledError: Cancelled via cancel scope
Root Cause Analysis:
The error occurs because MCP Toolset attempts to create an MCP session during tool discovery in the preprocessing phase, but the session creation fails when OAuth2 authentication is required.
File: src/google/adk/flows/llm_flows/base_llm_flow.py (Lines 435-437)
Function: _preprocess_async()
# Problematic code in base_llm_flow.py
tools = await _convert_tool_union_to_tools(
tool_union, ReadonlyContext(invocation_context) # Problem: ReadonlyContext lacks auth capabilities
)Call Chain:
_preprocess_async()→_convert_tool_union_to_tools()→tool_union.get_tools_with_prefix(ctx)get_tools_with_prefix(ctx)→get_tools(readonly_context)→_mcp_session_manager.create_session()create_session()→session.initialize()→ MCP session initialization fails due to missing authenticationReadonlyContextlacksrequest_credential()method to trigger OAuth2 authentication flow
Core Issues:
- MCP session creation requires authentication: OAuth2-protected MCP servers require authentication before session initialization
- ReadonlyContext lacks authentication capability: No
request_credential()method available during preprocessing - Session initialization timing mismatch: MCP session creation happens in
_preprocess_async, but authentication event processing occurs in_postprocess_async - Tool discovery dependency: MCP Toolsets must establish authenticated sessions before tools can be discovered
Expected behavior
- Seamless MCP Toolset Authentication: MCP Toolsets should be able to trigger OAuth2 authentication flows during tool discovery phase with proper user interaction
- Consistent Authentication Experience: OAuth2 authentication for MCP Toolsets should integrate with ADK's standard
adk_request_credentialevent system - Runtime Compatibility: Authentication flows should work consistently across different execution environments (CLI, web server, deployed agents)
- User-Friendly Flow: Users should receive clear authentication prompts and be able to complete OAuth2 flows seamlessly
Screenshots
Not applicable for this authentication flow issue.
Desktop (please complete the following information):
Not applicable for this authentication flow issue.
Model Information:
- Are you using LiteLLM: No
- Which model is being used: Gemini 2.0 Flash / Gemini 2.5 Pro
Additional context
Proposed Solution:
Modify BaseToolset.process_llm_request to Support Event Generation
Leverage the existing toolset processing mechanism in _preprocess_async to handle authentication:
- Modify BaseToolset.process_llm_request signature: Change return type from
NonetoAsyncGenerator[Event, None] - Update _preprocess_async to handle toolset events: Modify lines 479-481 in
base_llm_flow.pyto process events from toolsets:# Current code (line 479-481): await tool_union.process_llm_request( tool_context=tool_context, llm_request=llm_request ) # Proposed change: async with Aclosing( tool_union.process_llm_request( tool_context=tool_context, llm_request=llm_request ) ) as agen: async for event in agen: yield event
This addresses fundamental architectural limitations that prevent proper OAuth2 integration with MCP Toolsets, affecting both developer experience and end-user functionality in production deployments.
Activity
Strandor commentedon Oct 29, 2025
I can confirm this issue. I’m also running a protected MCP resource that requires OAuth2 authentication during tool discovery, and the same failure occurs because ReadonlyContext can’t trigger the authentication flow. This currently blocks using authenticated MCP endpoints in production, so a fix would be very valuable.
loveyana commentedon Oct 30, 2025
@seanzhou1023 Could you please take a look at this? I submitted #3342
to add a new event generation method for the toolset. This will be the first step — later, I’ll work on implementing an authentication event generation mechanism for the current McpToolset, similar to what McpTool has.
surajksharma07 commentedon Nov 2, 2025
@loveyana Thanks for the detailed analysis and PR #3342
You've correctly identified the root cause - the preprocessing phase uses ReadonlyContext which can't trigger OAuth2 flows.
The solution is to modify BaseToolset.process_llm_request to return AsyncGenerator[Event, None] and update _preprocess_async (base_llm_flow.py:479-481) to handle authentication events before tool discovery.
Your PR implements the generate_preprocessing_events method which is the first step.
Once merged, McpToolset can override process_llm_request to yield adk_request_credential events, allowing OAuth2 authentication to complete before get_tools() is called.
Strandor commentedon Nov 11, 2025
Seems to be duplicate of #2168
surajksharma07 commentedon Dec 6, 2025
The core issue remains unresolved in ADK v1.20.0.
While we added
process_llm_requestto BaseToolset (commit 3643b4a), it returnsNoneinstead ofAsyncGenerator[Event, None]as needed for OAuth2 flows during preprocessing.PR #3342's event generation mechanism is still under review.
Until then, OAuth2-protected MCP endpoints won't work during tool discovery - the workaround is to use API-key authentication (commit 045aea9) instead of OAuth2.
guilmour commentedon Feb 26, 2026
I think this is solved in v 1.24.0 (798f65d)
surajksharma07 commentedon Feb 26, 2026
This is fixed in v1.24.0 — upgrade to resolve it.
The fix went in via commits
381d44ca,ee873cae, and798f65df: a new_resolve_toolset_auth()method inBaseLlmFlownow runs beforeget_tools(), resolves OAuth2 credentials throughCredentialManager, and yieldsadk_request_credentialevents when auth is needed — completely bypassing theReadonlyContextlimitation.McpToolsetnow also exposes aget_auth_config()override and injects auth headers when creating MCP sessions, so theCancelledErrorduring tool discovery no longer occurs.Closing this since v1.24.0, v1.24.1, v1.25.0, and v1.25.1 all contain the fix.