Skip to content

enhanced MCP session management with mcp-session-id support#4466

Draft
jayy-77 wants to merge 1 commit intogoogle:mainfrom
jayy-77:mcp_toolset_fix
Draft

enhanced MCP session management with mcp-session-id support#4466
jayy-77 wants to merge 1 commit intogoogle:mainfrom
jayy-77:mcp_toolset_fix

Conversation

@jayy-77
Copy link

@jayy-77 jayy-77 commented Feb 12, 2026

Please ensure you have read the contribution guide before creating a pull request.

Link to Issue or Description of Change

1. Link to an existing issue (if applicable):

2. Or, if no issue exists, describe the change:

If applicable, please follow the issue templates to provide as much detail as
possible.

Problem:
A clear and concise description of what the problem is.

Solution:
A clear and concise description of what you want to happen and why you choose
this solution.

Testing Plan

Please describe the tests that you ran to verify your changes. This is required
for all PRs that are not small documentation or typo fixes.

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally.

Please include a summary of passed pytest results.

Manual End-to-End (E2E) Tests:

Please provide instructions on how to manually test your changes, including any
necessary setup or configuration. Please provide logs or screenshots to help
reviewers better understand the fix.

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.
  • Any dependent changes have been merged and published in downstream modules.

Additional context

Add any other context or screenshots about the feature request here.

@adk-bot adk-bot added the mcp [Component] Issues about MCP support label Feb 12, 2026
@adk-bot
Copy link
Collaborator

adk-bot commented Feb 12, 2026

Response from ADK Triaging Agent

Hello @jayy-77, thank you for creating this PR!

Could you please fill out the PR template? This PR is missing a link to an issue (or a description of the change), a testing plan, and the checklist is not filled out.

This information will help reviewers to review your PR more efficiently. Thanks!

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @jayy-77, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves the handling of MCP sessions by introducing support for mcp-session-id. The changes enable the system to maintain persistent, stateful connections with the server by recognizing and utilizing a unique session identifier provided by the server. This enhancement ensures that subsequent requests within a session are correctly routed and processed, leading to more robust and efficient communication.

Highlights

  • MCP Session ID Support: Enhanced MCP session management to support mcp-session-id, allowing for stateful sessions with the server by capturing and reusing this identifier.
  • Session Key Generation: Modified the session key generation logic to incorporate the mcp-session-id, ensuring unique identification and proper reuse of sessions.
  • Header Management: Updated header merging to include the mcp-session-id in outgoing requests when available, maintaining session continuity.
  • Session Information Exposure: Added a new method to McpToolset to expose current MCP session state, including mcp-session-id values, for debugging purposes.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/google/adk/tools/mcp_tool/mcp_session_manager.py
    • Updated the session pool data structure to store the mcp_session_id alongside other session details.
    • Modified _generate_session_key to include mcp_session_id in the session key, making it more specific to the server-assigned session.
    • Adjusted _merge_headers to add the mcp-session-id to the request headers when present.
    • Enhanced create_session to proactively search for and reuse an existing mcp-session-id and to update the session key if a new mcp-session-id is received from the server.
    • Updated the close method to correctly unpack the session tuple, accounting for the newly added mcp_session_id field.
  • src/google/adk/tools/mcp_tool/mcp_toolset.py
    • Added a new public method get_session_info to retrieve a dictionary containing details about active MCP sessions, including their mcp-session-id.
  • src/google/adk/tools/mcp_tool/session_context.py
    • Introduced a new attribute _mcp_session_id to store the MCP session ID within the session context.
    • Added a property mcp_session_id to provide read-only access to the stored MCP session ID.
    • Modified the _run method to extract the mcp-session-id from the initialize() result provided by the server.
Activity
  • The pull request description provides a template for issue linking, problem/solution description, testing plan, and checklist, but no specific activity or comments have been recorded yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for mcp-session-id to enable stateful server sessions, which enhances the MCP toolset. However, this implementation introduces a vulnerability: the sensitive mcp-session-id is being logged and exposed through public methods, which could lead to session information leakage. To mitigate this, ensure the session ID is masked or removed from log statements and public informational methods. Additionally, there is a critical bug in the session reuse logic within MCPSessionManager that prevents the feature from working as intended, and a minor encapsulation issue in McpToolset.

Comment on lines +270 to +276
if mcp_session_id:
key_parts.append(f'mcp_id:{mcp_session_id}')

if merged_headers:
headers_json = json.dumps(merged_headers, sort_keys=True)
headers_hash = hashlib.md5(headers_json.encode()).hexdigest()
return f'session_{headers_hash}'
key_parts.append(f'headers:{headers_hash}')
Copy link
Contributor

Choose a reason for hiding this comment

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

high

To enable correct and simple session reuse logic in create_session, the constant part of the session key (derived from headers) should precede the mcp_session_id part. This allows for simple prefix matching. Please swap the order of these if blocks.

Suggested change
if mcp_session_id:
key_parts.append(f'mcp_id:{mcp_session_id}')
if merged_headers:
headers_json = json.dumps(merged_headers, sort_keys=True)
headers_hash = hashlib.md5(headers_json.encode()).hexdigest()
return f'session_{headers_hash}'
key_parts.append(f'headers:{headers_hash}')
if merged_headers:
headers_json = json.dumps(merged_headers, sort_keys=True)
headers_hash = hashlib.md5(headers_json.encode()).hexdigest()
key_parts.append(f'headers:{headers_hash}')
if mcp_session_id:
key_parts.append(f'mcp_id:{mcp_session_id}')

async with self._session_lock:
for key, (session, exit_stack, stored_loop, mcp_id) in list(self._sessions.items()):
# Check if this session matches our connection params (ignoring mcp-session-id)
if key.startswith(temp_key.split('_mcp_id')[0]) and mcp_id:
Copy link
Contributor

Choose a reason for hiding this comment

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

high

This logic for finding a matching session is incorrect. temp_key.split('_mcp_id')[0] will not work as _mcp_id is not in the key string, and the original key part order makes prefix matching fail.

With the suggested change to _generate_session_key (placing the headers part first), this check can be simplified and corrected to use startswith.

Suggested change
if key.startswith(temp_key.split('_mcp_id')[0]) and mcp_id:
if key.startswith(temp_key + '_') and mcp_id:

if stored_loop is current_loop and not self._is_session_disconnected(session):
# Found a valid session with mcp-session-id, use it
existing_mcp_session_id = mcp_id
logger.debug('Reusing existing mcp-session-id: %s', existing_mcp_session_id)
Copy link
Contributor

Choose a reason for hiding this comment

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

security-medium medium

The mcp_session_id is a sensitive session identifier used to maintain stateful sessions with the MCP server. Logging it at the DEBUG level can lead to session identifier leakage in log files, which could be exploited to interfere with active sessions.

Suggested change
logger.debug('Reusing existing mcp-session-id: %s', existing_mcp_session_id)
logger.debug('Reusing existing mcp-session-id')


# If we got a new mcp-session-id, update the session key and re-store
if new_mcp_session_id and new_mcp_session_id != existing_mcp_session_id:
logger.info('Received new mcp-session-id from server: %s', new_mcp_session_id)
Copy link
Contributor

Choose a reason for hiding this comment

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

security-medium medium

The mcp_session_id is logged at the INFO level. Since INFO logs are frequently enabled in production environments, this poses a significant risk of leaking session identifiers to log management systems.

Suggested change
logger.info('Received new mcp-session-id from server: %s', new_mcp_session_id)
logger.info('Received new mcp-session-id from server')

Comment on lines +199 to +201
logger.debug(
'Captured mcp-session-id from server: %s', self._mcp_session_id
)
Copy link
Contributor

Choose a reason for hiding this comment

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

security-medium medium

Logging the mcp_session_id returned by the server during initialization can expose sensitive session state identifiers in debug logs.

Suggested change
logger.debug(
'Captured mcp-session-id from server: %s', self._mcp_session_id
)
logger.debug(
'Captured mcp-session-id from server'
)

session_info = {}
for key, (_, _, _, mcp_id) in self._mcp_session_manager._sessions.items():
session_info[key] = {
'mcp_session_id': mcp_id,
Copy link
Contributor

Choose a reason for hiding this comment

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

security-medium medium

The get_session_info method returns the raw mcp_session_id for all active sessions. As a public method intended for debugging, it should avoid exposing full session identifiers which could be leaked if the method's output is displayed in a UI or exposed via an API. Consider masking the identifier.

Suggested change
'mcp_session_id': mcp_id,
'mcp_session_id': mcp_id[:8] + '...' if mcp_id else None,

and mcp-session-id values.
"""
session_info = {}
for key, (_, _, _, mcp_id) in self._mcp_session_manager._sessions.items():
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Accessing the private member _sessions of _mcp_session_manager breaks encapsulation. This makes McpToolset dependent on the internal implementation of MCPSessionManager and more brittle to future changes. It would be better to add a public method to MCPSessionManager to provide this debugging information.

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

Labels

mcp [Component] Issues about MCP support

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants