langchain-mcp-tools 0.1.11__py3-none-any.whl → 0.2.1__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.
- langchain_mcp_tools/__init__.py +1 -0
- langchain_mcp_tools/langchain_mcp_tools.py +101 -57
- {langchain_mcp_tools-0.1.11.dist-info → langchain_mcp_tools-0.2.1.dist-info}/METADATA +75 -17
- langchain_mcp_tools-0.2.1.dist-info/RECORD +8 -0
- langchain_mcp_tools-0.1.11.dist-info/RECORD +0 -8
- {langchain_mcp_tools-0.1.11.dist-info → langchain_mcp_tools-0.2.1.dist-info}/WHEEL +0 -0
- {langchain_mcp_tools-0.1.11.dist-info → langchain_mcp_tools-0.2.1.dist-info}/licenses/LICENSE +0 -0
- {langchain_mcp_tools-0.1.11.dist-info → langchain_mcp_tools-0.2.1.dist-info}/top_level.txt +0 -0
langchain_mcp_tools/__init__.py
CHANGED
@@ -1,8 +1,4 @@
|
|
1
1
|
# Standard library imports
|
2
|
-
from anyio.streams.memory import (
|
3
|
-
MemoryObjectReceiveStream,
|
4
|
-
MemoryObjectSendStream,
|
5
|
-
)
|
6
2
|
import logging
|
7
3
|
import os
|
8
4
|
import sys
|
@@ -11,21 +7,27 @@ from typing import (
|
|
11
7
|
Any,
|
12
8
|
Awaitable,
|
13
9
|
Callable,
|
14
|
-
|
15
|
-
List,
|
10
|
+
cast,
|
16
11
|
NoReturn,
|
17
|
-
|
18
|
-
|
19
|
-
Type,
|
12
|
+
NotRequired,
|
13
|
+
TextIO,
|
20
14
|
TypeAlias,
|
15
|
+
TypedDict,
|
21
16
|
)
|
17
|
+
from urllib.parse import urlparse
|
22
18
|
|
23
19
|
# Third-party imports
|
24
20
|
try:
|
21
|
+
from anyio.streams.memory import (
|
22
|
+
MemoryObjectReceiveStream,
|
23
|
+
MemoryObjectSendStream,
|
24
|
+
)
|
25
25
|
from jsonschema_pydantic import jsonschema_to_pydantic # type: ignore
|
26
26
|
from langchain_core.tools import BaseTool, ToolException
|
27
27
|
from mcp import ClientSession
|
28
|
+
from mcp.client.sse import sse_client
|
28
29
|
from mcp.client.stdio import stdio_client, StdioServerParameters
|
30
|
+
from mcp.client.websocket import websocket_client
|
29
31
|
import mcp.types as mcp_types
|
30
32
|
from pydantic import BaseModel
|
31
33
|
# from pydantic_core import to_json
|
@@ -35,6 +37,27 @@ except ImportError as e:
|
|
35
37
|
sys.exit(1)
|
36
38
|
|
37
39
|
|
40
|
+
class McpServerCommandBasedConfig(TypedDict):
|
41
|
+
command: str
|
42
|
+
args: NotRequired[list[str] | None]
|
43
|
+
env: NotRequired[dict[str, str] | None]
|
44
|
+
cwd: NotRequired[str | None]
|
45
|
+
errlog: NotRequired[TextIO | None]
|
46
|
+
|
47
|
+
|
48
|
+
class McpServerUrlBasedConfig(TypedDict):
|
49
|
+
url: str
|
50
|
+
args: NotRequired[list[str] | None]
|
51
|
+
env: NotRequired[dict[str, str] | None]
|
52
|
+
cwd: NotRequired[str | None]
|
53
|
+
errlog: NotRequired[TextIO | None]
|
54
|
+
|
55
|
+
|
56
|
+
McpServerConfig = McpServerCommandBasedConfig | McpServerUrlBasedConfig
|
57
|
+
|
58
|
+
McpServersConfig = dict[str, McpServerConfig]
|
59
|
+
|
60
|
+
|
38
61
|
def fix_schema(schema: dict) -> dict:
|
39
62
|
"""Converts JSON Schema 'type': ['string', 'null'] to 'anyOf' format"""
|
40
63
|
if isinstance(schema, dict):
|
@@ -48,7 +71,7 @@ def fix_schema(schema: dict) -> dict:
|
|
48
71
|
|
49
72
|
# Type alias for the bidirectional communication channels with the MCP server
|
50
73
|
# FIXME: not defined in mcp.types, really?
|
51
|
-
|
74
|
+
Transport: TypeAlias = tuple[
|
52
75
|
MemoryObjectReceiveStream[mcp_types.JSONRPCMessage | Exception],
|
53
76
|
MemoryObjectSendStream[mcp_types.JSONRPCMessage]
|
54
77
|
]
|
@@ -56,10 +79,10 @@ StdioTransport: TypeAlias = tuple[
|
|
56
79
|
|
57
80
|
async def spawn_mcp_server_and_get_transport(
|
58
81
|
server_name: str,
|
59
|
-
server_config:
|
82
|
+
server_config: McpServerConfig,
|
60
83
|
exit_stack: AsyncExitStack,
|
61
84
|
logger: logging.Logger = logging.getLogger(__name__)
|
62
|
-
) ->
|
85
|
+
) -> Transport:
|
63
86
|
"""
|
64
87
|
Spawns an MCP server process and establishes communication channels.
|
65
88
|
|
@@ -79,54 +102,75 @@ async def spawn_mcp_server_and_get_transport(
|
|
79
102
|
logger.info(f'MCP server "{server_name}": '
|
80
103
|
f'initializing with: {server_config}')
|
81
104
|
|
82
|
-
|
83
|
-
#
|
84
|
-
|
85
|
-
env = dict(server_config.get('env', {}))
|
86
|
-
if 'PATH' not in env:
|
87
|
-
env['PATH'] = os.environ.get('PATH', '')
|
88
|
-
|
89
|
-
# Create server parameters with command, arguments and environment
|
90
|
-
server_params = StdioServerParameters(
|
91
|
-
command=server_config['command'],
|
92
|
-
args=server_config.get('args', []),
|
93
|
-
env=env,
|
94
|
-
cwd=server_config.get('cwd', None)
|
95
|
-
)
|
105
|
+
url_str = str(server_config.get('url')) # None becomes 'None'
|
106
|
+
# no exception thrown even for a malformed URL
|
107
|
+
url_scheme = urlparse(url_str).scheme
|
96
108
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
+
if url_scheme in ('http', 'https'):
|
110
|
+
transport = await exit_stack.enter_async_context(
|
111
|
+
sse_client(url_str)
|
112
|
+
)
|
113
|
+
|
114
|
+
elif url_scheme in ('ws', 'wss'):
|
115
|
+
transport = await exit_stack.enter_async_context(
|
116
|
+
websocket_client(url_str)
|
117
|
+
)
|
118
|
+
|
119
|
+
else:
|
120
|
+
# NOTE: `uv` and `npx` seem to require PATH to be set.
|
121
|
+
# To avoid confusion, it was decided to automatically append it
|
122
|
+
# to the env if not explicitly set by the config.
|
123
|
+
config = cast(McpServerCommandBasedConfig, server_config)
|
124
|
+
# env = config.get('env', {}) does't work since it can yield None
|
125
|
+
env_val = config.get('env')
|
126
|
+
env = {} if env_val is None else dict(env_val)
|
127
|
+
if 'PATH' not in env:
|
128
|
+
env['PATH'] = os.environ.get('PATH', '')
|
129
|
+
|
130
|
+
# Use stdio client for commands
|
131
|
+
# args = config.get('args', []) does't work since it can yield None
|
132
|
+
args_val = config.get('args')
|
133
|
+
args = [] if args_val is None else list(args_val)
|
134
|
+
server_parameters = StdioServerParameters(
|
135
|
+
command=config.get('command', ''),
|
136
|
+
args=args,
|
137
|
+
env=env,
|
138
|
+
cwd=config.get('cwd', None)
|
139
|
+
)
|
140
|
+
|
141
|
+
# Initialize stdio client and register it with exit stack for
|
142
|
+
# cleanup
|
143
|
+
# NOTE: Why the key name `errlog` for `server_config` was chosen:
|
144
|
+
# Unlike TypeScript SDK's `StdioServerParameters`, the Python
|
145
|
+
# SDK's `StdioServerParameters` doesn't include `stderr: int`.
|
146
|
+
# Instead, it calls `stdio_client()` with a separate argument
|
147
|
+
# `errlog: TextIO`. I once included `stderr: int` for
|
148
|
+
# compatibility with the TypeScript version, but decided to
|
149
|
+
# follow the Python SDK more closely.
|
150
|
+
errlog_val = server_config.get('errlog')
|
151
|
+
kwargs = {'errlog': errlog_val} if errlog_val is not None else {}
|
152
|
+
transport = await exit_stack.enter_async_context(
|
153
|
+
stdio_client(server_parameters, **kwargs)
|
109
154
|
)
|
110
|
-
)
|
111
155
|
except Exception as e:
|
112
156
|
logger.error(f'Error spawning MCP server: {str(e)}')
|
113
157
|
raise
|
114
158
|
|
115
|
-
return
|
159
|
+
return transport
|
116
160
|
|
117
161
|
|
118
162
|
async def get_mcp_server_tools(
|
119
163
|
server_name: str,
|
120
|
-
|
164
|
+
transport: Transport,
|
121
165
|
exit_stack: AsyncExitStack,
|
122
166
|
logger: logging.Logger = logging.getLogger(__name__)
|
123
|
-
) ->
|
167
|
+
) -> list[BaseTool]:
|
124
168
|
"""
|
125
169
|
Retrieves and converts MCP server tools to LangChain format.
|
126
170
|
|
127
171
|
Args:
|
128
172
|
server_name: Server instance name to use for better logging
|
129
|
-
|
173
|
+
transport: Communication channels tuple
|
130
174
|
exit_stack: Context manager for cleanup handling
|
131
175
|
logger: Logger instance for debugging and monitoring
|
132
176
|
|
@@ -137,7 +181,7 @@ async def get_mcp_server_tools(
|
|
137
181
|
Exception: If tool conversion fails
|
138
182
|
"""
|
139
183
|
try:
|
140
|
-
read, write =
|
184
|
+
read, write = transport
|
141
185
|
|
142
186
|
# Use an intermediate `asynccontextmanager` to log the cleanup message
|
143
187
|
@asynccontextmanager
|
@@ -164,7 +208,7 @@ async def get_mcp_server_tools(
|
|
164
208
|
tools_response = await session.list_tools()
|
165
209
|
|
166
210
|
# Wrap MCP tools into LangChain tools
|
167
|
-
langchain_tools:
|
211
|
+
langchain_tools: list[BaseTool] = []
|
168
212
|
for tool in tools_response.tools:
|
169
213
|
|
170
214
|
# Define adapter class to convert MCP tool to LangChain format
|
@@ -172,10 +216,10 @@ async def get_mcp_server_tools(
|
|
172
216
|
name: str = tool.name or 'NO NAME'
|
173
217
|
description: str = tool.description or ''
|
174
218
|
# Convert JSON schema to Pydantic model for argument validation
|
175
|
-
args_schema:
|
219
|
+
args_schema: type[BaseModel] = jsonschema_to_pydantic(
|
176
220
|
fix_schema(tool.inputSchema) # Apply schema conversion
|
177
221
|
)
|
178
|
-
session:
|
222
|
+
session: ClientSession | None = None
|
179
223
|
|
180
224
|
def _run(self, **kwargs: Any) -> NoReturn:
|
181
225
|
raise NotImplementedError(
|
@@ -272,9 +316,9 @@ McpServerCleanupFn = Callable[[], Awaitable[None]]
|
|
272
316
|
|
273
317
|
|
274
318
|
async def convert_mcp_to_langchain_tools(
|
275
|
-
server_configs:
|
276
|
-
logger:
|
277
|
-
) ->
|
319
|
+
server_configs: dict[str, McpServerConfig],
|
320
|
+
logger: logging.Logger | None = None
|
321
|
+
) -> tuple[list[BaseTool], McpServerCleanupFn]:
|
278
322
|
"""Initialize multiple MCP servers and convert their tools to
|
279
323
|
LangChain format.
|
280
324
|
|
@@ -318,7 +362,7 @@ async def convert_mcp_to_langchain_tools(
|
|
318
362
|
logger = init_logger()
|
319
363
|
|
320
364
|
# Initialize AsyncExitStack for managing multiple server lifecycles
|
321
|
-
|
365
|
+
transports: list[Transport] = []
|
322
366
|
async_exit_stack = AsyncExitStack()
|
323
367
|
|
324
368
|
# Spawn all MCP servers concurrently
|
@@ -327,24 +371,24 @@ async def convert_mcp_to_langchain_tools(
|
|
327
371
|
# is spawned, i.e. after returning from the `await`, the spawned
|
328
372
|
# subprocess starts its initialization independently of (so in
|
329
373
|
# parallel with) the Python execution of the following lines.
|
330
|
-
|
374
|
+
transport = await spawn_mcp_server_and_get_transport(
|
331
375
|
server_name,
|
332
376
|
server_config,
|
333
377
|
async_exit_stack,
|
334
378
|
logger
|
335
379
|
)
|
336
|
-
|
380
|
+
transports.append(transport)
|
337
381
|
|
338
382
|
# Convert tools from each server to LangChain format
|
339
|
-
langchain_tools:
|
340
|
-
for (server_name, server_config),
|
383
|
+
langchain_tools: list[BaseTool] = []
|
384
|
+
for (server_name, server_config), transport in zip(
|
341
385
|
server_configs.items(),
|
342
|
-
|
386
|
+
transports,
|
343
387
|
strict=True
|
344
388
|
):
|
345
389
|
tools = await get_mcp_server_tools(
|
346
390
|
server_name,
|
347
|
-
|
391
|
+
transport,
|
348
392
|
async_exit_stack,
|
349
393
|
logger
|
350
394
|
)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: langchain-mcp-tools
|
3
|
-
Version: 0.1
|
3
|
+
Version: 0.2.1
|
4
4
|
Summary: Model Context Protocol (MCP) To LangChain Tools Conversion Utility
|
5
5
|
Project-URL: Bug Tracker, https://github.com/hideya/langchain-mcp-tools-py/issues
|
6
6
|
Project-URL: Source Code, https://github.com/hideya/langchain-mcp-tools-py
|
@@ -12,6 +12,7 @@ Requires-Dist: jsonschema-pydantic>=0.6
|
|
12
12
|
Requires-Dist: langchain>=0.3.14
|
13
13
|
Requires-Dist: mcp>=1.6.0
|
14
14
|
Requires-Dist: pyjson5>=1.6.8
|
15
|
+
Requires-Dist: websockets>=15.0.1
|
15
16
|
Provides-Extra: dev
|
16
17
|
Requires-Dist: dotenv>=0.9.9; extra == "dev"
|
17
18
|
Requires-Dist: langchain-anthropic>=0.3.1; extra == "dev"
|
@@ -65,6 +66,9 @@ pip install langchain-mcp-tools
|
|
65
66
|
|
66
67
|
## Quick Start
|
67
68
|
|
69
|
+
A minimal but complete working usage example can be found
|
70
|
+
[in this example in the langchain-mcp-tools-py-usage repo](https://github.com/hideya/langchain-mcp-tools-py-usage/blob/main/src/example.py)
|
71
|
+
|
68
72
|
`convert_mcp_to_langchain_tools()` utility function accepts MCP server configurations
|
69
73
|
that follow the same structure as
|
70
74
|
[Claude for Desktop](https://modelcontextprotocol.io/quickstart/user),
|
@@ -73,13 +77,13 @@ and is expressed as a `dict`, e.g.:
|
|
73
77
|
|
74
78
|
```python
|
75
79
|
mcp_servers = {
|
76
|
-
|
77
|
-
|
78
|
-
|
80
|
+
"filesystem": {
|
81
|
+
"command": "npx",
|
82
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "."]
|
79
83
|
},
|
80
|
-
|
81
|
-
|
82
|
-
|
84
|
+
"fetch": {
|
85
|
+
"command": "uvx",
|
86
|
+
"args": ["mcp-server-fetch"]
|
83
87
|
}
|
84
88
|
}
|
85
89
|
|
@@ -90,7 +94,7 @@ tools, cleanup = await convert_mcp_to_langchain_tools(
|
|
90
94
|
|
91
95
|
This utility function initializes all specified MCP servers in parallel,
|
92
96
|
and returns LangChain Tools
|
93
|
-
([`tools:
|
97
|
+
([`tools: list[BaseTool]`](https://python.langchain.com/api_reference/core/tools/langchain_core.tools.base.BaseTool.html#langchain_core.tools.base.BaseTool))
|
94
98
|
by gathering available MCP tools from the servers,
|
95
99
|
and by wrapping them into LangChain tools.
|
96
100
|
It also returns an async callback function (`cleanup: McpServerCleanupFn`)
|
@@ -101,8 +105,8 @@ The returned tools can be used with LangChain, e.g.:
|
|
101
105
|
```python
|
102
106
|
# from langchain.chat_models import init_chat_model
|
103
107
|
llm = init_chat_model(
|
104
|
-
model=
|
105
|
-
model_provider=
|
108
|
+
model="claude-3-7-sonnet-latest",
|
109
|
+
model_provider="anthropic"
|
106
110
|
)
|
107
111
|
|
108
112
|
# from langgraph.prebuilt import create_react_agent
|
@@ -112,22 +116,76 @@ agent = create_react_agent(
|
|
112
116
|
)
|
113
117
|
```
|
114
118
|
|
115
|
-
Find complete, minimal working usage examples
|
116
|
-
[here](https://github.com/hideya/langchain-mcp-tools-py-usage/blob/main/src/example.py)
|
117
|
-
|
118
119
|
For hands-on experimentation with MCP server integration,
|
119
120
|
try [this LangChain application built with the utility](https://github.com/hideya/mcp-client-langchain-py)
|
120
121
|
|
121
122
|
For detailed information on how to use this library, please refer to the following document:
|
122
123
|
["Supercharging LangChain: Integrating 2000+ MCP with ReAct"](https://medium.com/@h1deya/supercharging-langchain-integrating-450-mcp-with-react-d4e467cbf41a)
|
123
124
|
|
124
|
-
##
|
125
|
+
## Experimental Features
|
126
|
+
|
127
|
+
### Remote MCP Server Support
|
128
|
+
|
129
|
+
`mcp_servers` configuration for SSE and Websocket servers are as follows:
|
130
|
+
|
131
|
+
```python
|
132
|
+
"sse-server-name": {
|
133
|
+
"url": f"http://{sse_server_host}:{sse_server_port}/..."
|
134
|
+
},
|
135
|
+
|
136
|
+
"ws-server-name": {
|
137
|
+
"url": f"ws://{ws_server_host}:{ws_server_port}/..."
|
138
|
+
},
|
139
|
+
```
|
140
|
+
|
141
|
+
Note that the key `"url"` may be changed in the future to match
|
142
|
+
the MCP server configurations used by Claude for Desktop once
|
143
|
+
it introduces remote server support.
|
144
|
+
|
145
|
+
A usage example can be found [here](
|
146
|
+
https://github.com/hideya/langchain-mcp-tools-py-usage/blob/e759edf886bdaef7c162e7f228e32fbb43993e37/src/example.py#L43-L54)
|
147
|
+
|
148
|
+
### Working Directory Configuration for Local MCP Servers
|
125
149
|
|
126
|
-
|
150
|
+
The working directory that is used when spawning a local (stdio) MCP server
|
151
|
+
can be specified with the `"cwd"` key as follows:
|
127
152
|
|
128
|
-
|
153
|
+
```python
|
154
|
+
"local-server-name": {
|
155
|
+
"command": "...",
|
156
|
+
"args": [...],
|
157
|
+
"cwd": "/working/directory" # the working dir to be use by the server
|
158
|
+
},
|
159
|
+
```
|
160
|
+
|
161
|
+
The key name `cwd` is derived from Python SDK's `StdioServerParameters`.
|
162
|
+
|
163
|
+
### Configuration for Local MCP Server `stderr` Redirection
|
164
|
+
|
165
|
+
A new key `"errlog"` has been introduced in to specify a file-like object
|
166
|
+
to which local (stdio) MCP server's stderr is redirected.
|
167
|
+
|
168
|
+
```python
|
169
|
+
log_path = f"mcp-server-{server_name}.log"
|
170
|
+
log_file = open(log_path, "w")
|
171
|
+
mcp_servers[server_name]["errlog"] = log_file
|
172
|
+
```
|
173
|
+
|
174
|
+
A usage example can be found [here](
|
175
|
+
https://github.com/hideya/langchain-mcp-tools-py-usage/blob/e759edf886bdaef7c162e7f228e32fbb43993e37/src/example.py#L88-L108)
|
176
|
+
|
177
|
+
**NOTE: Why the key name `errlog` was chosen:**
|
178
|
+
Unlike TypeScript SDK's `StdioServerParameters`, the Python
|
179
|
+
SDK's `StdioServerParameters` doesn't include `stderr: int`.
|
180
|
+
Instead, it calls `stdio_client()` with a separate argument
|
181
|
+
`errlog: TextIO`. I once included `stderr: int` for
|
182
|
+
compatibility with the TypeScript version, but decided to
|
183
|
+
follow the Python SDK more closely.
|
184
|
+
|
185
|
+
## Limitations
|
129
186
|
|
130
|
-
|
187
|
+
- Currently, only text results of tool calls are supported.
|
188
|
+
- MCP features other than [Tools](https://modelcontextprotocol.io/docs/concepts/tools) are not supported.
|
131
189
|
|
132
190
|
## Change Log
|
133
191
|
|
@@ -0,0 +1,8 @@
|
|
1
|
+
langchain_mcp_tools/__init__.py,sha256=iatHG2fCpz143wgQUZpyFVilgri4yOh2P0vxr22gguE,114
|
2
|
+
langchain_mcp_tools/langchain_mcp_tools.py,sha256=n4u9fN3_sVMG1CmSKk8FrlXrBt79Ly1tz0TLhmDUaic,15118
|
3
|
+
langchain_mcp_tools/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
+
langchain_mcp_tools-0.2.1.dist-info/licenses/LICENSE,sha256=CRC91e8v116gCpnp7h49oIa6_zjhxqnHFTREeoZFJwA,1072
|
5
|
+
langchain_mcp_tools-0.2.1.dist-info/METADATA,sha256=6_d5jxaN8KqL6ZyJHwVDI0YQLe30xy0-7sgyRs85Zlc,7287
|
6
|
+
langchain_mcp_tools-0.2.1.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
7
|
+
langchain_mcp_tools-0.2.1.dist-info/top_level.txt,sha256=aR_9V2A1Yt-Bca60KmndmGLUWb2wiM5IOG-Gkaf1dxY,20
|
8
|
+
langchain_mcp_tools-0.2.1.dist-info/RECORD,,
|
@@ -1,8 +0,0 @@
|
|
1
|
-
langchain_mcp_tools/__init__.py,sha256=Xtv2VphhrWB_KlxTIofHZqtCIGtNEl0MxugnrNXTERA,94
|
2
|
-
langchain_mcp_tools/langchain_mcp_tools.py,sha256=O6TxRRuS-uTOY08-WVKK86Dxx7-dCeFZZRLpBYaPIng,13577
|
3
|
-
langchain_mcp_tools/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
-
langchain_mcp_tools-0.1.11.dist-info/licenses/LICENSE,sha256=CRC91e8v116gCpnp7h49oIa6_zjhxqnHFTREeoZFJwA,1072
|
5
|
-
langchain_mcp_tools-0.1.11.dist-info/METADATA,sha256=lW4Mm8snEac1hYSuS0szfHmJZFBs79GAEo0bwyEW_sw,5212
|
6
|
-
langchain_mcp_tools-0.1.11.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
7
|
-
langchain_mcp_tools-0.1.11.dist-info/top_level.txt,sha256=aR_9V2A1Yt-Bca60KmndmGLUWb2wiM5IOG-Gkaf1dxY,20
|
8
|
-
langchain_mcp_tools-0.1.11.dist-info/RECORD,,
|
File without changes
|
{langchain_mcp_tools-0.1.11.dist-info → langchain_mcp_tools-0.2.1.dist-info}/licenses/LICENSE
RENAMED
File without changes
|
File without changes
|