Testing Strategy
Relevant source files
The following files were used as context for generating this wiki page:
The python-sdk project employs a comprehensive testing strategy to ensure the reliability, correctness, and quality of both the server and client components. The strategy relies on a combination of integration and unit tests, leveraging modern Python testing frameworks and tools. The primary goal is to validate the full lifecycle of the Model Context Protocol (MCP), from server setup and client connection to feature-specific interactions like tool calls, resource management, and authentication.
Testing is a mandatory part of the development workflow. New features require corresponding tests, and bug fixes must include regression tests to prevent recurrence. The entire test suite is executed using pytest and is designed to handle asynchronous operations extensively with anyio.
Sources: CONTRIBUTING.md:40-42, CLAUDE.md:19-23
Core Testing Tools and Frameworks
The project's testing foundation is built upon a set of standard, high-quality tools. Adherence to these tools is part of the development guidelines.
| Tool | Purpose | Command Example |
|---|---|---|
uv | Package and environment management, including running test commands. | uv sync --frozen --all-extras --dev |
pytest | The core test framework for discovering and running tests. | uv run pytest |
anyio | The backend for all asynchronous testing, used instead of asyncio. | N/A (used via pytest-anyio) |
ruff | Linter and code formatter to ensure code quality and consistency. | uv run ruff check . |
pyright | Static type checker to enforce type safety. | uv run pyright |
Sources: CONTRIBUTING.md:13-15, 40-42, CLAUDE.md:7-8, 19-20, 42-43, 52-53
Integration Testing
A significant portion of the testing strategy is focused on integration tests that validate the end-to-end functionality between a live MCP server and a client. These tests cover all major features of the protocol.
Sources: tests/server/fastmcp/test_integration.py
Test Architecture
Integration tests spin up a real uvicorn server in a separate process and then execute a test client that connects to it. This ensures that the entire communication stack, including transports like Server-Sent Events (SSE) and StreamableHTTP, is exercised.
The server_transport fixture is a key component of this architecture. It is parameterized to run test suites against different server configurations and transport mechanisms, ensuring broad coverage.
The following diagram illustrates the setup flow for an integration test.
This diagram shows the lifecycle of an integration test, from starting a server in a separate process to the client connecting and the final cleanup.
Sources: tests/server/fastmcp/test_integration.py:126-160
Transport Coverage
Tests are systematically parameterized to run against both sse and streamable-http transports. This is achieved by decorating test functions with pytest.mark.parametrize. This approach ensures that features behave consistently regardless of the underlying transport protocol.
# tests/server/fastmcp/test_integration.py:268-274
@pytest.mark.anyio
@pytest.mark.parametrize(
"server_transport",
[
("basic_tool", "sse"),
("basic_tool", "streamable-http"),
],
indirect=True,
)
Sources: tests/server/fastmcp/test_integration.py:268-274
Feature Validation
Integration tests are organized by feature, with dedicated test functions for:
- Tools:
test_basic_tools,test_tool_progress - Resources:
test_basic_resources - Prompts:
test_basic_prompts - Sampling (LLM Interaction):
test_sampling - Elicitation (User Interaction):
test_elicitation - Notifications:
test_notifications - Completions:
test_completion - Structured Output:
test_structured_output
Sources: tests/server/fastmcp/test_integration.py
A typical client-server interaction during a test, such as calling a tool, follows this sequence:
This diagram shows a client making a call_tool request and receiving a result from the test server.
Sources: tests/server/fastmcp/test_integration.py:280-285
Notification Handling
Server-sent notifications are tested using a NotificationCollector helper class. This class is passed to the ClientSession via a message handler, where it collects various types of notifications into lists for later assertion.
This diagram illustrates how the NotificationCollector intercepts and stores notifications sent from the server during a tool call.
Sources: tests/server/fastmcp/test_integration.py:75-94, 436-441
Unit and Component Testing
Alongside broad integration tests, the project includes focused unit and component tests for core server-side logic. These tests are crucial for verifying the internal mechanics of managers and decorators.
In-Memory Client-Server Testing
For testing server-side logic without the overhead of network communication, the create_connected_server_and_client_session helper is used. This function creates a FastMCP server and a ClientSession that are connected directly in memory, allowing for rapid and isolated testing of the MCP message-passing logic.
Sources: tests/server/fastmcp/test_server.py:41-43
Manager and Decorator Testing
Key components like ToolManager, ResourceManager, and the @mcp.tool decorator are tested in isolation to ensure they handle registration, schema generation, and execution correctly.
ToolManager: Tests intest_tool_manager.pyverify adding synchronous and asynchronous functions, callable objects, handling of Pydantic models, context injection, and structured output conversion.ResourceManager:test_resource_manager.pyandtest_resource_template.pycover the registration of static resources and dynamic resource templates, URI matching, and resource creation.@mcp.tool/@mcp.resource:test_server.pyincludes tests to ensure decorators correctly register functions with theFastMCPinstance and handle incorrect usage.
Sources: tests/server/fastmcp/test_tool_manager.py, tests/server/fastmcp/resources/test_resource_manager.py, tests/server/fastmcp/test_server.py:157-185
Specialized Testing Areas
Authentication
The OAuth 2.0 authorization flow is tested through a dedicated integration test suite. It uses a MockOAuthProvider to simulate a full OAuth server, allowing tests to cover client registration, authorization code exchange, token refresh, and token revocation.
The diagram below shows the tested authorization code grant flow.
This diagram outlines the OAuth2 authorization code flow as validated in the authentication integration tests.
Sources: tests/server/fastmcp/auth/test_auth_integration.py:299-361
StreamableHTTP Transport
The StreamableHTTP transport, an alternative to SSE, has its own extensive test suite. These tests validate the low-level mechanics of the transport, including:
- Header validation (
Accept,Content-Type,mcp-session-id). - Session management (creation, termination, rejection of multiple GET streams).
- Client-side session resumption and event replay using an in-memory
EventStore. - Propagation of request context and headers.
- Server-initiated sampling requests.
Sources: tests/shared/test_streamable_http.py
Summary
The testing strategy for python-sdk is robust and multi-layered. It combines high-level integration tests that validate real-world client-server interactions over multiple transports with lower-level unit tests for core components. The use of pytest fixtures and parametrization allows for efficient and comprehensive coverage of features, transports, and edge cases. This rigorous approach ensures that the SDK is stable, reliable, and conformant to the Model Context Protocol specification.