style: reformat code style
Browse files- owl/run_mcp.py +8 -25
- owl/utils/mcp/mcp_servers_config.json +1 -5
- owl/utils/mcp/mcp_toolkit_manager.py +19 -10
owl/run_mcp.py
CHANGED
@@ -1,14 +1,11 @@
|
|
1 |
-
# run_mcp.py
|
2 |
-
|
3 |
import asyncio
|
4 |
-
import sys
|
5 |
from pathlib import Path
|
6 |
from typing import List
|
7 |
|
8 |
from dotenv import load_dotenv
|
9 |
|
10 |
from camel.models import ModelFactory
|
11 |
-
from camel.toolkits import
|
12 |
from camel.types import ModelPlatformType, ModelType
|
13 |
from camel.logger import set_log_level
|
14 |
|
@@ -25,11 +22,12 @@ async def construct_society(
|
|
25 |
question: str,
|
26 |
tools: List[FunctionTool],
|
27 |
) -> OwlRolePlaying:
|
|
|
|
|
|
|
|
|
|
|
28 |
"""
|
29 |
-
构建一个多Agent的OwlRolePlaying实例。
|
30 |
-
这里的tools已经是用户想交给assistant使用的全部Tool集合。
|
31 |
-
"""
|
32 |
-
# 1. 创建模型
|
33 |
models = {
|
34 |
"user": ModelFactory.create(
|
35 |
model_platform=ModelPlatformType.OPENAI,
|
@@ -43,20 +41,17 @@ async def construct_society(
|
|
43 |
),
|
44 |
}
|
45 |
|
46 |
-
# 2. 配置User和Assistant
|
47 |
user_agent_kwargs = {"model": models["user"]}
|
48 |
assistant_agent_kwargs = {
|
49 |
"model": models["assistant"],
|
50 |
-
"tools": tools,
|
51 |
}
|
52 |
|
53 |
-
# 3. 设置任务参数
|
54 |
task_kwargs = {
|
55 |
"task_prompt": question,
|
56 |
"with_task_specify": False,
|
57 |
}
|
58 |
|
59 |
-
# 4. 构造并返回OwlRolePlaying
|
60 |
society = OwlRolePlaying(
|
61 |
**task_kwargs,
|
62 |
user_role_name="user",
|
@@ -68,39 +63,27 @@ async def construct_society(
|
|
68 |
|
69 |
|
70 |
async def main():
|
71 |
-
# 准备MCP Servers
|
72 |
config_path = str(
|
73 |
Path(__file__).parent / "utils/mcp/mcp_servers_config.json"
|
74 |
)
|
75 |
|
76 |
manager = MCPToolkitManager.from_config(config_path)
|
77 |
|
78 |
-
# 示例问题
|
79 |
question = (
|
80 |
"I'd like a academic report about Guohao Li, including his research "
|
81 |
"direction, published papers (up to 20), institutions, etc."
|
82 |
"Then organize the report in Markdown format and save it to my desktop"
|
83 |
)
|
84 |
|
85 |
-
#
|
86 |
async with manager.connection():
|
87 |
-
# 这里 manager.is_connected() = True
|
88 |
-
# 获取合并后的tools
|
89 |
tools = manager.get_all_tools()
|
90 |
|
91 |
-
# 构造Society
|
92 |
society = await construct_society(question, tools)
|
93 |
|
94 |
-
# 运行对话
|
95 |
answer, chat_history, token_count = await run_society(society)
|
96 |
|
97 |
-
# 出了 with 块,这些toolkit就全部关闭
|
98 |
-
# manager.is_connected() = False
|
99 |
-
|
100 |
-
# 打印结果
|
101 |
print(f"\033[94mAnswer: {answer}\033[0m")
|
102 |
-
print("Chat History:", chat_history)
|
103 |
-
print("Token Count:", token_count)
|
104 |
|
105 |
|
106 |
if __name__ == "__main__":
|
|
|
|
|
|
|
1 |
import asyncio
|
|
|
2 |
from pathlib import Path
|
3 |
from typing import List
|
4 |
|
5 |
from dotenv import load_dotenv
|
6 |
|
7 |
from camel.models import ModelFactory
|
8 |
+
from camel.toolkits import FunctionTool
|
9 |
from camel.types import ModelPlatformType, ModelType
|
10 |
from camel.logger import set_log_level
|
11 |
|
|
|
22 |
question: str,
|
23 |
tools: List[FunctionTool],
|
24 |
) -> OwlRolePlaying:
|
25 |
+
r"""build a multi-agent OwlRolePlaying instance.
|
26 |
+
|
27 |
+
Args:
|
28 |
+
question (str): The question to ask.
|
29 |
+
tools (List[FunctionTool]): The MCP tools to use.
|
30 |
"""
|
|
|
|
|
|
|
|
|
31 |
models = {
|
32 |
"user": ModelFactory.create(
|
33 |
model_platform=ModelPlatformType.OPENAI,
|
|
|
41 |
),
|
42 |
}
|
43 |
|
|
|
44 |
user_agent_kwargs = {"model": models["user"]}
|
45 |
assistant_agent_kwargs = {
|
46 |
"model": models["assistant"],
|
47 |
+
"tools": tools,
|
48 |
}
|
49 |
|
|
|
50 |
task_kwargs = {
|
51 |
"task_prompt": question,
|
52 |
"with_task_specify": False,
|
53 |
}
|
54 |
|
|
|
55 |
society = OwlRolePlaying(
|
56 |
**task_kwargs,
|
57 |
user_role_name="user",
|
|
|
63 |
|
64 |
|
65 |
async def main():
|
|
|
66 |
config_path = str(
|
67 |
Path(__file__).parent / "utils/mcp/mcp_servers_config.json"
|
68 |
)
|
69 |
|
70 |
manager = MCPToolkitManager.from_config(config_path)
|
71 |
|
|
|
72 |
question = (
|
73 |
"I'd like a academic report about Guohao Li, including his research "
|
74 |
"direction, published papers (up to 20), institutions, etc."
|
75 |
"Then organize the report in Markdown format and save it to my desktop"
|
76 |
)
|
77 |
|
78 |
+
# Connect to all MCP toolkits
|
79 |
async with manager.connection():
|
|
|
|
|
80 |
tools = manager.get_all_tools()
|
81 |
|
|
|
82 |
society = await construct_society(question, tools)
|
83 |
|
|
|
84 |
answer, chat_history, token_count = await run_society(society)
|
85 |
|
|
|
|
|
|
|
|
|
86 |
print(f"\033[94mAnswer: {answer}\033[0m")
|
|
|
|
|
87 |
|
88 |
|
89 |
if __name__ == "__main__":
|
owl/utils/mcp/mcp_servers_config.json
CHANGED
@@ -12,9 +12,5 @@
|
|
12 |
"args": ["-m", "mcp_simple_arxiv"]
|
13 |
}
|
14 |
},
|
15 |
-
"mcpWebServers": {
|
16 |
-
"weather": {
|
17 |
-
"url": "https://c9a9-89-185-25-132.ngrok-free.app/sse"
|
18 |
-
}
|
19 |
-
}
|
20 |
}
|
|
|
12 |
"args": ["-m", "mcp_simple_arxiv"]
|
13 |
}
|
14 |
},
|
15 |
+
"mcpWebServers": {}
|
|
|
|
|
|
|
|
|
16 |
}
|
owl/utils/mcp/mcp_toolkit_manager.py
CHANGED
@@ -7,8 +7,12 @@ from contextlib import AsyncExitStack, asynccontextmanager
|
|
7 |
|
8 |
|
9 |
class MCPToolkitManager:
|
10 |
-
"""
|
11 |
-
|
|
|
|
|
|
|
|
|
12 |
"""
|
13 |
|
14 |
def __init__(self, toolkits: List[MCPToolkit]):
|
@@ -19,17 +23,21 @@ class MCPToolkitManager:
|
|
19 |
|
20 |
@staticmethod
|
21 |
def from_config(config_path: str) -> "MCPToolkitManager":
|
22 |
-
"""
|
|
|
|
|
|
|
|
|
23 |
|
24 |
-
:
|
25 |
-
|
26 |
"""
|
27 |
with open(config_path, "r", encoding="utf-8") as f:
|
28 |
data = json.load(f)
|
29 |
|
30 |
all_toolkits = []
|
31 |
|
32 |
-
#
|
33 |
mcp_servers = data.get("mcpServers", {})
|
34 |
for name, cfg in mcp_servers.items():
|
35 |
toolkit = MCPToolkit(
|
@@ -40,7 +48,7 @@ class MCPToolkitManager:
|
|
40 |
)
|
41 |
all_toolkits.append(toolkit)
|
42 |
|
43 |
-
#
|
44 |
mcp_web_servers = data.get("mcpWebServers", {})
|
45 |
for name, cfg in mcp_web_servers.items():
|
46 |
toolkit = MCPToolkit(
|
@@ -53,10 +61,10 @@ class MCPToolkitManager:
|
|
53 |
|
54 |
@asynccontextmanager
|
55 |
async def connection(self) -> AsyncGenerator["MCPToolkitManager", None]:
|
56 |
-
"""
|
|
|
57 |
self._exit_stack = AsyncExitStack()
|
58 |
try:
|
59 |
-
# 顺序进入每个 toolkit 的 async context
|
60 |
for tk in self.toolkits:
|
61 |
await self._exit_stack.enter_async_context(tk.connection())
|
62 |
self._connected = True
|
@@ -67,10 +75,11 @@ class MCPToolkitManager:
|
|
67 |
self._exit_stack = None
|
68 |
|
69 |
def is_connected(self) -> bool:
|
|
|
70 |
return self._connected
|
71 |
|
72 |
def get_all_tools(self):
|
73 |
-
"""
|
74 |
all_tools = []
|
75 |
for tk in self.toolkits:
|
76 |
all_tools.extend(tk.get_tools())
|
|
|
7 |
|
8 |
|
9 |
class MCPToolkitManager:
|
10 |
+
r"""MCPToolkitManager is a class for managing multiple MCPToolkit
|
11 |
+
instances and providing unified connection management.
|
12 |
+
|
13 |
+
Attributes:
|
14 |
+
toolkits (List[MCPToolkit]): A list of MCPToolkit instances to be
|
15 |
+
managed.
|
16 |
"""
|
17 |
|
18 |
def __init__(self, toolkits: List[MCPToolkit]):
|
|
|
23 |
|
24 |
@staticmethod
|
25 |
def from_config(config_path: str) -> "MCPToolkitManager":
|
26 |
+
r"""Loads an MCPToolkit instance from a JSON configuration file and
|
27 |
+
returns an MCPToolkitManager instance.
|
28 |
+
|
29 |
+
Args:
|
30 |
+
config_path (str): The path to the JSON configuration file.
|
31 |
|
32 |
+
Returns:
|
33 |
+
MCPToolkitManager: The MCPToolkitManager instance.
|
34 |
"""
|
35 |
with open(config_path, "r", encoding="utf-8") as f:
|
36 |
data = json.load(f)
|
37 |
|
38 |
all_toolkits = []
|
39 |
|
40 |
+
# "mcpServers" is the MCP server configuration running as stdio mode
|
41 |
mcp_servers = data.get("mcpServers", {})
|
42 |
for name, cfg in mcp_servers.items():
|
43 |
toolkit = MCPToolkit(
|
|
|
48 |
)
|
49 |
all_toolkits.append(toolkit)
|
50 |
|
51 |
+
# "mcpWebServers" is the MCP server configuration running as sse mode
|
52 |
mcp_web_servers = data.get("mcpWebServers", {})
|
53 |
for name, cfg in mcp_web_servers.items():
|
54 |
toolkit = MCPToolkit(
|
|
|
61 |
|
62 |
@asynccontextmanager
|
63 |
async def connection(self) -> AsyncGenerator["MCPToolkitManager", None]:
|
64 |
+
r"""Connect multiple MCPToolkit instances and close them when
|
65 |
+
leaving"""
|
66 |
self._exit_stack = AsyncExitStack()
|
67 |
try:
|
|
|
68 |
for tk in self.toolkits:
|
69 |
await self._exit_stack.enter_async_context(tk.connection())
|
70 |
self._connected = True
|
|
|
75 |
self._exit_stack = None
|
76 |
|
77 |
def is_connected(self) -> bool:
|
78 |
+
r"""Returns whether the MCPToolkitManager is connected."""
|
79 |
return self._connected
|
80 |
|
81 |
def get_all_tools(self):
|
82 |
+
r"""Returns all tools from all MCPToolkit instances."""
|
83 |
all_tools = []
|
84 |
for tk in self.toolkits:
|
85 |
all_tools.extend(tk.get_tools())
|