feat(server): lifespan redesign with server-scoped and session-scoped lifetimes#2127
Closed
gspeter-max wants to merge 18 commits intomodelcontextprotocol:mainfrom
Closed
feat(server): lifespan redesign with server-scoped and session-scoped lifetimes#2127gspeter-max wants to merge 18 commits intomodelcontextprotocol:mainfrom
gspeter-max wants to merge 18 commits intomodelcontextprotocol:mainfrom
Conversation
This clarifies that the default lifespan function is for session-scoped resources. Server lifespan will be added separately.
This provides the infrastructure for managing server-level lifecycle resources that live for the entire server process. The server lifespan context is stored in a context variable, making it accessible to all sessions without re-initializing.
CRITICAL FIX: Server lifespan now runs at Starlette app startup (once), not in session manager. This is the correct fix for bugs modelcontextprotocol#1300 and modelcontextprotocol#1304. The server lifespan runs BEFORE the session manager starts, ensuring database pools and ML models are initialized once and shared across all client sessions. Note: Type errors will be fixed in subsequent commits when context access is updated.
…contexts This separates server-level resources (database pools, ML models) from session-level resources (user data, auth context) for clarity. BREAKING CHANGE: ctx.lifespan_context is now split into: - ctx.server_lifespan_context - ctx.session_lifespan_context
…texts Request handlers now receive both server_lifespan_context and session_lifespan_context. The server context is retrieved from the context variable set by ServerLifespanManager. Note: Type errors will be fixed in subsequent commits when tests are updated.
Tests now use session_lifespan parameter instead of lifespan for low-level Server. MCPServer continues to use lifespan parameter internally. Also updated MCPServer Context class to use new type variables (ServerLifespanContextT, SessionLifespanContextT) and updated import references.
Tests verify: - Server lifespan runs once at startup - Context is accessible via manager and context variable - Context persists across sessions - Default server lifespan works - Error handling when context not set
…le-http Tests verify: - Server lifespan runs at startup (not on client connect) - Session lifespan runs per-client - Handlers can access both contexts - Proper lifecycle ordering
Example now demonstrates: - Server lifespan (runs once, shared database) - Session lifespan (runs per-client, session_id) - How to access both contexts in handlers Shows the clear separation between server-level and session-level resources, which is the key improvement in the redesigned API.
Documents the breaking change from single lifespan to server_lifespan + session_lifespan parameters. Includes: - Before/after code examples - Key differences table - When to use each lifespan type - Explanation of the bug fix (modelcontextprotocol#1300, modelcontextprotocol#1304)
Updated two sections: 1. MCPServer lifespan example - now shows server_lifespan and session_lifespan 2. Request Context Properties - documents both server_lifespan_context and session_lifespan_context Clarifies when to use each lifespan type and what resources belong in each scope.
Fixed imports in: - MCPServer and all its submodules - test_tool_manager.py Changed from LifespanContextT to ServerLifespanContextT and SessionLifespanContextT to match the updated context module.
The _create_app_lifespan method was causing issues when called as a bound method from within the combined_lifespan lambda. Fixed by inlining the logic directly in the lambda function. This fixes integration tests that were failing with: TypeError: Server._create_app_lifespan() takes 2 positional arguments but 3 were given
Fixed tests that were still using the old lifespan_context parameter: - Updated to server_lifespan_context and session_lifespan_context - Fixed experimental tasks tests - Fixed shared streamable-http tests - Fixed issues tests
Updated all type annotations from Context[LifespanContextT, RequestT] to Context[ServerLifespanContextT, SessionLifespanContextT, RequestT] This fixes type errors in: - prompts/base.py, prompts/manager.py - resources/resource_manager.py, resources/templates.py - tools/base.py, tools/tool_manager.py
ROOT CAUSE: The MCPServer lifespan example was showing the dual-lifespan API (server_lifespan + session_lifespan) which is only for the lowlevel Server API. MCPServer uses a single 'lifespan' parameter mapped to session_lifespan internally. CHANGES: - Reverted lifespan_example.py to use single 'lifespan' parameter - Updated context access to use session_lifespan_context (correct for MCPServer) - Regenerated README.v2.md code snippets via update_readme_snippets.py IMPACT: - Fixes CI failure in README snippet validation - Documents correct MCPServer API usage - Lowlevel Server API (with dual lifespans) remains documented separately Github-Issue:modelcontextprotocol#2113
ROOT CAUSE: Pre-commit hook detected files with inconsistent formatting. CHANGES: - Collapsed multi-line function call arguments to single line - Fixed type annotation line wrapping in resource_manager.py - Applied consistent formatting across 4 files IMPACT: - Fixes pre-commit CI failure - Ensures code style consistency Github-Issue:modelcontextprotocol#2113
ROOT CAUSE: The experimental task tests were using the old 'lifespan' parameter which was renamed to 'session_lifespan' in the lifespan redesign. CHANGES: - Updated tests/experimental/tasks/server/test_integration.py - Updated tests/experimental/tasks/client/test_tasks.py - Changed Server() calls from lifespan= to session_lifespan= IMPACT: - Fixes test failures in experimental/tasks/ directory - All 217 task tests now pass Github-Issue:modelcontextprotocol#2113
Author
|
Closing PR - will be deleted and resubmitted |
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.
Summary
This PR implements Option B (Breaking Change) for the lifespan redesign, separating server-level and session-level resource lifecycles. This fixes critical bugs #1300 and #1304 where database pools were being initialized on the first client connection instead of at server startup.
Key Changes
server_lifespanparameter: Runs ONCE at server startup (for database pools, ML models, shared caches)lifespantosession_lifespan: Runs PER-CLIENT connection (for user auth, session-specific state)ctx.lifespan_context→ctx.server_lifespan_context+ctx.session_lifespan_contextServerLifespanManager: Infrastructure for managing server-scoped resources via context variableMigration Impact
Breaking Change: Users must update their code from:
See Migration Guide for detailed examples.
Test Plan
Fixes
Documentation
docs/migration.mdFiles Changed
Server,ServerRequestContext,ServerLifespanManager🤖 Generated with Claude Code