mcp-use 0.0.6__py3-none-any.whl → 1.0.0__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 mcp-use might be problematic. Click here for more details.
- mcp_use/agents/langchain_agent.py +62 -77
- mcp_use/agents/mcpagent.py +34 -31
- mcp_use/client.py +55 -42
- {mcp_use-0.0.6.dist-info → mcp_use-1.0.0.dist-info}/METADATA +63 -2
- {mcp_use-0.0.6.dist-info → mcp_use-1.0.0.dist-info}/RECORD +7 -7
- {mcp_use-0.0.6.dist-info → mcp_use-1.0.0.dist-info}/WHEEL +0 -0
- {mcp_use-0.0.6.dist-info → mcp_use-1.0.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -78,7 +78,7 @@ class LangChainAgent:
|
|
|
78
78
|
|
|
79
79
|
def __init__(
|
|
80
80
|
self,
|
|
81
|
-
|
|
81
|
+
connectors: list[BaseConnector],
|
|
82
82
|
llm: BaseLanguageModel,
|
|
83
83
|
max_steps: int = 5,
|
|
84
84
|
system_message: str | None = None,
|
|
@@ -91,7 +91,7 @@ class LangChainAgent:
|
|
|
91
91
|
max_steps: The maximum number of steps to take.
|
|
92
92
|
system_message: Optional custom system message to use.
|
|
93
93
|
"""
|
|
94
|
-
self.
|
|
94
|
+
self.connectors = connectors
|
|
95
95
|
self.llm = llm
|
|
96
96
|
self.max_steps = max_steps
|
|
97
97
|
self.system_message = system_message or self.DEFAULT_SYSTEM_MESSAGE
|
|
@@ -139,67 +139,70 @@ class LangChainAgent:
|
|
|
139
139
|
Returns:
|
|
140
140
|
A list of LangChain tools created from MCP tools.
|
|
141
141
|
"""
|
|
142
|
-
tools = self.connector.tools
|
|
143
|
-
local_connector = self.connector
|
|
144
|
-
|
|
145
|
-
# Wrap MCP tools into LangChain tools
|
|
146
142
|
langchain_tools: list[BaseTool] = []
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
143
|
+
|
|
144
|
+
for connector in self.connectors:
|
|
145
|
+
tools = connector.tools
|
|
146
|
+
local_connector = connector
|
|
147
|
+
|
|
148
|
+
# Wrap MCP tools into LangChain tools
|
|
149
|
+
for tool in tools:
|
|
150
|
+
# Define adapter class to convert MCP tool to LangChain format
|
|
151
|
+
class McpToLangChainAdapter(BaseTool):
|
|
152
|
+
name: str = tool.name or "NO NAME"
|
|
153
|
+
description: str = tool.description or ""
|
|
154
|
+
# Convert JSON schema to Pydantic model for argument validation
|
|
155
|
+
args_schema: type[BaseModel] = jsonschema_to_pydantic(
|
|
156
|
+
self.fix_schema(tool.inputSchema) # Apply schema conversion
|
|
157
|
+
)
|
|
158
|
+
connector: BaseConnector = local_connector
|
|
159
|
+
handle_tool_error: bool = True
|
|
160
|
+
|
|
161
|
+
def _run(self, **kwargs: Any) -> NoReturn:
|
|
162
|
+
"""Synchronous run method that always raises an error.
|
|
163
|
+
|
|
164
|
+
Raises:
|
|
165
|
+
NotImplementedError: Always raises this error because MCP tools
|
|
166
|
+
only support async operations.
|
|
167
|
+
"""
|
|
168
|
+
raise NotImplementedError("MCP tools only support async operations")
|
|
169
|
+
|
|
170
|
+
async def _arun(self, **kwargs: Any) -> Any:
|
|
171
|
+
"""Asynchronously execute the tool with given arguments.
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
kwargs: The arguments to pass to the tool.
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
The result of the tool execution.
|
|
178
|
+
|
|
179
|
+
Raises:
|
|
180
|
+
ToolException: If tool execution fails.
|
|
181
|
+
"""
|
|
182
|
+
logger.info(f'MCP tool: "{self.name}" received input: {kwargs}')
|
|
183
|
+
|
|
186
184
|
try:
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
except Exception as e:
|
|
190
|
-
# Log the exception for debugging
|
|
191
|
-
logger.error(f"Error parsing tool result: {e}")
|
|
192
|
-
# Shortened line:
|
|
193
|
-
return (
|
|
194
|
-
f"Error parsing result: {e!s}; Raw content: {tool_result.content!r}"
|
|
185
|
+
tool_result: CallToolResult = await self.connector.call_tool(
|
|
186
|
+
self.name, kwargs
|
|
195
187
|
)
|
|
188
|
+
try:
|
|
189
|
+
# Use the helper function to parse the result
|
|
190
|
+
return _parse_mcp_tool_result(tool_result)
|
|
191
|
+
except Exception as e:
|
|
192
|
+
# Log the exception for debugging
|
|
193
|
+
logger.error(f"Error parsing tool result: {e}")
|
|
194
|
+
# Shortened line:
|
|
195
|
+
return (
|
|
196
|
+
f"Error parsing result: {e!s};"
|
|
197
|
+
f" Raw content: {tool_result.content!r}"
|
|
198
|
+
)
|
|
196
199
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
200
|
+
except Exception as e:
|
|
201
|
+
if self.handle_tool_error:
|
|
202
|
+
return f"Error executing MCP tool: {str(e)}"
|
|
203
|
+
raise
|
|
201
204
|
|
|
202
|
-
|
|
205
|
+
langchain_tools.append(McpToLangChainAdapter())
|
|
203
206
|
|
|
204
207
|
# Log available tools for debugging
|
|
205
208
|
logger.info(f"Available tools: {[tool.name for tool in langchain_tools]}")
|
|
@@ -256,25 +259,7 @@ class LangChainAgent:
|
|
|
256
259
|
if chat_history is None:
|
|
257
260
|
chat_history = []
|
|
258
261
|
|
|
259
|
-
# Add a hint to use tools for queries about current information
|
|
260
|
-
enhanced_query = query
|
|
261
|
-
if any(
|
|
262
|
-
keyword in query.lower()
|
|
263
|
-
for keyword in [
|
|
264
|
-
"weather",
|
|
265
|
-
"current",
|
|
266
|
-
"today",
|
|
267
|
-
"now",
|
|
268
|
-
"latest",
|
|
269
|
-
"news",
|
|
270
|
-
"price",
|
|
271
|
-
"stock",
|
|
272
|
-
]
|
|
273
|
-
):
|
|
274
|
-
# Just log this, don't modify the query
|
|
275
|
-
logger.info("Query involves current information that may benefit from tool use")
|
|
276
|
-
|
|
277
262
|
# Invoke with all required variables
|
|
278
|
-
result = await self.agent.ainvoke({"input":
|
|
263
|
+
result = await self.agent.ainvoke({"input": query, "chat_history": chat_history})
|
|
279
264
|
|
|
280
265
|
return result["output"]
|
mcp_use/agents/mcpagent.py
CHANGED
|
@@ -31,7 +31,7 @@ class MCPAgent:
|
|
|
31
31
|
self,
|
|
32
32
|
llm: BaseLanguageModel,
|
|
33
33
|
client: MCPClient | None = None,
|
|
34
|
-
|
|
34
|
+
connectors: list[BaseConnector] | None = None,
|
|
35
35
|
server_name: str | None = None,
|
|
36
36
|
max_steps: int = 5,
|
|
37
37
|
auto_initialize: bool = False,
|
|
@@ -45,7 +45,7 @@ class MCPAgent:
|
|
|
45
45
|
Args:
|
|
46
46
|
llm: The LangChain LLM to use.
|
|
47
47
|
client: The MCPClient to use. If provided, connector is ignored.
|
|
48
|
-
|
|
48
|
+
connectors: A list of MCP connectors to use if client is not provided.
|
|
49
49
|
server_name: The name of the server to use if client is provided.
|
|
50
50
|
max_steps: The maximum number of steps to take.
|
|
51
51
|
auto_initialize: Whether to automatically initialize the agent when run is called.
|
|
@@ -56,7 +56,7 @@ class MCPAgent:
|
|
|
56
56
|
"""
|
|
57
57
|
self.llm = llm
|
|
58
58
|
self.client = client
|
|
59
|
-
self.
|
|
59
|
+
self.connectors = connectors
|
|
60
60
|
self.server_name = server_name
|
|
61
61
|
self.max_steps = max_steps
|
|
62
62
|
self.auto_initialize = auto_initialize
|
|
@@ -70,34 +70,35 @@ class MCPAgent:
|
|
|
70
70
|
self.additional_instructions = additional_instructions
|
|
71
71
|
|
|
72
72
|
# Either client or connector must be provided
|
|
73
|
-
if not client and
|
|
73
|
+
if not client and len(connectors) == 0:
|
|
74
74
|
raise ValueError("Either client or connector must be provided")
|
|
75
75
|
|
|
76
76
|
self._agent: LangChainAgent | None = None
|
|
77
|
-
self.
|
|
77
|
+
self._sessions: dict[str, MCPSession] | None = None
|
|
78
78
|
self._system_message: SystemMessage | None = None
|
|
79
79
|
|
|
80
80
|
async def initialize(self) -> None:
|
|
81
81
|
"""Initialize the MCP client and agent."""
|
|
82
82
|
# If using client, get or create a session
|
|
83
83
|
if self.client:
|
|
84
|
-
try
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
84
|
+
# First try to get existing sessions
|
|
85
|
+
self._sessions = self.client.get_all_active_sessions()
|
|
86
|
+
|
|
87
|
+
# If no active sessions exist, create new ones
|
|
88
|
+
if not self._sessions:
|
|
89
|
+
self._sessions = await self.client.create_all_sessions()
|
|
90
|
+
connectors_to_use = [session.connector for session in self._sessions.values()]
|
|
89
91
|
else:
|
|
90
92
|
# Using direct connector
|
|
91
|
-
|
|
92
|
-
await
|
|
93
|
-
await
|
|
94
|
-
|
|
93
|
+
connectors_to_use = self.connectors
|
|
94
|
+
await [c_to_use.connect() for c_to_use in connectors_to_use]
|
|
95
|
+
await [c_to_use.initialize() for c_to_use in connectors_to_use]
|
|
95
96
|
# Create the system message based on available tools
|
|
96
|
-
await self._create_system_message(
|
|
97
|
+
await self._create_system_message(connectors_to_use)
|
|
97
98
|
|
|
98
99
|
# Create the agent
|
|
99
100
|
self._agent = LangChainAgent(
|
|
100
|
-
|
|
101
|
+
connectors=connectors_to_use,
|
|
101
102
|
llm=self.llm,
|
|
102
103
|
max_steps=self.max_steps,
|
|
103
104
|
system_message=(self._system_message.content if self._system_message else None),
|
|
@@ -107,7 +108,7 @@ class MCPAgent:
|
|
|
107
108
|
await self._agent.initialize()
|
|
108
109
|
self._initialized = True
|
|
109
110
|
|
|
110
|
-
async def _create_system_message(self,
|
|
111
|
+
async def _create_system_message(self, connectors: list[BaseConnector]) -> None:
|
|
111
112
|
"""Create the system message based on available tools.
|
|
112
113
|
|
|
113
114
|
Args:
|
|
@@ -119,15 +120,17 @@ class MCPAgent:
|
|
|
119
120
|
return
|
|
120
121
|
|
|
121
122
|
# Otherwise, build the system prompt from the template and tool descriptions
|
|
122
|
-
tools = connector.tools
|
|
123
|
-
|
|
124
|
-
# Generate tool descriptions
|
|
125
123
|
tool_descriptions = []
|
|
126
|
-
for
|
|
127
|
-
|
|
128
|
-
#
|
|
129
|
-
|
|
130
|
-
|
|
124
|
+
for connector in connectors:
|
|
125
|
+
tools = connector.tools
|
|
126
|
+
# Generate tool descriptions
|
|
127
|
+
for tool in tools:
|
|
128
|
+
# Escape curly braces in the description by doubling them
|
|
129
|
+
# (sometimes e.g. blender mcp they are used in the description)
|
|
130
|
+
description = (
|
|
131
|
+
f"- {tool.name}: {tool.description.replace('{', '{{').replace('}', '}}')}"
|
|
132
|
+
)
|
|
133
|
+
tool_descriptions.append(description)
|
|
131
134
|
|
|
132
135
|
# Format the system prompt template with tool descriptions
|
|
133
136
|
system_prompt = self.system_prompt_template.format(
|
|
@@ -140,7 +143,6 @@ class MCPAgent:
|
|
|
140
143
|
|
|
141
144
|
# Create the system message
|
|
142
145
|
self._system_message = SystemMessage(content=system_prompt)
|
|
143
|
-
logger.info(f"Created system message with {len(tools)} tool descriptions")
|
|
144
146
|
|
|
145
147
|
def get_conversation_history(self) -> list[BaseMessage]:
|
|
146
148
|
"""Get the current conversation history.
|
|
@@ -290,14 +292,15 @@ class MCPAgent:
|
|
|
290
292
|
self._agent = None
|
|
291
293
|
|
|
292
294
|
# If using client with session, close the session through client
|
|
293
|
-
if self.client and self.
|
|
295
|
+
if self.client and self._sessions:
|
|
294
296
|
logger.debug("Closing session through client")
|
|
295
|
-
await self.client.
|
|
297
|
+
await self.client.close_all_sessions()
|
|
296
298
|
self._session = None
|
|
297
299
|
# If using direct connector, disconnect
|
|
298
|
-
elif self.
|
|
299
|
-
|
|
300
|
-
|
|
300
|
+
elif self.connectors:
|
|
301
|
+
for connector in self.connectors:
|
|
302
|
+
logger.debug("Disconnecting connector")
|
|
303
|
+
await connector.disconnect()
|
|
301
304
|
|
|
302
305
|
self._initialized = False
|
|
303
306
|
logger.info("Agent closed successfully")
|
mcp_use/client.py
CHANGED
|
@@ -32,7 +32,7 @@ class MCPClient:
|
|
|
32
32
|
"""
|
|
33
33
|
self.config: dict[str, Any] = {}
|
|
34
34
|
self.sessions: dict[str, MCPSession] = {}
|
|
35
|
-
self.
|
|
35
|
+
self.active_sessions: list[str] = []
|
|
36
36
|
|
|
37
37
|
# Load configuration if provided
|
|
38
38
|
if config is not None:
|
|
@@ -84,9 +84,9 @@ class MCPClient:
|
|
|
84
84
|
if "mcpServers" in self.config and name in self.config["mcpServers"]:
|
|
85
85
|
del self.config["mcpServers"][name]
|
|
86
86
|
|
|
87
|
-
# If we removed
|
|
88
|
-
if name
|
|
89
|
-
self.
|
|
87
|
+
# If we removed an active session, remove it from active_sessions
|
|
88
|
+
if name in self.active_sessions:
|
|
89
|
+
self.active_sessions.remove(name)
|
|
90
90
|
|
|
91
91
|
def get_server_names(self) -> list[str]:
|
|
92
92
|
"""Get the list of configured server names.
|
|
@@ -105,17 +105,11 @@ class MCPClient:
|
|
|
105
105
|
with open(filepath, "w") as f:
|
|
106
106
|
json.dump(self.config, f, indent=2)
|
|
107
107
|
|
|
108
|
-
async def create_session(
|
|
109
|
-
self,
|
|
110
|
-
server_name: str | None = None,
|
|
111
|
-
auto_initialize: bool = True,
|
|
112
|
-
) -> MCPSession:
|
|
108
|
+
async def create_session(self, server_name: str, auto_initialize: bool = True) -> MCPSession:
|
|
113
109
|
"""Create a session for the specified server.
|
|
114
110
|
|
|
115
111
|
Args:
|
|
116
112
|
server_name: The name of the server to create a session for.
|
|
117
|
-
If None, uses the first available server.
|
|
118
|
-
auto_initialize: Whether to automatically initialize the session.
|
|
119
113
|
|
|
120
114
|
Returns:
|
|
121
115
|
The created MCPSession.
|
|
@@ -128,10 +122,6 @@ class MCPClient:
|
|
|
128
122
|
if not servers:
|
|
129
123
|
raise ValueError("No MCP servers defined in config")
|
|
130
124
|
|
|
131
|
-
# If server_name not specified, use the first one
|
|
132
|
-
if not server_name:
|
|
133
|
-
server_name = next(iter(servers.keys()))
|
|
134
|
-
|
|
135
125
|
if server_name not in servers:
|
|
136
126
|
raise ValueError(f"Server '{server_name}' not found in config")
|
|
137
127
|
|
|
@@ -140,57 +130,80 @@ class MCPClient:
|
|
|
140
130
|
|
|
141
131
|
# Create the session
|
|
142
132
|
session = MCPSession(connector)
|
|
143
|
-
self.sessions[server_name] = session
|
|
144
|
-
|
|
145
|
-
# Make this the active session
|
|
146
|
-
self.active_session = server_name
|
|
147
|
-
|
|
148
|
-
# Initialize if requested
|
|
149
133
|
if auto_initialize:
|
|
150
134
|
await session.initialize()
|
|
135
|
+
self.sessions[server_name] = session
|
|
136
|
+
|
|
137
|
+
# Add to active sessions
|
|
138
|
+
if server_name not in self.active_sessions:
|
|
139
|
+
self.active_sessions.append(server_name)
|
|
151
140
|
|
|
152
141
|
return session
|
|
153
142
|
|
|
154
|
-
def
|
|
143
|
+
async def create_all_sessions(
|
|
144
|
+
self,
|
|
145
|
+
auto_initialize: bool = True,
|
|
146
|
+
) -> dict[str, MCPSession]:
|
|
147
|
+
"""Create a session for the specified server.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
auto_initialize: Whether to automatically initialize the session.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
The created MCPSession. If server_name is None, returns the first created session.
|
|
154
|
+
|
|
155
|
+
Raises:
|
|
156
|
+
ValueError: If no servers are configured or the specified server doesn't exist.
|
|
157
|
+
"""
|
|
158
|
+
# Get server config
|
|
159
|
+
servers = self.config.get("mcpServers", {})
|
|
160
|
+
if not servers:
|
|
161
|
+
raise ValueError("No MCP servers defined in config")
|
|
162
|
+
|
|
163
|
+
# Create sessions for all servers
|
|
164
|
+
for name in servers:
|
|
165
|
+
session = await self.create_session(name, auto_initialize)
|
|
166
|
+
if auto_initialize:
|
|
167
|
+
await session.initialize()
|
|
168
|
+
|
|
169
|
+
return self.sessions
|
|
170
|
+
|
|
171
|
+
def get_session(self, server_name: str) -> MCPSession:
|
|
155
172
|
"""Get an existing session.
|
|
156
173
|
|
|
157
174
|
Args:
|
|
158
175
|
server_name: The name of the server to get the session for.
|
|
159
|
-
If None, uses the active session.
|
|
176
|
+
If None, uses the first active session.
|
|
160
177
|
|
|
161
178
|
Returns:
|
|
162
179
|
The MCPSession for the specified server.
|
|
163
180
|
|
|
164
181
|
Raises:
|
|
165
|
-
ValueError: If no active
|
|
182
|
+
ValueError: If no active sessions exist or the specified session doesn't exist.
|
|
166
183
|
"""
|
|
167
|
-
if server_name is None:
|
|
168
|
-
if self.active_session is None:
|
|
169
|
-
raise ValueError("No active session")
|
|
170
|
-
server_name = self.active_session
|
|
171
|
-
|
|
172
184
|
if server_name not in self.sessions:
|
|
173
185
|
raise ValueError(f"No session exists for server '{server_name}'")
|
|
174
186
|
|
|
175
187
|
return self.sessions[server_name]
|
|
176
188
|
|
|
177
|
-
|
|
189
|
+
def get_all_active_sessions(self) -> dict[str, MCPSession]:
|
|
190
|
+
"""Get all active sessions.
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
Dictionary mapping server names to their MCPSession instances.
|
|
194
|
+
"""
|
|
195
|
+
return {name: self.sessions[name] for name in self.active_sessions if name in self.sessions}
|
|
196
|
+
|
|
197
|
+
async def close_session(self, server_name: str) -> None:
|
|
178
198
|
"""Close a session.
|
|
179
199
|
|
|
180
200
|
Args:
|
|
181
201
|
server_name: The name of the server to close the session for.
|
|
182
|
-
If None, uses the active session.
|
|
202
|
+
If None, uses the first active session.
|
|
183
203
|
|
|
184
204
|
Raises:
|
|
185
|
-
ValueError: If no active
|
|
205
|
+
ValueError: If no active sessions exist or the specified session doesn't exist.
|
|
186
206
|
"""
|
|
187
|
-
# Determine which server to close
|
|
188
|
-
if server_name is None:
|
|
189
|
-
if self.active_session is None:
|
|
190
|
-
logger.warning("No active session to close")
|
|
191
|
-
return
|
|
192
|
-
server_name = self.active_session
|
|
193
|
-
|
|
194
207
|
# Check if the session exists
|
|
195
208
|
if server_name not in self.sessions:
|
|
196
209
|
logger.warning(f"No session exists for server '{server_name}', nothing to close")
|
|
@@ -209,9 +222,9 @@ class MCPClient:
|
|
|
209
222
|
# Remove the session regardless of whether disconnect succeeded
|
|
210
223
|
del self.sessions[server_name]
|
|
211
224
|
|
|
212
|
-
#
|
|
213
|
-
if server_name
|
|
214
|
-
self.
|
|
225
|
+
# Remove from active_sessions
|
|
226
|
+
if server_name in self.active_sessions:
|
|
227
|
+
self.active_sessions.remove(server_name)
|
|
215
228
|
|
|
216
229
|
async def close_all_sessions(self) -> None:
|
|
217
230
|
"""Close all active sessions.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcp-use
|
|
3
|
-
Version: 0.0
|
|
3
|
+
Version: 1.0.0
|
|
4
4
|
Summary: MCP Library for LLMs
|
|
5
5
|
Author-email: Pietro Zullo <pietro.zullo@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -285,9 +285,70 @@ if __name__ == "__main__":
|
|
|
285
285
|
asyncio.run(main())
|
|
286
286
|
```
|
|
287
287
|
|
|
288
|
+
# Multi-Server Support
|
|
289
|
+
|
|
290
|
+
MCP-Use supports working with multiple MCP servers simultaneously, allowing you to combine tools from different servers in a single agent. This is useful for complex tasks that require multiple capabilities, such as web browsing combined with file operations or 3D modeling.
|
|
291
|
+
|
|
292
|
+
## Configuration
|
|
293
|
+
|
|
294
|
+
You can configure multiple servers in your configuration file:
|
|
295
|
+
|
|
296
|
+
```json
|
|
297
|
+
{
|
|
298
|
+
"mcpServers": {
|
|
299
|
+
"airbnb": {
|
|
300
|
+
"command": "npx",
|
|
301
|
+
"args": ["-y", "@openbnb/mcp-server-airbnb", "--ignore-robots-txt"]
|
|
302
|
+
},
|
|
303
|
+
"playwright": {
|
|
304
|
+
"command": "npx",
|
|
305
|
+
"args": ["@playwright/mcp@latest"],
|
|
306
|
+
"env": {
|
|
307
|
+
"DISPLAY": ":1"
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
## Usage
|
|
315
|
+
|
|
316
|
+
The `MCPClient` class provides several methods for managing multiple servers:
|
|
317
|
+
|
|
318
|
+
```python
|
|
319
|
+
import asyncio
|
|
320
|
+
from mcp_use import MCPClient, MCPAgent
|
|
321
|
+
from langchain_anthropic import ChatAnthropic
|
|
322
|
+
|
|
323
|
+
async def main():
|
|
324
|
+
# Create client with multiple servers
|
|
325
|
+
client = MCPClient.from_config_file("multi_server_config.json")
|
|
326
|
+
|
|
327
|
+
# Create agent with the client
|
|
328
|
+
agent = MCPAgent(
|
|
329
|
+
llm=ChatAnthropic(model="claude-3-5-sonnet-20240620"),
|
|
330
|
+
client=client
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
try:
|
|
334
|
+
# Run a query that uses tools from multiple servers
|
|
335
|
+
result = await agent.run(
|
|
336
|
+
"Search for a nice place to stay in Barcelona on Airbnb, "
|
|
337
|
+
"then use Google to find nearby restaurants and attractions."
|
|
338
|
+
)
|
|
339
|
+
print(result)
|
|
340
|
+
finally:
|
|
341
|
+
# Clean up all sessions
|
|
342
|
+
await client.close_all_sessions()
|
|
343
|
+
|
|
344
|
+
if __name__ == "__main__":
|
|
345
|
+
asyncio.run(main())
|
|
346
|
+
```
|
|
347
|
+
|
|
288
348
|
## Roadmap
|
|
349
|
+
|
|
289
350
|
<ul>
|
|
290
|
-
<li>[
|
|
351
|
+
<li>[x] Multiple Servers at once </li>
|
|
291
352
|
<li>[ ] Test remote connectors (http, ws)</li>
|
|
292
353
|
<li>[ ] ... </li>
|
|
293
354
|
</ul>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
mcp_use/__init__.py,sha256=PSoxLAu1GPjfIDPcZiJyI3k66MMS3lcfx5kERUgFb1o,723
|
|
2
|
-
mcp_use/client.py,sha256=
|
|
2
|
+
mcp_use/client.py,sha256=0rvlJBwvPD19sjDRtXfnp15-F1VHJlXWxLQNt9cHwPA,8275
|
|
3
3
|
mcp_use/config.py,sha256=D9LuCuT1mFUSBiO2DUGa5Pnd-yjNcvM9u_v11N5UmK8,1624
|
|
4
4
|
mcp_use/logging.py,sha256=2-hSB7ZWcHEx_OFHNg8GIbSGCZx3MW4mZGGWxi2Ew3E,2690
|
|
5
5
|
mcp_use/session.py,sha256=Z4EZTUnQUX0QyGMzkJIrMRTX4SDk6qQUoBld408LIJE,3449
|
|
6
6
|
mcp_use/agents/__init__.py,sha256=ukchMTqCOID6ikvLmJ-6sldWTVFIzztGQo4BX6QeQr8,312
|
|
7
7
|
mcp_use/agents/base.py,sha256=bfuldi_89AbSbNc8KeTiCArRT9V62CNxHOWYkLHWjyA,1605
|
|
8
|
-
mcp_use/agents/langchain_agent.py,sha256=
|
|
9
|
-
mcp_use/agents/mcpagent.py,sha256=
|
|
8
|
+
mcp_use/agents/langchain_agent.py,sha256=q6zIb9J9fc15HRGDjPAhmPdM_8UOqQToy8ESeyry1kc,10035
|
|
9
|
+
mcp_use/agents/mcpagent.py,sha256=lTRutdT1QIMiTbMSKfSbqlqNq_Y6uDPfkjAzJAKb6H0,12727
|
|
10
10
|
mcp_use/agents/prompts/default.py,sha256=tnwt9vOiVBhdpu-lIHhwEJo3rvE6EobPfUgS9JURBzg,941
|
|
11
11
|
mcp_use/connectors/__init__.py,sha256=jnd-7pPPJMb0UNJ6aD9lInj5Tlamc8lA_mFyG8RWJpo,385
|
|
12
12
|
mcp_use/connectors/base.py,sha256=caUaTfsODUOik8JF9mPtcZDyZhoIz2X12I_BhAfZK10,1616
|
|
@@ -18,7 +18,7 @@ mcp_use/task_managers/base.py,sha256=ksNdxTwq8N-zqymxVoKGnWXq9iqkLYC61uB91o6Mh-4
|
|
|
18
18
|
mcp_use/task_managers/http.py,sha256=XhrF73RGRnVctBVW2FlFrFTJR2pIGXhtNvfJFiW0Olw,1881
|
|
19
19
|
mcp_use/task_managers/stdio.py,sha256=DEISpXv4mo3d5a-WT8lkWbrXJwUh7QW0nMT_IM3fHGg,2269
|
|
20
20
|
mcp_use/task_managers/websocket.py,sha256=SVgTLFogiynb48eyi6ZioWIKLLWiVBCNE59rXi6GrCM,1943
|
|
21
|
-
mcp_use-0.0.
|
|
22
|
-
mcp_use-0.0.
|
|
23
|
-
mcp_use-0.0.
|
|
24
|
-
mcp_use-0.0.
|
|
21
|
+
mcp_use-1.0.0.dist-info/METADATA,sha256=SutQOwdz5oeqwsqGZJEgALeYG3evLZ8pNabca1lJppw,10113
|
|
22
|
+
mcp_use-1.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
23
|
+
mcp_use-1.0.0.dist-info/licenses/LICENSE,sha256=7Pw7dbwJSBw8zH-WE03JnR5uXvitRtaGTP9QWPcexcs,1068
|
|
24
|
+
mcp_use-1.0.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|