camel-ai 0.2.37__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.

Files changed (122) hide show
  1. camel/__init__.py +1 -1
  2. camel/agents/chat_agent.py +4 -0
  3. camel/agents/repo_agent.py +2 -2
  4. camel/benchmarks/apibank.py +1 -1
  5. camel/benchmarks/apibench.py +1 -1
  6. camel/configs/__init__.py +3 -0
  7. camel/configs/modelscope_config.py +59 -0
  8. camel/datagen/evol_instruct/__init__.py +20 -0
  9. camel/datagen/evol_instruct/evol_instruct.py +424 -0
  10. camel/datagen/evol_instruct/scorer.py +166 -0
  11. camel/datagen/evol_instruct/templates.py +268 -0
  12. camel/datagen/self_improving_cot.py +1 -1
  13. camel/datasets/__init__.py +2 -0
  14. camel/datasets/base_generator.py +22 -9
  15. camel/datasets/few_shot_generator.py +2 -3
  16. camel/datasets/self_instruct_generator.py +415 -0
  17. camel/embeddings/openai_compatible_embedding.py +13 -5
  18. camel/environments/models.py +10 -4
  19. camel/environments/single_step.py +181 -41
  20. camel/interpreters/docker_interpreter.py +2 -2
  21. camel/interpreters/e2b_interpreter.py +1 -1
  22. camel/interpreters/internal_python_interpreter.py +1 -1
  23. camel/interpreters/subprocess_interpreter.py +1 -1
  24. camel/loaders/__init__.py +2 -2
  25. camel/loaders/{panda_reader.py → pandas_reader.py} +61 -30
  26. camel/loaders/unstructured_io.py +2 -1
  27. camel/memories/blocks/chat_history_block.py +1 -1
  28. camel/memories/context_creators/score_based.py +198 -67
  29. camel/models/__init__.py +2 -0
  30. camel/models/aiml_model.py +9 -3
  31. camel/models/anthropic_model.py +11 -3
  32. camel/models/azure_openai_model.py +9 -3
  33. camel/models/base_audio_model.py +6 -0
  34. camel/models/base_model.py +4 -0
  35. camel/models/deepseek_model.py +9 -3
  36. camel/models/gemini_model.py +9 -3
  37. camel/models/groq_model.py +9 -3
  38. camel/models/internlm_model.py +8 -2
  39. camel/models/model_factory.py +123 -0
  40. camel/models/modelscope_model.py +208 -0
  41. camel/models/moonshot_model.py +8 -2
  42. camel/models/nemotron_model.py +9 -3
  43. camel/models/nvidia_model.py +9 -3
  44. camel/models/ollama_model.py +9 -3
  45. camel/models/openai_audio_models.py +7 -5
  46. camel/models/openai_compatible_model.py +9 -3
  47. camel/models/openai_model.py +58 -5
  48. camel/models/openrouter_model.py +9 -3
  49. camel/models/qwen_model.py +9 -3
  50. camel/models/samba_model.py +9 -3
  51. camel/models/sglang_model.py +11 -4
  52. camel/models/siliconflow_model.py +8 -2
  53. camel/models/stub_model.py +2 -1
  54. camel/models/togetherai_model.py +11 -5
  55. camel/models/vllm_model.py +10 -4
  56. camel/models/yi_model.py +9 -3
  57. camel/models/zhipuai_model.py +11 -5
  58. camel/retrievers/auto_retriever.py +14 -0
  59. camel/retrievers/vector_retriever.py +1 -1
  60. camel/storages/__init__.py +2 -0
  61. camel/storages/graph_storages/neo4j_graph.py +1 -1
  62. camel/storages/vectordb_storages/__init__.py +2 -0
  63. camel/storages/vectordb_storages/base.py +2 -2
  64. camel/storages/vectordb_storages/milvus.py +2 -2
  65. camel/storages/vectordb_storages/qdrant.py +2 -2
  66. camel/storages/vectordb_storages/tidb.py +332 -0
  67. camel/tasks/task.py +2 -2
  68. camel/toolkits/__init__.py +9 -1
  69. camel/toolkits/arxiv_toolkit.py +2 -1
  70. camel/toolkits/ask_news_toolkit.py +11 -3
  71. camel/toolkits/audio_analysis_toolkit.py +2 -0
  72. camel/toolkits/base.py +3 -0
  73. camel/toolkits/browser_toolkit.py +84 -61
  74. camel/toolkits/code_execution.py +3 -1
  75. camel/toolkits/dappier_toolkit.py +2 -1
  76. camel/toolkits/data_commons_toolkit.py +2 -0
  77. camel/toolkits/excel_toolkit.py +2 -0
  78. camel/toolkits/file_write_toolkit.py +2 -0
  79. camel/toolkits/github_toolkit.py +6 -4
  80. camel/toolkits/google_scholar_toolkit.py +2 -0
  81. camel/toolkits/human_toolkit.py +17 -1
  82. camel/toolkits/image_analysis_toolkit.py +2 -0
  83. camel/toolkits/linkedin_toolkit.py +2 -1
  84. camel/toolkits/math_toolkit.py +2 -0
  85. camel/toolkits/mcp_toolkit.py +42 -52
  86. camel/toolkits/meshy_toolkit.py +20 -2
  87. camel/toolkits/networkx_toolkit.py +2 -0
  88. camel/toolkits/notion_toolkit.py +7 -0
  89. camel/toolkits/openai_agent_toolkit.py +131 -0
  90. camel/toolkits/openbb_toolkit.py +2 -1
  91. camel/toolkits/pubmed_toolkit.py +2 -0
  92. camel/toolkits/reddit_toolkit.py +2 -1
  93. camel/toolkits/retrieval_toolkit.py +2 -1
  94. camel/toolkits/search_toolkit.py +2 -1
  95. camel/toolkits/searxng_toolkit.py +207 -0
  96. camel/toolkits/semantic_scholar_toolkit.py +2 -0
  97. camel/toolkits/slack_toolkit.py +2 -0
  98. camel/toolkits/stripe_toolkit.py +2 -1
  99. camel/toolkits/sympy_toolkit.py +2 -0
  100. camel/toolkits/terminal_toolkit.py +2 -0
  101. camel/toolkits/thinking_toolkit.py +168 -12
  102. camel/toolkits/twitter_toolkit.py +2 -1
  103. camel/toolkits/video_analysis_toolkit.py +2 -1
  104. camel/toolkits/video_download_toolkit.py +2 -1
  105. camel/toolkits/weather_toolkit.py +2 -0
  106. camel/toolkits/whatsapp_toolkit.py +2 -1
  107. camel/toolkits/zapier_toolkit.py +2 -1
  108. camel/types/enums.py +66 -0
  109. camel/types/unified_model_type.py +5 -0
  110. camel/utils/__init__.py +2 -0
  111. camel/utils/chunker/code_chunker.py +9 -9
  112. camel/utils/commons.py +50 -30
  113. camel/utils/constants.py +2 -2
  114. camel/utils/mcp.py +79 -0
  115. camel/verifiers/__init__.py +2 -0
  116. camel/verifiers/base.py +15 -15
  117. camel/verifiers/math_verifier.py +182 -0
  118. camel/verifiers/python_verifier.py +28 -28
  119. {camel_ai-0.2.37.dist-info → camel_ai-0.2.39.dist-info}/METADATA +54 -4
  120. {camel_ai-0.2.37.dist-info → camel_ai-0.2.39.dist-info}/RECORD +122 -110
  121. {camel_ai-0.2.37.dist-info → camel_ai-0.2.39.dist-info}/WHEEL +0 -0
  122. {camel_ai-0.2.37.dist-info → camel_ai-0.2.39.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,207 @@
1
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
+
15
+ from typing import ClassVar, Dict, List, Optional, Union
16
+ from urllib.parse import urlparse
17
+
18
+ import requests
19
+
20
+ from camel.logger import get_logger
21
+ from camel.toolkits.base import BaseToolkit
22
+ from camel.toolkits.function_tool import FunctionTool
23
+
24
+ logger = get_logger(__name__)
25
+
26
+
27
+ class SearxNGToolkit(BaseToolkit):
28
+ r"""A toolkit for performing web searches using SearxNG search engine.
29
+
30
+ This toolkit provides methods to search the web using SearxNG,
31
+ a privacy-respecting metasearch engine. It supports customizable
32
+ search parameters and safe search levels.
33
+
34
+ Args:
35
+ searxng_host (str): The URL of the SearxNG instance to use for
36
+ searches. Must be a valid HTTP/HTTPS URL.
37
+ language (str, optional): Search language code for results.
38
+ (default: :obj:`"en"`)
39
+ categories (List[str], optional): List of search categories to use.
40
+ (default: :obj:`None`)
41
+ time_range (str, optional): Time range filter for search results.Valid
42
+ values are "day", "week", "month", "year". (default: :obj:`None`)
43
+ safe_search (int, optional): Safe search level (0: None, 1: Moderate,
44
+ 2: Strict). (default: :obj:`1`)
45
+
46
+ Raises:
47
+ ValueError: If searxng_host is not a valid HTTP/HTTPS URL.
48
+ ValueError: If safe_search is not in the valid range [0, 2].
49
+ ValueError: If time_range is provided but not in valid options.
50
+ """
51
+
52
+ # Constants for validation
53
+ _SAFE_SEARCH_LEVELS: ClassVar[Dict[int, str]] = {
54
+ 0: "Disabled",
55
+ 1: "Moderate",
56
+ 2: "Strict",
57
+ }
58
+ _VALID_TIME_RANGES: ClassVar[List[str]] = ["day", "week", "month", "year"]
59
+ _DEFAULT_CATEGORY: ClassVar[str] = "general"
60
+
61
+ def __init__(
62
+ self,
63
+ searxng_host: str,
64
+ language: str = "en",
65
+ categories: Optional[List[str]] = None,
66
+ time_range: Optional[str] = None,
67
+ safe_search: int = 1,
68
+ ) -> None:
69
+ self._validate_searxng_host(searxng_host)
70
+ self._validate_safe_search(safe_search)
71
+ if time_range is not None:
72
+ self._validate_time_range(time_range)
73
+
74
+ self.searxng_host = searxng_host.rstrip('/')
75
+ self.language = language
76
+ self.categories = categories or [self._DEFAULT_CATEGORY]
77
+ self.time_range = time_range
78
+ self.safe_search = safe_search
79
+
80
+ logger.info(
81
+ f"Initialized SearxNG toolkit with host: {searxng_host}, "
82
+ f"safe_search: {self._SAFE_SEARCH_LEVELS[safe_search]}"
83
+ )
84
+
85
+ def _validate_searxng_host(self, url: str) -> None:
86
+ r"""Validate if the given URL is a proper HTTP/HTTPS URL.
87
+
88
+ Args:
89
+ url (str): The URL to validate.
90
+
91
+ Raises:
92
+ ValueError: If the URL is not valid.
93
+ """
94
+ try:
95
+ result = urlparse(url)
96
+ is_valid = all(
97
+ [
98
+ result.scheme in ('http', 'https'),
99
+ result.netloc,
100
+ ]
101
+ )
102
+ if not is_valid:
103
+ raise ValueError
104
+ except Exception:
105
+ raise ValueError(
106
+ "Invalid searxng_host URL. Must be a valid HTTP/HTTPS URL."
107
+ )
108
+
109
+ def _validate_safe_search(self, level: int) -> None:
110
+ r"""Validate if the safe search level is valid.
111
+
112
+ Args:
113
+ level (int): The safe search level to validate.
114
+
115
+ Raises:
116
+ ValueError: If the safe search level is not valid.
117
+ """
118
+ if level not in self._SAFE_SEARCH_LEVELS:
119
+ raise ValueError(
120
+ f"Invalid safe_search level: {level}. Must be one of: "
121
+ f"{list(self._SAFE_SEARCH_LEVELS.keys())}"
122
+ )
123
+
124
+ def _validate_time_range(self, time_range: str) -> None:
125
+ r"""Validate if the time range is valid.
126
+
127
+ Args:
128
+ time_range (str): The time range to validate.
129
+
130
+ Raises:
131
+ ValueError: If the time range is not valid.
132
+ """
133
+ if time_range not in self._VALID_TIME_RANGES:
134
+ raise ValueError(
135
+ f"Invalid time_range: {time_range}. Must be one of: "
136
+ f"{self._VALID_TIME_RANGES}"
137
+ )
138
+
139
+ def search(
140
+ self,
141
+ query: str,
142
+ num_results: int = 10,
143
+ category: Optional[str] = None,
144
+ ) -> List[Dict[str, str]]:
145
+ r"""Perform a web search using the configured SearxNG instance.
146
+
147
+ Args:
148
+ query (str): The search query string to execute.
149
+ num_results (int, optional): Maximum number of results to return.
150
+ (default: :obj:`10`)
151
+ category (str, optional): Specific search category to use. If not
152
+ provided, uses the first category from self.categories.
153
+ (default: :obj:`None`)
154
+
155
+ Returns:
156
+ List[Dict[str, str]]: List of search results, where each result is
157
+ dictionary containing 'title', 'link', and 'snippet' keys.
158
+ """
159
+ params: Dict[str, Union[str, int]] = {
160
+ "q": query,
161
+ "format": "json",
162
+ "language": self.language,
163
+ "categories": category or self.categories[0],
164
+ "pageno": 1,
165
+ "safe": self.safe_search,
166
+ }
167
+
168
+ if self.time_range:
169
+ params["time_range"] = self.time_range
170
+
171
+ try:
172
+ logger.debug(f"Sending search request with query: {query}")
173
+ response = requests.get(
174
+ f"{self.searxng_host}/search",
175
+ params=params, # type: ignore[arg-type]
176
+ headers={"User-Agent": "camel-ai/searxng-toolkit"},
177
+ )
178
+ response.raise_for_status()
179
+ results = response.json().get("results", [])
180
+
181
+ formatted_results = []
182
+ for result in results[:num_results]:
183
+ formatted_results.append(
184
+ {
185
+ "title": result.get("title", ""),
186
+ "link": result.get("url", ""),
187
+ "snippet": result.get("content", ""),
188
+ }
189
+ )
190
+
191
+ logger.debug(f"Retrieved {len(formatted_results)} results")
192
+ return formatted_results
193
+
194
+ except Exception as error:
195
+ logger.error(f"Search failed: {error!s}")
196
+ return []
197
+
198
+ def get_tools(self) -> List[FunctionTool]:
199
+ r"""Get the list of available tools in the toolkit.
200
+
201
+ Returns:
202
+ List[FunctionTool]: A list of FunctionTool objects representing the
203
+ available functions in the toolkit.
204
+ """
205
+ return [
206
+ FunctionTool(self.search),
207
+ ]
@@ -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.
@@ -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
 
@@ -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
 
@@ -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
 
@@ -22,11 +22,7 @@ logger = get_logger(__name__)
22
22
 
23
23
 
24
24
  class ThinkingToolkit(BaseToolkit):
25
- r"""A toolkit for recording thoughts during reasoning processes.
26
-
27
- Attributes:
28
- thoughts (List[str]): A list to store the recorded thoughts.
29
- """
25
+ r"""A toolkit for recording thoughts during reasoning processes."""
30
26
 
31
27
  def __init__(
32
28
  self,
@@ -39,36 +35,196 @@ class ThinkingToolkit(BaseToolkit):
39
35
  (default: :obj: `None`)
40
36
  """
41
37
  super().__init__(timeout=timeout)
38
+ self.plans: List[str] = []
39
+ self.hypotheses: List[str] = []
42
40
  self.thoughts: List[str] = []
41
+ self.contemplations: List[str] = []
42
+ self.critiques: List[str] = []
43
+ self.syntheses: List[str] = []
44
+ self.reflections: List[str] = []
45
+
46
+ def plan(self, plan: str) -> str:
47
+ r"""Use the tool to create a plan or strategy.
48
+ This tool is for outlining the approach or steps to be taken before
49
+ starting the actual thinking process.
50
+
51
+ Args:
52
+ plan (str): A forward-looking plan or strategy.
53
+
54
+ Returns:
55
+ str: The recorded plan.
56
+ """
57
+ try:
58
+ logger.debug(f"Plan: {plan}")
59
+ self.plans.append(plan)
60
+ return f"Plan: {plan}"
61
+
62
+ except Exception as e:
63
+ error_msg = f"Error recording plan: {e}"
64
+ logger.error(error_msg)
65
+ return error_msg
66
+
67
+ def hypothesize(self, hypothesis: str) -> str:
68
+ r"""Use the tool to form a hypothesis or make a prediction.
69
+ This tool is for making educated guesses or predictions based on
70
+ the plan, before detailed thinking.
71
+
72
+ Args:
73
+ hypothesis (str): A hypothesis or prediction to test.
74
+
75
+ Returns:
76
+ str: The recorded hypothesis.
77
+ """
78
+ try:
79
+ logger.debug(f"Hypothesis: {hypothesis}")
80
+ if not self.plans:
81
+ return "Consider creating a plan before forming hypotheses."
82
+ self.hypotheses.append(hypothesis)
83
+ return f"Hypothesis: {hypothesis}"
84
+
85
+ except Exception as e:
86
+ error_msg = f"Error recording hypothesis: {e}"
87
+ logger.error(error_msg)
88
+ return error_msg
43
89
 
44
90
  def think(self, thought: str) -> str:
45
91
  r"""Use the tool to think about something.
46
92
  It will not obtain new information or change the database, but just
47
- append the thought to the log. Use it when complex reasoning or some
48
- cache memory is needed.
93
+ append the thought to the log. Use it for initial thoughts and
94
+ observations during the execution of the plan.
49
95
 
50
96
  Args:
51
97
  thought (str): A thought to think about.
52
98
 
53
99
  Returns:
54
- str: The full log of thoughts including the new thought.
100
+ str: The recorded thought.
55
101
  """
56
102
  try:
57
103
  logger.debug(f"Thought: {thought}")
104
+ if not self.plans:
105
+ return (
106
+ "Consider creating a plan before thinking "
107
+ "through the process."
108
+ )
58
109
  self.thoughts.append(thought)
59
-
60
- thoughts = "\n".join([f"- {t}" for t in self.thoughts])
61
- return f"Thoughts:\n{thoughts}"
110
+ return f"Thought: {thought}"
62
111
 
63
112
  except Exception as e:
64
113
  error_msg = f"Error recording thought: {e}"
65
114
  logger.error(error_msg)
66
115
  return error_msg
67
116
 
117
+ def contemplate(self, contemplation: str) -> str:
118
+ r"""Use the tool to deeply contemplate an idea or concept.
119
+ This tool is for deeper, more thorough exploration of thoughts,
120
+ considering multiple perspectives and implications. It's more
121
+ comprehensive than basic thinking but more focused than reflection.
122
+
123
+ Args:
124
+ contemplation (str): A deeper exploration of thoughts or concepts.
125
+
126
+ Returns:
127
+ str: The recorded contemplation.
128
+ """
129
+ try:
130
+ logger.debug(f"Contemplation: {contemplation}")
131
+ if not self.thoughts:
132
+ return (
133
+ "Consider thinking about the topic before "
134
+ "deep contemplation."
135
+ )
136
+ self.contemplations.append(contemplation)
137
+ return f"Contemplation: {contemplation}"
138
+
139
+ except Exception as e:
140
+ error_msg = f"Error recording contemplation: {e}"
141
+ logger.error(error_msg)
142
+ return error_msg
143
+
144
+ def critique(self, critique: str) -> str:
145
+ r"""Use the tool to critically evaluate current thoughts.
146
+ This tool is for identifying potential flaws, biases, or
147
+ weaknesses in the current thinking process.
148
+
149
+ Args:
150
+ critique (str): A critical evaluation of current thoughts.
151
+
152
+ Returns:
153
+ str: The recorded critique.
154
+ """
155
+ try:
156
+ logger.debug(f"Critique: {critique}")
157
+ if not self.contemplations:
158
+ return "Consider contemplating deeply before critiquing."
159
+ self.critiques.append(critique)
160
+ return f"Critique: {critique}"
161
+
162
+ except Exception as e:
163
+ error_msg = f"Error recording critique: {e}"
164
+ logger.error(error_msg)
165
+ return error_msg
166
+
167
+ def synthesize(self, synthesis: str) -> str:
168
+ r"""Use the tool to combine and integrate various thoughts.
169
+ This tool is for bringing together different thoughts, contemplations,
170
+ and critiques into a coherent understanding.
171
+
172
+ Args:
173
+ synthesis (str): An integration of multiple thoughts and insights.
174
+
175
+ Returns:
176
+ str: The recorded synthesis.
177
+ """
178
+ try:
179
+ logger.debug(f"Synthesis: {synthesis}")
180
+ if not self.critiques:
181
+ return "Consider critiquing thoughts before synthesizing."
182
+ self.syntheses.append(synthesis)
183
+ return f"Synthesis: {synthesis}"
184
+
185
+ except Exception as e:
186
+ error_msg = f"Error recording synthesis: {e}"
187
+ logger.error(error_msg)
188
+ return error_msg
189
+
190
+ def reflect(self, reflection: str) -> str:
191
+ r"""Use the tool to reflect on the entire process.
192
+ This tool is for final evaluation of the entire thinking process,
193
+ including plans, hypotheses, thoughts, contemplations, critiques,
194
+ and syntheses.
195
+
196
+ Args:
197
+ reflection (str): A comprehensive reflection on the process.
198
+
199
+ Returns:
200
+ str: The recorded reflection.
201
+ """
202
+ try:
203
+ logger.debug(f"Reflection: {reflection}")
204
+ if not self.syntheses:
205
+ return (
206
+ "Consider synthesizing insights before final reflection."
207
+ )
208
+ self.reflections.append(reflection)
209
+ return f"Reflection: {reflection}"
210
+
211
+ except Exception as e:
212
+ error_msg = f"Error recording reflection: {e}"
213
+ logger.error(error_msg)
214
+ return error_msg
215
+
68
216
  def get_tools(self) -> List[FunctionTool]:
69
217
  r"""Get all tools in the toolkit.
70
218
 
71
219
  Returns:
72
220
  List[FunctionTool]: A list of tools.
73
221
  """
74
- return [FunctionTool(self.think)]
222
+ return [
223
+ FunctionTool(self.plan),
224
+ FunctionTool(self.hypothesize),
225
+ FunctionTool(self.think),
226
+ FunctionTool(self.contemplate),
227
+ FunctionTool(self.critique),
228
+ FunctionTool(self.synthesize),
229
+ FunctionTool(self.reflect),
230
+ ]
@@ -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
 
@@ -19,9 +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 retry_on_error
22
+ from camel.utils import MCPServer, retry_on_error
23
23
 
24
24
 
25
+ @MCPServer()
25
26
  class WhatsAppToolkit(BaseToolkit):
26
27
  r"""A class representing a toolkit for WhatsApp operations.
27
28
 
@@ -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 ZapierToolkit(BaseToolkit):
26
27
  r"""A class representing a toolkit for interacting with Zapier's NLA API.
27
28