-
Notifications
You must be signed in to change notification settings - Fork 3k
Add ergonomic Client class for testing MCP servers #1870
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
base: main
Are you sure you want to change the base?
Conversation
d0f5279 to
3fce73d
Compare
This commit adds: - Client class stub with from_server() class method - InMemoryTransport class stub - Comprehensive test suite for Client (TDD approach) All methods currently raise NotImplementedError. Github-Issue:#1728
- Client class wraps ClientSession with transport management - Client.from_server() provides ergonomic in-memory testing - create_in_memory_transport() reuses existing memory stream logic - All 23 Client tests pass Github-Issue:#1728
- Export Client from mcp and mcp.client modules - Add deprecation warning to create_connected_server_and_client_session - Document migration path in docstring Github-Issue:#1728
- Migrate tests/server/fastmcp/test_title.py to use Client.from_server() - Fix circular import by not re-exporting ClientSessionGroup from client module - Demonstrates cleaner API: no need to access ._mcp_server Github-Issue:#1728
Migrate the following files to use the new Client API: - tests/server/fastmcp/test_server.py: Use Client.from_server(mcp) instead of client_session(mcp._mcp_server) - tests/shared/test_session.py: Use InMemoryTransport + ClientSession for low-level session tests - tests/shared/test_progress_notifications.py: Use InMemoryTransport for progress callback exception test - examples/fastmcp/weather_structured.py: Use Client.from_server(mcp) for the example The high-level Client API is used for tests that just need to call tools, resources, and prompts. The low-level InMemoryTransport + ClientSession pattern is used for tests that need direct session access (e.g., _in_flight, send_notification, send_request).
…r_and_client_session
Breaking change for v2:
- Replace create_connected_server_and_client_session() function with InMemoryTransport class
- Add Client.from_server() for ergonomic testing
- Migrate all tests to use new API patterns
- Update stream spy fixture to patch both module locations
High-level tests now use:
async with Client.from_server(server) as client:
result = await client.call_tool(...)
Low-level tests use:
transport = InMemoryTransport(server)
async with transport.connect() as (read, write):
async with ClientSession(read, write) as session:
...
Github-Issue:#1728
- Refactor Client constructor to accept Server/FastMCP directly - Remove from_server() classmethod (simpler, matches FastMCP pattern) - Update all tests and examples to use new pattern Github-Issue:#1728
- Add module-level pytestmark = pytest.mark.anyio - Convert 16 test classes to standalone async functions - Remove self parameters and individual decorators - Maintain 100% test coverage
The session methods in this branch don't have the deprecated cursor overloads, so convert cursor to PaginatedRequestParams instead of trying to call a non-existent deprecated signature.
The ClientSession in this branch only supports the params parameter, not the deprecated cursor parameter. Remove tests that were testing the deprecated cursor behavior and consolidate to params-only tests.
e3c2972 to
0b610a8
Compare
- Replace AnyUrl usage with plain strings for Resource URIs - Update test_1574 to use Client instead of removed client_session helper
This reverts commit 26c7db6.
- Add list_resources() call to test_with_simple_server to cover the handler - Remove incomplete test_logging_callback that never triggered logging - Mark fixture handlers as no-cover where they exist only for metadata (list tests don't invoke handlers, they only list available items)
- Convert TestInMemoryTransport class to plain test functions - Remove section header comments from test_client.py - Make pragma: no cover comments more explicit about why handlers aren't covered - Add TODO in Client docstring outlining planned transport expansion
|
Key files to review:
Remainder is tests being updated to use the new interface. NOTE: This only implements test support. Refactoring Client to support different transports for the end-user API (streamable HTTP, stdio, SSE, etc.) is coming, marked as TODO in the Client docstring. |
Use params=PaginatedRequestParams(cursor=...) instead.
|
|
||
| try: | ||
| # Create transport and connect | ||
| transport = InMemoryTransport(self._server, raise_exceptions=self._raise_exceptions) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right now this is hard-coded but we'd add a infer_transport_from_args or similar method during init that would set up SHTTP / STDIO / SSE as required.
Summary
Adds a high-level
Clientclass that provides an ergonomic API for testing MCP servers with in-memory transport.Motivation and Context
Testing MCP servers currently requires using the verbose
create_connected_server_and_client_sessionfunction. This PR introduces a simpler API:Related issues:
How Has This Been Tested?
ClientandInMemoryTransportcreate_connected_server_and_client_sessionto new APIBreaking Changes
create_connected_server_and_client_sessionfrommcp.shared.memory(v2 breaking change)Types of changes
Checklist
Additional context
New API
High-level (recommended):
Low-level (for advanced use cases):