mirror of
https://github.com/mcloh/Enterprise-MCP-Service-Bus.git
synced 2026-11-05 22:14:11 +00:00
82 lines
2.5 KiB
Python
82 lines
2.5 KiB
Python
"""Contract tests connect directly to a domain server -- never through the
|
|
Gateway -- because a tool's input/output contract is a property of the
|
|
domain server itself (ADR-023: it's "dumb" about authorization, but not
|
|
about its own data shape), independent of who is or isn't entitled to call
|
|
it. Reuses `RunningServer`/`free_port` from the e2e suite rather than
|
|
duplicating them.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import AsyncIterator
|
|
from typing import Any
|
|
|
|
import mcp_types as types
|
|
import pytest
|
|
import uvicorn
|
|
from mcp.client.session import ClientSession
|
|
from mcp.client.streamable_http import ( # type: ignore[attr-defined]
|
|
create_mcp_http_client,
|
|
streamable_http_client,
|
|
)
|
|
|
|
from tests.e2e.conftest import RunningServer, free_port
|
|
|
|
|
|
async def call_tool_directly(
|
|
server_url: str, tool_name: str, arguments: dict[str, Any]
|
|
) -> types.CallToolResult:
|
|
"""No auth header at all -- these servers are `main()`-unwrapped here
|
|
(no `BackendCredentialGate`), matching how the rest of the e2e suite
|
|
already constructs them for in-process tests."""
|
|
async with (
|
|
create_mcp_http_client() as http_client,
|
|
streamable_http_client(server_url, http_client=http_client) as (read, write),
|
|
ClientSession(read, write) as session,
|
|
):
|
|
await session.initialize()
|
|
result = await session.call_tool(tool_name, arguments)
|
|
if not isinstance(result, types.CallToolResult):
|
|
raise TypeError(f"Unexpected result type: {type(result)!r}")
|
|
return result
|
|
|
|
|
|
@pytest.fixture
|
|
async def sales_domain_url() -> AsyncIterator[str]:
|
|
import example_mcp_servers.sales_domain.server as sales_module
|
|
|
|
port = free_port()
|
|
server = RunningServer(
|
|
uvicorn.Config(
|
|
sales_module.server.streamable_http_app(host="127.0.0.1"),
|
|
host="127.0.0.1",
|
|
port=port,
|
|
log_level="warning",
|
|
)
|
|
)
|
|
await server.start()
|
|
try:
|
|
yield f"http://127.0.0.1:{port}/mcp"
|
|
finally:
|
|
await server.stop()
|
|
|
|
|
|
@pytest.fixture
|
|
async def finance_domain_url() -> AsyncIterator[str]:
|
|
import example_mcp_servers.finance_domain.server as finance_module
|
|
|
|
port = free_port()
|
|
server = RunningServer(
|
|
uvicorn.Config(
|
|
finance_module.server.streamable_http_app(host="127.0.0.1"),
|
|
host="127.0.0.1",
|
|
port=port,
|
|
log_level="warning",
|
|
)
|
|
)
|
|
await server.start()
|
|
try:
|
|
yield f"http://127.0.0.1:{port}/mcp"
|
|
finally:
|
|
await server.stop()
|