Skip to content

MCP Toolset OAuth2 User Interaction Flow Defects #3331

Closed

Description

@loveyana

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:

  1. Install ADK Python with MCP Toolset support
  2. 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
    )
  3. Attempt to use the agent with the MCP Toolset
  4. 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:

  1. _preprocess_async() → _convert_tool_union_to_tools() → tool_union.get_tools_with_prefix(ctx)
  2. get_tools_with_prefix(ctx) → get_tools(readonly_context) → _mcp_session_manager.create_session()
  3. create_session() → session.initialize() → MCP session initialization fails due to missing authentication
  4. ReadonlyContext lacks request_credential() method to trigger OAuth2 authentication flow

Core Issues:

  1. MCP session creation requires authentication: OAuth2-protected MCP servers require authentication before session initialization
  2. ReadonlyContext lacks authentication capability: No request_credential() method available during preprocessing
  3. Session initialization timing mismatch: MCP session creation happens in _preprocess_async, but authentication event processing occurs in _postprocess_async
  4. Tool discovery dependency: MCP Toolsets must establish authenticated sessions before tools can be discovered

Expected behavior

  1. Seamless MCP Toolset Authentication: MCP Toolsets should be able to trigger OAuth2 authentication flows during tool discovery phase with proper user interaction
  2. Consistent Authentication Experience: OAuth2 authentication for MCP Toolsets should integrate with ADK's standard adk_request_credential event system
  3. Runtime Compatibility: Authentication flows should work consistently across different execution environments (CLI, web server, deployed agents)
  4. 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:

  1. Modify BaseToolset.process_llm_request signature: Change return type from None to AsyncGenerator[Event, None]
  2. Update _preprocess_async to handle toolset events: Modify lines 479-481 in base_llm_flow.py to 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

  1. added
    mcp[Component] This issues is related to MCP support
    on Oct 29, 2025
  2. added theissue type on Oct 29, 2025
  3. Strandor commented on Oct 29, 2025

    @Strandor

    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.

  4. loveyana commented on Oct 30, 2025

    @loveyana
    Author

    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.

    @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.

  5. surajksharma07 commented on Nov 2, 2025

    @surajksharma07
    Collaborator

    @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.

  6. Strandor commented on Nov 11, 2025

    @Strandor

    Seems to be duplicate of #2168

  7. added
    need attention[Status] This issue is important but the maintainers haven't started working on it
    on Nov 23, 2025
  8. added
    needs review[Status] The PR/issue is awaiting review from the maintainer
    and removed
    need attention[Status] This issue is important but the maintainers haven't started working on it
    on Dec 6, 2025
  9. surajksharma07 commented on Dec 6, 2025

    @surajksharma07
    Collaborator

    The core issue remains unresolved in ADK v1.20.0.

    While we added process_llm_request to BaseToolset (commit 3643b4a), it returns None instead of AsyncGenerator[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.

  10. guilmour commented on Feb 26, 2026

    @guilmour

    I think this is solved in v 1.24.0 (798f65d)

  11. surajksharma07 commented on Feb 26, 2026

    @surajksharma07
    Collaborator

    This is fixed in v1.24.0 — upgrade to resolve it.

    The fix went in via commits 381d44ca, ee873cae, and 798f65df: a new _resolve_toolset_auth() method in BaseLlmFlow now runs before get_tools(), resolves OAuth2 credentials through CredentialManager, and yields adk_request_credential events when auth is needed — completely bypassing the ReadonlyContext limitation.

    McpToolset now also exposes a get_auth_config() override and injects auth headers when creating MCP sessions, so the CancelledError during 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.

  12. removed
    needs review[Status] The PR/issue is awaiting review from the maintainer
    on Feb 26, 2026
  13. added
    answered[Status] This issue has been answered by the maintainer
    on Feb 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

answered[Status] This issue has been answered by the maintainermcp[Component] This issues is related to MCP support

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions