Skip to content

Commit 5e19c7c

Browse files
authored
Merge pull request #176 from sheffler/fixFirstProgressReport
progress_token is 0 on first tool-call and the return is taken mistakenly
2 parents 44c0004 + 53bfac0 commit 5e19c7c

File tree

3 files changed

+48
-2
lines changed

3 files changed

+48
-2
lines changed

src/mcp/server/fastmcp/server.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,7 @@ async def report_progress(
602602
else None
603603
)
604604

605-
if not progress_token:
605+
if progress_token is None:
606606
return
607607

608608
await self.request_context.session.send_progress_notification(
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from unittest.mock import AsyncMock, MagicMock
2+
3+
import pytest
4+
5+
from mcp.server.fastmcp import Context
6+
from mcp.shared.context import RequestContext
7+
8+
pytestmark = pytest.mark.anyio
9+
10+
11+
async def test_progress_token_zero_first_call():
12+
"""Test that progress notifications work when progress_token is 0 on first call."""
13+
14+
# Create mock session with progress notification tracking
15+
mock_session = AsyncMock()
16+
mock_session.send_progress_notification = AsyncMock()
17+
18+
# Create request context with progress token 0
19+
mock_meta = MagicMock()
20+
mock_meta.progressToken = 0 # This is the key test case - token is 0
21+
22+
request_context = RequestContext(
23+
request_id="test-request", session=mock_session, meta=mock_meta
24+
)
25+
26+
# Create context with our mocks
27+
ctx = Context(request_context=request_context, fastmcp=MagicMock())
28+
29+
# Test progress reporting
30+
await ctx.report_progress(0, 10) # First call with 0
31+
await ctx.report_progress(5, 10) # Middle progress
32+
await ctx.report_progress(10, 10) # Complete
33+
34+
# Verify progress notifications
35+
assert (
36+
mock_session.send_progress_notification.call_count == 3
37+
), "All progress notifications should be sent"
38+
mock_session.send_progress_notification.assert_any_call(
39+
progress_token=0, progress=0.0, total=10.0
40+
)
41+
mock_session.send_progress_notification.assert_any_call(
42+
progress_token=0, progress=5.0, total=10.0
43+
)
44+
mock_session.send_progress_notification.assert_any_call(
45+
progress_token=0, progress=10.0, total=10.0
46+
)

tests/shared/test_sse.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ async def http_client(server, server_url) -> AsyncGenerator[httpx.AsyncClient, N
164164
async def test_raw_sse_connection(http_client: httpx.AsyncClient) -> None:
165165
"""Test the SSE connection establishment simply with an HTTP client."""
166166
async with anyio.create_task_group():
167+
167168
async def connection_test() -> None:
168169
async with http_client.stream("GET", "/sse") as response:
169170
assert response.status_code == 200
@@ -211,7 +212,6 @@ async def initialized_sse_client_session(
211212
yield session
212213

213214

214-
215215
@pytest.mark.anyio
216216
async def test_sse_client_happy_request_and_response(
217217
initialized_sse_client_session: ClientSession,

0 commit comments

Comments
 (0)