mcp-use 1.2.13__py3-none-any.whl → 1.3.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/mcpagent.py +8 -12
- mcp_use/client.py +18 -9
- mcp_use/config.py +30 -4
- mcp_use/connectors/__init__.py +12 -5
- mcp_use/connectors/sandbox.py +291 -0
- mcp_use/connectors/utils.py +13 -0
- mcp_use/types/clientoptions.py +23 -0
- mcp_use/types/sandbox.py +23 -0
- {mcp_use-1.2.13.dist-info → mcp_use-1.3.0.dist-info}/METADATA +146 -19
- {mcp_use-1.2.13.dist-info → mcp_use-1.3.0.dist-info}/RECORD +12 -8
- {mcp_use-1.2.13.dist-info → mcp_use-1.3.0.dist-info}/WHEEL +0 -0
- {mcp_use-1.2.13.dist-info → mcp_use-1.3.0.dist-info}/licenses/LICENSE +0 -0
mcp_use/agents/mcpagent.py
CHANGED
|
@@ -9,6 +9,7 @@ import logging
|
|
|
9
9
|
from collections.abc import AsyncIterator
|
|
10
10
|
|
|
11
11
|
from langchain.agents import AgentExecutor, create_tool_calling_agent
|
|
12
|
+
from langchain.agents.output_parsers.tools import ToolAgentAction
|
|
12
13
|
from langchain.globals import set_debug
|
|
13
14
|
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
|
|
14
15
|
from langchain.schema import AIMessage, BaseMessage, HumanMessage, SystemMessage
|
|
@@ -21,7 +22,6 @@ from langchain_core.utils.input import get_color_mapping
|
|
|
21
22
|
|
|
22
23
|
from mcp_use.client import MCPClient
|
|
23
24
|
from mcp_use.connectors.base import BaseConnector
|
|
24
|
-
from mcp_use.session import MCPSession
|
|
25
25
|
|
|
26
26
|
from ..adapters.langchain_adapter import LangChainAdapter
|
|
27
27
|
from ..logging import logger
|
|
@@ -102,9 +102,7 @@ class MCPAgent:
|
|
|
102
102
|
|
|
103
103
|
# State tracking
|
|
104
104
|
self._agent_executor: AgentExecutor | None = None
|
|
105
|
-
self._sessions: dict[str, MCPSession] = {}
|
|
106
105
|
self._system_message: SystemMessage | None = None
|
|
107
|
-
self._tools: list[BaseTool] = []
|
|
108
106
|
|
|
109
107
|
async def initialize(self) -> None:
|
|
110
108
|
"""Initialize the MCP client and agent."""
|
|
@@ -346,20 +344,18 @@ class MCPAgent:
|
|
|
346
344
|
history_to_use = (
|
|
347
345
|
external_history if external_history is not None else self._conversation_history
|
|
348
346
|
)
|
|
349
|
-
|
|
350
|
-
m for m in history_to_use if isinstance(m, HumanMessage | AIMessage)
|
|
351
|
-
]
|
|
352
|
-
inputs = {"input": query, "chat_history": langchain_history}
|
|
347
|
+
inputs = {"input": query, "chat_history": history_to_use}
|
|
353
348
|
|
|
354
349
|
# 3. Stream & diff -------------------------------------------------------
|
|
355
|
-
accumulated = ""
|
|
356
350
|
async for event in self._agent_executor.astream_events(inputs):
|
|
351
|
+
if event.get("event") == "on_chain_end":
|
|
352
|
+
output = event["data"]["output"]
|
|
353
|
+
if isinstance(output, list):
|
|
354
|
+
for message in output:
|
|
355
|
+
if not isinstance(message, ToolAgentAction):
|
|
356
|
+
self.add_to_history(message)
|
|
357
357
|
yield event
|
|
358
358
|
|
|
359
|
-
# 4. Persist assistant message ------------------------------------------
|
|
360
|
-
if self.memory_enabled and accumulated:
|
|
361
|
-
self.add_to_history(AIMessage(content=accumulated))
|
|
362
|
-
|
|
363
359
|
# 5. House-keeping -------------------------------------------------------
|
|
364
360
|
if initialised_here and manage_connector:
|
|
365
361
|
await self.close()
|
mcp_use/client.py
CHANGED
|
@@ -12,6 +12,7 @@ from typing import Any
|
|
|
12
12
|
from .config import create_connector_from_config, load_config_file
|
|
13
13
|
from .logging import logger
|
|
14
14
|
from .session import MCPSession
|
|
15
|
+
from .types.clientoptions import ClientOptions
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
class MCPClient:
|
|
@@ -24,14 +25,17 @@ class MCPClient:
|
|
|
24
25
|
def __init__(
|
|
25
26
|
self,
|
|
26
27
|
config: str | dict[str, Any] | None = None,
|
|
28
|
+
options: ClientOptions | None = None,
|
|
27
29
|
) -> None:
|
|
28
30
|
"""Initialize a new MCP client.
|
|
29
31
|
|
|
30
32
|
Args:
|
|
31
33
|
config: Either a dict containing configuration or a path to a JSON config file.
|
|
32
34
|
If None, an empty configuration is used.
|
|
35
|
+
options: Configuration options for the client.
|
|
33
36
|
"""
|
|
34
37
|
self.config: dict[str, Any] = {}
|
|
38
|
+
self.options = options or {}
|
|
35
39
|
self.sessions: dict[str, MCPSession] = {}
|
|
36
40
|
self.active_sessions: list[str] = []
|
|
37
41
|
|
|
@@ -43,22 +47,24 @@ class MCPClient:
|
|
|
43
47
|
self.config = config
|
|
44
48
|
|
|
45
49
|
@classmethod
|
|
46
|
-
def from_dict(cls, config: dict[str, Any]) -> "MCPClient":
|
|
50
|
+
def from_dict(cls, config: dict[str, Any], options: ClientOptions | None = None) -> "MCPClient":
|
|
47
51
|
"""Create a MCPClient from a dictionary.
|
|
48
52
|
|
|
49
53
|
Args:
|
|
50
54
|
config: The configuration dictionary.
|
|
55
|
+
options: Optional client configuration options.
|
|
51
56
|
"""
|
|
52
|
-
return cls(config=config)
|
|
57
|
+
return cls(config=config, options=options)
|
|
53
58
|
|
|
54
59
|
@classmethod
|
|
55
|
-
def from_config_file(cls, filepath: str) -> "MCPClient":
|
|
60
|
+
def from_config_file(cls, filepath: str, options: ClientOptions | None = None) -> "MCPClient":
|
|
56
61
|
"""Create a MCPClient from a configuration file.
|
|
57
62
|
|
|
58
63
|
Args:
|
|
59
64
|
filepath: The path to the configuration file.
|
|
65
|
+
options: Optional client configuration options.
|
|
60
66
|
"""
|
|
61
|
-
return cls(config=load_config_file(filepath))
|
|
67
|
+
return cls(config=load_config_file(filepath), options=options)
|
|
62
68
|
|
|
63
69
|
def add_server(
|
|
64
70
|
self,
|
|
@@ -111,6 +117,7 @@ class MCPClient:
|
|
|
111
117
|
|
|
112
118
|
Args:
|
|
113
119
|
server_name: The name of the server to create a session for.
|
|
120
|
+
auto_initialize: Whether to automatically initialize the session.
|
|
114
121
|
|
|
115
122
|
Returns:
|
|
116
123
|
The created MCPSession.
|
|
@@ -128,7 +135,9 @@ class MCPClient:
|
|
|
128
135
|
raise ValueError(f"Server '{server_name}' not found in config")
|
|
129
136
|
|
|
130
137
|
server_config = servers[server_name]
|
|
131
|
-
|
|
138
|
+
|
|
139
|
+
# Create connector with options
|
|
140
|
+
connector = create_connector_from_config(server_config, options=self.options)
|
|
132
141
|
|
|
133
142
|
# Create the session
|
|
134
143
|
session = MCPSession(connector)
|
|
@@ -146,16 +155,16 @@ class MCPClient:
|
|
|
146
155
|
self,
|
|
147
156
|
auto_initialize: bool = True,
|
|
148
157
|
) -> dict[str, MCPSession]:
|
|
149
|
-
"""Create
|
|
158
|
+
"""Create sessions for all configured servers.
|
|
150
159
|
|
|
151
160
|
Args:
|
|
152
|
-
auto_initialize: Whether to automatically initialize the
|
|
161
|
+
auto_initialize: Whether to automatically initialize the sessions.
|
|
153
162
|
|
|
154
163
|
Returns:
|
|
155
|
-
|
|
164
|
+
Dictionary mapping server names to their MCPSession instances.
|
|
156
165
|
|
|
157
166
|
Warns:
|
|
158
|
-
|
|
167
|
+
UserWarning: If no servers are configured.
|
|
159
168
|
"""
|
|
160
169
|
# Get server config
|
|
161
170
|
servers = self.config.get("mcpServers", {})
|
mcp_use/config.py
CHANGED
|
@@ -7,7 +7,15 @@ This module provides functionality to load MCP configuration from JSON files.
|
|
|
7
7
|
import json
|
|
8
8
|
from typing import Any
|
|
9
9
|
|
|
10
|
-
from .connectors import
|
|
10
|
+
from .connectors import (
|
|
11
|
+
BaseConnector,
|
|
12
|
+
HttpConnector,
|
|
13
|
+
SandboxConnector,
|
|
14
|
+
StdioConnector,
|
|
15
|
+
WebSocketConnector,
|
|
16
|
+
)
|
|
17
|
+
from .connectors.utils import is_stdio_server
|
|
18
|
+
from .types.clientoptions import ClientOptions
|
|
11
19
|
|
|
12
20
|
|
|
13
21
|
def load_config_file(filepath: str) -> dict[str, Any]:
|
|
@@ -23,23 +31,41 @@ def load_config_file(filepath: str) -> dict[str, Any]:
|
|
|
23
31
|
return json.load(f)
|
|
24
32
|
|
|
25
33
|
|
|
26
|
-
def create_connector_from_config(
|
|
34
|
+
def create_connector_from_config(
|
|
35
|
+
server_config: dict[str, Any],
|
|
36
|
+
options: ClientOptions | None = None,
|
|
37
|
+
) -> BaseConnector:
|
|
27
38
|
"""Create a connector based on server configuration.
|
|
28
|
-
|
|
39
|
+
This function can be called with just the server_config parameter:
|
|
40
|
+
create_connector_from_config(server_config)
|
|
29
41
|
Args:
|
|
30
42
|
server_config: The server configuration section
|
|
43
|
+
options: Optional client configuration options including sandboxing preferences.
|
|
44
|
+
If None, default client options will be used.
|
|
31
45
|
|
|
32
46
|
Returns:
|
|
33
47
|
A configured connector instance
|
|
34
48
|
"""
|
|
49
|
+
# Use default options if none provided
|
|
50
|
+
options = options or {"is_sandboxed": False}
|
|
51
|
+
|
|
35
52
|
# Stdio connector (command-based)
|
|
36
|
-
if
|
|
53
|
+
if is_stdio_server(server_config) and not options.get("is_sandboxed", False):
|
|
37
54
|
return StdioConnector(
|
|
38
55
|
command=server_config["command"],
|
|
39
56
|
args=server_config["args"],
|
|
40
57
|
env=server_config.get("env", None),
|
|
41
58
|
)
|
|
42
59
|
|
|
60
|
+
# Sandboxed connector
|
|
61
|
+
elif is_stdio_server(server_config) and options.get("is_sandboxed", False):
|
|
62
|
+
return SandboxConnector(
|
|
63
|
+
command=server_config["command"],
|
|
64
|
+
args=server_config["args"],
|
|
65
|
+
env=server_config.get("env", None),
|
|
66
|
+
e2b_options=options.get("sandbox_options", {}),
|
|
67
|
+
)
|
|
68
|
+
|
|
43
69
|
# HTTP connector
|
|
44
70
|
elif "url" in server_config:
|
|
45
71
|
return HttpConnector(
|
mcp_use/connectors/__init__.py
CHANGED
|
@@ -5,9 +5,16 @@ This module provides interfaces for connecting to MCP implementations
|
|
|
5
5
|
through different transport mechanisms.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
from .base import BaseConnector
|
|
9
|
-
from .http import HttpConnector
|
|
10
|
-
from .
|
|
11
|
-
from .
|
|
8
|
+
from .base import BaseConnector # noqa: F401
|
|
9
|
+
from .http import HttpConnector # noqa: F401
|
|
10
|
+
from .sandbox import SandboxConnector # noqa: F401
|
|
11
|
+
from .stdio import StdioConnector # noqa: F401
|
|
12
|
+
from .websocket import WebSocketConnector # noqa: F401
|
|
12
13
|
|
|
13
|
-
__all__ = [
|
|
14
|
+
__all__ = [
|
|
15
|
+
"BaseConnector",
|
|
16
|
+
"StdioConnector",
|
|
17
|
+
"HttpConnector",
|
|
18
|
+
"WebSocketConnector",
|
|
19
|
+
"SandboxConnector",
|
|
20
|
+
]
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Sandbox connector for MCP implementations.
|
|
3
|
+
|
|
4
|
+
This module provides a connector for communicating with MCP implementations
|
|
5
|
+
that are executed inside a sandbox environment (currently using E2B).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import asyncio
|
|
9
|
+
import os
|
|
10
|
+
import sys
|
|
11
|
+
import time
|
|
12
|
+
|
|
13
|
+
import aiohttp
|
|
14
|
+
from mcp import ClientSession
|
|
15
|
+
|
|
16
|
+
from ..logging import logger
|
|
17
|
+
from ..task_managers import SseConnectionManager
|
|
18
|
+
|
|
19
|
+
# Import E2B SDK components (optional dependency)
|
|
20
|
+
try:
|
|
21
|
+
logger.debug("Attempting to import e2b_code_interpreter...")
|
|
22
|
+
from e2b_code_interpreter import (
|
|
23
|
+
CommandHandle,
|
|
24
|
+
Sandbox,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
logger.debug("Successfully imported e2b_code_interpreter")
|
|
28
|
+
except ImportError as e:
|
|
29
|
+
logger.debug(f"Failed to import e2b_code_interpreter: {e}")
|
|
30
|
+
CommandHandle = None
|
|
31
|
+
Sandbox = None
|
|
32
|
+
|
|
33
|
+
from ..types.sandbox import SandboxOptions
|
|
34
|
+
from .base import BaseConnector
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class SandboxConnector(BaseConnector):
|
|
38
|
+
"""Connector for MCP implementations running in a sandbox environment.
|
|
39
|
+
|
|
40
|
+
This connector runs a user-defined stdio command within a sandbox environment,
|
|
41
|
+
currently implemented using E2B, potentially wrapped by a utility like 'supergateway'
|
|
42
|
+
to expose its stdio.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(
|
|
46
|
+
self,
|
|
47
|
+
command: str,
|
|
48
|
+
args: list[str],
|
|
49
|
+
env: dict[str, str] | None = None,
|
|
50
|
+
e2b_options: SandboxOptions | None = None,
|
|
51
|
+
timeout: float = 5,
|
|
52
|
+
sse_read_timeout: float = 60 * 5,
|
|
53
|
+
):
|
|
54
|
+
"""Initialize a new sandbox connector.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
command: The user's MCP server command to execute in the sandbox.
|
|
58
|
+
args: Command line arguments for the user's MCP server command.
|
|
59
|
+
env: Environment variables for the user's MCP server command.
|
|
60
|
+
e2b_options: Configuration options for the E2B sandbox environment.
|
|
61
|
+
See SandboxOptions for available options and defaults.
|
|
62
|
+
timeout: Timeout for the sandbox process in seconds.
|
|
63
|
+
sse_read_timeout: Timeout for the SSE connection in seconds.
|
|
64
|
+
"""
|
|
65
|
+
super().__init__()
|
|
66
|
+
if Sandbox is None:
|
|
67
|
+
raise ImportError(
|
|
68
|
+
"E2B SDK (e2b-code-interpreter) not found. "
|
|
69
|
+
"Please install it with 'pip install mcp-use[e2b]' "
|
|
70
|
+
"(or 'pip install e2b-code-interpreter')."
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
self.user_command = command
|
|
74
|
+
self.user_args = args or []
|
|
75
|
+
self.user_env = env or {}
|
|
76
|
+
|
|
77
|
+
_e2b_options = e2b_options or {}
|
|
78
|
+
|
|
79
|
+
self.api_key = _e2b_options.get("api_key") or os.environ.get("E2B_API_KEY")
|
|
80
|
+
if not self.api_key:
|
|
81
|
+
raise ValueError(
|
|
82
|
+
"E2B API key is required. Provide it via 'e2b_options.api_key' "
|
|
83
|
+
"or the E2B_API_KEY environment variable."
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
self.sandbox_template_id = _e2b_options.get("sandbox_template_id", "base")
|
|
87
|
+
self.supergateway_cmd_parts = _e2b_options.get(
|
|
88
|
+
"supergateway_command", "npx -y supergateway"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
self.sandbox: Sandbox | None = None
|
|
92
|
+
self.process: CommandHandle | None = None
|
|
93
|
+
self.client: ClientSession | None = None
|
|
94
|
+
self.errlog = sys.stderr
|
|
95
|
+
self.base_url: str | None = None
|
|
96
|
+
self._connected = False
|
|
97
|
+
self._connection_manager: SseConnectionManager | None = None
|
|
98
|
+
|
|
99
|
+
# SSE connection parameters
|
|
100
|
+
self.headers = {}
|
|
101
|
+
self.timeout = timeout
|
|
102
|
+
self.sse_read_timeout = sse_read_timeout
|
|
103
|
+
|
|
104
|
+
self.stdout_lines: list[str] = []
|
|
105
|
+
self.stderr_lines: list[str] = []
|
|
106
|
+
self._server_ready = asyncio.Event()
|
|
107
|
+
|
|
108
|
+
def _handle_stdout(self, data: str) -> None:
|
|
109
|
+
"""Handle stdout data from the sandbox process."""
|
|
110
|
+
self.stdout_lines.append(data)
|
|
111
|
+
logger.debug(f"[SANDBOX STDOUT] {data}", end="", flush=True)
|
|
112
|
+
|
|
113
|
+
def _handle_stderr(self, data: str) -> None:
|
|
114
|
+
"""Handle stderr data from the sandbox process."""
|
|
115
|
+
self.stderr_lines.append(data)
|
|
116
|
+
logger.debug(f"[SANDBOX STDERR] {data}", file=self.errlog, end="", flush=True)
|
|
117
|
+
|
|
118
|
+
async def wait_for_server_response(self, base_url: str, timeout: int = 30) -> bool:
|
|
119
|
+
"""Wait for the server to respond to HTTP requests.
|
|
120
|
+
Args:
|
|
121
|
+
base_url: The base URL to check for server readiness
|
|
122
|
+
timeout: Maximum time to wait in seconds
|
|
123
|
+
Returns:
|
|
124
|
+
True if server is responding, raises TimeoutError otherwise
|
|
125
|
+
"""
|
|
126
|
+
logger.info(f"Waiting for server at {base_url} to respond...")
|
|
127
|
+
sys.stdout.flush()
|
|
128
|
+
|
|
129
|
+
start_time = time.time()
|
|
130
|
+
ping_url = f"{base_url}/sse"
|
|
131
|
+
|
|
132
|
+
# Try to connect to the server
|
|
133
|
+
while time.time() - start_time < timeout:
|
|
134
|
+
try:
|
|
135
|
+
async with aiohttp.ClientSession() as session:
|
|
136
|
+
try:
|
|
137
|
+
# First try the endpoint
|
|
138
|
+
async with session.get(ping_url, timeout=2) as response:
|
|
139
|
+
if response.status == 200:
|
|
140
|
+
elapsed = time.time() - start_time
|
|
141
|
+
logger.info(
|
|
142
|
+
f"Server is ready! "
|
|
143
|
+
f"SSE endpoint responded with 200 after {elapsed:.1f}s"
|
|
144
|
+
)
|
|
145
|
+
return True
|
|
146
|
+
except Exception:
|
|
147
|
+
# If sse endpoint doesn't work, try the base URL
|
|
148
|
+
async with session.get(base_url, timeout=2) as response:
|
|
149
|
+
if response.status < 500: # Accept any non-server error
|
|
150
|
+
elapsed = time.time() - start_time
|
|
151
|
+
logger.info(
|
|
152
|
+
f"Server is ready! Base URL responded with "
|
|
153
|
+
f"{response.status} after {elapsed:.1f}s"
|
|
154
|
+
)
|
|
155
|
+
return True
|
|
156
|
+
except Exception:
|
|
157
|
+
# Wait a bit before trying again
|
|
158
|
+
await asyncio.sleep(0.5)
|
|
159
|
+
continue
|
|
160
|
+
|
|
161
|
+
# If we get here, the request failed
|
|
162
|
+
await asyncio.sleep(0.5)
|
|
163
|
+
|
|
164
|
+
# Log status every 5 seconds
|
|
165
|
+
elapsed = time.time() - start_time
|
|
166
|
+
if int(elapsed) % 5 == 0:
|
|
167
|
+
logger.info(f"Still waiting for server to respond... ({elapsed:.1f}s elapsed)")
|
|
168
|
+
sys.stdout.flush()
|
|
169
|
+
|
|
170
|
+
# If we get here, we timed out
|
|
171
|
+
raise TimeoutError(f"Timeout waiting for server to respond (waited {timeout} seconds)")
|
|
172
|
+
|
|
173
|
+
async def connect(self):
|
|
174
|
+
"""Connect to the sandbox and start the MCP server."""
|
|
175
|
+
|
|
176
|
+
if self._connected:
|
|
177
|
+
logger.debug("Already connected to MCP implementation")
|
|
178
|
+
return
|
|
179
|
+
|
|
180
|
+
logger.debug("Connecting to MCP implementation in sandbox")
|
|
181
|
+
|
|
182
|
+
try:
|
|
183
|
+
# Create and start the sandbox
|
|
184
|
+
self.sandbox = Sandbox(
|
|
185
|
+
template=self.sandbox_template_id,
|
|
186
|
+
api_key=self.api_key,
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
# Get the host for the sandbox
|
|
190
|
+
host = self.sandbox.get_host(3000)
|
|
191
|
+
self.base_url = f"https://{host}".rstrip("/")
|
|
192
|
+
|
|
193
|
+
# Append command with args
|
|
194
|
+
command = f"{self.user_command} {' '.join(self.user_args)}"
|
|
195
|
+
|
|
196
|
+
# Construct the full command with supergateway
|
|
197
|
+
full_command = f'{self.supergateway_cmd_parts} \
|
|
198
|
+
--base-url {self.base_url} \
|
|
199
|
+
--port 3000 \
|
|
200
|
+
--cors \
|
|
201
|
+
--stdio "{command}"'
|
|
202
|
+
|
|
203
|
+
logger.debug(f"Full command: {full_command}")
|
|
204
|
+
|
|
205
|
+
# Start the process in the sandbox with our stdout/stderr handlers
|
|
206
|
+
self.process: CommandHandle = self.sandbox.commands.run(
|
|
207
|
+
full_command,
|
|
208
|
+
envs=self.user_env,
|
|
209
|
+
timeout=1000 * 60 * 10, # 10 minutes timeout
|
|
210
|
+
background=True,
|
|
211
|
+
on_stdout=self._handle_stdout,
|
|
212
|
+
on_stderr=self._handle_stderr,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
# Wait for the server to be ready
|
|
216
|
+
await self.wait_for_server_response(self.base_url, timeout=30)
|
|
217
|
+
logger.debug("Initializing connection manager...")
|
|
218
|
+
|
|
219
|
+
# Create the SSE connection URL
|
|
220
|
+
sse_url = f"{self.base_url}/sse"
|
|
221
|
+
|
|
222
|
+
# Create and start the connection manager
|
|
223
|
+
self._connection_manager = SseConnectionManager(
|
|
224
|
+
sse_url, self.headers, self.timeout, self.sse_read_timeout
|
|
225
|
+
)
|
|
226
|
+
read_stream, write_stream = await self._connection_manager.start()
|
|
227
|
+
|
|
228
|
+
# Create the client session
|
|
229
|
+
self.client = ClientSession(read_stream, write_stream, sampling_callback=None)
|
|
230
|
+
await self.client.__aenter__()
|
|
231
|
+
|
|
232
|
+
# Mark as connected
|
|
233
|
+
self._connected = True
|
|
234
|
+
logger.debug(
|
|
235
|
+
f"Successfully connected to MCP implementation via HTTP/SSE: {self.base_url}"
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
except Exception as e:
|
|
239
|
+
logger.error(f"Failed to connect to MCP implementation: {e}")
|
|
240
|
+
|
|
241
|
+
# Clean up any resources if connection failed
|
|
242
|
+
await self._cleanup_resources()
|
|
243
|
+
|
|
244
|
+
raise e
|
|
245
|
+
|
|
246
|
+
async def _cleanup_resources(self) -> None:
|
|
247
|
+
"""Clean up all resources associated with this connector, including the sandbox.
|
|
248
|
+
This method extends the base implementation to also terminate the sandbox instance
|
|
249
|
+
and clean up any processes running in the sandbox.
|
|
250
|
+
"""
|
|
251
|
+
logger.debug("Cleaning up sandbox resources")
|
|
252
|
+
|
|
253
|
+
# Terminate any running process
|
|
254
|
+
if self.process:
|
|
255
|
+
try:
|
|
256
|
+
logger.debug("Terminating sandbox process")
|
|
257
|
+
self.process.kill()
|
|
258
|
+
except Exception as e:
|
|
259
|
+
logger.warning(f"Error terminating sandbox process: {e}")
|
|
260
|
+
finally:
|
|
261
|
+
self.process = None
|
|
262
|
+
|
|
263
|
+
# Close the sandbox
|
|
264
|
+
if self.sandbox:
|
|
265
|
+
try:
|
|
266
|
+
logger.debug("Closing sandbox instance")
|
|
267
|
+
self.sandbox.kill()
|
|
268
|
+
logger.debug("Sandbox instance closed successfully")
|
|
269
|
+
except Exception as e:
|
|
270
|
+
logger.warning(f"Error closing sandbox: {e}")
|
|
271
|
+
finally:
|
|
272
|
+
self.sandbox = None
|
|
273
|
+
|
|
274
|
+
# Then call the parent method to clean up the rest
|
|
275
|
+
await super()._cleanup_resources()
|
|
276
|
+
|
|
277
|
+
# Clear any collected output
|
|
278
|
+
self.stdout_lines = []
|
|
279
|
+
self.stderr_lines = []
|
|
280
|
+
self.base_url = None
|
|
281
|
+
|
|
282
|
+
async def disconnect(self) -> None:
|
|
283
|
+
"""Close the connection to the MCP implementation."""
|
|
284
|
+
if not self._connected:
|
|
285
|
+
logger.debug("Not connected to MCP implementation")
|
|
286
|
+
return
|
|
287
|
+
|
|
288
|
+
logger.debug("Disconnecting from MCP implementation")
|
|
289
|
+
await self._cleanup_resources()
|
|
290
|
+
self._connected = False
|
|
291
|
+
logger.debug("Disconnected from MCP implementation")
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def is_stdio_server(server_config: dict[str, Any]) -> bool:
|
|
5
|
+
"""Check if the server configuration is for a stdio server.
|
|
6
|
+
|
|
7
|
+
Args:
|
|
8
|
+
server_config: The server configuration section
|
|
9
|
+
|
|
10
|
+
Returns:
|
|
11
|
+
True if the server is a stdio server, False otherwise
|
|
12
|
+
"""
|
|
13
|
+
return "command" in server_config and "args" in server_config
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Options for MCP client configuration.
|
|
3
|
+
|
|
4
|
+
This module provides data classes and type definitions for configuring the MCP client.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import NotRequired, TypedDict
|
|
8
|
+
|
|
9
|
+
from .sandbox import SandboxOptions
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ClientOptions(TypedDict):
|
|
13
|
+
"""Options for configuring the MCP client.
|
|
14
|
+
|
|
15
|
+
This class encapsulates all configuration options for the MCPClient,
|
|
16
|
+
making it easier to extend the API without breaking backward compatibility.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
is_sandboxed: NotRequired[bool]
|
|
20
|
+
"""Whether to use sandboxed execution mode for running MCP servers."""
|
|
21
|
+
|
|
22
|
+
sandbox_options: NotRequired[SandboxOptions]
|
|
23
|
+
"""Options for sandbox configuration when is_sandboxed=True."""
|
mcp_use/types/sandbox.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Type definitions for sandbox-related configurations."""
|
|
2
|
+
|
|
3
|
+
from typing import NotRequired, TypedDict
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class SandboxOptions(TypedDict):
|
|
7
|
+
"""Configuration options for sandbox execution.
|
|
8
|
+
|
|
9
|
+
This type defines the configuration options available when running
|
|
10
|
+
MCP servers in a sandboxed environment (e.g., using E2B).
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
api_key: str
|
|
14
|
+
"""Direct API key for sandbox provider (e.g., E2B API key).
|
|
15
|
+
If not provided, will use E2B_API_KEY environment variable."""
|
|
16
|
+
|
|
17
|
+
sandbox_template_id: NotRequired[str]
|
|
18
|
+
"""Template ID for the sandbox environment.
|
|
19
|
+
Default: 'base'"""
|
|
20
|
+
|
|
21
|
+
supergateway_command: NotRequired[str]
|
|
22
|
+
"""Command to run supergateway.
|
|
23
|
+
Default: 'npx -y supergateway'"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcp-use
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: MCP Library for LLMs
|
|
5
5
|
Author-email: Pietro Zullo <pietro.zullo@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -33,6 +33,8 @@ Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
|
33
33
|
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
|
|
34
34
|
Requires-Dist: pytest>=7.4.0; extra == 'dev'
|
|
35
35
|
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
36
|
+
Provides-Extra: e2b
|
|
37
|
+
Requires-Dist: e2b-code-interpreter>=1.5.0; extra == 'e2b'
|
|
36
38
|
Provides-Extra: openai
|
|
37
39
|
Requires-Dist: openai>=1.10.0; extra == 'openai'
|
|
38
40
|
Provides-Extra: search
|
|
@@ -67,30 +69,64 @@ Description-Content-Type: text/markdown
|
|
|
67
69
|
<img src="https://img.shields.io/github/stars/pietrozullo/mcp-use?style=social" /></a>
|
|
68
70
|
</p>
|
|
69
71
|
<p align="center">
|
|
70
|
-
<a href="https://x.com/pietrozullo" alt="Twitter Follow">
|
|
72
|
+
<a href="https://x.com/pietrozullo" alt="Twitter Follow - Pietro">
|
|
71
73
|
<img src="https://img.shields.io/twitter/follow/Pietro?style=social" /></a>
|
|
74
|
+
<a href="https://x.com/pederzh" alt="Twitter Follow - Luigi">
|
|
75
|
+
<img src="https://img.shields.io/twitter/follow/Luigi?style=social" /></a>
|
|
72
76
|
<a href="https://discord.gg/XkNkSkMz3V" alt="Discord">
|
|
73
77
|
<img src="https://dcbadge.limes.pink/api/server/https://discord.gg/XkNkSkMz3V?style=flat" /></a>
|
|
74
78
|
</p>
|
|
75
79
|
🌐 MCP-Use is the open source way to connect **any LLM to any MCP server** and build custom agents that have tool access, without using closed source or application clients.
|
|
76
80
|
|
|
81
|
+
💬 Get started quickly - chat with your servers on our <b>hosted version</b>! <b>[Try mcp-use chat *(beta)* ](https://chat.mcp-use.io)</b>.
|
|
82
|
+
|
|
77
83
|
💡 Let developers easily connect any LLM to tools like web browsing, file operations, and more.
|
|
78
84
|
|
|
79
85
|
# Features
|
|
80
86
|
|
|
81
87
|
## ✨ Key Features
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
88
|
+
<table>
|
|
89
|
+
<tr>
|
|
90
|
+
<th width="400">Feature</th>
|
|
91
|
+
<th>Description</th>
|
|
92
|
+
</tr>
|
|
93
|
+
<tr>
|
|
94
|
+
<td>🔄 <a href="#quick-start"><strong>Ease of use</strong></a></td>
|
|
95
|
+
<td>Create your first MCP capable agent you need only 6 lines of code</td>
|
|
96
|
+
</tr>
|
|
97
|
+
<tr>
|
|
98
|
+
<td>🤖 <a href="#installing-langchain-providers"><strong>LLM Flexibility</strong></a></td>
|
|
99
|
+
<td>Works with any langchain supported LLM that supports tool calling (OpenAI, Anthropic, Groq, LLama etc.)</td>
|
|
100
|
+
</tr>
|
|
101
|
+
<tr>
|
|
102
|
+
<td>🌐 <a href="https://mcp-use.io/builder"><strong>Code Builder</strong></a></td>
|
|
103
|
+
<td>Explore MCP capabilities and generate starter code with the interactive <a href="https://mcp-use.io/builder">code builder</a>.</td>
|
|
104
|
+
</tr>
|
|
105
|
+
<tr>
|
|
106
|
+
<td>🔗 <a href="#http-connection-example"><strong>HTTP Support</strong></a></td>
|
|
107
|
+
<td>Direct connection to MCP servers running on specific HTTP ports</td>
|
|
108
|
+
</tr>
|
|
109
|
+
<tr>
|
|
110
|
+
<td>⚙️ <a href="#dynamic-server-selection-server-manager"><strong>Dynamic Server Selection</strong></a></td>
|
|
111
|
+
<td>Agents can dynamically choose the most appropriate MCP server for a given task from the available pool</td>
|
|
112
|
+
</tr>
|
|
113
|
+
<tr>
|
|
114
|
+
<td>🧩 <a href="#multi-server-support"><strong>Multi-Server Support</strong></a></td>
|
|
115
|
+
<td>Use multiple MCP servers simultaneously in a single agent</td>
|
|
116
|
+
</tr>
|
|
117
|
+
<tr>
|
|
118
|
+
<td>🛡️ <a href="#tool-access-control"><strong>Tool Restrictions</strong></a></td>
|
|
119
|
+
<td>Restrict potentially dangerous tools like file system or network access</td>
|
|
120
|
+
</tr>
|
|
121
|
+
<tr>
|
|
122
|
+
<td>🔧 <a href="#build-a-custom-agent"><strong>Custom Agents</strong></a></td>
|
|
123
|
+
<td>Build your own agents with any framework using the LangChain adapter or create new adapters</td>
|
|
124
|
+
</tr>
|
|
125
|
+
<tr>
|
|
126
|
+
<td>❓ <a href="https://mcp-use.io/what-should-we-build-next"><strong>What should we build next</strong></a></td>
|
|
127
|
+
<td>Let us know what you'd like us to build next</td>
|
|
128
|
+
</tr>
|
|
129
|
+
</table>
|
|
94
130
|
|
|
95
131
|
# Quick start
|
|
96
132
|
|
|
@@ -118,11 +154,8 @@ pip install langchain-openai
|
|
|
118
154
|
|
|
119
155
|
# For Anthropic
|
|
120
156
|
pip install langchain-anthropic
|
|
121
|
-
|
|
122
|
-
# For other providers, check the [LangChain chat models documentation](https://python.langchain.com/docs/integrations/chat/)
|
|
123
157
|
```
|
|
124
|
-
|
|
125
|
-
and add your API keys for the provider you want to use to your `.env` file.
|
|
158
|
+
For other providers, check the [LangChain chat models documentation](https://python.langchain.com/docs/integrations/chat/) and add your API keys for the provider you want to use to your `.env` file.
|
|
126
159
|
|
|
127
160
|
```bash
|
|
128
161
|
OPENAI_API_KEY=
|
|
@@ -561,6 +594,101 @@ if __name__ == "__main__":
|
|
|
561
594
|
asyncio.run(main())
|
|
562
595
|
```
|
|
563
596
|
|
|
597
|
+
# Sandboxed Execution
|
|
598
|
+
|
|
599
|
+
MCP-Use supports running MCP servers in a sandboxed environment using E2B's cloud infrastructure. This allows you to run MCP servers without having to install dependencies locally, making it easier to use tools that might have complex setups or system requirements.
|
|
600
|
+
|
|
601
|
+
## Installation
|
|
602
|
+
|
|
603
|
+
To use sandboxed execution, you need to install the E2B dependency:
|
|
604
|
+
|
|
605
|
+
```bash
|
|
606
|
+
# Install mcp-use with E2B support
|
|
607
|
+
pip install "mcp-use[e2b]"
|
|
608
|
+
|
|
609
|
+
# Or install the dependency directly
|
|
610
|
+
pip install e2b-code-interpreter
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
You'll also need an E2B API key. You can sign up at [e2b.dev](https://e2b.dev) to get your API key.
|
|
614
|
+
|
|
615
|
+
## Configuration
|
|
616
|
+
|
|
617
|
+
To enable sandboxed execution, use the `ClientOptions` parameter when creating your `MCPClient`:
|
|
618
|
+
|
|
619
|
+
```python
|
|
620
|
+
import asyncio
|
|
621
|
+
import os
|
|
622
|
+
from dotenv import load_dotenv
|
|
623
|
+
from langchain_openai import ChatOpenAI
|
|
624
|
+
from mcp_use import MCPAgent, MCPClient
|
|
625
|
+
from mcp_use.types.sandbox import SandboxOptions
|
|
626
|
+
from mcp_use.types.clientoptions import ClientOptions
|
|
627
|
+
|
|
628
|
+
async def main():
|
|
629
|
+
# Load environment variables (needs E2B_API_KEY)
|
|
630
|
+
load_dotenv()
|
|
631
|
+
|
|
632
|
+
# Define MCP server configuration
|
|
633
|
+
server_config = {
|
|
634
|
+
"mcpServers": {
|
|
635
|
+
"everything": {
|
|
636
|
+
"command": "npx",
|
|
637
|
+
"args": ["-y", "@modelcontextprotocol/server-everything"],
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
# Define sandbox options
|
|
643
|
+
sandbox_options: SandboxOptions = {
|
|
644
|
+
"api_key": os.getenv("E2B_API_KEY"), # API key can also be provided directly
|
|
645
|
+
"sandbox_template_id": "base", # Use base template
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
# Create client options for sandboxed mode
|
|
649
|
+
client_options: ClientOptions = {
|
|
650
|
+
"is_sandboxed": True,
|
|
651
|
+
"sandbox_options": sandbox_options
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
# Create client with sandboxed mode enabled
|
|
655
|
+
client = MCPClient(
|
|
656
|
+
config=server_config,
|
|
657
|
+
options=client_options
|
|
658
|
+
)
|
|
659
|
+
|
|
660
|
+
# Create agent with the sandboxed client
|
|
661
|
+
llm = ChatOpenAI(model="gpt-4o")
|
|
662
|
+
agent = MCPAgent(llm=llm, client=client)
|
|
663
|
+
|
|
664
|
+
# Run your agent
|
|
665
|
+
result = await agent.run("Use the command line tools to help me add 1+1")
|
|
666
|
+
print(result)
|
|
667
|
+
|
|
668
|
+
# Clean up
|
|
669
|
+
await client.close_all_sessions()
|
|
670
|
+
|
|
671
|
+
if __name__ == "__main__":
|
|
672
|
+
asyncio.run(main())
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
## Sandbox Options
|
|
676
|
+
|
|
677
|
+
The `SandboxOptions` type provides configuration for the sandbox environment:
|
|
678
|
+
|
|
679
|
+
| Option | Description | Default |
|
|
680
|
+
| ---------------------- | ---------------------------------------------------------------------------------------- | --------------------- |
|
|
681
|
+
| `api_key` | E2B API key. Required - can be provided directly or via E2B_API_KEY environment variable | None |
|
|
682
|
+
| `sandbox_template_id` | Template ID for the sandbox environment | "base" |
|
|
683
|
+
| `supergateway_command` | Command to run supergateway | "npx -y supergateway" |
|
|
684
|
+
|
|
685
|
+
## Benefits of Sandboxed Execution
|
|
686
|
+
|
|
687
|
+
- **No local dependencies**: Run MCP servers without installing dependencies locally
|
|
688
|
+
- **Isolation**: Execute code in a secure, isolated environment
|
|
689
|
+
- **Consistent environment**: Ensure consistent behavior across different systems
|
|
690
|
+
- **Resource efficiency**: Offload resource-intensive tasks to cloud infrastructure
|
|
691
|
+
|
|
564
692
|
# Build a Custom Agent:
|
|
565
693
|
|
|
566
694
|
You can also build your own custom agent using the LangChain adapter:
|
|
@@ -652,7 +780,6 @@ agent = MCPAgent(
|
|
|
652
780
|
|
|
653
781
|
This is useful when you only need to see the agent's steps and decision-making process without all the low-level debug information from other components.
|
|
654
782
|
|
|
655
|
-
|
|
656
783
|
# Roadmap
|
|
657
784
|
|
|
658
785
|
<ul>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
mcp_use/__init__.py,sha256=FikKagS6u8mugJOeslN3xfSA-tBLhjOywZSEcQ-y23g,1006
|
|
2
|
-
mcp_use/client.py,sha256=
|
|
3
|
-
mcp_use/config.py,sha256=
|
|
2
|
+
mcp_use/client.py,sha256=n0sJtRmntJtsVnmI1qCSTY8iuY9xYFybmA7V8rn09bE,8863
|
|
3
|
+
mcp_use/config.py,sha256=ks-aX1Kzk_iUBbUAA2_-BRGN4oltYU3CN5CKanMfPUs,2564
|
|
4
4
|
mcp_use/logging.py,sha256=UhQdMx0H0q08-ZPjY_hAJVErkEUAkU1oahHqwdfdK_U,4274
|
|
5
5
|
mcp_use/session.py,sha256=IPVzYASFMZx7-xpK4X_MR5chcsIwGvcs6vYXiO1hutM,2604
|
|
6
6
|
mcp_use/adapters/__init__.py,sha256=-xCrgPThuX7x0PHGFDdjb7M-mgw6QV3sKu5PM7ShnRg,275
|
|
@@ -8,13 +8,15 @@ mcp_use/adapters/base.py,sha256=bPVjHERySX6Vw16mEmgFaJuy4Yc_sM8JPtOAqJrP6Rg,7164
|
|
|
8
8
|
mcp_use/adapters/langchain_adapter.py,sha256=nrsOYDQu-nlLw14f2uNHM-pH8l-yQfZelWXZLhBSMeQ,11008
|
|
9
9
|
mcp_use/agents/__init__.py,sha256=N3eVYP2PxqNO2KcQv5fY8UMUX2W3eLTNkkzuFIJ1DUA,261
|
|
10
10
|
mcp_use/agents/base.py,sha256=bfuldi_89AbSbNc8KeTiCArRT9V62CNxHOWYkLHWjyA,1605
|
|
11
|
-
mcp_use/agents/mcpagent.py,sha256=
|
|
11
|
+
mcp_use/agents/mcpagent.py,sha256=1T6ZJkuMvXdR9dP-59V-m40wJ0dgO0Hxoz14jaTYPCE,26913
|
|
12
12
|
mcp_use/agents/prompts/system_prompt_builder.py,sha256=GH5Pvl49IBpKpZA9YTI83xMsdYSkRN_hw4LFHkKtxbg,4122
|
|
13
13
|
mcp_use/agents/prompts/templates.py,sha256=AZKrGWuI516C-PmyOPvxDBibNdqJtN24sOHTGR06bi4,1933
|
|
14
|
-
mcp_use/connectors/__init__.py,sha256=
|
|
14
|
+
mcp_use/connectors/__init__.py,sha256=cUF4yT0bNr8qeLkSzg28SHueiV5qDaHEB1l1GZ2K0dc,536
|
|
15
15
|
mcp_use/connectors/base.py,sha256=uJFU80kIpr0bVRAHDXTWRziIwdb_5Yjf2HsDNokZw-M,7731
|
|
16
16
|
mcp_use/connectors/http.py,sha256=2ZG5JxcK1WZ4jkTfTir6bEQLMxXBTPHyi0s42RHGeFs,2837
|
|
17
|
+
mcp_use/connectors/sandbox.py,sha256=SxSOOLOCDPtlVTCxxZSRbVfvva6rzDWfBLa56ne7esc,10902
|
|
17
18
|
mcp_use/connectors/stdio.py,sha256=MTzsqmVVihACUKngE-g5BignK3jAFds2CFv3aSzbJfs,2608
|
|
19
|
+
mcp_use/connectors/utils.py,sha256=zQ8GdNQx0Twz3by90BoU1RsWPf9wODGof4K3-NxPXeA,366
|
|
18
20
|
mcp_use/connectors/websocket.py,sha256=LeU53YI3zjbwKq5GzFRziqA_z9Dn5qACiNyxWDrn2ns,9540
|
|
19
21
|
mcp_use/managers/__init__.py,sha256=rzsJbOhtlmxNQLGcdmtmHaiExEXmiQiUuzPrAgKhAJw,439
|
|
20
22
|
mcp_use/managers/server_manager.py,sha256=YVl5ciNIQfVzP-BR9hA0ac6YSwq0WChpA_Lxvh2e9HE,3984
|
|
@@ -31,7 +33,9 @@ mcp_use/task_managers/base.py,sha256=xBrS9_GdlR0tr6sKN5pyMGUrQVGKRD6Qlk6hhOFcxRE
|
|
|
31
33
|
mcp_use/task_managers/sse.py,sha256=nLKt99OiqoJxFT62zCeNwSZUmdPPg4SD7M1pCEPOa3c,2391
|
|
32
34
|
mcp_use/task_managers/stdio.py,sha256=MJcW03lUZUs_HEUxwFPaqy7m8QLbmdn6LagpcfZdjc8,2130
|
|
33
35
|
mcp_use/task_managers/websocket.py,sha256=POB4YwCff6IJ0vj4eGpYqfDwLiqA0_fEUS4hbborGa4,1848
|
|
34
|
-
mcp_use
|
|
35
|
-
mcp_use
|
|
36
|
-
mcp_use-1.
|
|
37
|
-
mcp_use-1.
|
|
36
|
+
mcp_use/types/clientoptions.py,sha256=COzZPg19OlVm5F5ou6RhgzDVkPRs88Jz4c4uBanq5Ko,687
|
|
37
|
+
mcp_use/types/sandbox.py,sha256=opJ9r56F1FvaqVvPovfAj5jZbsOexgwYx5wLgSlN8_U,712
|
|
38
|
+
mcp_use-1.3.0.dist-info/METADATA,sha256=45e-TFXg17LD7sE8kyBgUqCYaeDVebgn63fED2vEznI,25427
|
|
39
|
+
mcp_use-1.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
40
|
+
mcp_use-1.3.0.dist-info/licenses/LICENSE,sha256=7Pw7dbwJSBw8zH-WE03JnR5uXvitRtaGTP9QWPcexcs,1068
|
|
41
|
+
mcp_use-1.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|