1111# See the License for the specific language governing permissions and
1212# limitations under the License.
1313# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14+ """MCP Multi-Agent System Example
15+
16+ This example demonstrates how to use MCP (Model Context Protocol) with CAMEL agents
17+ for advanced information retrieval and processing tasks.
18+
19+ Environment Setup:
20+ 1. Configure the required dependencies of owl library
21+ Refer to: https://github.com/camel-ai/owl for installation guide
22+
23+ 2. MCP Server Setup:
24+
25+
26+ 2.1 MCP Playwright Service:
27+ ```bash
28+ # Install MCP service
29+ npm install -g @executeautomation/playwright-mcp-server
30+ npx playwright install-deps
31+
32+ # Configure in mcp_servers_config.json:
33+ {
34+ "mcpServers": {
35+ "playwright": {
36+ "command": "npx",
37+ "args": ["-y", "@executeautomation/playwright-mcp-server"]
38+ }
39+ }
40+ }
41+ ```
42+
43+ 2.2 MCP Fetch Service (Optional - for better retrieval):
44+ ```bash
45+ # Install MCP service
46+ pip install mcp-server-fetch
47+
48+ # Configure in mcp_servers_config.json:
49+ {
50+ "mcpServers": {
51+ "fetch": {
52+ "command": "python",
53+ "args": ["-m", "mcp_server_fetch"]
54+ }
55+ }
56+ }
57+ ```
58+
59+ Usage:
60+ 1. Ensure all MCP servers are properly configured in mcp_servers_config.json
61+ 2. Run this script to create a multi-agent system that can:
62+ - Access and manipulate files through MCP Desktop Commander
63+ - Perform web automation tasks using Playwright
64+ - Process and generate information using Mistral
65+ - Fetch web content (if fetch service is configured)
66+ 3. The system will execute the specified task while maintaining security through
67+ controlled access
68+
69+ Note:
70+ - All file operations are restricted to configured directories
71+ - Supports asynchronous operations for efficient processing
72+ """
73+
74+ import asyncio
1475import sys
15- import pathlib
76+ from pathlib import Path
77+ from typing import List
78+
1679from dotenv import load_dotenv
80+
1781from camel .models import ModelFactory
18- from camel .toolkits import (
19- AudioAnalysisToolkit ,
20- CodeExecutionToolkit ,
21- ExcelToolkit ,
22- ImageAnalysisToolkit ,
23- SearchToolkit ,
24- VideoAnalysisToolkit ,
25- BrowserToolkit ,
26- FileWriteToolkit ,
27- )
82+ from camel .toolkits import FunctionTool
2883from camel .types import ModelPlatformType , ModelType
2984from camel .logger import set_log_level
85+ from camel .toolkits import MCPToolkit
3086from camel .societies import RolePlaying
3187
32- from owl .utils import run_society , DocumentProcessingToolkit
88+ from owl .utils .enhanced_role_playing import arun_society
89+
90+ import pathlib
3391
3492base_dir = pathlib .Path (__file__ ).parent .parent
3593env_path = base_dir / "owl" / ".env"
3896set_log_level (level = "DEBUG" )
3997
4098
41- def construct_society (question : str ) -> RolePlaying :
42- r"""Construct a society of agents based on Mistral model(s).
99+ async def construct_society (
100+ question : str ,
101+ tools : List [FunctionTool ],
102+ ) -> RolePlaying :
103+ r"""build a multi-agent RolePlaying instance.
43104
44105 Args:
45- question (str): The task or question to be addressed by the society.
46-
47- Returns:
48- RolePlaying: A configured society of agents ready to address the question.
106+ question (str): The question to ask.
107+ tools (List[FunctionTool]): The MCP tools to use.
49108 """
50-
51- # Create models for different components
52109 models = {
53110 "user" : ModelFactory .create (
54111 model_platform = ModelPlatformType .MISTRAL ,
@@ -60,89 +117,60 @@ def construct_society(question: str) -> RolePlaying:
60117 model_type = ModelType .MISTRAL_LARGE ,
61118 model_config_dict = {"temperature" : 0 },
62119 ),
63- "browsing" : ModelFactory .create (
64- model_platform = ModelPlatformType .MISTRAL ,
65- model_type = ModelType .MISTRAL_LARGE ,
66- model_config_dict = {"temperature" : 0 },
67- ),
68- "planning" : ModelFactory .create (
69- model_platform = ModelPlatformType .MISTRAL ,
70- model_type = ModelType .MISTRAL_LARGE ,
71- model_config_dict = {"temperature" : 0 },
72- ),
73- "video" : ModelFactory .create (
74- model_platform = ModelPlatformType .MISTRAL ,
75- model_type = ModelType .MISTRAL_PIXTRAL_12B ,
76- model_config_dict = {"temperature" : 0 },
77- ),
78- "image" : ModelFactory .create (
79- model_platform = ModelPlatformType .MISTRAL ,
80- model_type = ModelType .MISTRAL_PIXTRAL_12B ,
81- model_config_dict = {"temperature" : 0 },
82- ),
83- "document" : ModelFactory .create (
84- model_platform = ModelPlatformType .MISTRAL ,
85- model_type = ModelType .MISTRAL_LARGE ,
86- model_config_dict = {"temperature" : 0 },
87- ),
88120 }
89121
90- # Configure toolkits
91- tools = [
92- * BrowserToolkit (
93- headless = True ,
94- web_agent_model = models ["browsing" ],
95- planning_agent_model = models ["planning" ],
96- ).get_tools (),
97- * VideoAnalysisToolkit (model = models ["video" ]).get_tools (),
98- * AudioAnalysisToolkit ().get_tools (),
99- * CodeExecutionToolkit (sandbox = "subprocess" , verbose = True ).get_tools (),
100- * ImageAnalysisToolkit (model = models ["image" ]).get_tools (),
101- SearchToolkit ().search_duckduckgo ,
102- SearchToolkit ().search_google ,
103- SearchToolkit ().search_wiki ,
104- * ExcelToolkit ().get_tools (),
105- * DocumentProcessingToolkit (model = models ["document" ]).get_tools (),
106- * FileWriteToolkit (output_dir = "./" ).get_tools (),
107- ]
108-
109- # Configure agent roles and parameters
110122 user_agent_kwargs = {"model" : models ["user" ]}
111- assistant_agent_kwargs = {"model" : models ["assistant" ], "tools" : tools }
123+ assistant_agent_kwargs = {
124+ "model" : models ["assistant" ],
125+ "tools" : tools ,
126+ }
112127
113- # Configure task parameters
114128 task_kwargs = {
115129 "task_prompt" : question ,
116130 "with_task_specify" : False ,
117131 }
118132
119- # Create and return the society
120133 society = RolePlaying (
121134 ** task_kwargs ,
122135 user_role_name = "user" ,
123136 user_agent_kwargs = user_agent_kwargs ,
124137 assistant_role_name = "assistant" ,
125138 assistant_agent_kwargs = assistant_agent_kwargs ,
126139 )
127-
128140 return society
129141
130142
131- def main ():
132- r"""Main function to run the OWL system with an example question."""
133- # Default research question
134- default_task = "Open Brave search, summarize the github stars, fork counts, etc. of camel-ai's camel framework, and write the numbers into a python file using the plot package, save it locally, and run the generated python file. Note: You have been provided with the necessary tools to complete this task."
143+ async def main ():
144+ config_path = Path (__file__ ).parent / "mcp_servers_config.json"
145+ mcp_toolkit = MCPToolkit (config_path = str (config_path ))
146+
147+ try :
148+ await mcp_toolkit .connect ()
149+
150+ # Default task
151+ default_task = (
152+ "I'd like a academic report about Andrew Ng, including "
153+ "his research direction, published papers (At least 3), "
154+ "institutions, etc. You have been provided with tools to do "
155+ "browser operation. Open browser to finish the task."
156+ )
135157
136- # Override default task if command line argument is provided
137- task = sys .argv [1 ] if len (sys .argv ) > 1 else default_task
158+ # Override default task if command line argument is provided
159+ task = sys .argv [1 ] if len (sys .argv ) > 1 else default_task
138160
139- # Construct and run the society
140- society = construct_society (task )
141- answer , chat_history , token_count = run_society (society )
161+ # Connect to all MCP toolkits
162+ tools = [* mcp_toolkit .get_tools ()]
163+ society = await construct_society (task , tools )
164+ answer , chat_history , token_count = await arun_society (society )
165+ print (f"\033 [94mAnswer: { answer } \033 [0m" )
142166
143- # Output the result
144- print (f"\033 [94mAnswer: { answer } \033 [0m" )
167+ finally :
168+ # Make sure to disconnect safely after all operations are completed.
169+ try :
170+ await mcp_toolkit .disconnect ()
171+ except Exception :
172+ print ("Disconnect failed" )
145173
146174
147175if __name__ == "__main__" :
148- main ()
176+ asyncio . run ( main () )
0 commit comments