Skip to content

Commit b83ca96

Browse files
committed
Add MCPTools for loading a subset of tools
1 parent 5b8460b commit b83ca96

File tree

6 files changed

+44
-17
lines changed

6 files changed

+44
-17
lines changed

coagent/agents/react_agent/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# ruff: noqa: F401
22
from .agent import ReActAgent
33
from .context import RunContext
4+
from .mcp import MCPTools
45
from .messages import InputMessage, InputHistory, OutputMessage
56
from .types import (
67
MessageOutputItem,

coagent/agents/react_agent/agent.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
MessageOutputItem,
3939
StreamEvent,
4040
)
41+
from .mcp import MCPTools
4142
from .messages import InputHistory, OutputMessage
4243
from ..model import default_model, Model
4344
from .converter import Converter
@@ -101,19 +102,19 @@ def model_settings(self) -> ModelSettings:
101102
async def started(self) -> None:
102103
final_tools: list[Callable] = []
103104

104-
mcp_clients: list[mcputil.Client] = []
105+
mcp_loaders: list[MCPTools] = []
105106
subagents: list[Subagent] = []
106107

107108
for tool in self._tools:
108-
if isinstance(tool, mcputil.Client):
109-
mcp_clients.append(tool)
109+
if isinstance(tool, MCPTools):
110+
mcp_loaders.append(tool)
110111
elif isinstance(tool, Subagent):
111112
subagents.append(tool)
112113
else:
113114
final_tools.append(tool)
114115

115-
# Load tools from MCP clients
116-
mcp_tools = await self._load_mcp_tools(mcp_clients)
116+
# Load tools from MCP loaders
117+
mcp_tools = await self._load_mcp_tools(mcp_loaders)
117118
final_tools.extend(mcp_tools)
118119

119120
# Create tools from subagents
@@ -124,22 +125,20 @@ async def started(self) -> None:
124125

125126
self._tools = final_tools
126127

127-
async def _load_mcp_tools(
128-
self, mcp_clients: list[mcputil.Client]
129-
) -> list[Callable]:
128+
async def _load_mcp_tools(self, mcp_loaders: list[MCPTools]) -> list[mcputil.Tool]:
130129
"""Load tools from all MCP clients concurrently."""
131130

132-
async def get_client_tools(client):
131+
async def load_tools(loader: MCPTools) -> list[mcputil.Tool]:
133132
try:
134-
return await client.get_tools()
133+
return await loader.load()
135134
except Exception as exc:
136135
# Log error but continue with empty tools list
137136
logger.error(f"Error getting tools from MCP client: {exc}")
138137
return []
139138

140139
# Fetch all tools concurrently and flatten the results
141140
all_mcp_tools = await asyncio.gather(
142-
*[get_client_tools(client) for client in mcp_clients]
141+
*[load_tools(loader) for loader in mcp_loaders]
143142
)
144143

145144
return [tool for sublist in all_mcp_tools for tool in sublist]

coagent/agents/react_agent/mcp.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from dataclasses import dataclass
2+
3+
import mcputil
4+
5+
6+
@dataclass
7+
class MCPTools:
8+
"""A loader for MCP tools. This class can be used to load a subset of tools from an MCP server."""
9+
10+
client: mcputil.Client
11+
"""The MCP client to use for loading the tools."""
12+
13+
include: list[str] | None = None
14+
"""The list of tool names to include. If None, all tools are included."""
15+
16+
exclude: list[str] | None = None
17+
"""The list of tool names to exclude. If None, no tools are excluded."""
18+
19+
async def load(self) -> list[mcputil.Tool]:
20+
return await self.client.get_tools(include=self.include, exclude=self.exclude)
21+
22+
async def connect(self) -> None:
23+
await self.client.connect()
24+
25+
async def close(self) -> None:
26+
await self.client.close()

examples/react-mcp/agent.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
InputMessage,
55
InputHistory,
66
OutputMessage,
7+
MCPTools,
78
MessageOutputItem,
89
ToolCallItem,
910
ToolCallOutputItem,
@@ -32,7 +33,7 @@ async def main():
3233
ReActAgent,
3334
name="reporter",
3435
system="You are a helpful weather reporter",
35-
tools=[mcp_client],
36+
tools=[MCPTools(mcp_client)],
3637
),
3738
)
3839
await runtime.register(reporter)

poetry.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ litellm = "1.60.4"
3838
mcp = ">=1.19.0"
3939
jinja2 = "3.1.5"
4040
aiorwlock = ">=1.5.0"
41-
mcputil = "0.2.0"
41+
mcputil = "0.3.0"
4242

4343
# A list of optional dependencies, which are included in the
4444
# below `extras`.

0 commit comments

Comments
 (0)