Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add lifespan context manager support #203

Merged
merged 6 commits into from
Feb 13, 2025
Merged

Conversation

dsp-ant
Copy link
Member

@dsp-ant dsp-ant commented Feb 11, 2025

Summary

  • Add comprehensive lifespan support to both Server and FastMCP classes
  • Enable type-safe resource initialization and cleanup
  • Pass context from startup to request handlers
  • Add support for async startup/shutdown operations

Test plan

  • Run pytest to verify tests for both Server and FastMCP
  • Test startup, shutdown, and context passing functionality
  • Verify compatibility with existing code

Adds a context manager based lifespan API in mcp.server.lowlevel.server to manage server lifecycles in a
type-safe way. This enables servers to:
- Initialize resources on startup and clean them up on shutdown
- Pass context data from startup to request handlers
- Support async startup/shutdown operations
Adds support for the lifespan API to FastMCP server, enabling:
- Simple setup with FastMCP constructor
- Type-safe context passing to tools and handlers
- Configuration via Settings class
Adds comprehensive tests for lifespan functionality:
- Tests for both low-level Server and FastMCP classes
- Coverage for startup, shutdown, and context access
- Verifies context passing to request handlers
Add comprehensive documentation for lifespan support:
- Add usage examples for both Server and FastMPC classes
- Document startup/shutdown patterns
- Show context access in tools and handlers
- Clean up spacing in test files
Replace nested context managers with AsyncExitStack to ensure proper cleanup
order during server shutdown and make the code more maintainable.
@dsp-ant dsp-ant force-pushed the davidsp/clean-lifespan branch from 91d9271 to fddba00 Compare February 11, 2025 13:33
jspahrsummers
jspahrsummers previously approved these changes Feb 12, 2025
Copy link
Member

@jspahrsummers jspahrsummers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly questions/confusions from me, overall looks good!

Comment on lines +475 to +479
async with AsyncExitStack() as stack:
lifespan_context = await stack.enter_async_context(self.lifespan(self))
session = await stack.enter_async_context(
ServerSession(read_stream, write_stream, initialization_options)
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this different from doing async with lifespan_context, session?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AsyncExitStack() version provides more granular control over multiple context managers. If an error occurs during the second enter_async_context, the first one will still be properly cleaned up.

Chatted more with Claude about it, we came to the. conclusion that AsyncExitStack is better here.

)

async def _handle_request(
self,
message: RequestResponder,
req: Any,
session: ServerSession,
lifespan_context: object,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
lifespan_context: object,
lifespan_context: LifespanResultT,

- Add proper generic parameter for lifespan context type
- Update README with TypedDict example for strong typing
- Fix context variable initialization in server
- Improve property return type safety
- Remove redundant documentation
- Ensure compatibility with existing tests
@dsp-ant dsp-ant merged commit 7c47d1f into main Feb 13, 2025
5 checks passed
@dsp-ant dsp-ant deleted the davidsp/clean-lifespan branch February 13, 2025 14:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants