Files
lda-wf/examples/mcp_tool_workflow.py
T

111 lines
3.5 KiB
Python

from __future__ import annotations
import asyncio
import sys
from pathlib import Path
from wf_core import END
from wf_mcp.broker import WfMcpService
from wf_mcp.models import ConnectionConfig, RawWorkflowPlan
from wf_mcp.sdk import McpSdkAdapter
from wf_mcp.storage import FileStore
FIXTURE_SERVER = (
Path(__file__).resolve().parents[1] / "tests" / "fixtures" / "mcp_echo_server.py"
)
async def run_example() -> dict[str, object]:
"""Discover an MCP tool, compile it into a workflow, and execute it."""
service = WfMcpService(store=FileStore(Path(".wf_mcp_store") / "example"))
service.register_connection(
ConnectionConfig(
id="fixture.personal",
server="fixture",
account="personal",
metadata={
"transport": "stdio",
"command": sys.executable,
"args": [str(FIXTURE_SERVER)],
},
)
)
service.register_adapter("fixture", McpSdkAdapter())
await service.refresh_connection_catalog("fixture.personal")
plan = RawWorkflowPlan.model_validate(
{
"name": "mcp_echo_workflow",
"input_schema": {
"type": "object",
"properties": {"text": {"type": "string"}},
"required": ["text"],
},
"state_schema": {
"type": "object",
"properties": {"echoed": {"type": "string"}},
},
"output_schema": {
"type": "object",
"properties": {"echoed": {"type": "string"}},
"required": ["echoed"],
},
"start": "echo",
"nodes": [
{
"id": "echo",
"type": "node",
"node": "fixture.personal.echo_tool",
"input": [
{
"target": {"root": "local", "parts": ["text"]},
"path": {"root": "input", "parts": ["text"]},
}
],
"output": [
{
"source": {"root": "local", "parts": ["echoed"]},
"target": {"root": "state", "parts": ["echoed"]},
}
],
},
{
"id": "raise_mcp_error",
"type": "node",
"node": "wf.std.runtime_error",
"input": [
{
"target": {"root": "local", "parts": ["message"]},
"path": {"root": "input", "parts": ["text"]},
}
],
"output": [],
},
],
"edges": [
{"from": "echo", "outcome": "ok", "to": END},
{"from": "echo", "outcome": "error", "to": "raise_mcp_error"},
{"from": "raise_mcp_error", "outcome": "ok", "to": END},
],
}
)
run = await service.run_workflow_from_plan(plan, {"text": "hello from MCP"})
return {
"status": run.status.value,
"output": run.output,
"catalog": service.get_catalog().as_payload(),
}
def main() -> None:
"""Run the MCP tool workflow example and print the result."""
import json
print(json.dumps(asyncio.run(run_example()), indent=2))
if __name__ == "__main__":
main()