Skip to content

Commit d83a79e

Browse files
feat: Refactor MCPToolkits (#3095)
Co-authored-by: Wendong-Fan <133094783+Wendong-Fan@users.noreply.github.com>
1 parent 2307871 commit d83a79e

9 files changed

+105
-183
lines changed

camel/toolkits/edgeone_pages_mcp_toolkit.py

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,12 @@
1212
# limitations under the License.
1313
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
1414

15-
from typing import List, Optional
16-
17-
from camel.toolkits import BaseToolkit, FunctionTool
15+
from typing import Optional
1816

1917
from .mcp_toolkit import MCPToolkit
2018

2119

22-
class EdgeOnePagesMCPToolkit(BaseToolkit):
20+
class EdgeOnePagesMCPToolkit(MCPToolkit):
2321
r"""EdgeOnePagesMCPToolkit provides an interface for interacting with
2422
EdgeOne pages using the EdgeOne Pages MCP server.
2523
@@ -38,32 +36,14 @@ def __init__(
3836
timeout (Optional[float]): Connection timeout in seconds.
3937
(default: :obj:`None`)
4038
"""
41-
super().__init__(timeout=timeout)
42-
43-
self._mcp_toolkit = MCPToolkit(
44-
config_dict={
45-
"mcpServers": {
46-
"edgeone-pages-mcp-server": {
47-
"command": "npx",
48-
"args": ["edgeone-pages-mcp"],
49-
}
39+
config_dict = {
40+
"mcpServers": {
41+
"edgeone-pages-mcp-server": {
42+
"command": "npx",
43+
"args": ["edgeone-pages-mcp"],
5044
}
51-
},
52-
timeout=timeout,
53-
)
54-
55-
async def connect(self):
56-
r"""Explicitly connect to the EdgeOne Pages MCP server."""
57-
await self._mcp_toolkit.connect()
45+
}
46+
}
5847

59-
async def disconnect(self):
60-
r"""Explicitly disconnect from the EdgeOne Pages MCP server."""
61-
await self._mcp_toolkit.disconnect()
62-
63-
def get_tools(self) -> List[FunctionTool]:
64-
r"""Returns a list of tools provided by the EdgeOnePagesMCPToolkit.
65-
66-
Returns:
67-
List[FunctionTool]: List of available tools.
68-
"""
69-
return self._mcp_toolkit.get_tools()
48+
# Initialize parent MCPToolkit with EdgeOne Pages configuration
49+
super().__init__(config_dict=config_dict, timeout=timeout)

camel/toolkits/google_drive_mcp_toolkit.py

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,12 @@
1212
# limitations under the License.
1313
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
1414

15-
from typing import List, Optional
16-
17-
from camel.toolkits import BaseToolkit, FunctionTool
15+
from typing import Optional
1816

1917
from .mcp_toolkit import MCPToolkit
2018

2119

22-
class GoogleDriveMCPToolkit(BaseToolkit):
20+
class GoogleDriveMCPToolkit(MCPToolkit):
2321
r"""GoogleDriveMCPToolkit provides an interface for interacting with
2422
Google Drive using the Google Drive MCP server.
2523
@@ -41,33 +39,16 @@ def __init__(
4139
credentials_path (Optional[str]): Path to the Google Drive
4240
credentials file. (default: :obj:`None`)
4341
"""
44-
super().__init__(timeout=timeout)
4542

46-
self._mcp_toolkit = MCPToolkit(
47-
config_dict={
48-
"mcpServers": {
49-
"gdrive": {
50-
"command": "npx",
51-
"args": ["-y", "@modelcontextprotocol/server-gdrive"],
52-
"env": {"GDRIVE_CREDENTIALS_PATH": credentials_path},
53-
}
43+
config_dict = {
44+
"mcpServers": {
45+
"gdrive": {
46+
"command": "npx",
47+
"args": ["-y", "@modelcontextprotocol/server-gdrive"],
48+
"env": {"GDRIVE_CREDENTIALS_PATH": credentials_path},
5449
}
55-
},
56-
timeout=timeout,
57-
)
58-
59-
async def connect(self):
60-
r"""Explicitly connect to the Google Drive MCP server."""
61-
await self._mcp_toolkit.connect()
62-
63-
async def disconnect(self):
64-
r"""Explicitly disconnect from the Google Drive MCP server."""
65-
await self._mcp_toolkit.disconnect()
50+
}
51+
}
6652

67-
def get_tools(self) -> List[FunctionTool]:
68-
r"""Returns a list of tools provided by the GoogleDriveMCPToolkit.
69-
70-
Returns:
71-
List[FunctionTool]: List of available tools.
72-
"""
73-
return self._mcp_toolkit.get_tools()
53+
# Initialize parent MCPToolkit with Playwright configuration
54+
super().__init__(config_dict=config_dict, timeout=timeout)

camel/toolkits/notion_mcp_toolkit.py

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414

1515
from typing import Any, ClassVar, Dict, List, Optional, Set
1616

17-
from camel.toolkits import BaseToolkit, FunctionTool
17+
from camel.toolkits import FunctionTool
1818

1919
from .mcp_toolkit import MCPToolkit
2020

2121

22-
class NotionMCPToolkit(BaseToolkit):
22+
class NotionMCPToolkit(MCPToolkit):
2323
r"""NotionMCPToolkit provides an interface for interacting with Notion
2424
through the Model Context Protocol (MCP).
2525
@@ -75,31 +75,21 @@ def __init__(
7575
timeout (Optional[float]): Connection timeout in seconds.
7676
(default: :obj:`None`)
7777
"""
78-
super().__init__(timeout=timeout)
79-
80-
self._mcp_toolkit = MCPToolkit(
81-
config_dict={
82-
"mcpServers": {
83-
"notionMCP": {
84-
"command": "npx",
85-
"args": [
86-
"-y",
87-
"mcp-remote",
88-
"https://mcp.notion.com/mcp",
89-
],
90-
}
78+
config_dict = {
79+
"mcpServers": {
80+
"notionMCP": {
81+
"command": "npx",
82+
"args": [
83+
"-y",
84+
"mcp-remote",
85+
"https://mcp.notion.com/mcp",
86+
],
9187
}
92-
},
93-
timeout=timeout,
94-
)
95-
96-
async def connect(self):
97-
r"""Explicitly connect to the Notion MCP server."""
98-
await self._mcp_toolkit.connect()
88+
}
89+
}
9990

100-
async def disconnect(self):
101-
r"""Explicitly disconnect from the Notion MCP server."""
102-
await self._mcp_toolkit.disconnect()
91+
# Initialize parent MCPToolkit with Notion configuration
92+
super().__init__(config_dict=config_dict, timeout=timeout)
10393

10494
def get_tools(self) -> List[FunctionTool]:
10595
r"""Returns a list of tools provided by the NotionMCPToolkit.
@@ -108,7 +98,7 @@ def get_tools(self) -> List[FunctionTool]:
10898
List[FunctionTool]: List of available tools.
10999
"""
110100
all_tools = []
111-
for client in self._mcp_toolkit.clients:
101+
for client in self.clients:
112102
try:
113103
original_build_schema = client._build_tool_schema
114104

camel/toolkits/origene_mcp_toolkit.py

Lines changed: 7 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@
1212
# limitations under the License.
1313
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
1414

15-
from typing import Dict, List, Optional
15+
from typing import Dict, Optional
1616

17-
from camel.toolkits import BaseToolkit, FunctionTool, MCPToolkit
17+
from .mcp_toolkit import MCPToolkit
1818

1919

20-
class OrigeneToolkit(BaseToolkit):
20+
class OrigeneToolkit(MCPToolkit):
2121
r"""OrigeneToolkit provides an interface for interacting with
2222
Origene MCP server.
2323
@@ -43,55 +43,14 @@ def __init__(
4343
4444
Args:
4545
config_dict (Optional[Dict]): Configuration dictionary for MCP
46-
servers. If None, uses default configuration for chembl_mcp.
46+
servers. If None, raises ValueError as configuration is required.
4747
(default: :obj:`None`)
4848
timeout (Optional[float]): Connection timeout in seconds.
4949
(default: :obj:`None`)
5050
"""
51-
super().__init__(timeout=timeout)
52-
53-
# Use default configuration if none provided
51+
# Validate that config_dict is provided
5452
if config_dict is None:
5553
raise ValueError("config_dict must be provided")
5654

57-
self._mcp_toolkit = MCPToolkit(
58-
config_dict=config_dict,
59-
timeout=timeout,
60-
)
61-
62-
async def connect(self):
63-
r"""Explicitly connect to the Origene MCP server."""
64-
await self._mcp_toolkit.connect()
65-
66-
async def disconnect(self):
67-
r"""Explicitly disconnect from the Origene MCP server."""
68-
await self._mcp_toolkit.disconnect()
69-
70-
async def __aenter__(self) -> "OrigeneToolkit":
71-
r"""Async context manager entry point.
72-
73-
Returns:
74-
OrigeneToolkit: The connected toolkit instance.
75-
76-
Example:
77-
async with OrigeneToolkit(config_dict=config) as toolkit:
78-
tools = toolkit.get_tools()
79-
"""
80-
await self.connect()
81-
return self
82-
83-
async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
84-
r"""Async context manager exit point.
85-
86-
Automatically disconnects from the Origene MCP server.
87-
"""
88-
await self.disconnect()
89-
return None
90-
91-
def get_tools(self) -> List[FunctionTool]:
92-
r"""Returns a list of tools provided by the Origene MCP server.
93-
94-
Returns:
95-
List[FunctionTool]: List of available tools.
96-
"""
97-
return self._mcp_toolkit.get_tools()
55+
# Initialize parent MCPToolkit with provided configuration
56+
super().__init__(config_dict=config_dict, timeout=timeout)

camel/toolkits/playwright_mcp_toolkit.py

Lines changed: 14 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414

1515
from typing import List, Optional
1616

17-
from camel.toolkits import BaseToolkit, FunctionTool
17+
from camel.toolkits import FunctionTool
1818

1919
from .mcp_toolkit import MCPToolkit
2020

2121

22-
class PlaywrightMCPToolkit(BaseToolkit):
22+
class PlaywrightMCPToolkit(MCPToolkit):
2323
r"""PlaywrightMCPToolkit provides an interface for interacting with web
2424
browsers using the Playwright automation library through the Model Context
2525
Protocol (MCP).
@@ -51,33 +51,18 @@ def __init__(
5151
`["--cdp-endpoint=http://localhost:9222"]`.
5252
(default: :obj:`None`)
5353
"""
54-
super().__init__(timeout=timeout)
55-
56-
self._mcp_toolkit = MCPToolkit(
57-
config_dict={
58-
"mcpServers": {
59-
"playwright": {
60-
"command": "npx",
61-
"args": ["@playwright/mcp@latest"]
62-
+ (additional_args or []),
63-
}
54+
# Create config for Playwright MCP server
55+
config_dict = {
56+
"mcpServers": {
57+
"playwright": {
58+
"command": "npx",
59+
"args": ["@playwright/mcp@latest"]
60+
+ (additional_args or []),
6461
}
65-
},
66-
timeout=timeout,
67-
)
68-
69-
async def connect(self):
70-
r"""Explicitly connect to the Playwright MCP server."""
71-
await self._mcp_toolkit.connect()
62+
}
63+
}
64+
65+
# Initialize parent MCPToolkit with Playwright configuration
66+
super().__init__(config_dict=config_dict, timeout=timeout)
7267

73-
async def disconnect(self):
74-
r"""Explicitly disconnect from the Playwright MCP server."""
75-
await self._mcp_toolkit.disconnect()
7668

77-
def get_tools(self) -> List[FunctionTool]:
78-
r"""Returns a list of tools provided by the PlaywrightMCPToolkit.
79-
80-
Returns:
81-
List[FunctionTool]: List of available tools.
82-
"""
83-
return self._mcp_toolkit.get_tools()

examples/toolkits/edgeone_pages_mcp_toolkit.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ async def main():
3838
response = await chat_agent.astep(
3939
"write a hello world page",
4040
)
41+
42+
print("=== Model Response ===")
4143
print(response.msg.content)
4244

4345
# disconnect from edgeone pages mcp
@@ -50,7 +52,14 @@ async def main():
5052

5153
"""
5254
==============================================================================
53-
I have created a "Hello, World!" web page for you. You can view it here:
54-
https://mcp.edgeone.site/share/7D8SNj2ftY9SRtPrWZ5rW
55+
I've created a Hello World page for you! The page has been deployed and is now live at:
56+
57+
**https://mcp.edgeone.site/share/M-MXzJzHJ3mGc013OQNIM**
58+
59+
The page features:
60+
- A modern, gradient background
61+
- Centered "Hello World!" heading
62+
- Clean, responsive design
63+
- A welcome message below the main heading
5564
==============================================================================
5665
"""

examples/toolkits/goole_drive_mcp_toolkit.py renamed to examples/toolkits/google_drive_mcp_toolkit.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ async def main():
4040
response = await chat_agent.astep(
4141
"what is the name of the file in the root of my drive?",
4242
)
43+
44+
print("=== Model Response ===")
4345
print(response.msg.content)
4446

4547
# disconnect from google drive mcp

0 commit comments

Comments
 (0)