mcp-use 0.1.0__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mcp-use might be problematic. Click here for more details.
- mcp_use/__init__.py +6 -6
- mcp_use/agents/langchain_agent.py +88 -64
- mcp_use/agents/mcpagent.py +216 -52
- mcp_use/agents/prompts/default.py +22 -0
- mcp_use/client.py +93 -68
- mcp_use/config.py +0 -54
- mcp_use/connectors/base.py +1 -3
- mcp_use/connectors/http.py +91 -7
- mcp_use/connectors/stdio.py +97 -33
- mcp_use/connectors/websocket.py +124 -21
- mcp_use/session.py +0 -55
- mcp_use/task_managers/__init__.py +18 -0
- mcp_use/task_managers/base.py +151 -0
- mcp_use/task_managers/http.py +62 -0
- mcp_use/task_managers/stdio.py +73 -0
- mcp_use/task_managers/websocket.py +63 -0
- mcp_use-1.0.0.dist-info/METADATA +382 -0
- mcp_use-1.0.0.dist-info/RECORD +24 -0
- {mcp_use-0.1.0.dist-info → mcp_use-1.0.0.dist-info}/WHEEL +1 -2
- mcp_use/tools/__init__.py +0 -11
- mcp_use/tools/converter.py +0 -108
- mcp_use/tools/formats.py +0 -181
- mcp_use/types.py +0 -33
- mcp_use-0.1.0.dist-info/METADATA +0 -287
- mcp_use-0.1.0.dist-info/RECORD +0 -23
- mcp_use-0.1.0.dist-info/top_level.txt +0 -1
- {mcp_use-0.1.0.dist-info → mcp_use-1.0.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Connection management for MCP implementations.
|
|
3
|
+
|
|
4
|
+
This module provides an abstract base class for different types of connection
|
|
5
|
+
managers used in MCP connectors.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import asyncio
|
|
9
|
+
from abc import ABC, abstractmethod
|
|
10
|
+
from typing import Generic, TypeVar
|
|
11
|
+
|
|
12
|
+
from ..logging import logger
|
|
13
|
+
|
|
14
|
+
# Type variable for connection types
|
|
15
|
+
T = TypeVar("T")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ConnectionManager(Generic[T], ABC):
|
|
19
|
+
"""Abstract base class for connection managers.
|
|
20
|
+
|
|
21
|
+
This class defines the interface for different types of connection managers
|
|
22
|
+
used with MCP connectors.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(self):
|
|
26
|
+
"""Initialize a new connection manager."""
|
|
27
|
+
self._ready_event = asyncio.Event()
|
|
28
|
+
self._done_event = asyncio.Event()
|
|
29
|
+
self._exception: Exception | None = None
|
|
30
|
+
self._connection: T | None = None
|
|
31
|
+
self._task: asyncio.Task | None = None
|
|
32
|
+
|
|
33
|
+
@abstractmethod
|
|
34
|
+
async def _establish_connection(self) -> T:
|
|
35
|
+
"""Establish the connection.
|
|
36
|
+
|
|
37
|
+
This method should be implemented by subclasses to establish
|
|
38
|
+
the specific type of connection needed.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
The established connection.
|
|
42
|
+
|
|
43
|
+
Raises:
|
|
44
|
+
Exception: If connection cannot be established.
|
|
45
|
+
"""
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
@abstractmethod
|
|
49
|
+
async def _close_connection(self, connection: T) -> None:
|
|
50
|
+
"""Close the connection.
|
|
51
|
+
|
|
52
|
+
This method should be implemented by subclasses to close
|
|
53
|
+
the specific type of connection.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
connection: The connection to close.
|
|
57
|
+
"""
|
|
58
|
+
pass
|
|
59
|
+
|
|
60
|
+
async def start(self) -> T:
|
|
61
|
+
"""Start the connection manager and establish a connection.
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
The established connection.
|
|
65
|
+
|
|
66
|
+
Raises:
|
|
67
|
+
Exception: If connection cannot be established.
|
|
68
|
+
"""
|
|
69
|
+
# Reset state
|
|
70
|
+
self._ready_event.clear()
|
|
71
|
+
self._done_event.clear()
|
|
72
|
+
self._exception = None
|
|
73
|
+
|
|
74
|
+
# Create a task to establish and maintain the connection
|
|
75
|
+
self._task = asyncio.create_task(
|
|
76
|
+
self._connection_task(), name=f"{self.__class__.__name__}_task"
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Wait for the connection to be ready or fail
|
|
80
|
+
await self._ready_event.wait()
|
|
81
|
+
|
|
82
|
+
# If there was an exception, raise it
|
|
83
|
+
if self._exception:
|
|
84
|
+
raise self._exception
|
|
85
|
+
|
|
86
|
+
# Return the connection
|
|
87
|
+
if self._connection is None:
|
|
88
|
+
raise RuntimeError("Connection was not established")
|
|
89
|
+
return self._connection
|
|
90
|
+
|
|
91
|
+
async def stop(self) -> None:
|
|
92
|
+
"""Stop the connection manager and close the connection."""
|
|
93
|
+
if self._task and not self._task.done():
|
|
94
|
+
# Cancel the task
|
|
95
|
+
logger.debug(f"Cancelling {self.__class__.__name__} task")
|
|
96
|
+
self._task.cancel()
|
|
97
|
+
|
|
98
|
+
# Wait for it to complete
|
|
99
|
+
try:
|
|
100
|
+
await self._task
|
|
101
|
+
except asyncio.CancelledError:
|
|
102
|
+
logger.debug(f"{self.__class__.__name__} task cancelled successfully")
|
|
103
|
+
except Exception as e:
|
|
104
|
+
logger.warning(f"Error stopping {self.__class__.__name__} task: {e}")
|
|
105
|
+
|
|
106
|
+
# Wait for the connection to be done
|
|
107
|
+
await self._done_event.wait()
|
|
108
|
+
logger.debug(f"{self.__class__.__name__} task completed")
|
|
109
|
+
|
|
110
|
+
async def _connection_task(self) -> None:
|
|
111
|
+
"""Run the connection task.
|
|
112
|
+
|
|
113
|
+
This task establishes and maintains the connection until cancelled.
|
|
114
|
+
"""
|
|
115
|
+
logger.debug(f"Starting {self.__class__.__name__} task")
|
|
116
|
+
try:
|
|
117
|
+
# Establish the connection
|
|
118
|
+
self._connection = await self._establish_connection()
|
|
119
|
+
logger.debug(f"{self.__class__.__name__} connected successfully")
|
|
120
|
+
|
|
121
|
+
# Signal that the connection is ready
|
|
122
|
+
self._ready_event.set()
|
|
123
|
+
|
|
124
|
+
# Wait indefinitely until cancelled
|
|
125
|
+
try:
|
|
126
|
+
# This keeps the connection open until cancelled
|
|
127
|
+
await asyncio.Event().wait()
|
|
128
|
+
except asyncio.CancelledError:
|
|
129
|
+
# Expected when stopping
|
|
130
|
+
logger.debug(f"{self.__class__.__name__} task received cancellation")
|
|
131
|
+
pass
|
|
132
|
+
|
|
133
|
+
except Exception as e:
|
|
134
|
+
# Store the exception
|
|
135
|
+
self._exception = e
|
|
136
|
+
logger.error(f"Error in {self.__class__.__name__} task: {e}")
|
|
137
|
+
|
|
138
|
+
# Signal that the connection is ready (with error)
|
|
139
|
+
self._ready_event.set()
|
|
140
|
+
|
|
141
|
+
finally:
|
|
142
|
+
# Close the connection if it was established
|
|
143
|
+
if self._connection is not None:
|
|
144
|
+
try:
|
|
145
|
+
await self._close_connection(self._connection)
|
|
146
|
+
except Exception as e:
|
|
147
|
+
logger.warning(f"Error closing connection in {self.__class__.__name__}: {e}")
|
|
148
|
+
self._connection = None
|
|
149
|
+
|
|
150
|
+
# Signal that the connection is done
|
|
151
|
+
self._done_event.set()
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""
|
|
2
|
+
HTTP connection management for MCP implementations.
|
|
3
|
+
|
|
4
|
+
This module provides a connection manager for HTTP-based MCP connections.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import aiohttp
|
|
8
|
+
|
|
9
|
+
from ..logging import logger
|
|
10
|
+
from .base import ConnectionManager
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class HttpConnectionManager(ConnectionManager[aiohttp.ClientSession]):
|
|
14
|
+
"""Connection manager for HTTP-based MCP connections.
|
|
15
|
+
|
|
16
|
+
This class handles the lifecycle of HTTP client sessions, ensuring proper
|
|
17
|
+
connection establishment and cleanup.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
base_url: str,
|
|
23
|
+
headers: dict[str, str] | None = None,
|
|
24
|
+
):
|
|
25
|
+
"""Initialize a new HTTP connection manager.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
base_url: The base URL for HTTP requests
|
|
29
|
+
headers: Optional headers to include in all HTTP requests
|
|
30
|
+
"""
|
|
31
|
+
super().__init__()
|
|
32
|
+
self.base_url = base_url.rstrip("/")
|
|
33
|
+
self.headers = headers or {}
|
|
34
|
+
|
|
35
|
+
async def _establish_connection(self) -> aiohttp.ClientSession:
|
|
36
|
+
"""Establish an HTTP client session.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
The established HTTP client session
|
|
40
|
+
|
|
41
|
+
Raises:
|
|
42
|
+
Exception: If session cannot be established
|
|
43
|
+
"""
|
|
44
|
+
logger.debug(f"Creating HTTP client session for: {self.base_url}")
|
|
45
|
+
try:
|
|
46
|
+
session = aiohttp.ClientSession(headers=self.headers)
|
|
47
|
+
return session
|
|
48
|
+
except Exception as e:
|
|
49
|
+
logger.error(f"Failed to create HTTP client session: {e}")
|
|
50
|
+
raise
|
|
51
|
+
|
|
52
|
+
async def _close_connection(self, connection: aiohttp.ClientSession) -> None:
|
|
53
|
+
"""Close the HTTP client session.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
connection: The HTTP client session to close
|
|
57
|
+
"""
|
|
58
|
+
try:
|
|
59
|
+
logger.debug("Closing HTTP client session")
|
|
60
|
+
await connection.close()
|
|
61
|
+
except Exception as e:
|
|
62
|
+
logger.warning(f"Error closing HTTP client session: {e}")
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""
|
|
2
|
+
StdIO connection management for MCP implementations.
|
|
3
|
+
|
|
4
|
+
This module provides a connection manager for stdio-based MCP connections
|
|
5
|
+
that ensures proper task isolation and resource cleanup.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
from typing import Any, TextIO
|
|
10
|
+
|
|
11
|
+
from mcp import StdioServerParameters
|
|
12
|
+
from mcp.client.stdio import stdio_client
|
|
13
|
+
|
|
14
|
+
from ..logging import logger
|
|
15
|
+
from .base import ConnectionManager
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class StdioConnectionManager(ConnectionManager[tuple[Any, Any]]):
|
|
19
|
+
"""Connection manager for stdio-based MCP connections.
|
|
20
|
+
|
|
21
|
+
This class handles the proper task isolation for stdio_client context managers
|
|
22
|
+
to prevent the "cancel scope in different task" error. It runs the stdio_client
|
|
23
|
+
in a dedicated task and manages its lifecycle.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
server_params: StdioServerParameters,
|
|
29
|
+
errlog: TextIO = sys.stderr,
|
|
30
|
+
):
|
|
31
|
+
"""Initialize a new stdio connection manager.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
server_params: The parameters for the stdio server
|
|
35
|
+
errlog: The error log stream
|
|
36
|
+
"""
|
|
37
|
+
super().__init__()
|
|
38
|
+
self.server_params = server_params
|
|
39
|
+
self.errlog = errlog
|
|
40
|
+
self._stdio_ctx = None
|
|
41
|
+
|
|
42
|
+
async def _establish_connection(self) -> tuple[Any, Any]:
|
|
43
|
+
"""Establish a stdio connection.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
A tuple of (read_stream, write_stream)
|
|
47
|
+
|
|
48
|
+
Raises:
|
|
49
|
+
Exception: If connection cannot be established.
|
|
50
|
+
"""
|
|
51
|
+
# Create the context manager
|
|
52
|
+
self._stdio_ctx = stdio_client(self.server_params, self.errlog)
|
|
53
|
+
|
|
54
|
+
# Enter the context manager
|
|
55
|
+
read_stream, write_stream = await self._stdio_ctx.__aenter__()
|
|
56
|
+
|
|
57
|
+
# Return the streams
|
|
58
|
+
return (read_stream, write_stream)
|
|
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
|
+
"""
|
|
66
|
+
if self._stdio_ctx:
|
|
67
|
+
# Exit the context manager
|
|
68
|
+
try:
|
|
69
|
+
await self._stdio_ctx.__aexit__(None, None, None)
|
|
70
|
+
except Exception as e:
|
|
71
|
+
logger.warning(f"Error closing stdio context: {e}")
|
|
72
|
+
finally:
|
|
73
|
+
self._stdio_ctx = None
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""
|
|
2
|
+
WebSocket connection management for MCP implementations.
|
|
3
|
+
|
|
4
|
+
This module provides a connection manager for WebSocket-based MCP connections.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import websockets
|
|
8
|
+
from websockets.client import WebSocketClientProtocol
|
|
9
|
+
|
|
10
|
+
from ..logging import logger
|
|
11
|
+
from .base import ConnectionManager
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class WebSocketConnectionManager(ConnectionManager[WebSocketClientProtocol]):
|
|
15
|
+
"""Connection manager for WebSocket-based MCP connections.
|
|
16
|
+
|
|
17
|
+
This class handles the lifecycle of WebSocket connections, ensuring proper
|
|
18
|
+
connection establishment and cleanup.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(
|
|
22
|
+
self,
|
|
23
|
+
url: str,
|
|
24
|
+
headers: dict[str, str] | None = None,
|
|
25
|
+
):
|
|
26
|
+
"""Initialize a new WebSocket connection manager.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
url: The WebSocket URL to connect to
|
|
30
|
+
headers: Optional headers to include in the WebSocket connection
|
|
31
|
+
"""
|
|
32
|
+
super().__init__()
|
|
33
|
+
self.url = url
|
|
34
|
+
self.headers = headers or {}
|
|
35
|
+
|
|
36
|
+
async def _establish_connection(self) -> WebSocketClientProtocol:
|
|
37
|
+
"""Establish a WebSocket connection.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
The established WebSocket connection
|
|
41
|
+
|
|
42
|
+
Raises:
|
|
43
|
+
Exception: If connection cannot be established
|
|
44
|
+
"""
|
|
45
|
+
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: WebSocketClientProtocol) -> 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}")
|