mcp-use 1.2.11__py3-none-any.whl → 1.2.13__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/adapters/base.py CHANGED
@@ -5,7 +5,9 @@ This module provides the abstract base class that all MCP tool adapters should i
5
5
  """
6
6
 
7
7
  from abc import ABC, abstractmethod
8
- from typing import Any, TypeVar
8
+ from typing import TypeVar
9
+
10
+ from mcp.types import Prompt, Resource, Tool
9
11
 
10
12
  from ..client import MCPClient
11
13
  from ..connectors.base import BaseConnector
@@ -90,13 +92,13 @@ class BaseAdapter(ABC):
90
92
  return self._connector_tool_map[connector]
91
93
 
92
94
  # Create tools for this connector
93
- connector_tools = []
94
95
 
95
96
  # Make sure the connector is initialized and has tools
96
97
  success = await self._ensure_connector_initialized(connector)
97
98
  if not success:
98
99
  return []
99
100
 
101
+ connector_tools = []
100
102
  # Now create tools for each MCP tool
101
103
  for tool in connector.tools:
102
104
  # Convert the tool and add it to the list if conversion was successful
@@ -104,6 +106,23 @@ class BaseAdapter(ABC):
104
106
  if converted_tool:
105
107
  connector_tools.append(converted_tool)
106
108
 
109
+ # Convert resources to tools so that agents can access resource content directly
110
+ resources_list = connector.resources or []
111
+ if resources_list:
112
+ for resource in resources_list:
113
+ converted_resource = self._convert_resource(resource, connector)
114
+ if converted_resource:
115
+ connector_tools.append(converted_resource)
116
+
117
+ # Convert prompts to tools so that agents can retrieve prompt content
118
+ prompts_list = connector.prompts or []
119
+ if prompts_list:
120
+ for prompt in prompts_list:
121
+ converted_prompt = self._convert_prompt(prompt, connector)
122
+ if converted_prompt:
123
+ connector_tools.append(converted_prompt)
124
+ # ------------------------------
125
+
107
126
  # Store the tools for this connector
108
127
  self._connector_tool_map[connector] = connector_tools
109
128
 
@@ -116,16 +135,18 @@ class BaseAdapter(ABC):
116
135
  return connector_tools
117
136
 
118
137
  @abstractmethod
119
- def _convert_tool(self, mcp_tool: dict[str, Any], connector: BaseConnector) -> T:
120
- """Convert an MCP tool to the target framework's tool format.
138
+ def _convert_tool(self, mcp_tool: Tool, connector: BaseConnector) -> T:
139
+ """Convert an MCP tool to the target framework's tool format."""
140
+ pass
121
141
 
122
- Args:
123
- mcp_tool: The MCP tool to convert.
124
- connector: The connector that provides this tool.
142
+ @abstractmethod
143
+ def _convert_resource(self, mcp_resource: Resource, connector: BaseConnector) -> T:
144
+ """Convert an MCP resource to the target framework's resource format."""
145
+ pass
125
146
 
126
- Returns:
127
- A tool in the target framework's format.
128
- """
147
+ @abstractmethod
148
+ def _convert_prompt(self, mcp_prompt: Prompt, connector: BaseConnector) -> T:
149
+ """Convert an MCP prompt to the target framework's prompt format."""
129
150
  pass
130
151
 
131
152
  async def _create_tools_from_connectors(self, connectors: list[BaseConnector]) -> list[T]:
@@ -4,12 +4,21 @@ LangChain adapter for MCP tools.
4
4
  This module provides utilities to convert MCP tools to LangChain tools.
5
5
  """
6
6
 
7
+ import re
7
8
  from typing import Any, NoReturn
8
9
 
9
10
  from jsonschema_pydantic import jsonschema_to_pydantic
10
11
  from langchain_core.tools import BaseTool, ToolException
11
- from mcp.types import CallToolResult, EmbeddedResource, ImageContent, TextContent
12
- from pydantic import BaseModel
12
+ from mcp.types import (
13
+ CallToolResult,
14
+ EmbeddedResource,
15
+ ImageContent,
16
+ Prompt,
17
+ ReadResourceRequestParams,
18
+ Resource,
19
+ TextContent,
20
+ )
21
+ from pydantic import BaseModel, Field, create_model
13
22
 
14
23
  from ..connectors.base import BaseConnector
15
24
  from ..logging import logger
@@ -162,3 +171,104 @@ class LangChainAdapter(BaseAdapter):
162
171
  raise
163
172
 
164
173
  return McpToLangChainAdapter()
174
+
175
+ def _convert_resource(self, mcp_resource: Resource, connector: BaseConnector) -> BaseTool:
176
+ """Convert an MCP resource to LangChain's tool format.
177
+
178
+ Each resource becomes an async tool that returns its content when called.
179
+ The tool takes **no** arguments because the resource URI is fixed.
180
+ """
181
+
182
+ def _sanitize(name: str) -> str:
183
+ return re.sub(r"[^A-Za-z0-9_]+", "_", name).lower().strip("_")
184
+
185
+ class ResourceTool(BaseTool):
186
+ name: str = _sanitize(mcp_resource.name or f"resource_{mcp_resource.uri}")
187
+ description: str = (
188
+ mcp_resource.description
189
+ or f"Return the content of the resource located at URI {mcp_resource.uri}."
190
+ )
191
+ args_schema: type[BaseModel] = ReadResourceRequestParams
192
+ tool_connector: BaseConnector = connector
193
+ handle_tool_error: bool = True
194
+
195
+ def _run(self, **kwargs: Any) -> NoReturn:
196
+ raise NotImplementedError("Resource tools only support async operations")
197
+
198
+ async def _arun(self, **kwargs: Any) -> Any:
199
+ logger.debug(f'Resource tool: "{self.name}" called')
200
+ try:
201
+ result = await self.tool_connector.read_resource(mcp_resource.uri)
202
+ for content in result.contents:
203
+ # Attempt to decode bytes if necessary
204
+ if isinstance(content, bytes):
205
+ content_decoded = content.decode()
206
+ else:
207
+ content_decoded = str(content)
208
+
209
+ return content_decoded
210
+ except Exception as e:
211
+ if self.handle_tool_error:
212
+ return f"Error reading resource: {str(e)}"
213
+ raise
214
+
215
+ return ResourceTool()
216
+
217
+ def _convert_prompt(self, mcp_prompt: Prompt, connector: BaseConnector) -> BaseTool:
218
+ """Convert an MCP prompt to LangChain's tool format.
219
+
220
+ The resulting tool executes `get_prompt` on the connector with the prompt's name and
221
+ the user-provided arguments (if any). The tool returns the decoded prompt content.
222
+ """
223
+ prompt_arguments = mcp_prompt.arguments
224
+
225
+ # Sanitize the prompt name to create a valid Python identifier for the model name
226
+ base_model_name = re.sub(r"[^a-zA-Z0-9_]", "_", mcp_prompt.name)
227
+ if not base_model_name or base_model_name[0].isdigit():
228
+ base_model_name = "PromptArgs_" + base_model_name
229
+ dynamic_model_name = f"{base_model_name}_InputSchema"
230
+
231
+ if prompt_arguments:
232
+ field_definitions_for_create: dict[str, Any] = {}
233
+ for arg in prompt_arguments:
234
+ param_type: type = getattr(arg, "type", str)
235
+ if arg.required:
236
+ field_definitions_for_create[arg.name] = (
237
+ param_type,
238
+ Field(description=arg.description),
239
+ )
240
+ else:
241
+ field_definitions_for_create[arg.name] = (
242
+ param_type | None,
243
+ Field(None, description=arg.description),
244
+ )
245
+
246
+ InputSchema = create_model(
247
+ dynamic_model_name, **field_definitions_for_create, __base__=BaseModel
248
+ )
249
+ else:
250
+ # Create an empty Pydantic model if there are no arguments
251
+ InputSchema = create_model(dynamic_model_name, __base__=BaseModel)
252
+
253
+ class PromptTool(BaseTool):
254
+ name: str = mcp_prompt.name
255
+ description: str = mcp_prompt.description
256
+
257
+ args_schema: type[BaseModel] = InputSchema
258
+ tool_connector: BaseConnector = connector
259
+ handle_tool_error: bool = True
260
+
261
+ def _run(self, **kwargs: Any) -> NoReturn:
262
+ raise NotImplementedError("Prompt tools only support async operations")
263
+
264
+ async def _arun(self, **kwargs: Any) -> Any:
265
+ logger.debug(f'Prompt tool: "{self.name}" called with args: {kwargs}')
266
+ try:
267
+ result = await self.tool_connector.get_prompt(self.name, kwargs)
268
+ return result.messages
269
+ except Exception as e:
270
+ if self.handle_tool_error:
271
+ return f"Error fetching prompt: {str(e)}"
272
+ raise
273
+
274
+ return PromptTool()
mcp_use/client.py CHANGED
@@ -6,6 +6,7 @@ and sessions from configuration.
6
6
  """
7
7
 
8
8
  import json
9
+ import warnings
9
10
  from typing import Any
10
11
 
11
12
  from .config import create_connector_from_config, load_config_file
@@ -115,12 +116,12 @@ class MCPClient:
115
116
  The created MCPSession.
116
117
 
117
118
  Raises:
118
- ValueError: If no servers are configured or the specified server doesn't exist.
119
+ ValueError: If the specified server doesn't exist.
119
120
  """
120
121
  # Get server config
121
122
  servers = self.config.get("mcpServers", {})
122
123
  if not servers:
123
- logger.warning("No MCP servers defined in config")
124
+ warnings.warn("No MCP servers defined in config", UserWarning, stacklevel=2)
124
125
  return None
125
126
 
126
127
  if server_name not in servers:
@@ -153,13 +154,13 @@ class MCPClient:
153
154
  Returns:
154
155
  The created MCPSession. If server_name is None, returns the first created session.
155
156
 
156
- Raises:
157
- ValueError: If no servers are configured or the specified server doesn't exist.
157
+ Warns:
158
+ Warning: If no servers are configured.
158
159
  """
159
160
  # Get server config
160
161
  servers = self.config.get("mcpServers", {})
161
162
  if not servers:
162
- logger.warning("No MCP servers defined in config")
163
+ warnings.warn("No MCP servers defined in config", UserWarning, stacklevel=2)
163
164
  return {}
164
165
 
165
166
  # Create sessions for all servers
@@ -9,7 +9,8 @@ from abc import ABC, abstractmethod
9
9
  from typing import Any
10
10
 
11
11
  from mcp import ClientSession
12
- from mcp.types import CallToolResult, Tool
12
+ from mcp.shared.exceptions import McpError
13
+ from mcp.types import CallToolResult, GetPromptResult, Prompt, ReadResourceResult, Resource, Tool
13
14
 
14
15
  from ..logging import logger
15
16
  from ..task_managers import ConnectionManager
@@ -26,6 +27,8 @@ class BaseConnector(ABC):
26
27
  self.client: ClientSession | None = None
27
28
  self._connection_manager: ConnectionManager | None = None
28
29
  self._tools: list[Tool] | None = None
30
+ self._resources: list[Resource] | None = None
31
+ self._prompts: list[Prompt] | None = None
29
32
  self._connected = False
30
33
 
31
34
  @abstractmethod
@@ -74,6 +77,8 @@ class BaseConnector(ABC):
74
77
 
75
78
  # Reset tools
76
79
  self._tools = None
80
+ self._resources = None
81
+ self._prompts = None
77
82
 
78
83
  if errors:
79
84
  logger.warning(f"Encountered {len(errors)} errors during resource cleanup")
@@ -88,21 +93,58 @@ class BaseConnector(ABC):
88
93
  # Initialize the session
89
94
  result = await self.client.initialize()
90
95
 
91
- # Get available tools
92
- tools_result = await self.client.list_tools()
93
- self._tools = tools_result.tools
94
-
95
- logger.debug(f"MCP session initialized with {len(self._tools)} tools")
96
+ server_capabilities = result.capabilities
97
+
98
+ if server_capabilities.tools:
99
+ # Get available tools
100
+ tools_result = await self.list_tools()
101
+ self._tools = tools_result or []
102
+ else:
103
+ self._tools = []
104
+
105
+ if server_capabilities.resources:
106
+ # Get available resources
107
+ resources_result = await self.list_resources()
108
+ self._resources = resources_result or []
109
+ else:
110
+ self._resources = []
111
+
112
+ if server_capabilities.prompts:
113
+ # Get available prompts
114
+ prompts_result = await self.list_prompts()
115
+ self._prompts = prompts_result or []
116
+ else:
117
+ self._prompts = []
118
+
119
+ logger.debug(
120
+ f"MCP session initialized with {len(self._tools)} tools, "
121
+ f"{len(self._resources)} resources, "
122
+ f"and {len(self._prompts)} prompts"
123
+ )
96
124
 
97
125
  return result
98
126
 
99
127
  @property
100
128
  def tools(self) -> list[Tool]:
101
129
  """Get the list of available tools."""
102
- if not self._tools:
130
+ if self._tools is None:
103
131
  raise RuntimeError("MCP client is not initialized")
104
132
  return self._tools
105
133
 
134
+ @property
135
+ def resources(self) -> list[Resource]:
136
+ """Get the list of available resources."""
137
+ if self._resources is None:
138
+ raise RuntimeError("MCP client is not initialized")
139
+ return self._resources
140
+
141
+ @property
142
+ def prompts(self) -> list[Prompt]:
143
+ """Get the list of available prompts."""
144
+ if self._prompts is None:
145
+ raise RuntimeError("MCP client is not initialized")
146
+ return self._prompts
147
+
106
148
  async def call_tool(self, name: str, arguments: dict[str, Any]) -> CallToolResult:
107
149
  """Call an MCP tool with the given arguments."""
108
150
  if not self.client:
@@ -113,43 +155,64 @@ class BaseConnector(ABC):
113
155
  logger.debug(f"Tool '{name}' called with result: {result}")
114
156
  return result
115
157
 
116
- async def list_resources(self) -> list[dict[str, Any]]:
158
+ async def list_tools(self) -> list[Tool]:
159
+ """List all available tools from the MCP implementation."""
160
+ if not self.client:
161
+ raise RuntimeError("MCP client is not connected")
162
+
163
+ logger.debug("Listing tools")
164
+ try:
165
+ result = await self.client.list_tools()
166
+ return result.tools
167
+ except McpError as e:
168
+ logger.error(f"Error listing tools: {e}")
169
+ return []
170
+
171
+ async def list_resources(self) -> list[Resource]:
117
172
  """List all available resources from the MCP implementation."""
118
173
  if not self.client:
119
174
  raise RuntimeError("MCP client is not connected")
120
175
 
121
176
  logger.debug("Listing resources")
122
- resources = await self.client.list_resources()
123
- return resources
124
-
125
- async def read_resource(self, uri: str) -> tuple[bytes, str]:
177
+ try:
178
+ result = await self.client.list_resources()
179
+ return result.resources
180
+ except McpError as e:
181
+ logger.error(f"Error listing resources: {e}")
182
+ return []
183
+
184
+ async def read_resource(self, uri: str) -> ReadResourceResult:
126
185
  """Read a resource by URI."""
127
186
  if not self.client:
128
187
  raise RuntimeError("MCP client is not connected")
129
188
 
130
189
  logger.debug(f"Reading resource: {uri}")
131
- resource = await self.client.read_resource(uri)
132
- return resource.content, resource.mimeType
190
+ result = await self.client.read_resource(uri)
191
+ return result
133
192
 
134
- async def list_prompts(self) -> list[dict[str, Any]]:
193
+ async def list_prompts(self) -> list[Prompt]:
135
194
  """List all available prompts from the MCP implementation."""
136
195
  if not self.client:
137
196
  raise RuntimeError("MCP client is not connected")
138
197
 
139
198
  logger.debug("Listing prompts")
140
- prompts = await self.client.list_prompts()
141
- return prompts
199
+ try:
200
+ result = await self.client.list_prompts()
201
+ return result.prompts
202
+ except McpError as e:
203
+ logger.error(f"Error listing prompts: {e}")
204
+ return []
142
205
 
143
206
  async def get_prompt(
144
207
  self, name: str, arguments: dict[str, Any] | None = None
145
- ) -> tuple[bytes, str]:
208
+ ) -> GetPromptResult:
146
209
  """Get a prompt by name."""
147
210
  if not self.client:
148
211
  raise RuntimeError("MCP client is not connected")
149
212
 
150
213
  logger.debug(f"Getting prompt: {name}")
151
- prompt = await self.client.get_prompt(name, arguments)
152
- return prompt
214
+ result = await self.client.get_prompt(name, arguments)
215
+ return result
153
216
 
154
217
  async def request(self, method: str, params: dict[str, Any] | None = None) -> Any:
155
218
  """Send a raw request to the MCP implementation."""
mcp_use/session.py CHANGED
@@ -7,6 +7,8 @@ which handles authentication, initialization, and tool discovery.
7
7
 
8
8
  from typing import Any
9
9
 
10
+ from mcp.types import Tool
11
+
10
12
  from .connectors.base import BaseConnector
11
13
 
12
14
 
@@ -30,7 +32,7 @@ class MCPSession:
30
32
  """
31
33
  self.connector = connector
32
34
  self.session_info: dict[str, Any] | None = None
33
- self.tools: list[dict[str, Any]] = []
35
+ self.tools: list[Tool] = []
34
36
  self.auto_connect = auto_connect
35
37
 
36
38
  async def __aenter__(self) -> "MCPSession":
@@ -73,9 +75,6 @@ class MCPSession:
73
75
  # Initialize the session
74
76
  self.session_info = await self.connector.initialize()
75
77
 
76
- # Discover available tools
77
- await self.discover_tools()
78
-
79
78
  return self.session_info
80
79
 
81
80
  @property
@@ -86,28 +85,3 @@ class MCPSession:
86
85
  True if the connector is connected, False otherwise.
87
86
  """
88
87
  return hasattr(self.connector, "client") and self.connector.client is not None
89
-
90
- async def discover_tools(self) -> list[dict[str, Any]]:
91
- """Discover available tools from the MCP implementation.
92
-
93
- Returns:
94
- The list of available tools in MCP format.
95
- """
96
- self.tools = self.connector.tools
97
- return self.tools
98
-
99
- async def call_tool(self, name: str, arguments: dict[str, Any]) -> Any:
100
- """Call an MCP tool with the given arguments.
101
-
102
- Args:
103
- name: The name of the tool to call.
104
- arguments: The arguments to pass to the tool.
105
-
106
- Returns:
107
- The result of the tool call.
108
- """
109
- # Make sure we're connected
110
- if not self.is_connected and self.auto_connect:
111
- await self.connect()
112
-
113
- return await self.connector.call_tool(name, arguments)
@@ -46,14 +46,12 @@ class ConnectionManager(Generic[T], ABC):
46
46
  pass
47
47
 
48
48
  @abstractmethod
49
- async def _close_connection(self, connection: T) -> None:
49
+ async def _close_connection(self) -> None:
50
50
  """Close the connection.
51
51
 
52
52
  This method should be implemented by subclasses to close
53
53
  the specific type of connection.
54
54
 
55
- Args:
56
- connection: The connection to close.
57
55
  """
58
56
  pass
59
57
 
@@ -139,10 +137,10 @@ class ConnectionManager(Generic[T], ABC):
139
137
  self._ready_event.set()
140
138
 
141
139
  finally:
142
- # Close the connection if it was established
140
+ # Close the connection if it was establishedSUPABASE_URL
143
141
  if self._connection is not None:
144
142
  try:
145
- await self._close_connection(self._connection)
143
+ await self._close_connection()
146
144
  except Exception as e:
147
145
  logger.warning(f"Error closing connection in {self.__class__.__name__}: {e}")
148
146
  self._connection = None
@@ -66,12 +66,9 @@ class SseConnectionManager(ConnectionManager[tuple[Any, Any]]):
66
66
  # Return the streams
67
67
  return (read_stream, write_stream)
68
68
 
69
- async def _close_connection(self, connection: tuple[Any, Any]) -> None:
70
- """Close the SSE connection.
69
+ async def _close_connection(self) -> None:
70
+ """Close the SSE connection."""
71
71
 
72
- Args:
73
- connection: The connection to close (ignored, we use the context manager)
74
- """
75
72
  if self._sse_ctx:
76
73
  # Exit the context manager
77
74
  try:
@@ -57,12 +57,8 @@ class StdioConnectionManager(ConnectionManager[tuple[Any, Any]]):
57
57
  # Return the streams
58
58
  return (read_stream, write_stream)
59
59
 
60
- async def _close_connection(self, connection: tuple[Any, Any]) -> None:
61
- """Close the stdio connection.
62
-
63
- Args:
64
- connection: The connection to close (ignored, we use the context manager)
65
- """
60
+ async def _close_connection(self) -> None:
61
+ """Close the stdio connection."""
66
62
  if self._stdio_ctx:
67
63
  # Exit the context manager
68
64
  try:
@@ -4,14 +4,15 @@ WebSocket connection management for MCP implementations.
4
4
  This module provides a connection manager for WebSocket-based MCP connections.
5
5
  """
6
6
 
7
- import websockets
8
- from websockets.client import ClientConnection
7
+ from typing import Any
8
+
9
+ from mcp.client.websocket import websocket_client
9
10
 
10
11
  from ..logging import logger
11
12
  from .base import ConnectionManager
12
13
 
13
14
 
14
- class WebSocketConnectionManager(ConnectionManager[ClientConnection]):
15
+ class WebSocketConnectionManager(ConnectionManager[tuple[Any, Any]]):
15
16
  """Connection manager for WebSocket-based MCP connections.
16
17
 
17
18
  This class handles the lifecycle of WebSocket connections, ensuring proper
@@ -21,19 +22,16 @@ class WebSocketConnectionManager(ConnectionManager[ClientConnection]):
21
22
  def __init__(
22
23
  self,
23
24
  url: str,
24
- headers: dict[str, str] | None = None,
25
25
  ):
26
26
  """Initialize a new WebSocket connection manager.
27
27
 
28
28
  Args:
29
29
  url: The WebSocket URL to connect to
30
- headers: Optional headers to include in the WebSocket connection
31
30
  """
32
31
  super().__init__()
33
32
  self.url = url
34
- self.headers = headers or {}
35
33
 
36
- async def _establish_connection(self) -> ClientConnection:
34
+ async def _establish_connection(self) -> tuple[Any, Any]:
37
35
  """Establish a WebSocket connection.
38
36
 
39
37
  Returns:
@@ -43,21 +41,23 @@ class WebSocketConnectionManager(ConnectionManager[ClientConnection]):
43
41
  Exception: If connection cannot be established
44
42
  """
45
43
  logger.debug(f"Connecting to WebSocket: {self.url}")
46
- try:
47
- ws = await websockets.connect(self.url, extra_headers=self.headers)
48
- return ws
49
- except Exception as e:
50
- logger.error(f"Failed to connect to WebSocket: {e}")
51
- raise
52
-
53
- async def _close_connection(self, connection: ClientConnection) -> None:
54
- """Close the WebSocket connection.
55
-
56
- Args:
57
- connection: The WebSocket connection to close
58
- """
59
- try:
60
- logger.debug("Closing WebSocket connection")
61
- await connection.close()
62
- except Exception as e:
63
- logger.warning(f"Error closing WebSocket connection: {e}")
44
+ # Create the context manager
45
+ self._ws_ctx = websocket_client(self.url)
46
+
47
+ # Enter the context manager
48
+ read_stream, write_stream = await self._ws_ctx.__aenter__()
49
+
50
+ # Return the streams
51
+ return (read_stream, write_stream)
52
+
53
+ async def _close_connection(self) -> None:
54
+ """Close the WebSocket connection."""
55
+ if self._ws_ctx:
56
+ # Exit the context manager
57
+ try:
58
+ logger.debug("Closing WebSocket connection")
59
+ await self._ws_ctx.__aexit__(None, None, None)
60
+ except Exception as e:
61
+ logger.warning(f"Error closing WebSocket connection: {e}")
62
+ finally:
63
+ self._ws_ctx = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-use
3
- Version: 1.2.11
3
+ Version: 1.2.13
4
4
  Summary: MCP Library for LLMs
5
5
  Author-email: Pietro Zullo <pietro.zullo@gmail.com>
6
6
  License: MIT
@@ -39,23 +39,39 @@ Provides-Extra: search
39
39
  Requires-Dist: fastembed>=0.0.1; extra == 'search'
40
40
  Description-Content-Type: text/markdown
41
41
 
42
- <picture>
43
- <img alt="" src="./static/image.jpg" width="full">
44
- </picture>
42
+ <div align="center" style="margin: 0 auto; max-width: 80%;">
43
+ <picture>
44
+ <source media="(prefers-color-scheme: dark)" srcset="static/logo_white.svg">
45
+ <source media="(prefers-color-scheme: light)" srcset="static/logo_black.svg">
46
+ <img alt="mcp use logo" src="./static/logo-white.svg" width="80%" style="margin: 20px auto;">
47
+ </picture>
48
+ </div>
45
49
 
46
50
  <h1 align="center">Unified MCP Client Library </h1>
47
-
48
- [![](https://img.shields.io/pypi/dw/mcp_use.svg)](https://pypi.org/project/mcp_use/)
49
- [![PyPI Downloads](https://img.shields.io/pypi/dm/mcp_use.svg)](https://pypi.org/project/mcp_use/)
50
- [![PyPI Version](https://img.shields.io/pypi/v/mcp_use.svg)](https://pypi.org/project/mcp_use/)
51
- [![Python Versions](https://img.shields.io/pypi/pyversions/mcp_use.svg)](https://pypi.org/project/mcp_use/)
52
- [![Documentation](https://img.shields.io/badge/docs-mcp--use.io-blue)](https://docs.mcp-use.io)
53
- [![Website](https://img.shields.io/badge/website-mcp--use.io-blue)](https://mcp-use.io)
54
- [![License](https://img.shields.io/github/license/pietrozullo/mcp-use)](https://github.com/pietrozullo/mcp-use/blob/main/LICENSE)
55
- [![Code style: Ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
56
- [![GitHub stars](https://img.shields.io/github/stars/pietrozullo/mcp-use?style=social)](https://github.com/pietrozullo/mcp-use/stargazers)
57
- [![Twitter Follow](https://img.shields.io/twitter/follow/Pietro?style=social)](https://x.com/pietrozullo)
58
-
51
+ <p align="center">
52
+ <a href="https://pypi.org/project/mcp_use/" alt="PyPI Version">
53
+ <img src="https://img.shields.io/pypi/v/mcp_use.svg"/></a>
54
+ <a href="https://pypi.org/project/mcp_use/" alt="PyPI Downloads">
55
+ <img src="https://static.pepy.tech/badge/mcp-use" /></a>
56
+ <a href="https://pypi.org/project/mcp_use/" alt="Python Versions">
57
+ <img src="https://img.shields.io/pypi/pyversions/mcp_use.svg" /></a>
58
+ <a href="https://docs.mcp-use.io" alt="Documentation">
59
+ <img src="https://img.shields.io/badge/docs-mcp--use.io-blue" /></a>
60
+ <a href="https://mcp-use.io" alt="Website">
61
+ <img src="https://img.shields.io/badge/website-mcp--use.io-blue" /></a>
62
+ <a href="https://github.com/pietrozullo/mcp-use/blob/main/LICENSE" alt="License">
63
+ <img src="https://img.shields.io/github/license/pietrozullo/mcp-use" /></a>
64
+ <a href="https://github.com/astral-sh/ruff" alt="Code style: Ruff">
65
+ <img src="https://img.shields.io/badge/code%20style-ruff-000000.svg" /></a>
66
+ <a href="https://github.com/pietrozullo/mcp-use/stargazers" alt="GitHub stars">
67
+ <img src="https://img.shields.io/github/stars/pietrozullo/mcp-use?style=social" /></a>
68
+ </p>
69
+ <p align="center">
70
+ <a href="https://x.com/pietrozullo" alt="Twitter Follow">
71
+ <img src="https://img.shields.io/twitter/follow/Pietro?style=social" /></a>
72
+ <a href="https://discord.gg/XkNkSkMz3V" alt="Discord">
73
+ <img src="https://dcbadge.limes.pink/api/server/https://discord.gg/XkNkSkMz3V?style=flat" /></a>
74
+ </p>
59
75
  🌐 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.
60
76
 
61
77
  💡 Let developers easily connect any LLM to tools like web browsing, file operations, and more.
@@ -1,18 +1,18 @@
1
1
  mcp_use/__init__.py,sha256=FikKagS6u8mugJOeslN3xfSA-tBLhjOywZSEcQ-y23g,1006
2
- mcp_use/client.py,sha256=hLaebFjVPiTDQbFnj6TN7hKctMXDFm-jqsQcQ5GaY0c,8320
2
+ mcp_use/client.py,sha256=3mEiAtGlC28iv0zeEtQcMI6cfTlllyjSvS0dwuoVBrw,8317
3
3
  mcp_use/config.py,sha256=O9V4pa-shZ2mPokRTrd7KZQ2GpuTcYBGUslefl1fosw,1653
4
4
  mcp_use/logging.py,sha256=UhQdMx0H0q08-ZPjY_hAJVErkEUAkU1oahHqwdfdK_U,4274
5
- mcp_use/session.py,sha256=Z4EZTUnQUX0QyGMzkJIrMRTX4SDk6qQUoBld408LIJE,3449
5
+ mcp_use/session.py,sha256=IPVzYASFMZx7-xpK4X_MR5chcsIwGvcs6vYXiO1hutM,2604
6
6
  mcp_use/adapters/__init__.py,sha256=-xCrgPThuX7x0PHGFDdjb7M-mgw6QV3sKu5PM7ShnRg,275
7
- mcp_use/adapters/base.py,sha256=ixLHXp8FWdyZPx7Kh6s-4jEVs3qT4DWrApSLXfqzNws,6141
8
- mcp_use/adapters/langchain_adapter.py,sha256=s8IHPPtqqXMmWQfeBqwESs3SZA6_ECSiGRwdTOIWki0,6417
7
+ mcp_use/adapters/base.py,sha256=bPVjHERySX6Vw16mEmgFaJuy4Yc_sM8JPtOAqJrP6Rg,7164
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
11
  mcp_use/agents/mcpagent.py,sha256=xZr-ihW5CW2wKAi0Gi-9GIXlJE0MGu-18xR8vi-Fu6Q,27025
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
14
  mcp_use/connectors/__init__.py,sha256=jnd-7pPPJMb0UNJ6aD9lInj5Tlamc8lA_mFyG8RWJpo,385
15
- mcp_use/connectors/base.py,sha256=5V8XHh3K-_zMBG22c6cxHynLyZps7M8FTIMt29OJa8o,5599
15
+ mcp_use/connectors/base.py,sha256=uJFU80kIpr0bVRAHDXTWRziIwdb_5Yjf2HsDNokZw-M,7731
16
16
  mcp_use/connectors/http.py,sha256=2ZG5JxcK1WZ4jkTfTir6bEQLMxXBTPHyi0s42RHGeFs,2837
17
17
  mcp_use/connectors/stdio.py,sha256=MTzsqmVVihACUKngE-g5BignK3jAFds2CFv3aSzbJfs,2608
18
18
  mcp_use/connectors/websocket.py,sha256=LeU53YI3zjbwKq5GzFRziqA_z9Dn5qACiNyxWDrn2ns,9540
@@ -27,11 +27,11 @@ mcp_use/managers/tools/list_servers_tool.py,sha256=OPDSMNe-VuAhlUyhDnR4CiuZFpoMh
27
27
  mcp_use/managers/tools/search_tools.py,sha256=sT2fe66IyOeASTGjdTsjyzSpqkIGKLVXBF8wXUtWXd4,12055
28
28
  mcp_use/managers/tools/use_tool.py,sha256=r7k7uMYzrk353qw7M5h1utu_IR2G85uMZkrNcg2RyZA,6824
29
29
  mcp_use/task_managers/__init__.py,sha256=4dgW5N61iiPLpwjU2rrn_uqrL8mmDJFDaF9Lukzk65A,486
30
- mcp_use/task_managers/base.py,sha256=ksNdxTwq8N-zqymxVoKGnWXq9iqkLYC61uB91o6Mh-4,4888
31
- mcp_use/task_managers/sse.py,sha256=WysmjwqRI3meXMZY_F4y9tSBMvSiUZfTJQfitM5l6jQ,2529
32
- mcp_use/task_managers/stdio.py,sha256=DEISpXv4mo3d5a-WT8lkWbrXJwUh7QW0nMT_IM3fHGg,2269
33
- mcp_use/task_managers/websocket.py,sha256=ZbCqdGgzCRtsXzRGFws-f2OzH8cPAkN4sJNDwEpRmCc,1915
34
- mcp_use-1.2.11.dist-info/METADATA,sha256=HudT6j4l5spNbzm-JTfi-Eo3yfwf6fFeG4T1-lV-ZaE,20199
35
- mcp_use-1.2.11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
36
- mcp_use-1.2.11.dist-info/licenses/LICENSE,sha256=7Pw7dbwJSBw8zH-WE03JnR5uXvitRtaGTP9QWPcexcs,1068
37
- mcp_use-1.2.11.dist-info/RECORD,,
30
+ mcp_use/task_managers/base.py,sha256=xBrS9_GdlR0tr6sKN5pyMGUrQVGKRD6Qlk6hhOFcxRE,4806
31
+ mcp_use/task_managers/sse.py,sha256=nLKt99OiqoJxFT62zCeNwSZUmdPPg4SD7M1pCEPOa3c,2391
32
+ mcp_use/task_managers/stdio.py,sha256=MJcW03lUZUs_HEUxwFPaqy7m8QLbmdn6LagpcfZdjc8,2130
33
+ mcp_use/task_managers/websocket.py,sha256=POB4YwCff6IJ0vj4eGpYqfDwLiqA0_fEUS4hbborGa4,1848
34
+ mcp_use-1.2.13.dist-info/METADATA,sha256=Jhij8qlF_RqgiiRlVSVZYIlP6TgGYjcr3j_2LLSe0bo,20966
35
+ mcp_use-1.2.13.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
36
+ mcp_use-1.2.13.dist-info/licenses/LICENSE,sha256=7Pw7dbwJSBw8zH-WE03JnR5uXvitRtaGTP9QWPcexcs,1068
37
+ mcp_use-1.2.13.dist-info/RECORD,,