mcp-use 1.3.0__py3-none-any.whl → 1.3.2__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/__init__.py +2 -0
- mcp_use/adapters/base.py +2 -6
- mcp_use/adapters/langchain_adapter.py +4 -11
- mcp_use/agents/base.py +1 -3
- mcp_use/agents/mcpagent.py +121 -45
- mcp_use/agents/prompts/system_prompt_builder.py +1 -3
- mcp_use/client.py +26 -11
- mcp_use/config.py +9 -9
- mcp_use/connectors/base.py +136 -32
- mcp_use/connectors/http.py +100 -30
- mcp_use/connectors/sandbox.py +11 -16
- mcp_use/connectors/stdio.py +8 -5
- mcp_use/connectors/websocket.py +8 -5
- mcp_use/logging.py +1 -1
- mcp_use/managers/server_manager.py +5 -16
- mcp_use/managers/tools/disconnect_server.py +1 -3
- mcp_use/managers/tools/get_active_server.py +1 -4
- mcp_use/managers/tools/search_tools.py +29 -36
- mcp_use/managers/tools/use_tool.py +5 -18
- mcp_use/observability/__init__.py +8 -0
- mcp_use/observability/laminar.py +21 -0
- mcp_use/observability/langfuse.py +35 -0
- mcp_use/session.py +1 -4
- mcp_use/task_managers/__init__.py +2 -1
- mcp_use/task_managers/base.py +10 -4
- mcp_use/task_managers/streamable_http.py +81 -0
- mcp_use/task_managers/websocket.py +5 -0
- mcp_use/telemetry/__init__.py +0 -0
- mcp_use/telemetry/events.py +93 -0
- mcp_use/telemetry/telemetry.py +306 -0
- mcp_use/telemetry/utils.py +48 -0
- mcp_use/utils.py +27 -0
- {mcp_use-1.3.0.dist-info → mcp_use-1.3.2.dist-info}/METADATA +82 -26
- mcp_use-1.3.2.dist-info/RECORD +49 -0
- mcp_use/types/clientoptions.py +0 -23
- mcp_use-1.3.0.dist-info/RECORD +0 -41
- {mcp_use-1.3.0.dist-info → mcp_use-1.3.2.dist-info}/WHEEL +0 -0
- {mcp_use-1.3.0.dist-info → mcp_use-1.3.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
import platform
|
|
4
|
+
import uuid
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
from functools import wraps
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from posthog import Posthog
|
|
11
|
+
from scarf import ScarfEventLogger
|
|
12
|
+
|
|
13
|
+
from mcp_use.logging import MCP_USE_DEBUG
|
|
14
|
+
from mcp_use.telemetry.events import (
|
|
15
|
+
BaseTelemetryEvent,
|
|
16
|
+
MCPAgentExecutionEvent,
|
|
17
|
+
)
|
|
18
|
+
from mcp_use.telemetry.utils import get_package_version
|
|
19
|
+
from mcp_use.utils import singleton
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def requires_telemetry(func: Callable) -> Callable:
|
|
25
|
+
"""Decorator that skips function execution if telemetry is disabled"""
|
|
26
|
+
|
|
27
|
+
@wraps(func)
|
|
28
|
+
def wrapper(self, *args, **kwargs):
|
|
29
|
+
if not self._posthog_client and not self._scarf_client:
|
|
30
|
+
return None
|
|
31
|
+
return func(self, *args, **kwargs)
|
|
32
|
+
|
|
33
|
+
return wrapper
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def get_cache_home() -> Path:
|
|
37
|
+
"""Get platform-appropriate cache directory."""
|
|
38
|
+
# XDG_CACHE_HOME for Linux and manually set envs
|
|
39
|
+
env_var: str | None = os.getenv("XDG_CACHE_HOME")
|
|
40
|
+
if env_var and (path := Path(env_var)).is_absolute():
|
|
41
|
+
return path
|
|
42
|
+
|
|
43
|
+
system = platform.system()
|
|
44
|
+
if system == "Windows":
|
|
45
|
+
appdata = os.getenv("LOCALAPPDATA") or os.getenv("APPDATA")
|
|
46
|
+
if appdata:
|
|
47
|
+
return Path(appdata)
|
|
48
|
+
return Path.home() / "AppData" / "Local"
|
|
49
|
+
elif system == "Darwin": # macOS
|
|
50
|
+
return Path.home() / "Library" / "Caches"
|
|
51
|
+
else: # Linux or other Unix
|
|
52
|
+
return Path.home() / ".cache"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@singleton
|
|
56
|
+
class Telemetry:
|
|
57
|
+
"""
|
|
58
|
+
Service for capturing anonymized telemetry data via PostHog and Scarf.
|
|
59
|
+
If the environment variable `MCP_USE_ANONYMIZED_TELEMETRY=false`, telemetry will be disabled.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
USER_ID_PATH = str(get_cache_home() / "mcp_use_3" / "telemetry_user_id")
|
|
63
|
+
VERSION_DOWNLOAD_PATH = str(get_cache_home() / "mcp_use" / "download_version")
|
|
64
|
+
PROJECT_API_KEY = "phc_lyTtbYwvkdSbrcMQNPiKiiRWrrM1seyKIMjycSvItEI"
|
|
65
|
+
HOST = "https://eu.i.posthog.com"
|
|
66
|
+
SCARF_GATEWAY_URL = "https://mcpuse.gateway.scarf.sh/events"
|
|
67
|
+
UNKNOWN_USER_ID = "UNKNOWN_USER_ID"
|
|
68
|
+
|
|
69
|
+
_curr_user_id = None
|
|
70
|
+
|
|
71
|
+
def __init__(self):
|
|
72
|
+
telemetry_disabled = os.getenv("MCP_USE_ANONYMIZED_TELEMETRY", "true").lower() == "false"
|
|
73
|
+
|
|
74
|
+
if telemetry_disabled:
|
|
75
|
+
self._posthog_client = None
|
|
76
|
+
self._scarf_client = None
|
|
77
|
+
logger.debug("Telemetry disabled")
|
|
78
|
+
else:
|
|
79
|
+
logger.info("Anonymized telemetry enabled. Set MCP_USE_ANONYMIZED_TELEMETRY=false to disable.")
|
|
80
|
+
|
|
81
|
+
# Initialize PostHog
|
|
82
|
+
try:
|
|
83
|
+
self._posthog_client = Posthog(
|
|
84
|
+
project_api_key=self.PROJECT_API_KEY,
|
|
85
|
+
host=self.HOST,
|
|
86
|
+
disable_geoip=False,
|
|
87
|
+
enable_exception_autocapture=True,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# Silence posthog's logging unless debug mode (level 2)
|
|
91
|
+
if MCP_USE_DEBUG < 2:
|
|
92
|
+
posthog_logger = logging.getLogger("posthog")
|
|
93
|
+
posthog_logger.disabled = True
|
|
94
|
+
|
|
95
|
+
except Exception as e:
|
|
96
|
+
logger.warning(f"Failed to initialize PostHog telemetry: {e}")
|
|
97
|
+
self._posthog_client = None
|
|
98
|
+
|
|
99
|
+
# Initialize Scarf
|
|
100
|
+
try:
|
|
101
|
+
self._scarf_client = ScarfEventLogger(
|
|
102
|
+
endpoint_url=self.SCARF_GATEWAY_URL,
|
|
103
|
+
timeout=3.0,
|
|
104
|
+
verbose=MCP_USE_DEBUG >= 2,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# Silence scarf's logging unless debug mode (level 2)
|
|
108
|
+
if MCP_USE_DEBUG < 2:
|
|
109
|
+
scarf_logger = logging.getLogger("scarf")
|
|
110
|
+
scarf_logger.disabled = True
|
|
111
|
+
|
|
112
|
+
except Exception as e:
|
|
113
|
+
logger.warning(f"Failed to initialize Scarf telemetry: {e}")
|
|
114
|
+
self._scarf_client = None
|
|
115
|
+
|
|
116
|
+
@property
|
|
117
|
+
def user_id(self) -> str:
|
|
118
|
+
"""Get or create a persistent anonymous user ID"""
|
|
119
|
+
if self._curr_user_id:
|
|
120
|
+
return self._curr_user_id
|
|
121
|
+
|
|
122
|
+
try:
|
|
123
|
+
is_first_time = not os.path.exists(self.USER_ID_PATH)
|
|
124
|
+
|
|
125
|
+
if is_first_time:
|
|
126
|
+
logger.debug(f"Creating user ID path: {self.USER_ID_PATH}")
|
|
127
|
+
os.makedirs(os.path.dirname(self.USER_ID_PATH), exist_ok=True)
|
|
128
|
+
with open(self.USER_ID_PATH, "w") as f:
|
|
129
|
+
new_user_id = str(uuid.uuid4())
|
|
130
|
+
f.write(new_user_id)
|
|
131
|
+
self._curr_user_id = new_user_id
|
|
132
|
+
|
|
133
|
+
logger.debug(f"User ID path created: {self.USER_ID_PATH}")
|
|
134
|
+
else:
|
|
135
|
+
with open(self.USER_ID_PATH) as f:
|
|
136
|
+
self._curr_user_id = f.read().strip()
|
|
137
|
+
|
|
138
|
+
# Always check for version-based download tracking
|
|
139
|
+
self.track_package_download(
|
|
140
|
+
{
|
|
141
|
+
"triggered_by": "user_id_property",
|
|
142
|
+
}
|
|
143
|
+
)
|
|
144
|
+
except Exception as e:
|
|
145
|
+
logger.debug(f"Failed to get/create user ID: {e}")
|
|
146
|
+
self._curr_user_id = self.UNKNOWN_USER_ID
|
|
147
|
+
|
|
148
|
+
return self._curr_user_id
|
|
149
|
+
|
|
150
|
+
@requires_telemetry
|
|
151
|
+
def capture(self, event: BaseTelemetryEvent) -> None:
|
|
152
|
+
"""Capture a telemetry event"""
|
|
153
|
+
# Send to PostHog
|
|
154
|
+
if self._posthog_client:
|
|
155
|
+
try:
|
|
156
|
+
# Add package version to all events
|
|
157
|
+
properties = event.properties.copy()
|
|
158
|
+
properties["mcp_use_version"] = get_package_version()
|
|
159
|
+
|
|
160
|
+
self._posthog_client.capture(distinct_id=self.user_id, event=event.name, properties=properties)
|
|
161
|
+
except Exception as e:
|
|
162
|
+
logger.debug(f"Failed to track PostHog event {event.name}: {e}")
|
|
163
|
+
|
|
164
|
+
# Send to Scarf
|
|
165
|
+
if self._scarf_client:
|
|
166
|
+
try:
|
|
167
|
+
# Add package version and user_id to all events
|
|
168
|
+
properties = {}
|
|
169
|
+
properties["mcp_use_version"] = get_package_version()
|
|
170
|
+
properties["user_id"] = self.user_id
|
|
171
|
+
properties["event"] = event.name
|
|
172
|
+
|
|
173
|
+
# Convert complex types to simple types for Scarf compatibility
|
|
174
|
+
self._scarf_client.log_event(properties=properties)
|
|
175
|
+
except Exception as e:
|
|
176
|
+
logger.debug(f"Failed to track Scarf event {event.name}: {e}")
|
|
177
|
+
|
|
178
|
+
@requires_telemetry
|
|
179
|
+
def track_package_download(self, properties: dict[str, Any] | None = None) -> None:
|
|
180
|
+
"""Track package download event specifically for Scarf analytics"""
|
|
181
|
+
if self._scarf_client:
|
|
182
|
+
try:
|
|
183
|
+
current_version = get_package_version()
|
|
184
|
+
should_track = False
|
|
185
|
+
first_download = False
|
|
186
|
+
|
|
187
|
+
# Check if version file exists
|
|
188
|
+
if not os.path.exists(self.VERSION_DOWNLOAD_PATH):
|
|
189
|
+
# First download
|
|
190
|
+
should_track = True
|
|
191
|
+
first_download = True
|
|
192
|
+
|
|
193
|
+
# Create directory and save version
|
|
194
|
+
os.makedirs(os.path.dirname(self.VERSION_DOWNLOAD_PATH), exist_ok=True)
|
|
195
|
+
with open(self.VERSION_DOWNLOAD_PATH, "w") as f:
|
|
196
|
+
f.write(current_version)
|
|
197
|
+
else:
|
|
198
|
+
# Read saved version
|
|
199
|
+
with open(self.VERSION_DOWNLOAD_PATH) as f:
|
|
200
|
+
saved_version = f.read().strip()
|
|
201
|
+
|
|
202
|
+
# Compare versions (simple string comparison for now)
|
|
203
|
+
if current_version > saved_version:
|
|
204
|
+
should_track = True
|
|
205
|
+
first_download = False
|
|
206
|
+
|
|
207
|
+
# Update saved version
|
|
208
|
+
with open(self.VERSION_DOWNLOAD_PATH, "w") as f:
|
|
209
|
+
f.write(current_version)
|
|
210
|
+
|
|
211
|
+
if should_track:
|
|
212
|
+
logger.debug(f"Tracking package download event with properties: {properties}")
|
|
213
|
+
# Add package version and user_id to event
|
|
214
|
+
event_properties = (properties or {}).copy()
|
|
215
|
+
event_properties["mcp_use_version"] = current_version
|
|
216
|
+
event_properties["user_id"] = self.user_id
|
|
217
|
+
event_properties["event"] = "package_download"
|
|
218
|
+
event_properties["first_download"] = first_download
|
|
219
|
+
|
|
220
|
+
# Convert complex types to simple types for Scarf compatibility
|
|
221
|
+
self._scarf_client.log_event(properties=event_properties)
|
|
222
|
+
except Exception as e:
|
|
223
|
+
logger.debug(f"Failed to track Scarf package_download event: {e}")
|
|
224
|
+
|
|
225
|
+
@requires_telemetry
|
|
226
|
+
def track_agent_execution(
|
|
227
|
+
self,
|
|
228
|
+
execution_method: str,
|
|
229
|
+
query: str,
|
|
230
|
+
success: bool,
|
|
231
|
+
model_provider: str,
|
|
232
|
+
model_name: str,
|
|
233
|
+
server_count: int,
|
|
234
|
+
server_identifiers: list[dict[str, str]],
|
|
235
|
+
total_tools_available: int,
|
|
236
|
+
tools_available_names: list[str],
|
|
237
|
+
max_steps_configured: int,
|
|
238
|
+
memory_enabled: bool,
|
|
239
|
+
use_server_manager: bool,
|
|
240
|
+
max_steps_used: int | None,
|
|
241
|
+
manage_connector: bool,
|
|
242
|
+
external_history_used: bool,
|
|
243
|
+
steps_taken: int | None = None,
|
|
244
|
+
tools_used_count: int | None = None,
|
|
245
|
+
tools_used_names: list[str] | None = None,
|
|
246
|
+
response: str | None = None,
|
|
247
|
+
execution_time_ms: int | None = None,
|
|
248
|
+
error_type: str | None = None,
|
|
249
|
+
conversation_history_length: int | None = None,
|
|
250
|
+
) -> None:
|
|
251
|
+
"""Track comprehensive agent execution"""
|
|
252
|
+
event = MCPAgentExecutionEvent(
|
|
253
|
+
execution_method=execution_method,
|
|
254
|
+
query=query,
|
|
255
|
+
success=success,
|
|
256
|
+
model_provider=model_provider,
|
|
257
|
+
model_name=model_name,
|
|
258
|
+
server_count=server_count,
|
|
259
|
+
server_identifiers=server_identifiers,
|
|
260
|
+
total_tools_available=total_tools_available,
|
|
261
|
+
tools_available_names=tools_available_names,
|
|
262
|
+
max_steps_configured=max_steps_configured,
|
|
263
|
+
memory_enabled=memory_enabled,
|
|
264
|
+
use_server_manager=use_server_manager,
|
|
265
|
+
max_steps_used=max_steps_used,
|
|
266
|
+
manage_connector=manage_connector,
|
|
267
|
+
external_history_used=external_history_used,
|
|
268
|
+
steps_taken=steps_taken,
|
|
269
|
+
tools_used_count=tools_used_count,
|
|
270
|
+
tools_used_names=tools_used_names,
|
|
271
|
+
response=response,
|
|
272
|
+
execution_time_ms=execution_time_ms,
|
|
273
|
+
error_type=error_type,
|
|
274
|
+
conversation_history_length=conversation_history_length,
|
|
275
|
+
)
|
|
276
|
+
self.capture(event)
|
|
277
|
+
|
|
278
|
+
@requires_telemetry
|
|
279
|
+
def flush(self) -> None:
|
|
280
|
+
"""Flush any queued telemetry events"""
|
|
281
|
+
# Flush PostHog
|
|
282
|
+
if self._posthog_client:
|
|
283
|
+
try:
|
|
284
|
+
self._posthog_client.flush()
|
|
285
|
+
logger.debug("PostHog client telemetry queue flushed")
|
|
286
|
+
except Exception as e:
|
|
287
|
+
logger.debug(f"Failed to flush PostHog client: {e}")
|
|
288
|
+
|
|
289
|
+
# Scarf events are sent immediately, no flush needed
|
|
290
|
+
if self._scarf_client:
|
|
291
|
+
logger.debug("Scarf telemetry events sent immediately (no flush needed)")
|
|
292
|
+
|
|
293
|
+
@requires_telemetry
|
|
294
|
+
def shutdown(self) -> None:
|
|
295
|
+
"""Shutdown telemetry clients and flush remaining events"""
|
|
296
|
+
# Shutdown PostHog
|
|
297
|
+
if self._posthog_client:
|
|
298
|
+
try:
|
|
299
|
+
self._posthog_client.shutdown()
|
|
300
|
+
logger.debug("PostHog client shutdown successfully")
|
|
301
|
+
except Exception as e:
|
|
302
|
+
logger.debug(f"Error shutting down PostHog client: {e}")
|
|
303
|
+
|
|
304
|
+
# Scarf doesn't require explicit shutdown
|
|
305
|
+
if self._scarf_client:
|
|
306
|
+
logger.debug("Scarf telemetry client shutdown (no action needed)")
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Utility functions for extracting model information from LangChain LLMs.
|
|
3
|
+
|
|
4
|
+
This module provides utilities to extract provider and model information
|
|
5
|
+
from LangChain language models for telemetry purposes.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import importlib.metadata
|
|
9
|
+
|
|
10
|
+
from langchain_core.language_models.base import BaseLanguageModel
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_package_version() -> str:
|
|
14
|
+
"""Get the current mcp-use package version."""
|
|
15
|
+
try:
|
|
16
|
+
return importlib.metadata.version("mcp-use")
|
|
17
|
+
except importlib.metadata.PackageNotFoundError:
|
|
18
|
+
return "unknown"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_model_provider(llm: BaseLanguageModel) -> str:
|
|
22
|
+
"""Extract the model provider from LangChain LLM using BaseChatModel standards."""
|
|
23
|
+
# Use LangChain's standard _llm_type property for identification
|
|
24
|
+
return getattr(llm, "_llm_type", llm.__class__.__name__.lower())
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_model_name(llm: BaseLanguageModel) -> str:
|
|
28
|
+
"""Extract the model name from LangChain LLM using BaseChatModel standards."""
|
|
29
|
+
# First try _identifying_params which may contain model info
|
|
30
|
+
if hasattr(llm, "_identifying_params"):
|
|
31
|
+
identifying_params = llm._identifying_params
|
|
32
|
+
if isinstance(identifying_params, dict):
|
|
33
|
+
# Common keys that contain model names
|
|
34
|
+
for key in ["model", "model_name", "model_id", "deployment_name"]:
|
|
35
|
+
if key in identifying_params:
|
|
36
|
+
return str(identifying_params[key])
|
|
37
|
+
|
|
38
|
+
# Fallback to direct model attributes
|
|
39
|
+
return getattr(llm, "model", getattr(llm, "model_name", llm.__class__.__name__))
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def extract_model_info(llm: BaseLanguageModel) -> tuple[str, str]:
|
|
43
|
+
"""Extract both provider and model name from LangChain LLM.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
Tuple of (provider, model_name)
|
|
47
|
+
"""
|
|
48
|
+
return get_model_provider(llm), get_model_name(llm)
|
mcp_use/utils.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
def singleton(cls):
|
|
2
|
+
"""A decorator that implements the singleton pattern for a class.
|
|
3
|
+
|
|
4
|
+
This decorator ensures that only one instance of a class is ever created.
|
|
5
|
+
Subsequent attempts to create a new instance will return the existing one.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
@singleton
|
|
9
|
+
class MySingletonClass:
|
|
10
|
+
def __init__(self):
|
|
11
|
+
# ... initialization ...
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
cls: The class to be decorated.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
A wrapper function that handles instance creation.
|
|
19
|
+
"""
|
|
20
|
+
instance = [None]
|
|
21
|
+
|
|
22
|
+
def wrapper(*args, **kwargs):
|
|
23
|
+
if instance[0] is None:
|
|
24
|
+
instance[0] = cls(*args, **kwargs)
|
|
25
|
+
return instance[0]
|
|
26
|
+
|
|
27
|
+
return wrapper
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcp-use
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.2
|
|
4
4
|
Summary: MCP Library for LLMs
|
|
5
5
|
Author-email: Pietro Zullo <pietro.zullo@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -15,18 +15,26 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
15
15
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
16
|
Requires-Python: >=3.11
|
|
17
17
|
Requires-Dist: aiohttp>=3.9.0
|
|
18
|
+
Requires-Dist: anyio>=4.0.0
|
|
19
|
+
Requires-Dist: authlib>=1.5.2
|
|
20
|
+
Requires-Dist: httpx>=0.28.1
|
|
18
21
|
Requires-Dist: jsonschema-pydantic>=0.1.0
|
|
19
22
|
Requires-Dist: langchain-community>=0.0.10
|
|
20
23
|
Requires-Dist: langchain>=0.1.0
|
|
21
|
-
Requires-Dist: mcp>=1.
|
|
24
|
+
Requires-Dist: mcp>=1.9.3
|
|
25
|
+
Requires-Dist: posthog>=4.8.0
|
|
22
26
|
Requires-Dist: pydantic>=2.0.0
|
|
23
27
|
Requires-Dist: python-dotenv>=1.0.0
|
|
28
|
+
Requires-Dist: scarf-sdk>=0.1.0
|
|
29
|
+
Requires-Dist: starlette>=0.41.0
|
|
24
30
|
Requires-Dist: typing-extensions>=4.8.0
|
|
31
|
+
Requires-Dist: uvicorn>=0.32.0
|
|
25
32
|
Requires-Dist: websockets>=12.0
|
|
26
33
|
Provides-Extra: anthropic
|
|
27
|
-
Requires-Dist: anthropic
|
|
34
|
+
Requires-Dist: langchain-anthropic; extra == 'anthropic'
|
|
28
35
|
Provides-Extra: dev
|
|
29
36
|
Requires-Dist: black>=23.9.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: fastmcp; extra == 'dev'
|
|
30
38
|
Requires-Dist: isort>=5.12.0; extra == 'dev'
|
|
31
39
|
Requires-Dist: mypy>=1.5.0; extra == 'dev'
|
|
32
40
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
@@ -36,7 +44,7 @@ Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
|
36
44
|
Provides-Extra: e2b
|
|
37
45
|
Requires-Dist: e2b-code-interpreter>=1.5.0; extra == 'e2b'
|
|
38
46
|
Provides-Extra: openai
|
|
39
|
-
Requires-Dist: openai
|
|
47
|
+
Requires-Dist: langchain-openai; extra == 'openai'
|
|
40
48
|
Provides-Extra: search
|
|
41
49
|
Requires-Dist: fastembed>=0.0.1; extra == 'search'
|
|
42
50
|
Description-Content-Type: text/markdown
|
|
@@ -74,7 +82,7 @@ Description-Content-Type: text/markdown
|
|
|
74
82
|
<a href="https://x.com/pederzh" alt="Twitter Follow - Luigi">
|
|
75
83
|
<img src="https://img.shields.io/twitter/follow/Luigi?style=social" /></a>
|
|
76
84
|
<a href="https://discord.gg/XkNkSkMz3V" alt="Discord">
|
|
77
|
-
<img src="https://dcbadge.limes.pink/api/server/
|
|
85
|
+
<img src="https://dcbadge.limes.pink/api/server/XkNkSkMz3V?style=flat" /></a>
|
|
78
86
|
</p>
|
|
79
87
|
🌐 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.
|
|
80
88
|
|
|
@@ -614,7 +622,7 @@ You'll also need an E2B API key. You can sign up at [e2b.dev](https://e2b.dev) t
|
|
|
614
622
|
|
|
615
623
|
## Configuration
|
|
616
624
|
|
|
617
|
-
To enable sandboxed execution, use the
|
|
625
|
+
To enable sandboxed execution, use the sandbox parameter when creating your `MCPClient`:
|
|
618
626
|
|
|
619
627
|
```python
|
|
620
628
|
import asyncio
|
|
@@ -623,7 +631,6 @@ from dotenv import load_dotenv
|
|
|
623
631
|
from langchain_openai import ChatOpenAI
|
|
624
632
|
from mcp_use import MCPAgent, MCPClient
|
|
625
633
|
from mcp_use.types.sandbox import SandboxOptions
|
|
626
|
-
from mcp_use.types.clientoptions import ClientOptions
|
|
627
634
|
|
|
628
635
|
async def main():
|
|
629
636
|
# Load environment variables (needs E2B_API_KEY)
|
|
@@ -645,16 +652,12 @@ async def main():
|
|
|
645
652
|
"sandbox_template_id": "base", # Use base template
|
|
646
653
|
}
|
|
647
654
|
|
|
648
|
-
# Create client options for sandboxed mode
|
|
649
|
-
client_options: ClientOptions = {
|
|
650
|
-
"is_sandboxed": True,
|
|
651
|
-
"sandbox_options": sandbox_options
|
|
652
|
-
}
|
|
653
|
-
|
|
654
655
|
# Create client with sandboxed mode enabled
|
|
655
656
|
client = MCPClient(
|
|
656
657
|
config=server_config,
|
|
657
|
-
|
|
658
|
+
sandbox=True,
|
|
659
|
+
sandbox_options=sandbox_options,
|
|
660
|
+
|
|
658
661
|
)
|
|
659
662
|
|
|
660
663
|
# Create agent with the sandboxed client
|
|
@@ -780,14 +783,6 @@ agent = MCPAgent(
|
|
|
780
783
|
|
|
781
784
|
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.
|
|
782
785
|
|
|
783
|
-
# Roadmap
|
|
784
|
-
|
|
785
|
-
<ul>
|
|
786
|
-
<li>[x] Multiple Servers at once </li>
|
|
787
|
-
<li>[x] Test remote connectors (http, ws)</li>
|
|
788
|
-
<li>[ ] ... </li>
|
|
789
|
-
</ul>
|
|
790
|
-
|
|
791
786
|
## Star History
|
|
792
787
|
|
|
793
788
|
[](https://www.star-history.com/#pietrozullo/mcp-use&Date)
|
|
@@ -796,12 +791,77 @@ This is useful when you only need to see the agent's steps and decision-making p
|
|
|
796
791
|
|
|
797
792
|
We love contributions! Feel free to open issues for bugs or feature requests. Look at [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
798
793
|
|
|
794
|
+
## Contributors
|
|
795
|
+
|
|
796
|
+
Thanks to all our amazing contributors!
|
|
797
|
+
|
|
798
|
+
<a href="https://github.com/mcp-use/mcp-use/graphs/contributors">
|
|
799
|
+
<img src="https://contrib.rocks/image?repo=mcp-use/mcp-use" />
|
|
800
|
+
</a>
|
|
801
|
+
|
|
802
|
+
|
|
803
|
+
## Top Starred Dependents
|
|
804
|
+
|
|
805
|
+
<!-- gh-dependents-info-used-by-start -->
|
|
806
|
+
|
|
807
|
+
<table>
|
|
808
|
+
<tr>
|
|
809
|
+
<th width="400">Repository</th>
|
|
810
|
+
<th>Stars</th>
|
|
811
|
+
</tr>
|
|
812
|
+
<tr>
|
|
813
|
+
<td><img src="https://avatars.githubusercontent.com/u/170207473?s=40&v=4" width="20" height="20" style="vertical-align: middle; margin-right: 8px;"> <a href="https://github.com/tavily-ai/meeting-prep-agent"><strong>tavily-ai/meeting-prep-agent</strong></a></td>
|
|
814
|
+
<td>⭐ 112</td>
|
|
815
|
+
</tr>
|
|
816
|
+
<tr>
|
|
817
|
+
<td><img src="https://avatars.githubusercontent.com/u/20041231?s=40&v=4" width="20" height="20" style="vertical-align: middle; margin-right: 8px;"> <a href="https://github.com/krishnaik06/MCP-CRASH-Course"><strong>krishnaik06/MCP-CRASH-Course</strong></a></td>
|
|
818
|
+
<td>⭐ 37</td>
|
|
819
|
+
</tr>
|
|
820
|
+
<tr>
|
|
821
|
+
<td><img src="https://avatars.githubusercontent.com/u/892404?s=40&v=4" width="20" height="20" style="vertical-align: middle; margin-right: 8px;"> <a href="https://github.com/truemagic-coder/solana-agent-app"><strong>truemagic-coder/solana-agent-app</strong></a></td>
|
|
822
|
+
<td>⭐ 29</td>
|
|
823
|
+
</tr>
|
|
824
|
+
<tr>
|
|
825
|
+
<td><img src="https://avatars.githubusercontent.com/u/8344498?s=40&v=4" width="20" height="20" style="vertical-align: middle; margin-right: 8px;"> <a href="https://github.com/schogini/techietalksai"><strong>schogini/techietalksai</strong></a></td>
|
|
826
|
+
<td>⭐ 21</td>
|
|
827
|
+
</tr>
|
|
828
|
+
<tr>
|
|
829
|
+
<td><img src="https://avatars.githubusercontent.com/u/201161342?s=40&v=4" width="20" height="20" style="vertical-align: middle; margin-right: 8px;"> <a href="https://github.com/autometa-dev/whatsapp-mcp-voice-agent"><strong>autometa-dev/whatsapp-mcp-voice-agent</strong></a></td>
|
|
830
|
+
<td>⭐ 18</td>
|
|
831
|
+
</tr>
|
|
832
|
+
<tr>
|
|
833
|
+
<td><img src="https://avatars.githubusercontent.com/u/100749943?s=40&v=4" width="20" height="20" style="vertical-align: middle; margin-right: 8px;"> <a href="https://github.com/Deniscartin/mcp-cli"><strong>Deniscartin/mcp-cli</strong></a></td>
|
|
834
|
+
<td>⭐ 17</td>
|
|
835
|
+
</tr>
|
|
836
|
+
<tr>
|
|
837
|
+
<td><img src="https://avatars.githubusercontent.com/u/6764390?s=40&v=4" width="20" height="20" style="vertical-align: middle; margin-right: 8px;"> <a href="https://github.com/elastic/genai-workshops"><strong>elastic/genai-workshops</strong></a></td>
|
|
838
|
+
<td>⭐ 9</td>
|
|
839
|
+
</tr>
|
|
840
|
+
<tr>
|
|
841
|
+
<td><img src="https://avatars.githubusercontent.com/u/6688805?s=40&v=4" width="20" height="20" style="vertical-align: middle; margin-right: 8px;"> <a href="https://github.com/innovaccer/Healthcare-MCP"><strong>innovaccer/Healthcare-MCP</strong></a></td>
|
|
842
|
+
<td>⭐ 6</td>
|
|
843
|
+
</tr>
|
|
844
|
+
<tr>
|
|
845
|
+
<td><img src="https://avatars.githubusercontent.com/u/205593730?s=40&v=4" width="20" height="20" style="vertical-align: middle; margin-right: 8px;"> <a href="https://github.com/Qingyon-AI/Revornix"><strong>Qingyon-AI/Revornix</strong></a></td>
|
|
846
|
+
<td>⭐ 5</td>
|
|
847
|
+
</tr>
|
|
848
|
+
<tr>
|
|
849
|
+
<td><img src="https://avatars.githubusercontent.com/u/68845761?s=40&v=4" width="20" height="20" style="vertical-align: middle; margin-right: 8px;"> <a href="https://github.com/entbappy/MCP-Tutorials"><strong>entbappy/MCP-Tutorials</strong></a></td>
|
|
850
|
+
<td>⭐ 5</td>
|
|
851
|
+
</tr>
|
|
852
|
+
</table>
|
|
853
|
+
|
|
854
|
+
<!-- gh-dependents-info-used-by-end -->
|
|
855
|
+
|
|
799
856
|
# Requirements
|
|
800
857
|
|
|
801
858
|
- Python 3.11+
|
|
802
859
|
- MCP implementation (like Playwright MCP)
|
|
803
860
|
- LangChain and appropriate model libraries (OpenAI, Anthropic, etc.)
|
|
804
861
|
|
|
862
|
+
# License
|
|
863
|
+
|
|
864
|
+
MIT
|
|
805
865
|
# Citation
|
|
806
866
|
|
|
807
867
|
If you use MCP-Use in your research or project, please cite:
|
|
@@ -815,7 +875,3 @@ If you use MCP-Use in your research or project, please cite:
|
|
|
815
875
|
url = {https://github.com/pietrozullo/mcp-use}
|
|
816
876
|
}
|
|
817
877
|
```
|
|
818
|
-
|
|
819
|
-
# License
|
|
820
|
-
|
|
821
|
-
MIT
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
mcp_use/__init__.py,sha256=I3gFxw6Id45RksUBIZS1kxBW3ItjFXuAfoReJabpnW0,1055
|
|
2
|
+
mcp_use/client.py,sha256=sAyZY6n5XHRW5dWKinfMZ-ovnUYi0s4u7T1mFfEHGLs,9476
|
|
3
|
+
mcp_use/config.py,sha256=jRjTVNMxi7pkqFHMJhzSWpwukE4PbdYU8Pe_IZ33sYI,2433
|
|
4
|
+
mcp_use/logging.py,sha256=CRtkPwR-bkXK_kQ0QOL86RikMWOHzEOi7A8VRHkNsZw,4270
|
|
5
|
+
mcp_use/session.py,sha256=4kwcB_IkTt_3FiBSTI1H17KhL1W_6N5oai3HTxFrTH4,2496
|
|
6
|
+
mcp_use/utils.py,sha256=QavJcVq2WxUUUCCpPCUeOB5bqIS0FFmpK-RAZkGc6aA,720
|
|
7
|
+
mcp_use/adapters/__init__.py,sha256=-xCrgPThuX7x0PHGFDdjb7M-mgw6QV3sKu5PM7ShnRg,275
|
|
8
|
+
mcp_use/adapters/base.py,sha256=tX5vNcz1HZtim4aID_KTfCeI6mQ6qI3bywTWJv0HaZs,7120
|
|
9
|
+
mcp_use/adapters/langchain_adapter.py,sha256=LdlpRyLORhl8NZvtAmisgPelXkhEbBErSNdGHb8SF18,10860
|
|
10
|
+
mcp_use/agents/__init__.py,sha256=N3eVYP2PxqNO2KcQv5fY8UMUX2W3eLTNkkzuFIJ1DUA,261
|
|
11
|
+
mcp_use/agents/base.py,sha256=EN-dRbwOi9vIqofFg3jmi5yT2VKlwEr9Cwi1DZgB3eE,1591
|
|
12
|
+
mcp_use/agents/mcpagent.py,sha256=7AsU8NE7vWmtTp2N2t1N0j4D-gxBFpBlC3XAjyVULWE,31297
|
|
13
|
+
mcp_use/agents/prompts/system_prompt_builder.py,sha256=E86STmxcl2Ic763_114awNqFB2RyLrQlbvgRmJajQjI,4116
|
|
14
|
+
mcp_use/agents/prompts/templates.py,sha256=AZKrGWuI516C-PmyOPvxDBibNdqJtN24sOHTGR06bi4,1933
|
|
15
|
+
mcp_use/connectors/__init__.py,sha256=cUF4yT0bNr8qeLkSzg28SHueiV5qDaHEB1l1GZ2K0dc,536
|
|
16
|
+
mcp_use/connectors/base.py,sha256=yajYF5P924VzggCJ-kt37Rh_srCu__Seb7KUBhjvFdQ,12255
|
|
17
|
+
mcp_use/connectors/http.py,sha256=Aw0DVQN-7fYebDKuX3bvlH9GAFS7Mq9CM_HylXdNqEI,6274
|
|
18
|
+
mcp_use/connectors/sandbox.py,sha256=Id6THKdBvPxFzOFJ2tSK300CiiRFE_EtN5Gu6NRfUTU,10870
|
|
19
|
+
mcp_use/connectors/stdio.py,sha256=rnJoLaHf1cIjk1KqfxfSsUs-iGTJ7KZonxgIc3kXeCM,2791
|
|
20
|
+
mcp_use/connectors/utils.py,sha256=zQ8GdNQx0Twz3by90BoU1RsWPf9wODGof4K3-NxPXeA,366
|
|
21
|
+
mcp_use/connectors/websocket.py,sha256=G7ZeLJNPVl9AG6kCmiNJz1N2Ing_QxT7pSswigTKi8Y,9650
|
|
22
|
+
mcp_use/managers/__init__.py,sha256=rzsJbOhtlmxNQLGcdmtmHaiExEXmiQiUuzPrAgKhAJw,439
|
|
23
|
+
mcp_use/managers/server_manager.py,sha256=Ag1EUSxkG6-UG004vcvaZarPoDnUUMMX7BUeKReUWRI,3704
|
|
24
|
+
mcp_use/managers/tools/__init__.py,sha256=JrA5iTRdtbgwROJE8pQ7GH1sYnqBRcgj4NzFVADKbQ4,510
|
|
25
|
+
mcp_use/managers/tools/base_tool.py,sha256=Jbbp7SwmHKDk8jT_6yVIv7iNsn6KaV_PljWuhhLcbXg,509
|
|
26
|
+
mcp_use/managers/tools/connect_server.py,sha256=MGYQCl11q-w6gSIYuT44dDk7ILV3Oh7kGAJ4fsNXbso,2923
|
|
27
|
+
mcp_use/managers/tools/disconnect_server.py,sha256=Y3kJN31efzsjfJwxUhpBxS-bgU21DCfGbn_LgEbzyvI,1586
|
|
28
|
+
mcp_use/managers/tools/get_active_server.py,sha256=tCaib76gYU3L5G82tEOTq4Io2cuCXWjOjPselb-92i8,964
|
|
29
|
+
mcp_use/managers/tools/list_servers_tool.py,sha256=OPDSMNe-VuAhlUyhDnR4CiuZFpoMhnhWpAablwO5S0k,1897
|
|
30
|
+
mcp_use/managers/tools/search_tools.py,sha256=Vxbi8j50q3DyV9dvWCdPeN4vWFG5ksuLG5sERpdlmWg,12226
|
|
31
|
+
mcp_use/managers/tools/use_tool.py,sha256=gMNjgJrI9XDitPyJglcJcAvowbEWkO5z57yt4DT2Lpc,6626
|
|
32
|
+
mcp_use/observability/__init__.py,sha256=kTUcP0d6L5_3ktfldhdAk-3AWckzVHs7ztG-R6cye64,186
|
|
33
|
+
mcp_use/observability/laminar.py,sha256=WWjmVXP55yCfAlqlayeuJmym1gdrv8is7UyrIp4Tbn0,839
|
|
34
|
+
mcp_use/observability/langfuse.py,sha256=9vgJgnGtVpv_CbCyJqyRkzq2ELqPfYFIUGnpSbm2RCo,1334
|
|
35
|
+
mcp_use/task_managers/__init__.py,sha256=LkXOjiDq5JcyB2tNJuSzyjbxZTl1Ordr_NKKD77Nb7g,557
|
|
36
|
+
mcp_use/task_managers/base.py,sha256=mvLFTVyOfvBWFmkx5l8DZVZUezbhsRARDDfMS2AuFLE,5031
|
|
37
|
+
mcp_use/task_managers/sse.py,sha256=nLKt99OiqoJxFT62zCeNwSZUmdPPg4SD7M1pCEPOa3c,2391
|
|
38
|
+
mcp_use/task_managers/stdio.py,sha256=MJcW03lUZUs_HEUxwFPaqy7m8QLbmdn6LagpcfZdjc8,2130
|
|
39
|
+
mcp_use/task_managers/streamable_http.py,sha256=Zky821Ston5CX0DQVyeRxc2uUqALD8soonRSe09cHcE,2683
|
|
40
|
+
mcp_use/task_managers/websocket.py,sha256=9JTw705rhYbP6x2xAPF6PwtNgF5yEWTQhx-dYSPMoaI,2154
|
|
41
|
+
mcp_use/telemetry/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
42
|
+
mcp_use/telemetry/events.py,sha256=K5xqbmkum30r4gM2PWtTiUWGF8oZzGZw2DYwco1RfOQ,3113
|
|
43
|
+
mcp_use/telemetry/telemetry.py,sha256=ck2MDFMtooafriR1W_zi41dWq-0O-ucF89pCkdkyc9E,11724
|
|
44
|
+
mcp_use/telemetry/utils.py,sha256=kDVTqt2oSeWNJbnTOlXOehr2yFO0PMyx2UGkrWkfJiw,1769
|
|
45
|
+
mcp_use/types/sandbox.py,sha256=opJ9r56F1FvaqVvPovfAj5jZbsOexgwYx5wLgSlN8_U,712
|
|
46
|
+
mcp_use-1.3.2.dist-info/METADATA,sha256=-74mIsLr1hd6BBPmXxpHKf7Yz_fk10W_kHmAQ6DK_K4,28683
|
|
47
|
+
mcp_use-1.3.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
48
|
+
mcp_use-1.3.2.dist-info/licenses/LICENSE,sha256=7Pw7dbwJSBw8zH-WE03JnR5uXvitRtaGTP9QWPcexcs,1068
|
|
49
|
+
mcp_use-1.3.2.dist-info/RECORD,,
|
mcp_use/types/clientoptions.py
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
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."""
|