feat: expose progress_callback in ServerSession methods#2041
Open
BryceEWatson wants to merge 6 commits into
Open
feat: expose progress_callback in ServerSession methods#2041BryceEWatson wants to merge 6 commits into
BryceEWatson wants to merge 6 commits into
Conversation
…elicit_form() Add progress_callback parameter to ServerSession methods that send requests to clients, matching the pattern already used by ClientSession.call_tool(). This brings the Python SDK into parity with the TypeScript SDK's RequestOptions.onprogress support. The MCP spec supports bidirectional progress notifications, and BaseSession.send_request() already accepts progress_callback, but the ServerSession convenience methods were not exposing it. Fixes modelcontextprotocol#1671 Github-Issue: modelcontextprotocol#1671
The if-guards checking for progress_token in context.meta always evaluate to True when progress_callback is provided, so the false branches are never taken. Mark with pragma: no branch to satisfy 100% coverage requirement.
Merge upstream/main into fix/1671-serversession-progress-callback. Resolved import conflict in mcpserver/server.py by keeping both the new ProgressFnT import and the expanded mcp.types imports from the lowlevel Server decorator refactor (modelcontextprotocol#1985).
Author
Merge upstream/main which included major refactors: - Context class moved from server.py to mcpserver/context.py (modelcontextprotocol#2203) - Lowlevel Server decorators replaced with on_* kwargs (modelcontextprotocol#1985) - Docstring formatting standardized with periods (modelcontextprotocol#2095) - mcp.shared.progress module removed (modelcontextprotocol#2080) Resolved conflicts by: - Taking upstream server.py (Context class removed) - Adding progress_callback to new context.py - Keeping progress_callback docstrings with upstream period style - Restoring RequestContext import for new tests - Updating tests to use ctx: Context injection pattern
606d106 to
b23b702
Compare
Sync the progress_callback feature branch onto current upstream/main, which had undergone a large refactor since the branch was last updated (dispatcher extraction, ProgressFnT moved from mcp.shared.session to mcp.shared.dispatcher, removal of the experimental tasks modules, and a test reorganization). Conflict resolution: - src/mcp/server/session.py: take upstream's import block (ProgressFnT now comes from mcp.shared.dispatcher). The progress_callback pass-throughs on create_message/elicit/elicit_form/elicit_url auto-merged onto upstream's refactored send_request, which already accepts progress_callback. - src/mcp/server/mcpserver/context.py: keep both upstream's LoggingLevel import and the ProgressFnT import (relocated to mcp.shared.dispatcher). - tests/shared/test_progress_notifications.py: upstream deleted this pre-existing file in its test reorg. Re-add it containing only this PR's two feature tests (create_message and elicit_form progress_callback pass-through), adapted to the new client callback API (mcp.client.ClientRequestContext). Verified locally: ruff format/lint clean, pyright clean, full suite green (2388 passed serially), coverage 100%.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1671
Motivation and Context
The
ServerSessionhigh-level methods for sending requests to clients (create_message,elicit_form,elicit_url) don't expose theprogress_callbackparameter, even though the underlyingBaseSession.send_request()fully supports it. This means servers can't easily receive progress notifications from clients during sampling or elicitation requests.ClientSession.call_tool()already exposesprogress_callbackfor the client→server direction. This PR adds the same support for the server→client direction, bringing the Python SDK into parity with the TypeScript SDK'sRequestOptions.onprogress.How Has This Been Tested?
tests/shared/test_progress_notifications.py:test_server_create_message_progress_callback: verifies progress callbacks work during sampling requests viaMCPServer+Clienttest_server_elicit_form_progress_callback: verifies progress callbacks work during elicitation requests viaMCPServer+Clientmain, the full test suite passes locally (uv run pytest),uv run pyrightreports 0 errors, anduv run ruff check .is clean. CI is green on all checks.Breaking Changes
No. All new parameters default to
None, maintaining full backward compatibility.Types of changes
Checklist
Additional context
Approach: Mirrors the existing
ClientSession.call_tool()pattern — addsprogress_callback: ProgressFnT | None = Noneto each method signature and passes it through tosend_request().Files changed (4):
src/mcp/server/session.py— Core: added param tocreate_message()(all overloads + impl),elicit(),elicit_form(),elicit_url()src/mcp/server/elicitation.py— Helpers: passthrough inelicit_with_validation()andelicit_url()src/mcp/server/mcpserver/context.py— Context API: passthrough inContext.elicit()andContext.elicit_url()tests/shared/test_progress_notifications.py— 2 new E2E testsIntentionally excluded:
list_roots()andsend_ping()— these are short-lived requests where progress tracking isn't meaningful.AI assistance disclosure
I used AI assistance while writing this change. I've reviewed and tested every line, understand the mechanism (
send_requestalready acceptsprogress_callbackand maps it toon_progress; these convenience methods just weren't forwarding it), and can answer questions on it directly.