-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathmcp_agent.py
More file actions
139 lines (113 loc) · 4.12 KB
/
mcp_agent.py
File metadata and controls
139 lines (113 loc) · 4.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
"""
Demonstrates MCP server integration via MCPSkillAdapter.
This example shows how to:
1. Initialize an MCP client with a mock transport (to avoid external dependencies).
2. Wrap the MCP client in an MCPSkillAdapter.
3. Install the adapter as a Skill into the agent's world.
4. Verify that MCP tools are correctly namespaced and accessible.
"""
import asyncio
import json
from typing import Any
from ecs_agent import SkillManager
from ecs_agent.components import ConversationComponent, LLMComponent
from ecs_agent.core import Runner, World
from ecs_agent.providers import FakeProvider
from ecs_agent.systems.reasoning import ReasoningSystem
from ecs_agent.systems.tool_execution import ToolExecutionSystem
from ecs_agent.types import CompletionResult, Message, ToolCall
# Check if MCP is available
try:
from ecs_agent.mcp.adapter import MCPSkillAdapter
from ecs_agent.mcp.client import MCPClient
from ecs_agent.mcp.components import MCPConfigComponent
HAS_MCP = True
except ImportError:
HAS_MCP = False
class MockMCPClient:
"""A mock MCP client that simulates server behavior for demonstration."""
def __init__(self, config: Any) -> None:
self.server_name = config.server_name
self.is_connected = False
async def connect(self) -> None:
self.is_connected = True
async def disconnect(self) -> None:
self.is_connected = False
async def list_tools(self) -> list[dict[str, Any]]:
return [
{
"name": "get_weather",
"description": "Get current weather for a city.",
"inputSchema": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
}
]
async def call_tool(self, name: str, args: dict[str, Any]) -> str:
if name == "get_weather":
city = args.get("city", "unknown")
return f"The weather in {city} is sunny, 22°C."
return "Unknown tool"
async def main() -> None:
if not HAS_MCP:
print("MCP dependencies not found. Install with: uv pip install -e '.[mcp]'")
return
world = World()
agent = world.create_entity()
# 1. Setup Mock MCP Infrastructure
config = MCPConfigComponent(
server_name="weather-service",
transport_type="stdio",
config={"command": "mock"},
)
mock_client = MockMCPClient(config)
# 2. Wrap in Adapter
skill = MCPSkillAdapter(mock_client, server_name="weather-service") # type: ignore[arg-type]
# 3. Setup Agent and Systems
provider = FakeProvider(
responses=[
CompletionResult(
message=Message(
role="assistant",
content="Checking weather...",
tool_calls=[
ToolCall(
id="call_weather",
name="weather-service/get_weather",
arguments={"city": "San Francisco"},
)
],
)
),
CompletionResult(
message=Message(
role="assistant", content="It's sunny in San Francisco!"
)
),
]
)
world.add_component(agent, LLMComponent(provider=provider, model="fake"))
world.add_component(
agent,
ConversationComponent(
messages=[Message(role="user", content="How is the weather in SF?")]
),
)
# 4. Install MCP Skill
manager = SkillManager()
manager.install(world, agent, skill)
world.register_system(ReasoningSystem(), priority=0)
world.register_system(ToolExecutionSystem(), priority=5)
# 5. Run loop
print("Starting MCP agent demo...")
runner = Runner()
await runner.run(world, max_ticks=5)
# Verify that the tool was called and results captured
conv = world.get_component(agent, ConversationComponent)
if conv:
for msg in conv.messages:
print(f"{msg.role}: {msg.content}")
if __name__ == "__main__":
asyncio.run(main())