121 lines
4.5 KiB
Python
121 lines
4.5 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
|
|
import httpx
|
|
import pytest
|
|
|
|
from app.services.mcp_config.runtime import MicrosoftLearnMCPRuntime
|
|
|
|
|
|
def _sse(payload: dict) -> httpx.Response:
|
|
body = f"event: message\ndata: {json.dumps(payload, ensure_ascii=False)}\n\n"
|
|
return httpx.Response(
|
|
200,
|
|
headers={"content-type": "text/event-stream", "mcp-session-id": "test-session"},
|
|
text=body,
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_microsoft_learn_runtime_probe_initializes_and_lists_tools() -> None:
|
|
calls: list[dict] = []
|
|
|
|
def _handler(request: httpx.Request) -> httpx.Response:
|
|
payload = json.loads(request.content.decode("utf-8"))
|
|
calls.append(payload)
|
|
if payload["method"] == "initialize":
|
|
return _sse(
|
|
{
|
|
"jsonrpc": "2.0",
|
|
"id": payload["id"],
|
|
"result": {
|
|
"serverInfo": {"name": "Microsoft Learn MCP Server", "version": "1.0.0"},
|
|
},
|
|
}
|
|
)
|
|
if payload["method"] == "tools/list":
|
|
assert request.headers["mcp-session-id"] == "test-session"
|
|
return _sse(
|
|
{
|
|
"jsonrpc": "2.0",
|
|
"id": payload["id"],
|
|
"result": {
|
|
"tools": [
|
|
{"name": "microsoft_docs_search"},
|
|
{"name": "microsoft_docs_fetch"},
|
|
]
|
|
},
|
|
}
|
|
)
|
|
raise AssertionError(f"unexpected method: {payload['method']}")
|
|
|
|
runtime = MicrosoftLearnMCPRuntime(
|
|
endpoint_url="https://learn.microsoft.com/api/mcp",
|
|
client_factory=lambda: httpx.AsyncClient(transport=httpx.MockTransport(_handler)),
|
|
)
|
|
|
|
probe = await runtime.probe()
|
|
|
|
assert probe["status"] == "ready"
|
|
assert probe["tool_names"] == ["microsoft_docs_search", "microsoft_docs_fetch"]
|
|
assert [item["method"] for item in calls] == ["initialize", "tools/list"]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_microsoft_learn_runtime_search_returns_external_evidence() -> None:
|
|
def _handler(request: httpx.Request) -> httpx.Response:
|
|
payload = json.loads(request.content.decode("utf-8"))
|
|
if payload["method"] == "initialize":
|
|
return _sse(
|
|
{
|
|
"jsonrpc": "2.0",
|
|
"id": payload["id"],
|
|
"result": {
|
|
"serverInfo": {"name": "Microsoft Learn MCP Server", "version": "1.0.0"},
|
|
},
|
|
}
|
|
)
|
|
if payload["method"] == "tools/call":
|
|
assert payload["params"]["name"] == "microsoft_docs_search"
|
|
assert payload["params"]["arguments"]["query"] == "azure openai quickstart"
|
|
return _sse(
|
|
{
|
|
"jsonrpc": "2.0",
|
|
"id": payload["id"],
|
|
"result": {
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": json.dumps(
|
|
{
|
|
"results": [
|
|
{
|
|
"title": "Quickstart: Azure OpenAI",
|
|
"content": "Use Azure OpenAI with official quickstart guidance.",
|
|
"contentUrl": "https://learn.microsoft.com/azure/ai-foundry/openai/chatgpt-quickstart",
|
|
}
|
|
]
|
|
},
|
|
ensure_ascii=False,
|
|
),
|
|
}
|
|
]
|
|
},
|
|
}
|
|
)
|
|
raise AssertionError(f"unexpected method: {payload['method']}")
|
|
|
|
runtime = MicrosoftLearnMCPRuntime(
|
|
endpoint_url="https://learn.microsoft.com/api/mcp",
|
|
client_factory=lambda: httpx.AsyncClient(transport=httpx.MockTransport(_handler)),
|
|
)
|
|
|
|
evidence = await runtime.search(query="azure openai quickstart", result_limit=3)
|
|
|
|
assert len(evidence) == 1
|
|
assert evidence[0].source_type == "mcp_search"
|
|
assert evidence[0].title == "Quickstart: Azure OpenAI"
|
|
assert evidence[0].target_url == "https://learn.microsoft.com/azure/ai-foundry/openai/chatgpt-quickstart"
|
|
assert evidence[0].authority_score >= 0.9
|