refactor: move mcp sdk protocols to wf_sources_mcp

This commit is contained in:
lda
2026-06-07 01:30:40 +07:00 Verified
parent 9bef0b0f63
commit 1385f935ca
21 changed files with 904 additions and 116 deletions
@@ -72,3 +72,31 @@ def test_wf_sources_mcp_does_not_import_wf_mcp_catalog_dtos() -> None:
"wf_sources_mcp still imports old wf_mcp catalog DTO modules:\n"
+ "\n".join(f" {violation}" for violation in violations)
)
def test_wf_sources_mcp_does_not_import_old_sdk_protocol_modules() -> None:
root = Path(__file__).resolve().parents[2] / "src" / "wf_sources_mcp"
forbidden = {
"wf_mcp.sdk",
"wf_mcp.sdk.base",
"wf_mcp.runtime",
"wf_mcp.runtime.protocols",
}
violations: list[str] = []
for py_file in sorted(root.rglob("*.py")):
rel = py_file.relative_to(root.parent)
module = str(rel.with_suffix("")).replace("/", ".").replace("\\", ".")
tree = ast.parse(py_file.read_text(encoding="utf-8"), filename=str(py_file))
for node in ast.walk(tree):
if isinstance(node, ast.ImportFrom) and node.module in forbidden:
violations.append(f"{module}:{node.lineno}: from {node.module} import ...")
elif isinstance(node, ast.Import):
for alias in node.names:
if alias.name in forbidden:
violations.append(f"{module}:{node.lineno}: import {alias.name}")
assert violations == [], (
"wf_sources_mcp still imports old wf_mcp SDK/runtime protocol modules:\n"
+ "\n".join(f" {violation}" for violation in violations)
)
@@ -0,0 +1,66 @@
from __future__ import annotations
from dataclasses import is_dataclass
from typing import cast
from wf_mcp.broker.models import ConnectionConfig
from wf_sources_mcp.auth import AuthRecord
from wf_sources_mcp.catalog import DiscoveredTool
from wf_sources_mcp.sdk import BackendAdapter, ToolCallResult, ToolExecutor
class EchoAdapter:
async def list_tools(
self,
connection: ConnectionConfig,
auth: AuthRecord | None,
) -> list[DiscoveredTool]:
return [
DiscoveredTool(
name="echo",
title=None,
description="Echo",
input_schema={"type": "object"},
output_schema={"type": "object"},
)
]
async def call_tool(
self,
connection: ConnectionConfig,
auth: AuthRecord | None,
tool_name: str,
payload: dict[str, object],
) -> ToolCallResult:
return ToolCallResult(outcome="ok", output={"echoed": payload})
def test_tool_call_result_is_slots_dataclass_with_empty_defaults() -> None:
result = ToolCallResult(outcome="ok")
assert is_dataclass(result)
assert result.output == {}
assert result.meta == {}
async def test_backend_adapter_protocol_can_describe_tool_listing() -> None:
adapter = cast(BackendAdapter, EchoAdapter())
tools = await adapter.list_tools(
ConnectionConfig(id="demo.default", server="demo", account="default"),
None,
)
assert tools[0].name == "echo"
async def test_tool_executor_protocol_can_describe_tool_calls() -> None:
executor = cast(ToolExecutor, EchoAdapter())
result = await executor.call_tool(
ConnectionConfig(id="demo.default", server="demo", account="default"),
None,
"echo",
{"message": "hello"},
)
assert result.outcome == "ok"
assert result.output == {"echoed": {"message": "hello"}}