Add ergonomic Client class for testing MCP servers (#1870)
This commit is contained in:
parent
8adb5bdce8
commit
df039bf97c
5 changed files with 1298 additions and 526 deletions
|
|
@ -1,10 +1,8 @@
|
|||
import pytest
|
||||
from pydantic import AnyUrl
|
||||
|
||||
from mcp import Client
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
from mcp.shared.memory import (
|
||||
create_connected_server_and_client_session as client_session,
|
||||
)
|
||||
from mcp.types import (
|
||||
ListResourceTemplatesResult,
|
||||
TextResourceContents,
|
||||
|
|
@ -78,10 +76,7 @@ async def test_resource_template_client_interaction():
|
|||
def get_user_profile(user_id: str) -> str:
|
||||
return f"Profile for user {user_id}"
|
||||
|
||||
async with client_session(mcp._mcp_server) as session:
|
||||
# Initialize the session
|
||||
await session.initialize()
|
||||
|
||||
async with Client(mcp) as session:
|
||||
# List available resources
|
||||
resources = await session.list_resource_templates()
|
||||
assert isinstance(resources, ListResourceTemplatesResult)
|
||||
|
|
|
|||
|
|
@ -3,13 +3,10 @@ import base64
|
|||
import pytest
|
||||
from pydantic import AnyUrl
|
||||
|
||||
from mcp import types
|
||||
from mcp import Client, types
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
from mcp.server.lowlevel import Server
|
||||
from mcp.server.lowlevel.helper_types import ReadResourceContents
|
||||
from mcp.shared.memory import (
|
||||
create_connected_server_and_client_session as client_session,
|
||||
)
|
||||
|
||||
pytestmark = pytest.mark.anyio
|
||||
|
||||
|
|
@ -33,7 +30,7 @@ async def test_fastmcp_resource_mime_type():
|
|||
return image_bytes
|
||||
|
||||
# Test that resources are listed with correct mime type
|
||||
async with client_session(mcp._mcp_server) as client:
|
||||
async with Client(mcp) as client:
|
||||
# List resources and verify mime types
|
||||
resources = await client.list_resources()
|
||||
assert resources.resources is not None
|
||||
|
|
@ -91,7 +88,7 @@ async def test_lowlevel_resource_mime_type():
|
|||
raise Exception(f"Resource not found: {uri}") # pragma: no cover
|
||||
|
||||
# Test that resources are listed with correct mime type
|
||||
async with client_session(server) as client:
|
||||
async with Client(server) as client:
|
||||
# List resources and verify mime types
|
||||
resources = await client.list_resources()
|
||||
assert resources.resources is not None
|
||||
|
|
|
|||
|
|
@ -12,12 +12,9 @@ These tests verify the fix works end-to-end through the JSON-RPC protocol.
|
|||
|
||||
import pytest
|
||||
|
||||
from mcp import types
|
||||
from mcp import Client, types
|
||||
from mcp.server.lowlevel import Server
|
||||
from mcp.server.lowlevel.helper_types import ReadResourceContents
|
||||
from mcp.shared.memory import (
|
||||
create_connected_server_and_client_session as client_session,
|
||||
)
|
||||
|
||||
pytestmark = pytest.mark.anyio
|
||||
|
||||
|
|
@ -48,7 +45,7 @@ async def test_relative_uri_roundtrip():
|
|||
)
|
||||
]
|
||||
|
||||
async with client_session(server) as client:
|
||||
async with Client(server) as client:
|
||||
# List should return the exact URIs we specified
|
||||
resources = await client.list_resources()
|
||||
uri_map = {r.uri: r for r in resources.resources}
|
||||
|
|
@ -83,7 +80,7 @@ async def test_custom_scheme_uri_roundtrip():
|
|||
async def read_resource(uri: str):
|
||||
return [ReadResourceContents(content="data", mime_type="text/plain")]
|
||||
|
||||
async with client_session(server) as client:
|
||||
async with Client(server) as client:
|
||||
resources = await client.list_resources()
|
||||
uri_map = {r.uri: r for r in resources.resources}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,10 +7,8 @@ with parameters like 'text/html;profile=mcp-app' which are valid per RFC 2045.
|
|||
import pytest
|
||||
from pydantic import AnyUrl
|
||||
|
||||
from mcp import Client
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
from mcp.shared.memory import (
|
||||
create_connected_server_and_client_session as client_session,
|
||||
)
|
||||
|
||||
pytestmark = pytest.mark.anyio
|
||||
|
||||
|
|
@ -63,7 +61,7 @@ async def test_mime_type_preserved_in_read_resource():
|
|||
def my_widget() -> str:
|
||||
return "<html><body>Hello MCP-UI</body></html>"
|
||||
|
||||
async with client_session(mcp._mcp_server) as client:
|
||||
async with Client(mcp) as client:
|
||||
# Read the resource
|
||||
result = await client.read_resource(AnyUrl("ui://my-widget"))
|
||||
assert len(result.contents) == 1
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import anyio
|
|||
import pytest
|
||||
from pydantic import AnyUrl
|
||||
|
||||
from mcp import Client
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
from mcp.shared.memory import create_connected_server_and_client_session as create_session
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
|
|
@ -30,7 +30,7 @@ async def test_messages_are_executed_concurrently_tools():
|
|||
call_order.append("trigger_end")
|
||||
return "slow"
|
||||
|
||||
async with create_session(server._mcp_server) as client_session:
|
||||
async with Client(server) as client_session:
|
||||
# First tool will wait on event, second will set it
|
||||
async with anyio.create_task_group() as tg:
|
||||
# Start the tool first (it will wait on event)
|
||||
|
|
@ -70,7 +70,7 @@ async def test_messages_are_executed_concurrently_tools_and_resources():
|
|||
call_order.append("resource_end")
|
||||
return "slow"
|
||||
|
||||
async with create_session(server._mcp_server) as client_session:
|
||||
async with Client(server) as client_session:
|
||||
# First tool will wait on event, second will set it
|
||||
async with anyio.create_task_group() as tg:
|
||||
# Start the tool first (it will wait on event)
|
||||
|
|
|
|||
Loading…
Reference in a new issue