-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Expose get_session_id callback #2486
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThe Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
Tip 📝 Customizable high-level summaries are now available in beta!You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.
Example instruction:
Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
tests/client/test_streamable_http.pyis excluded by none and included by none
📒 Files selected for processing (1)
src/fastmcp/client/transports.py(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/fastmcp/client/transports.py (2)
src/fastmcp/server/context.py (1)
session(383-393)src/fastmcp/client/client.py (1)
session(291-298)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Run tests with lowest-direct dependencies
- GitHub Check: Run tests: Python 3.10 on windows-latest
- GitHub Check: Run tests: Python 3.10 on ubuntu-latest
🔇 Additional comments (1)
src/fastmcp/client/transports.py (1)
285-292: Tuple unpack and callback capture look correctUnpacking the third element from
streamablehttp_clientand storing it on the instance gives callers a straightforward way to reach the session-id callback and matches the intended API surface for this transport.
| def get_session_id(self) -> str | None: | ||
| if self.get_session_id_cb: | ||
| return self.get_session_id_cb() | ||
| return None | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guard against missing get_session_id_cb to avoid AttributeError before connection
get_session_id assumes self.get_session_id_cb always exists. If a caller invokes get_session_id() before any connect_session() has run, this will raise AttributeError instead of cleanly returning None, which contradicts the intended “id or None” API.
Initialize the callback on construction and check it explicitly:
@@ class StreamableHttpTransport(ClientTransport):
def __init__(
self,
url: str | AnyUrl,
headers: dict[str, str] | None = None,
auth: httpx.Auth | Literal["oauth"] | str | None = None,
sse_read_timeout: datetime.timedelta | float | int | None = None,
httpx_client_factory: McpHttpClientFactory | None = None,
):
@@
if isinstance(sse_read_timeout, int | float):
sse_read_timeout = datetime.timedelta(seconds=float(sse_read_timeout))
self.sse_read_timeout = sse_read_timeout
+ # Session id callback provided by underlying streamablehttp_client transport
+ self.get_session_id_cb = None
@@
def get_session_id(self) -> str | None:
- if self.get_session_id_cb:
- return self.get_session_id_cb()
- return None
+ """
+ Return the current MCP session id, or None if no session has been established yet.
+ """
+ cb = self.get_session_id_cb
+ if cb is None:
+ return None
+ return cb()If you want stricter typing, you can additionally annotate the attribute in __init__:
from typing import Callable # at top of file
self.get_session_id_cb: Callable[[], str | None] | None = NoneThis keeps the method safe to call at any time while preserving the desired str | None return contract.
🤖 Prompt for AI Agents
In src/fastmcp/client/transports.py around lines 297 to 301, get_session_id()
assumes self.get_session_id_cb exists and can raise AttributeError if called
before connect_session(); initialize self.get_session_id_cb = None in __init__
(and optionally annotate it as Callable[[], str | None] | None after importing
Callable) and change get_session_id() to explicitly check "if
self.get_session_id_cb is not None:" before calling it, returning None otherwise
so the method always returns str | None without raising.
Test Failure AnalysisSummary: The test failure in the Windows CI run is not related to the PR changes. This is a known Windows-specific flaky test issue with pytest-xdist parallel execution. Root Cause: The failing test The error shows a pytest-xdist worker crash: This is accompanied by Windows-specific resource warnings about closed pipes and event loops ( Verification: I tested both the failing test and the new feature:
Suggested Solution: This is a flaky test infrastructure issue, not a code problem. The CI should be re-run. If the Windows test continues to flake, consider one of these approaches:
The PR code itself is solid and ready for merge once the CI passes. Detailed AnalysisWhat the PR Changes
What Failed
Log EvidenceThese are classic Windows asyncio cleanup issues when tests run in parallel with pytest-xdist. Related FilesModified by PR:
Unrelated failing test:
|
jlowin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
get_session_id_cbshould be a private variable (_get_session_id_cb) since it is only used to persist state for the duration of a connection- relatedly,
_get_session_id_cbneeds to be reset when the connection is closed. I'm not sure what would happen if the user tried to callget_session_id()after closing a session but I imagine it would raise a low-level error. Better to return None in that case - the private variable should get typing in init of
_get_session_id_cb: Callable[[], str | None] | NoneI believe
Description
This PR exposes the session id callback from MCP's
streamablehttp_clientas a method inStreamableHTTPTransport. It let's users have easier access tomcp-session-id.Contributors Checklist
Review Checklist