In-process callback failures break tool calls and notification sends
Nobody has claimed this yet.
Assessment
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 84/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- python
- Domain
- backend-api-design
Research direction
Start in the DirectDispatcher paths and compare their callback-failure handling with the stream-backed JSONRPCDispatcher. Run tests/shared/test_dispatcher.py with the two named -k cases to reproduce the failures. Done means both DirectDispatcher cases pass, successful tool calls and notification sends continue, and callback failures are logged.
Written by the indexing model from the issue text.
Description
Initial Checks
- I confirm that I am using the newest release of the 2.x line.
- I confirm that I searched the issue tracker before opening this issue.
Release line
2.x (current stable)
Description
Client(server) uses DirectDispatcher. If a progress callback raises, that exception crosses back into server tool execution, so a tool that otherwise returns successfully fails with UnexpectedToolError. DirectDispatcher also lets an inbound notification handler exception escape back to the sender's notify() call.
The stream-backed JSONRPCDispatcher logs and contains both callback failures. I expected the in-process path to keep the same boundary: log the callback failure, but let the protocol operation continue.
I have a small patch and regression tests for both paths and would like to fix this if maintainers want an outside pull request.
I used GitHub Copilot CLI to inspect the dispatcher paths, write the patch, and draft this report. I verified the reproduction and tests.
Example Code
import anyio
from mcp import Client
from mcp.server.mcpserver import Context, MCPServer
server = MCPServer("callback-repro")
@server.tool()
async def work(context: Context) -> str:
await context.report_progress(1, 1)
return "done"
async def broken_progress(progress: float, total: float | None, message: str | None) -> None:
raise RuntimeError("consumer failed")
async def main() -> None:
async with Client(server, mode="2026-07-28") as client:
result = await client.call_tool("work", progress_callback=broken_progress)
print(result.content[0].text)
anyio.run(main)
Current main ends with:
UnexpectedToolError: Error executing tool work
The tool should print done. The callback failure should still be logged.
Verification
With only the regression tests applied to clean main:
uv run --frozen pytest tests/shared/test_dispatcher.py \
-k 'progress_callback_exception_does_not_fail_request or notification_handler_exception_does_not_reach_sender' -q
# 2 failed, 2 passed. Both DirectDispatcher cases failed.
With the two callback guards applied:
uv run --frozen pytest tests/shared/test_dispatcher.py \
-k 'progress_callback_exception_does_not_fail_request or notification_handler_exception_does_not_reach_sender' -q
# 4 passed
Python & MCP Python SDK
Python 3.12.13
mcp 2.1.1
mcp 2.1.2.dev4+d060b36e at d060b36e1d095ef6e93e07ba5d59bb69b2ad449a
macOS
- Dominant language
- Python
- Stars
- 24.3k
- Forks
- 4k
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 30
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from modelcontextprotocol/python-sdk
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
modelcontextprotocol/python-sdk#3566 ·
-
v1 v2
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
modelcontextprotocol/python-sdk#3546 · 5 comments ·
-
v1 v2
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
modelcontextprotocol/python-sdk#3545 · 1 comment ·
-
v1 v2
Difficulty 1/5 Under an hour Newbie friendliness 91/100
modelcontextprotocol/python-sdk#3508 · 2 comments ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
modelcontextprotocol/python-sdk#3504 ·
All issues in modelcontextprotocol/python-sdk
Similar issues
-
essnmx good first issue
Difficulty 1/5 Under an hour Newbie friendliness 95/100
-
[Feature] 奇物选择添加优先级 Open
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
syfoud/Simulated_Scepter#174 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Giskard-AI/giskard-oss#2840 · 1 comment ·
-
A claim comment carrying the issue number is silently declined while the workflow reports success Openarea: repo bug perceived difficulty: 2
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
yeti-platform/yeti#1380 ·