René's URL Explorer Experiment


Title: ClientSession receive loop swallows callback exceptions, replying "Invalid request parameters" to the server instead of propagating to the call_tool awaiter · Issue #2673 · modelcontextprotocol/python-sdk · GitHub

Open Graph Title: ClientSession receive loop swallows callback exceptions, replying "Invalid request parameters" to the server instead of propagating to the call_tool awaiter · Issue #2673 · modelcontextprotocol/python-sdk

X Title: ClientSession receive loop swallows callback exceptions, replying "Invalid request parameters" to the server instead of propagating to the call_tool awaiter · Issue #2673 · modelcontextprotocol/python-sdk

Description: Initial Checks I confirm that I'm using the latest version of MCP Python SDK I confirm that I searched for my issue in https://github.com/modelcontextprotocol/python-sdk/issues before opening this issue Description I hit this while wirin...

Open Graph Description: Initial Checks I confirm that I'm using the latest version of MCP Python SDK I confirm that I searched for my issue in https://github.com/modelcontextprotocol/python-sdk/issues before opening this ...

X Description: Initial Checks I confirm that I'm using the latest version of MCP Python SDK I confirm that I searched for my issue in https://github.com/modelcontextprotocol/python-sdk/issues before opening t...

Opengraph URL: https://github.com/modelcontextprotocol/python-sdk/issues/2673

X: @github

direct link

Domain: github.com


Hey, it has json ld scripts:
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"ClientSession receive loop swallows callback exceptions, replying \"Invalid request parameters\" to the server instead of propagating to the call_tool awaiter","articleBody":"### Initial Checks\n\n- [x] I confirm that I'm using the latest version of MCP Python SDK\n- [x] I confirm that I searched for my issue in https://github.com/modelcontextprotocol/python-sdk/issues before opening this issue\n\n### Description\n\n\nI hit this while wiring an MCP tool that uses `ctx.elicit(...)` into a\nLangGraph agent — the natural pattern of calling `interrupt()` from the\nclient elicitation callback does not work because the callback's exception\nis swallowed by `_receive_loop` and replied to the server as\n`Invalid request parameters`. The same limitation blocks any framework that\nrelies on exception-based control flow on the awaiter's task (custom\nasync-cancellation strategies, Trio nursery patterns, retry/backoff\nlibraries, any human-in-the-loop integration), so a small SDK-level escape\nhatch would unblock a broad class of MCP client developers, not just this\none use case.\n\nAny exception raised inside a `ClientSession` callback\n(`elicitation_callback`, `sampling_callback`, `list_roots_callback`) is\ncaught by the blanket `except Exception` in `BaseSession._receive_loop`\n(`src/mcp/shared/session.py`) and turned into a JSON-RPC\n`Invalid request parameters` reply to the server:\n\n```python\nexcept Exception:\n    logging.warning(\"Failed to validate request\", exc_info=True)\n    error_response = JSONRPCError(\n        jsonrpc=\"2.0\",\n        id=message.message.id,\n        error=ErrorData(code=INVALID_PARAMS, message=\"Invalid request parameters\", data=\"\"),\n    )\n    await self._write_stream.send(SessionMessage(message=error_response))\n```\n\nConsequences:\n\n1. The server is blamed for \"invalid params\" when the failure was on the\n   client. The original callback traceback is lost from the awaiter of\n   `session.call_tool(...)`.\n2. Callbacks have no way to abort back to the awaiter. Frameworks that use\n   exception-based flow control on the caller's task (LangGraph's\n   `interrupt()` for human-in-the-loop pause/resume is the motivating\n   case) cannot be wired through MCP without per-framework workarounds.\n\n**Expected:** an opt-in escape hatch so a callback can raise an exception\nthat propagates out of the in-flight `session.call_tool(...)` instead of\nbecoming a JSON-RPC error to the server. Defaulting opt-in to off preserves\nexisting behaviour.\n\n**Proposed minimal fix (single file, ~30 lines, three coordinated edits):**\n\n```python\n# src/mcp/shared/session.py\n#\n# (1) BaseSession.__init__: add a per-session stash for marked exceptions.\nself._propagate_errors: dict[RequestId, BaseException] = {}\n\n# (2) Inside _receive_loop's request-handler `except Exception as e:` block,\n#     branch on the marker before the existing INVALID_PARAMS path.\nif getattr(e, \"__mcp_propagate__\", False):\n    # Notify the peer so their request doesn't hang.\n    error_response = JSONRPCError(\n        jsonrpc=\"2.0\",\n        id=message.message.root.id,\n        error=ErrorData(code=INTERNAL_ERROR, message=\"Handler raised\", data=\"\"),\n    )\n    await self._write_stream.send(SessionMessage(message=JSONRPCMessage(error_response)))\n    # Surface to the awaiter of any in-flight outgoing request on this session.\n    for in_flight_id, stream in list(self._response_streams.items()):\n        self._propagate_errors[in_flight_id] = e\n        await stream.aclose()\n    continue\n# ...existing INVALID_PARAMS path unchanged below this point.\n\n# (3) Inside send_request, alongside the existing `except TimeoutError:`,\n#     consume the stash on EndOfStream and re-raise the original exception.\nexcept anyio.EndOfStream:\n    propagate = self._propagate_errors.pop(request_id, None)\n    if propagate is not None:\n        raise propagate from None\n    raise\n```\n\n**I've already implemented and tested this locally** against `v1.x` (and the\nsame shape on `main` for the V2 rework): ~33 lines added to\n`src/mcp/shared/session.py` plus regression tests in\n`tests/shared/test_session.py`. The patch is strictly additive — without the\n`__mcp_propagate__` marker, behaviour is byte-identical to today. End-to-end\nverified by surfacing a LangGraph `interrupt()` from an elicitation callback\nas a normal `__interrupt__` on the agent's first invoke. `ruff` / `pyright`\nclean, existing session tests still pass. Happy to open a PR once the issue\nis accepted and you've confirmed the direction.\n\n\n### Example Code\n\n```Python\n# Self-contained reproduction. No third-party agent framework needed.\n#\n# Terminal A:  python repro_server.py\n# Terminal B:  python repro_client.py\n#\n# Observed in A: WARNING:root:Failed to validate request: CallbackBoom(...)\n# Observed in B: tool result.isError = True, CallbackBoom was NEVER raised\n#                on the awaiter — silently converted to INVALID_PARAMS.\n\n# --- repro_server.py ---\nfrom mcp.server.fastmcp import Context, FastMCP\nfrom pydantic import BaseModel\n\nclass Answer(BaseModel):\n    value: str\n\nserver = FastMCP(name=\"repro\", port=8765)\n\n@server.tool()\nasync def ask(ctx: Context) -\u003e str:\n    result = await ctx.elicit(message=\"hello?\", schema=Answer)\n    return f\"got: {result}\"\n\nif __name__ == \"__main__\":\n    server.run(transport=\"streamable-http\")\n\n\n# --- repro_client.py ---\nimport asyncio\nfrom mcp import ClientSession\nfrom mcp.client.streamable_http import streamablehttp_client\n\nclass CallbackBoom(Exception):\n    \"\"\"Stand-in for any framework's flow-control exception (e.g. GraphInterrupt).\"\"\"\n\nasync def on_elicit(ctx, params):\n    raise CallbackBoom(\"callback wants to abort back to the awaiter\")\n\nasync def main():\n    async with streamablehttp_client(\"http://127.0.0.1:8765/mcp\") as (r, w, _):\n        async with ClientSession(r, w, elicitation_callback=on_elicit) as session:\n            await session.initialize()\n            try:\n                result = await session.call_tool(\"ask\", {})\n            except CallbackBoom:\n                print(\"OK: CallbackBoom propagated to the awaiter\")\n                return\n            print(\"BUG: awaiter did not raise; result.isError =\", result.isError)\n            print(\"     content =\", result.content)\n\nasyncio.run(main())\n```\n\n### Python \u0026 MCP Python SDK\n\n```Text\nPython: 3.13\nmcp:    1.27.1\n```","author":{"url":"https://github.com/danielgshea","@type":"Person","name":"danielgshea"},"datePublished":"2026-05-24T03:45:45.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":4},"url":"https://github.com/2673/python-sdk/issues/2673"}

route-pattern/_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format)
route-controllervoltron_issues_fragments
route-actionissue_layout
fetch-noncev2:aaafd363-a85b-a586-d82b-577cc6e6c7e0
current-catalog-service-hash81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114
request-id84FE:11ACF6:12DF904:19516A6:6A5AB3FC
html-safe-nonceb6323050f37042293d26f97a8cc434651d6f4770f1e11cd028aac00ffd86f5e2
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI4NEZFOjExQUNGNjoxMkRGOTA0OjE5NTE2QTY6NkE1QUIzRkMiLCJ2aXNpdG9yX2lkIjoiNDYzMzQxNzgzMzE3NDk3MTM4OCIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9
visitor-hmac13b8e4014f250e7e137cdaf069fbf07ebf6118f1ab991f303c4f2ef0437c0691
hovercard-subject-tagissue:4510397688
github-keyboard-shortcutsrepository,issues,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///voltron/issues_fragments/issue_layout
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/modelcontextprotocol/python-sdk/2673/issue_layout
twitter:imagehttps://opengraph.githubassets.com/a441669998c2a201c25cba640f750cbfecc2ccbe748bc299f0605a78f4c08e9e/modelcontextprotocol/python-sdk/issues/2673
twitter:cardsummary_large_image
og:imagehttps://opengraph.githubassets.com/a441669998c2a201c25cba640f750cbfecc2ccbe748bc299f0605a78f4c08e9e/modelcontextprotocol/python-sdk/issues/2673
og:image:altInitial Checks I confirm that I'm using the latest version of MCP Python SDK I confirm that I searched for my issue in https://github.com/modelcontextprotocol/python-sdk/issues before opening this ...
og:image:width1200
og:image:height600
og:site_nameGitHub
og:typeobject
og:author:usernamedanielgshea
hostnamegithub.com
expected-hostnamegithub.com
None2702febe50e53f9152dda552dc2049a5eb182778b2655abd5b8619e82e899b4a
turbo-cache-controlno-preview
go-importgithub.com/modelcontextprotocol/python-sdk git https://github.com/modelcontextprotocol/python-sdk.git
octolytics-dimension-user_id182288589
octolytics-dimension-user_loginmodelcontextprotocol
octolytics-dimension-repository_id862584018
octolytics-dimension-repository_nwomodelcontextprotocol/python-sdk
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id862584018
octolytics-dimension-repository_network_root_nwomodelcontextprotocol/python-sdk
turbo-body-classeslogged-out env-production page-responsive
disable-turbofalse
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
releasec0211a077f9b056c5e115f996d9049616d85c3b5
ui-targetfull
theme-color#1e2327
color-schemelight dark

Links:

Skip to contenthttps://github.com/modelcontextprotocol/python-sdk/issues/2673#start-of-content
https://github.com/
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fmodelcontextprotocol%2Fpython-sdk%2Fissues%2F2673
GitHub CopilotWrite better code with AIhttps://github.com/features/copilot
GitHub Copilot appDirect agents from issue to mergehttps://github.com/features/ai/github-app
MCP RegistryNewIntegrate external toolshttps://github.com/mcp
ActionsAutomate any workflowhttps://github.com/features/actions
CodespacesInstant dev environmentshttps://github.com/features/codespaces
IssuesPlan and track workhttps://github.com/features/issues
Code ReviewManage code changeshttps://github.com/features/code-review
GitHub Advanced SecurityFind and fix vulnerabilitieshttps://github.com/security/advanced-security
Code securitySecure your code as you buildhttps://github.com/security/advanced-security/code-security
Secret protectionStop leaks before they starthttps://github.com/security/advanced-security/secret-protection
Why GitHubhttps://github.com/why-github
Documentationhttps://docs.github.com
Bloghttps://github.blog
Changeloghttps://github.blog/changelog
Marketplacehttps://github.com/marketplace
View all featureshttps://github.com/features
Enterpriseshttps://github.com/enterprise
Small and medium teamshttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
App Modernizationhttps://github.com/solutions/use-case/app-modernization
DevSecOpshttps://github.com/solutions/use-case/devsecops
DevOpshttps://github.com/solutions/use-case/devops
CI/CDhttps://github.com/solutions/use-case/ci-cd
View all use caseshttps://github.com/solutions/use-case
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
View all industrieshttps://github.com/solutions/industry
View all solutionshttps://github.com/solutions
AIhttps://github.com/resources/articles?topic=ai
Software Developmenthttps://github.com/resources/articles?topic=software-development
DevOpshttps://github.com/resources/articles?topic=devops
Securityhttps://github.com/resources/articles?topic=security
View all topicshttps://github.com/resources/articles
Customer storieshttps://github.com/customer-stories
Events & webinarshttps://github.com/resources/events
Ebooks & reportshttps://github.com/resources/whitepapers
Business insightshttps://github.com/solutions/executive-insights
GitHub Skillshttps://skills.github.com
Documentationhttps://docs.github.com
Customer supporthttps://support.github.com
Community forumhttps://github.com/orgs/community/discussions
Trust centerhttps://github.com/trust-center
Partnershttps://github.com/partners
View all resourceshttps://github.com/resources
GitHub SponsorsFund open source developershttps://github.com/open-source/sponsors
Security Labhttps://securitylab.github.com
Maintainer Communityhttps://maintainers.github.com
Acceleratorhttps://github.com/open-source/accelerator
GitHub Starshttps://stars.github.com
Archive Programhttps://archiveprogram.github.com
Topicshttps://github.com/topics
Trendinghttps://github.com/trending
Collectionshttps://github.com/collections
Enterprise platformAI-powered developer platformhttps://github.com/enterprise
GitHub Advanced SecurityEnterprise-grade security featureshttps://github.com/security/advanced-security
Copilot for BusinessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/enterprise/premium-support
Pricinghttps://github.com/pricing
Search syntax tipshttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
documentationhttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fmodelcontextprotocol%2Fpython-sdk%2Fissues%2F2673
Sign up https://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fvoltron%2Fissues_fragments%2Fissue_layout&source=header-repo&source_repo=modelcontextprotocol%2Fpython-sdk
Reloadhttps://github.com/modelcontextprotocol/python-sdk/issues/2673
Reloadhttps://github.com/modelcontextprotocol/python-sdk/issues/2673
Reloadhttps://github.com/modelcontextprotocol/python-sdk/issues/2673
Please reload this pagehttps://github.com/modelcontextprotocol/python-sdk/issues/2673
modelcontextprotocol https://github.com/modelcontextprotocol
python-sdkhttps://github.com/modelcontextprotocol/python-sdk
Notifications https://github.com/login?return_to=%2Fmodelcontextprotocol%2Fpython-sdk
Fork 3.7k https://github.com/login?return_to=%2Fmodelcontextprotocol%2Fpython-sdk
Star 23.6k https://github.com/login?return_to=%2Fmodelcontextprotocol%2Fpython-sdk
Code https://github.com/modelcontextprotocol/python-sdk
Issues 257 https://github.com/modelcontextprotocol/python-sdk/issues
Pull requests 301 https://github.com/modelcontextprotocol/python-sdk/pulls
Actions https://github.com/modelcontextprotocol/python-sdk/actions
Projects https://github.com/modelcontextprotocol/python-sdk/projects
Models https://github.com/modelcontextprotocol/python-sdk/models
Security and quality 6 https://github.com/modelcontextprotocol/python-sdk/security
Insights https://github.com/modelcontextprotocol/python-sdk/pulse
Code https://github.com/modelcontextprotocol/python-sdk
Issues https://github.com/modelcontextprotocol/python-sdk/issues
Pull requests https://github.com/modelcontextprotocol/python-sdk/pulls
Actions https://github.com/modelcontextprotocol/python-sdk/actions
Projects https://github.com/modelcontextprotocol/python-sdk/projects
Models https://github.com/modelcontextprotocol/python-sdk/models
Security and quality https://github.com/modelcontextprotocol/python-sdk/security
Insights https://github.com/modelcontextprotocol/python-sdk/pulse
ClientSession receive loop swallows callback exceptions, replying "Invalid request parameters" to the server instead of propagating to the call_tool awaiterhttps://github.com/modelcontextprotocol/python-sdk/issues/2673#top
P3Nice to haves, rare edge caseshttps://github.com/modelcontextprotocol/python-sdk/issues?q=state%3Aopen%20label%3A%22P3%22
enhancementRequest for a new feature that's not currently supportedhttps://github.com/modelcontextprotocol/python-sdk/issues?q=state%3Aopen%20label%3A%22enhancement%22
needs decisionIssue is actionable, needs maintainer decision on whether to implementhttps://github.com/modelcontextprotocol/python-sdk/issues?q=state%3Aopen%20label%3A%22needs%20decision%22
https://github.com/danielgshea
danielgsheahttps://github.com/danielgshea
on May 24, 2026https://github.com/modelcontextprotocol/python-sdk/issues/2673#issue-4510397688
https://github.com/modelcontextprotocol/python-sdk/issueshttps://github.com/modelcontextprotocol/python-sdk/issues
P3Nice to haves, rare edge caseshttps://github.com/modelcontextprotocol/python-sdk/issues?q=state%3Aopen%20label%3A%22P3%22
enhancementRequest for a new feature that's not currently supportedhttps://github.com/modelcontextprotocol/python-sdk/issues?q=state%3Aopen%20label%3A%22enhancement%22
needs decisionIssue is actionable, needs maintainer decision on whether to implementhttps://github.com/modelcontextprotocol/python-sdk/issues?q=state%3Aopen%20label%3A%22needs%20decision%22
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.