camel-ai 0.2.38__py3-none-any.whl → 0.2.39__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of camel-ai might be problematic. Click here for more details.
- camel/__init__.py +1 -1
- camel/agents/chat_agent.py +4 -0
- camel/agents/repo_agent.py +2 -2
- camel/benchmarks/apibank.py +1 -1
- camel/benchmarks/apibench.py +1 -1
- camel/configs/__init__.py +3 -0
- camel/configs/modelscope_config.py +59 -0
- camel/datagen/self_improving_cot.py +1 -1
- camel/datasets/__init__.py +2 -0
- camel/datasets/base_generator.py +22 -9
- camel/datasets/few_shot_generator.py +2 -3
- camel/datasets/self_instruct_generator.py +415 -0
- camel/embeddings/openai_compatible_embedding.py +13 -5
- camel/environments/models.py +1 -1
- camel/environments/single_step.py +155 -89
- camel/interpreters/docker_interpreter.py +1 -1
- camel/interpreters/internal_python_interpreter.py +1 -1
- camel/loaders/unstructured_io.py +2 -1
- camel/memories/blocks/chat_history_block.py +1 -1
- camel/memories/context_creators/score_based.py +2 -2
- camel/models/__init__.py +2 -0
- camel/models/model_factory.py +119 -0
- camel/models/modelscope_model.py +208 -0
- camel/models/openai_audio_models.py +2 -2
- camel/models/openai_model.py +49 -2
- camel/models/togetherai_model.py +2 -2
- camel/models/vllm_model.py +1 -1
- camel/models/zhipuai_model.py +2 -2
- camel/retrievers/vector_retriever.py +1 -1
- camel/storages/graph_storages/neo4j_graph.py +1 -1
- camel/storages/vectordb_storages/base.py +2 -2
- camel/storages/vectordb_storages/milvus.py +2 -2
- camel/storages/vectordb_storages/qdrant.py +2 -2
- camel/tasks/task.py +2 -2
- camel/toolkits/__init__.py +4 -1
- camel/toolkits/arxiv_toolkit.py +2 -1
- camel/toolkits/ask_news_toolkit.py +11 -3
- camel/toolkits/audio_analysis_toolkit.py +2 -0
- camel/toolkits/base.py +3 -0
- camel/toolkits/code_execution.py +3 -1
- camel/toolkits/dappier_toolkit.py +2 -1
- camel/toolkits/data_commons_toolkit.py +2 -0
- camel/toolkits/excel_toolkit.py +2 -0
- camel/toolkits/file_write_toolkit.py +2 -0
- camel/toolkits/github_toolkit.py +6 -4
- camel/toolkits/google_scholar_toolkit.py +2 -0
- camel/toolkits/human_toolkit.py +17 -1
- camel/toolkits/image_analysis_toolkit.py +2 -0
- camel/toolkits/linkedin_toolkit.py +2 -1
- camel/toolkits/math_toolkit.py +2 -0
- camel/toolkits/mcp_toolkit.py +42 -52
- camel/toolkits/meshy_toolkit.py +20 -2
- camel/toolkits/networkx_toolkit.py +2 -0
- camel/toolkits/notion_toolkit.py +7 -0
- camel/toolkits/openbb_toolkit.py +2 -1
- camel/toolkits/pubmed_toolkit.py +2 -0
- camel/toolkits/reddit_toolkit.py +2 -1
- camel/toolkits/retrieval_toolkit.py +2 -1
- camel/toolkits/search_toolkit.py +2 -1
- camel/toolkits/semantic_scholar_toolkit.py +2 -0
- camel/toolkits/slack_toolkit.py +2 -0
- camel/toolkits/stripe_toolkit.py +2 -1
- camel/toolkits/sympy_toolkit.py +2 -0
- camel/toolkits/terminal_toolkit.py +2 -0
- camel/toolkits/twitter_toolkit.py +2 -1
- camel/toolkits/video_analysis_toolkit.py +2 -1
- camel/toolkits/video_download_toolkit.py +2 -1
- camel/toolkits/weather_toolkit.py +2 -0
- camel/toolkits/whatsapp_toolkit.py +2 -1
- camel/toolkits/zapier_toolkit.py +2 -1
- camel/types/enums.py +65 -0
- camel/types/unified_model_type.py +5 -0
- camel/utils/__init__.py +2 -0
- camel/utils/chunker/code_chunker.py +9 -9
- camel/utils/commons.py +50 -30
- camel/utils/constants.py +2 -2
- camel/utils/mcp.py +79 -0
- camel/verifiers/__init__.py +2 -0
- camel/verifiers/base.py +15 -15
- camel/verifiers/math_verifier.py +182 -0
- camel/verifiers/python_verifier.py +18 -26
- {camel_ai-0.2.38.dist-info → camel_ai-0.2.39.dist-info}/METADATA +3 -1
- {camel_ai-0.2.38.dist-info → camel_ai-0.2.39.dist-info}/RECORD +85 -80
- {camel_ai-0.2.38.dist-info → camel_ai-0.2.39.dist-info}/WHEEL +0 -0
- {camel_ai-0.2.38.dist-info → camel_ai-0.2.39.dist-info}/licenses/LICENSE +0 -0
camel/toolkits/github_toolkit.py
CHANGED
|
@@ -18,11 +18,12 @@ from typing import Dict, List, Literal, Optional, Union
|
|
|
18
18
|
|
|
19
19
|
from camel.toolkits import FunctionTool
|
|
20
20
|
from camel.toolkits.base import BaseToolkit
|
|
21
|
-
from camel.utils import dependencies_required
|
|
21
|
+
from camel.utils import MCPServer, dependencies_required
|
|
22
22
|
|
|
23
23
|
logger = logging.getLogger(__name__)
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
@MCPServer()
|
|
26
27
|
class GithubToolkit(BaseToolkit):
|
|
27
28
|
r"""A class representing a toolkit for interacting with GitHub
|
|
28
29
|
repositories.
|
|
@@ -53,12 +54,13 @@ class GithubToolkit(BaseToolkit):
|
|
|
53
54
|
`get_github_access_token` method.
|
|
54
55
|
"""
|
|
55
56
|
super().__init__(timeout=timeout)
|
|
56
|
-
from github import
|
|
57
|
+
from github.Auth import Token
|
|
58
|
+
from github.MainClass import Github
|
|
57
59
|
|
|
58
60
|
if access_token is None:
|
|
59
61
|
access_token = self.get_github_access_token()
|
|
60
62
|
|
|
61
|
-
self.github = Github(auth=
|
|
63
|
+
self.github = Github(auth=Token(access_token))
|
|
62
64
|
self.repo = self.github.get_repo(repo_name)
|
|
63
65
|
|
|
64
66
|
def get_github_access_token(self) -> str:
|
|
@@ -110,7 +112,7 @@ class GithubToolkit(BaseToolkit):
|
|
|
110
112
|
successfully or not.
|
|
111
113
|
"""
|
|
112
114
|
sb = self.repo.get_branch(self.repo.default_branch)
|
|
113
|
-
from github import GithubException
|
|
115
|
+
from github.GithubException import GithubException
|
|
114
116
|
|
|
115
117
|
try:
|
|
116
118
|
self.repo.create_git_ref(
|
|
@@ -16,8 +16,10 @@ from typing import Any, Dict, List, Optional
|
|
|
16
16
|
|
|
17
17
|
from camel.toolkits import FunctionTool
|
|
18
18
|
from camel.toolkits.base import BaseToolkit
|
|
19
|
+
from camel.utils import MCPServer
|
|
19
20
|
|
|
20
21
|
|
|
22
|
+
@MCPServer()
|
|
21
23
|
class GoogleScholarToolkit(BaseToolkit):
|
|
22
24
|
r"""A toolkit for retrieving information about authors and their
|
|
23
25
|
publications from Google Scholar.
|
camel/toolkits/human_toolkit.py
CHANGED
|
@@ -39,6 +39,19 @@ class HumanToolkit(BaseToolkit):
|
|
|
39
39
|
logger.info(f"User reply: {reply}")
|
|
40
40
|
return reply
|
|
41
41
|
|
|
42
|
+
def send_message_to_user(self, message: str) -> None:
|
|
43
|
+
r"""Send a message to the user, without waiting for
|
|
44
|
+
a response. This will send to stdout in a noticeable way.
|
|
45
|
+
|
|
46
|
+
This is guaranteed to reach the user regardless of
|
|
47
|
+
actual user interface.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
message (str): The message to send to the user.
|
|
51
|
+
"""
|
|
52
|
+
print(f"\nAgent Message:\n{message}")
|
|
53
|
+
logger.info(f"\nAgent Message:\n{message}")
|
|
54
|
+
|
|
42
55
|
def get_tools(self) -> List[FunctionTool]:
|
|
43
56
|
r"""Returns a list of FunctionTool objects representing the
|
|
44
57
|
functions in the toolkit.
|
|
@@ -47,4 +60,7 @@ class HumanToolkit(BaseToolkit):
|
|
|
47
60
|
List[FunctionTool]: A list of FunctionTool objects
|
|
48
61
|
representing the functions in the toolkit.
|
|
49
62
|
"""
|
|
50
|
-
return [
|
|
63
|
+
return [
|
|
64
|
+
FunctionTool(self.ask_human_via_console),
|
|
65
|
+
FunctionTool(self.send_message_to_user),
|
|
66
|
+
]
|
|
@@ -25,10 +25,12 @@ from camel.models import BaseModelBackend, ModelFactory
|
|
|
25
25
|
from camel.toolkits import FunctionTool
|
|
26
26
|
from camel.toolkits.base import BaseToolkit
|
|
27
27
|
from camel.types import ModelPlatformType, ModelType
|
|
28
|
+
from camel.utils import MCPServer
|
|
28
29
|
|
|
29
30
|
logger = get_logger(__name__)
|
|
30
31
|
|
|
31
32
|
|
|
33
|
+
@MCPServer()
|
|
32
34
|
class ImageAnalysisToolkit(BaseToolkit):
|
|
33
35
|
r"""A toolkit for comprehensive image analysis and understanding.
|
|
34
36
|
The toolkit uses vision-capable language models to perform these tasks.
|
|
@@ -21,11 +21,12 @@ import requests
|
|
|
21
21
|
|
|
22
22
|
from camel.toolkits import FunctionTool
|
|
23
23
|
from camel.toolkits.base import BaseToolkit
|
|
24
|
-
from camel.utils import handle_http_error
|
|
24
|
+
from camel.utils import MCPServer, handle_http_error
|
|
25
25
|
|
|
26
26
|
LINKEDIN_POST_LIMIT = 1300
|
|
27
27
|
|
|
28
28
|
|
|
29
|
+
@MCPServer()
|
|
29
30
|
class LinkedInToolkit(BaseToolkit):
|
|
30
31
|
r"""A class representing a toolkit for LinkedIn operations.
|
|
31
32
|
|
camel/toolkits/math_toolkit.py
CHANGED
|
@@ -16,8 +16,10 @@ from typing import List
|
|
|
16
16
|
|
|
17
17
|
from camel.toolkits.base import BaseToolkit
|
|
18
18
|
from camel.toolkits.function_tool import FunctionTool
|
|
19
|
+
from camel.utils import MCPServer
|
|
19
20
|
|
|
20
21
|
|
|
22
|
+
@MCPServer()
|
|
21
23
|
class MathToolkit(BaseToolkit):
|
|
22
24
|
r"""A class representing a toolkit for mathematical operations.
|
|
23
25
|
|
camel/toolkits/mcp_toolkit.py
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import inspect
|
|
15
15
|
import json
|
|
16
16
|
import os
|
|
17
|
+
import shlex
|
|
17
18
|
from contextlib import AsyncExitStack, asynccontextmanager
|
|
18
19
|
from typing import (
|
|
19
20
|
TYPE_CHECKING,
|
|
@@ -25,11 +26,12 @@ from typing import (
|
|
|
25
26
|
Optional,
|
|
26
27
|
Set,
|
|
27
28
|
Union,
|
|
29
|
+
cast,
|
|
28
30
|
)
|
|
29
31
|
from urllib.parse import urlparse
|
|
30
32
|
|
|
31
33
|
if TYPE_CHECKING:
|
|
32
|
-
from mcp import ListToolsResult, Tool
|
|
34
|
+
from mcp import ClientSession, ListToolsResult, Tool
|
|
33
35
|
|
|
34
36
|
from camel.logger import get_logger
|
|
35
37
|
from camel.toolkits import BaseToolkit, FunctionTool
|
|
@@ -37,7 +39,7 @@ from camel.toolkits import BaseToolkit, FunctionTool
|
|
|
37
39
|
logger = get_logger(__name__)
|
|
38
40
|
|
|
39
41
|
|
|
40
|
-
class
|
|
42
|
+
class MCPClient(BaseToolkit):
|
|
41
43
|
r"""Internal class that provides an abstraction layer to interact with
|
|
42
44
|
external tools using the Model Context Protocol (MCP). It supports two
|
|
43
45
|
modes of connection:
|
|
@@ -69,7 +71,6 @@ class _MCPServer(BaseToolkit):
|
|
|
69
71
|
headers: Optional[Dict[str, str]] = None,
|
|
70
72
|
):
|
|
71
73
|
from mcp import Tool
|
|
72
|
-
from mcp.client.session import ClientSession
|
|
73
74
|
|
|
74
75
|
super().__init__(timeout=timeout)
|
|
75
76
|
|
|
@@ -87,7 +88,7 @@ class _MCPServer(BaseToolkit):
|
|
|
87
88
|
r"""Explicitly connect to the MCP server.
|
|
88
89
|
|
|
89
90
|
Returns:
|
|
90
|
-
|
|
91
|
+
MCPClient: The client used to connect to the server.
|
|
91
92
|
"""
|
|
92
93
|
from mcp.client.session import ClientSession
|
|
93
94
|
from mcp.client.sse import sse_client
|
|
@@ -110,11 +111,20 @@ class _MCPServer(BaseToolkit):
|
|
|
110
111
|
)
|
|
111
112
|
else:
|
|
112
113
|
command = self.command_or_url
|
|
114
|
+
arguments = self.args
|
|
115
|
+
if not self.args:
|
|
116
|
+
argv = shlex.split(command)
|
|
117
|
+
if not argv:
|
|
118
|
+
raise ValueError("Command is empty")
|
|
119
|
+
|
|
120
|
+
command = argv[0]
|
|
121
|
+
arguments = argv[1:]
|
|
122
|
+
|
|
113
123
|
if os.name == "nt" and command.lower() == "npx":
|
|
114
124
|
command = "npx.cmd"
|
|
115
125
|
|
|
116
126
|
server_parameters = StdioServerParameters(
|
|
117
|
-
command=command, args=
|
|
127
|
+
command=command, args=arguments, env=self.env
|
|
118
128
|
)
|
|
119
129
|
(
|
|
120
130
|
read_stream,
|
|
@@ -135,6 +145,7 @@ class _MCPServer(BaseToolkit):
|
|
|
135
145
|
# Ensure resources are cleaned up on connection failure
|
|
136
146
|
await self.disconnect()
|
|
137
147
|
logger.error(f"Failed to connect to MCP server: {e}")
|
|
148
|
+
raise e
|
|
138
149
|
|
|
139
150
|
async def disconnect(self):
|
|
140
151
|
r"""Explicitly disconnect from the MCP server."""
|
|
@@ -149,7 +160,7 @@ class _MCPServer(BaseToolkit):
|
|
|
149
160
|
on the provided `command_or_url`.
|
|
150
161
|
|
|
151
162
|
Yields:
|
|
152
|
-
|
|
163
|
+
MCPClient: Instance with active connection ready for tool
|
|
153
164
|
interaction.
|
|
154
165
|
"""
|
|
155
166
|
try:
|
|
@@ -170,7 +181,8 @@ class _MCPServer(BaseToolkit):
|
|
|
170
181
|
try:
|
|
171
182
|
return await self._session.list_tools()
|
|
172
183
|
except Exception as e:
|
|
173
|
-
|
|
184
|
+
logger.exception("Failed to list MCP tools")
|
|
185
|
+
raise e
|
|
174
186
|
|
|
175
187
|
def generate_function_from_mcp_tool(self, mcp_tool: "Tool") -> Callable:
|
|
176
188
|
r"""Dynamically generates a Python callable function corresponding to
|
|
@@ -235,7 +247,7 @@ class _MCPServer(BaseToolkit):
|
|
|
235
247
|
logger.error(
|
|
236
248
|
"MCP Client is not connected. Call `connection()` first."
|
|
237
249
|
)
|
|
238
|
-
|
|
250
|
+
raise RuntimeError(
|
|
239
251
|
"MCP Client is not connected. Call `connection()` first."
|
|
240
252
|
)
|
|
241
253
|
|
|
@@ -245,7 +257,7 @@ class _MCPServer(BaseToolkit):
|
|
|
245
257
|
)
|
|
246
258
|
except Exception as e:
|
|
247
259
|
logger.error(f"Failed to call MCP tool '{func_name}': {e!s}")
|
|
248
|
-
|
|
260
|
+
raise e
|
|
249
261
|
|
|
250
262
|
if not result.content or len(result.content) == 0:
|
|
251
263
|
return "No data available for this request."
|
|
@@ -272,7 +284,7 @@ class _MCPServer(BaseToolkit):
|
|
|
272
284
|
logger.error(
|
|
273
285
|
f"Error processing content from MCP tool response: {e!s}"
|
|
274
286
|
)
|
|
275
|
-
|
|
287
|
+
raise e
|
|
276
288
|
|
|
277
289
|
dynamic_function.__name__ = func_name
|
|
278
290
|
dynamic_function.__doc__ = func_desc
|
|
@@ -331,6 +343,10 @@ class _MCPServer(BaseToolkit):
|
|
|
331
343
|
for mcp_tool in self._mcp_tools
|
|
332
344
|
]
|
|
333
345
|
|
|
346
|
+
@property
|
|
347
|
+
def session(self) -> Optional["ClientSession"]:
|
|
348
|
+
return self._session
|
|
349
|
+
|
|
334
350
|
|
|
335
351
|
class MCPToolkit(BaseToolkit):
|
|
336
352
|
r"""MCPToolkit provides a unified interface for managing multiple
|
|
@@ -341,7 +357,7 @@ class MCPToolkit(BaseToolkit):
|
|
|
341
357
|
MCP services.
|
|
342
358
|
|
|
343
359
|
Args:
|
|
344
|
-
servers (Optional[List[
|
|
360
|
+
servers (Optional[List[MCPClient]]): List of MCPClient
|
|
345
361
|
instances to manage.
|
|
346
362
|
config_path (Optional[str]): Path to a JSON configuration file
|
|
347
363
|
defining MCP servers.
|
|
@@ -359,7 +375,7 @@ class MCPToolkit(BaseToolkit):
|
|
|
359
375
|
.. code-block:: json
|
|
360
376
|
|
|
361
377
|
{
|
|
362
|
-
"
|
|
378
|
+
"mcpServers": {
|
|
363
379
|
"protected-server": {
|
|
364
380
|
"url": "https://example.com/mcp",
|
|
365
381
|
"timeout": 30,
|
|
@@ -372,12 +388,12 @@ class MCPToolkit(BaseToolkit):
|
|
|
372
388
|
}
|
|
373
389
|
|
|
374
390
|
Attributes:
|
|
375
|
-
servers (List[
|
|
391
|
+
servers (List[MCPClient]): List of MCPClient instances being managed.
|
|
376
392
|
"""
|
|
377
393
|
|
|
378
394
|
def __init__(
|
|
379
395
|
self,
|
|
380
|
-
servers: Optional[List[
|
|
396
|
+
servers: Optional[List[MCPClient]] = None,
|
|
381
397
|
config_path: Optional[str] = None,
|
|
382
398
|
):
|
|
383
399
|
super().__init__()
|
|
@@ -388,7 +404,7 @@ class MCPToolkit(BaseToolkit):
|
|
|
388
404
|
"Servers from both sources will be combined."
|
|
389
405
|
)
|
|
390
406
|
|
|
391
|
-
self.servers = servers or []
|
|
407
|
+
self.servers: List[MCPClient] = servers or []
|
|
392
408
|
|
|
393
409
|
if config_path:
|
|
394
410
|
self.servers.extend(self._load_servers_from_config(config_path))
|
|
@@ -396,14 +412,14 @@ class MCPToolkit(BaseToolkit):
|
|
|
396
412
|
self._exit_stack = AsyncExitStack()
|
|
397
413
|
self._connected = False
|
|
398
414
|
|
|
399
|
-
def _load_servers_from_config(self, config_path: str) -> List[
|
|
415
|
+
def _load_servers_from_config(self, config_path: str) -> List[MCPClient]:
|
|
400
416
|
r"""Loads MCP server configurations from a JSON file.
|
|
401
417
|
|
|
402
418
|
Args:
|
|
403
419
|
config_path (str): Path to the JSON configuration file.
|
|
404
420
|
|
|
405
421
|
Returns:
|
|
406
|
-
List[
|
|
422
|
+
List[MCPClient]: List of configured MCPClient instances.
|
|
407
423
|
"""
|
|
408
424
|
try:
|
|
409
425
|
with open(config_path, "r", encoding="utf-8") as f:
|
|
@@ -413,14 +429,13 @@ class MCPToolkit(BaseToolkit):
|
|
|
413
429
|
logger.warning(
|
|
414
430
|
f"Invalid JSON in config file '{config_path}': {e!s}"
|
|
415
431
|
)
|
|
416
|
-
|
|
417
|
-
except FileNotFoundError:
|
|
432
|
+
raise e
|
|
433
|
+
except FileNotFoundError as e:
|
|
418
434
|
logger.warning(f"Config file not found: '{config_path}'")
|
|
419
|
-
|
|
435
|
+
raise e
|
|
420
436
|
|
|
421
437
|
all_servers = []
|
|
422
438
|
|
|
423
|
-
# Process local MCP servers
|
|
424
439
|
mcp_servers = data.get("mcpServers", {})
|
|
425
440
|
if not isinstance(mcp_servers, dict):
|
|
426
441
|
logger.warning("'mcpServers' is not a dictionary, skipping...")
|
|
@@ -433,47 +448,21 @@ class MCPToolkit(BaseToolkit):
|
|
|
433
448
|
)
|
|
434
449
|
continue
|
|
435
450
|
|
|
436
|
-
if "command" not in cfg:
|
|
451
|
+
if "command" not in cfg and "url" not in cfg:
|
|
437
452
|
logger.warning(
|
|
438
|
-
f"Missing required 'command' field for server
|
|
453
|
+
f"Missing required 'command' or 'url' field for server "
|
|
454
|
+
f"'{name}'"
|
|
439
455
|
)
|
|
440
456
|
continue
|
|
441
457
|
|
|
442
|
-
server =
|
|
443
|
-
command_or_url=cfg
|
|
458
|
+
server = MCPClient(
|
|
459
|
+
command_or_url=cast(str, cfg.get("command") or cfg.get("url")),
|
|
444
460
|
args=cfg.get("args", []),
|
|
445
461
|
env={**os.environ, **cfg.get("env", {})},
|
|
446
462
|
timeout=cfg.get("timeout", None),
|
|
447
463
|
)
|
|
448
464
|
all_servers.append(server)
|
|
449
465
|
|
|
450
|
-
# Process remote MCP web servers
|
|
451
|
-
mcp_web_servers = data.get("mcpWebServers", {})
|
|
452
|
-
if not isinstance(mcp_web_servers, dict):
|
|
453
|
-
logger.warning("'mcpWebServers' is not a dictionary, skipping...")
|
|
454
|
-
mcp_web_servers = {}
|
|
455
|
-
|
|
456
|
-
for name, cfg in mcp_web_servers.items():
|
|
457
|
-
if not isinstance(cfg, dict):
|
|
458
|
-
logger.warning(
|
|
459
|
-
f"Configuration for web server '{name}' must"
|
|
460
|
-
"be a dictionary"
|
|
461
|
-
)
|
|
462
|
-
continue
|
|
463
|
-
|
|
464
|
-
if "url" not in cfg:
|
|
465
|
-
logger.warning(
|
|
466
|
-
f"Missing required 'url' field for web server '{name}'"
|
|
467
|
-
)
|
|
468
|
-
continue
|
|
469
|
-
|
|
470
|
-
server = _MCPServer(
|
|
471
|
-
command_or_url=cfg["url"],
|
|
472
|
-
timeout=cfg.get("timeout", None),
|
|
473
|
-
headers=cfg.get("headers", {}),
|
|
474
|
-
)
|
|
475
|
-
all_servers.append(server)
|
|
476
|
-
|
|
477
466
|
return all_servers
|
|
478
467
|
|
|
479
468
|
async def connect(self):
|
|
@@ -497,6 +486,7 @@ class MCPToolkit(BaseToolkit):
|
|
|
497
486
|
# Ensure resources are cleaned up on connection failure
|
|
498
487
|
await self.disconnect()
|
|
499
488
|
logger.error(f"Failed to connect to one or more MCP servers: {e}")
|
|
489
|
+
raise e
|
|
500
490
|
|
|
501
491
|
async def disconnect(self):
|
|
502
492
|
r"""Explicitly disconnect from all MCP servers."""
|
camel/toolkits/meshy_toolkit.py
CHANGED
|
@@ -13,14 +13,16 @@
|
|
|
13
13
|
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
|
|
14
14
|
|
|
15
15
|
import os
|
|
16
|
-
from typing import Any, Dict, Optional
|
|
16
|
+
from typing import Any, Dict, List, Optional
|
|
17
17
|
|
|
18
18
|
import requests
|
|
19
19
|
|
|
20
|
+
from camel.toolkits import FunctionTool
|
|
20
21
|
from camel.toolkits.base import BaseToolkit
|
|
21
|
-
from camel.utils import api_keys_required
|
|
22
|
+
from camel.utils import MCPServer, api_keys_required
|
|
22
23
|
|
|
23
24
|
|
|
25
|
+
@MCPServer()
|
|
24
26
|
class MeshyToolkit(BaseToolkit):
|
|
25
27
|
r"""A class representing a toolkit for 3D model generation using Meshy.
|
|
26
28
|
|
|
@@ -188,3 +190,19 @@ class MeshyToolkit(BaseToolkit):
|
|
|
188
190
|
|
|
189
191
|
# Wait for refinement completion and return final result
|
|
190
192
|
return self.wait_for_task_completion(refine_task_id)
|
|
193
|
+
|
|
194
|
+
def get_tools(self) -> List[FunctionTool]:
|
|
195
|
+
r"""Returns a list of FunctionTool objects representing the
|
|
196
|
+
functions in the toolkit.
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
List[FunctionTool]: A list of FunctionTool objects
|
|
200
|
+
representing the functions in the toolkit.
|
|
201
|
+
"""
|
|
202
|
+
return [
|
|
203
|
+
FunctionTool(self.generate_3d_preview),
|
|
204
|
+
FunctionTool(self.refine_3d_model),
|
|
205
|
+
FunctionTool(self.get_task_status),
|
|
206
|
+
FunctionTool(self.wait_for_task_completion),
|
|
207
|
+
FunctionTool(self.generate_3d_model_complete),
|
|
208
|
+
]
|
|
@@ -18,10 +18,12 @@ from typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Union
|
|
|
18
18
|
from camel.logger import get_logger
|
|
19
19
|
from camel.toolkits import FunctionTool
|
|
20
20
|
from camel.toolkits.base import BaseToolkit
|
|
21
|
+
from camel.utils import MCPServer
|
|
21
22
|
|
|
22
23
|
logger = get_logger(__name__)
|
|
23
24
|
|
|
24
25
|
|
|
26
|
+
@MCPServer()
|
|
25
27
|
class NetworkXToolkit(BaseToolkit):
|
|
26
28
|
_nx = None # Class variable to store the networkx module
|
|
27
29
|
|
camel/toolkits/notion_toolkit.py
CHANGED
|
@@ -16,6 +16,7 @@ from typing import List, Optional, cast
|
|
|
16
16
|
|
|
17
17
|
from camel.toolkits import FunctionTool
|
|
18
18
|
from camel.toolkits.base import BaseToolkit
|
|
19
|
+
from camel.utils import MCPServer, api_keys_required
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
def get_plain_text_from_rich_text(rich_text: List[dict]) -> str:
|
|
@@ -66,6 +67,7 @@ def get_media_source_text(block: dict) -> str:
|
|
|
66
67
|
return source
|
|
67
68
|
|
|
68
69
|
|
|
70
|
+
@MCPServer()
|
|
69
71
|
class NotionToolkit(BaseToolkit):
|
|
70
72
|
r"""A toolkit for retrieving information from the user's notion pages.
|
|
71
73
|
|
|
@@ -76,6 +78,11 @@ class NotionToolkit(BaseToolkit):
|
|
|
76
78
|
the notion APIs.
|
|
77
79
|
"""
|
|
78
80
|
|
|
81
|
+
@api_keys_required(
|
|
82
|
+
[
|
|
83
|
+
("notion_token", 'NOTION_TOKEN'),
|
|
84
|
+
]
|
|
85
|
+
)
|
|
79
86
|
def __init__(
|
|
80
87
|
self,
|
|
81
88
|
notion_token: Optional[str] = None,
|
camel/toolkits/openbb_toolkit.py
CHANGED
|
@@ -17,9 +17,10 @@ from typing import List, Literal, Optional
|
|
|
17
17
|
|
|
18
18
|
from camel.toolkits.base import BaseToolkit
|
|
19
19
|
from camel.toolkits.function_tool import FunctionTool
|
|
20
|
-
from camel.utils import api_keys_required, dependencies_required
|
|
20
|
+
from camel.utils import MCPServer, api_keys_required, dependencies_required
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
@MCPServer()
|
|
23
24
|
class OpenBBToolkit(BaseToolkit):
|
|
24
25
|
r"""A toolkit for accessing financial data and analysis through OpenBB
|
|
25
26
|
Platform.
|
camel/toolkits/pubmed_toolkit.py
CHANGED
|
@@ -18,10 +18,12 @@ import requests
|
|
|
18
18
|
|
|
19
19
|
from camel.logger import get_logger
|
|
20
20
|
from camel.toolkits import BaseToolkit, FunctionTool
|
|
21
|
+
from camel.utils import MCPServer
|
|
21
22
|
|
|
22
23
|
logger = get_logger(__name__)
|
|
23
24
|
|
|
24
25
|
|
|
26
|
+
@MCPServer()
|
|
25
27
|
class PubMedToolkit(BaseToolkit):
|
|
26
28
|
r"""A toolkit for interacting with PubMed's E-utilities API to access
|
|
27
29
|
MEDLINE data.
|
camel/toolkits/reddit_toolkit.py
CHANGED
|
@@ -18,9 +18,10 @@ from typing import Any, Dict, List, Optional, Union
|
|
|
18
18
|
|
|
19
19
|
from camel.toolkits import FunctionTool
|
|
20
20
|
from camel.toolkits.base import BaseToolkit
|
|
21
|
-
from camel.utils import retry_on_error
|
|
21
|
+
from camel.utils import MCPServer, retry_on_error
|
|
22
22
|
|
|
23
23
|
|
|
24
|
+
@MCPServer()
|
|
24
25
|
class RedditToolkit(BaseToolkit):
|
|
25
26
|
r"""A class representing a toolkit for Reddit operations.
|
|
26
27
|
|
|
@@ -17,9 +17,10 @@ from camel.retrievers import AutoRetriever
|
|
|
17
17
|
from camel.toolkits import FunctionTool
|
|
18
18
|
from camel.toolkits.base import BaseToolkit
|
|
19
19
|
from camel.types import StorageType
|
|
20
|
-
from camel.utils import Constants
|
|
20
|
+
from camel.utils import Constants, MCPServer
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
@MCPServer()
|
|
23
24
|
class RetrievalToolkit(BaseToolkit):
|
|
24
25
|
r"""A class representing a toolkit for information retrieval.
|
|
25
26
|
|
camel/toolkits/search_toolkit.py
CHANGED
|
@@ -19,9 +19,10 @@ import requests
|
|
|
19
19
|
|
|
20
20
|
from camel.toolkits.base import BaseToolkit
|
|
21
21
|
from camel.toolkits.function_tool import FunctionTool
|
|
22
|
-
from camel.utils import api_keys_required, dependencies_required
|
|
22
|
+
from camel.utils import MCPServer, api_keys_required, dependencies_required
|
|
23
23
|
|
|
24
24
|
|
|
25
|
+
@MCPServer()
|
|
25
26
|
class SearchToolkit(BaseToolkit):
|
|
26
27
|
r"""A class representing a toolkit for web search.
|
|
27
28
|
|
|
@@ -19,8 +19,10 @@ import requests
|
|
|
19
19
|
|
|
20
20
|
from camel.toolkits import FunctionTool
|
|
21
21
|
from camel.toolkits.base import BaseToolkit
|
|
22
|
+
from camel.utils import MCPServer
|
|
22
23
|
|
|
23
24
|
|
|
25
|
+
@MCPServer()
|
|
24
26
|
class SemanticScholarToolkit(BaseToolkit):
|
|
25
27
|
r"""A toolkit for interacting with the Semantic Scholar
|
|
26
28
|
API to fetch paper and author data.
|
camel/toolkits/slack_toolkit.py
CHANGED
|
@@ -20,6 +20,7 @@ import os
|
|
|
20
20
|
from typing import TYPE_CHECKING, List, Optional
|
|
21
21
|
|
|
22
22
|
from camel.toolkits.base import BaseToolkit
|
|
23
|
+
from camel.utils import MCPServer
|
|
23
24
|
|
|
24
25
|
if TYPE_CHECKING:
|
|
25
26
|
from ssl import SSLContext
|
|
@@ -31,6 +32,7 @@ from camel.toolkits import FunctionTool
|
|
|
31
32
|
logger = logging.getLogger(__name__)
|
|
32
33
|
|
|
33
34
|
|
|
35
|
+
@MCPServer()
|
|
34
36
|
class SlackToolkit(BaseToolkit):
|
|
35
37
|
r"""A class representing a toolkit for Slack operations.
|
|
36
38
|
|
camel/toolkits/stripe_toolkit.py
CHANGED
|
@@ -19,9 +19,10 @@ from typing import List, Optional
|
|
|
19
19
|
|
|
20
20
|
from camel.toolkits import FunctionTool
|
|
21
21
|
from camel.toolkits.base import BaseToolkit
|
|
22
|
-
from camel.utils import api_keys_required
|
|
22
|
+
from camel.utils import MCPServer, api_keys_required
|
|
23
23
|
|
|
24
24
|
|
|
25
|
+
@MCPServer()
|
|
25
26
|
class StripeToolkit(BaseToolkit):
|
|
26
27
|
r"""A class representing a toolkit for Stripe operations.
|
|
27
28
|
|
camel/toolkits/sympy_toolkit.py
CHANGED
|
@@ -18,10 +18,12 @@ from typing import List, Optional
|
|
|
18
18
|
from camel.logger import get_logger
|
|
19
19
|
from camel.toolkits import FunctionTool
|
|
20
20
|
from camel.toolkits.base import BaseToolkit
|
|
21
|
+
from camel.utils import MCPServer
|
|
21
22
|
|
|
22
23
|
logger = get_logger(__name__)
|
|
23
24
|
|
|
24
25
|
|
|
26
|
+
@MCPServer()
|
|
25
27
|
class SymPyToolkit(BaseToolkit):
|
|
26
28
|
r"""A toolkit for performing symbolic computations using SymPy.
|
|
27
29
|
This includes methods for Algebraic manipulation calculus
|
|
@@ -19,10 +19,12 @@ from typing import Any, Dict, List, Optional
|
|
|
19
19
|
from camel.logger import get_logger
|
|
20
20
|
from camel.toolkits.base import BaseToolkit
|
|
21
21
|
from camel.toolkits.function_tool import FunctionTool
|
|
22
|
+
from camel.utils import MCPServer
|
|
22
23
|
|
|
23
24
|
logger = get_logger(__name__)
|
|
24
25
|
|
|
25
26
|
|
|
27
|
+
@MCPServer()
|
|
26
28
|
class TerminalToolkit(BaseToolkit):
|
|
27
29
|
r"""A toolkit for terminal operations across multiple operating systems.
|
|
28
30
|
|
|
@@ -23,7 +23,7 @@ from requests_oauthlib import OAuth1
|
|
|
23
23
|
from camel.logger import get_logger
|
|
24
24
|
from camel.toolkits import FunctionTool
|
|
25
25
|
from camel.toolkits.base import BaseToolkit
|
|
26
|
-
from camel.utils import api_keys_required
|
|
26
|
+
from camel.utils import MCPServer, api_keys_required
|
|
27
27
|
|
|
28
28
|
TWEET_TEXT_LIMIT = 280
|
|
29
29
|
|
|
@@ -418,6 +418,7 @@ def _handle_http_error(response: requests.Response) -> str:
|
|
|
418
418
|
return "Unexpected Exception"
|
|
419
419
|
|
|
420
420
|
|
|
421
|
+
@MCPServer()
|
|
421
422
|
class TwitterToolkit(BaseToolkit):
|
|
422
423
|
r"""A class representing a toolkit for Twitter operations.
|
|
423
424
|
|
|
@@ -24,7 +24,7 @@ from camel.messages import BaseMessage
|
|
|
24
24
|
from camel.models import BaseModelBackend, OpenAIAudioModels
|
|
25
25
|
from camel.toolkits.base import BaseToolkit
|
|
26
26
|
from camel.toolkits.function_tool import FunctionTool
|
|
27
|
-
from camel.utils import dependencies_required
|
|
27
|
+
from camel.utils import MCPServer, dependencies_required
|
|
28
28
|
|
|
29
29
|
from .video_download_toolkit import (
|
|
30
30
|
VideoDownloaderToolkit,
|
|
@@ -77,6 +77,7 @@ similar-looking species or objects
|
|
|
77
77
|
"""
|
|
78
78
|
|
|
79
79
|
|
|
80
|
+
@MCPServer()
|
|
80
81
|
class VideoAnalysisToolkit(BaseToolkit):
|
|
81
82
|
r"""A class for analysing videos with vision-language model.
|
|
82
83
|
|
|
@@ -23,7 +23,7 @@ from PIL import Image
|
|
|
23
23
|
from camel.logger import get_logger
|
|
24
24
|
from camel.toolkits.base import BaseToolkit
|
|
25
25
|
from camel.toolkits.function_tool import FunctionTool
|
|
26
|
-
from camel.utils import dependencies_required
|
|
26
|
+
from camel.utils import MCPServer, dependencies_required
|
|
27
27
|
|
|
28
28
|
logger = get_logger(__name__)
|
|
29
29
|
|
|
@@ -54,6 +54,7 @@ def _capture_screenshot(video_file: str, timestamp: float) -> Image.Image:
|
|
|
54
54
|
return Image.open(io.BytesIO(out))
|
|
55
55
|
|
|
56
56
|
|
|
57
|
+
@MCPServer()
|
|
57
58
|
class VideoDownloaderToolkit(BaseToolkit):
|
|
58
59
|
r"""A class for downloading videos and optionally splitting them into
|
|
59
60
|
chunks.
|
|
@@ -16,8 +16,10 @@ from typing import List, Literal
|
|
|
16
16
|
|
|
17
17
|
from camel.toolkits.base import BaseToolkit
|
|
18
18
|
from camel.toolkits.function_tool import FunctionTool
|
|
19
|
+
from camel.utils import MCPServer
|
|
19
20
|
|
|
20
21
|
|
|
22
|
+
@MCPServer()
|
|
21
23
|
class WeatherToolkit(BaseToolkit):
|
|
22
24
|
r"""A class representing a toolkit for interacting with weather data.
|
|
23
25
|
|