langchain-mcp-tools 0.2.1__py3-none-any.whl → 0.2.3__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.
@@ -32,25 +32,22 @@ try:
32
32
  from pydantic import BaseModel
33
33
  # from pydantic_core import to_json
34
34
  except ImportError as e:
35
- print(f'\nError: Required package not found: {e}')
36
- print('Please ensure all required packages are installed\n')
35
+ print(f"\nError: Required package not found: {e}")
36
+ print("Please ensure all required packages are installed\n")
37
37
  sys.exit(1)
38
38
 
39
39
 
40
40
  class McpServerCommandBasedConfig(TypedDict):
41
41
  command: str
42
42
  args: NotRequired[list[str] | None]
43
- env: NotRequired[dict[str, str] | None]
43
+ env: NotRequired[dict[str, str] | None]
44
44
  cwd: NotRequired[str | None]
45
45
  errlog: NotRequired[TextIO | None]
46
46
 
47
47
 
48
48
  class McpServerUrlBasedConfig(TypedDict):
49
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]
50
+ headers: NotRequired[dict[str, str] | None]
54
51
 
55
52
 
56
53
  McpServerConfig = McpServerCommandBasedConfig | McpServerUrlBasedConfig
@@ -59,11 +56,18 @@ McpServersConfig = dict[str, McpServerConfig]
59
56
 
60
57
 
61
58
  def fix_schema(schema: dict) -> dict:
62
- """Converts JSON Schema 'type': ['string', 'null'] to 'anyOf' format"""
59
+ """Converts JSON Schema "type": ["string", "null"] to "anyOf" format.
60
+
61
+ Args:
62
+ schema: A JSON schema dictionary
63
+
64
+ Returns:
65
+ Modified schema with converted type formats
66
+ """
63
67
  if isinstance(schema, dict):
64
- if 'type' in schema and isinstance(schema['type'], list):
65
- schema['anyOf'] = [{'type': t} for t in schema['type']]
66
- del schema['type'] # Remove 'type' and standardize to 'anyOf'
68
+ if "type" in schema and isinstance(schema["type"], list):
69
+ schema["anyOf"] = [{"type": t} for t in schema["type"]]
70
+ del schema["type"] # Remove "type" and standardize to "anyOf"
67
71
  for key, value in schema.items():
68
72
  schema[key] = fix_schema(value) # Apply recursively
69
73
  return schema
@@ -83,8 +87,7 @@ async def spawn_mcp_server_and_get_transport(
83
87
  exit_stack: AsyncExitStack,
84
88
  logger: logging.Logger = logging.getLogger(__name__)
85
89
  ) -> Transport:
86
- """
87
- Spawns an MCP server process and establishes communication channels.
90
+ """Spawns an MCP server process and establishes communication channels.
88
91
 
89
92
  Args:
90
93
  server_name: Server instance name to use for better logging
@@ -100,18 +103,20 @@ async def spawn_mcp_server_and_get_transport(
100
103
  """
101
104
  try:
102
105
  logger.info(f'MCP server "{server_name}": '
103
- f'initializing with: {server_config}')
106
+ f"initializing with: {server_config}")
104
107
 
105
- url_str = str(server_config.get('url')) # None becomes 'None'
108
+ url_str = str(server_config.get("url")) # None becomes "None"
109
+ headers = (cast(McpServerUrlBasedConfig, server_config)
110
+ .get("headers", None))
106
111
  # no exception thrown even for a malformed URL
107
112
  url_scheme = urlparse(url_str).scheme
108
113
 
109
- if url_scheme in ('http', 'https'):
114
+ if url_scheme in ("http", "https"):
110
115
  transport = await exit_stack.enter_async_context(
111
- sse_client(url_str)
116
+ sse_client(url_str, headers=headers)
112
117
  )
113
118
 
114
- elif url_scheme in ('ws', 'wss'):
119
+ elif url_scheme in ("ws", "wss"):
115
120
  transport = await exit_stack.enter_async_context(
116
121
  websocket_client(url_str)
117
122
  )
@@ -121,21 +126,21 @@ async def spawn_mcp_server_and_get_transport(
121
126
  # To avoid confusion, it was decided to automatically append it
122
127
  # to the env if not explicitly set by the config.
123
128
  config = cast(McpServerCommandBasedConfig, server_config)
124
- # env = config.get('env', {}) does't work since it can yield None
125
- env_val = config.get('env')
129
+ # env = config.get("env", {}) does't work since it can yield None
130
+ env_val = config.get("env")
126
131
  env = {} if env_val is None else dict(env_val)
127
- if 'PATH' not in env:
128
- env['PATH'] = os.environ.get('PATH', '')
132
+ if "PATH" not in env:
133
+ env["PATH"] = os.environ.get("PATH", "")
129
134
 
130
135
  # Use stdio client for commands
131
- # args = config.get('args', []) does't work since it can yield None
132
- args_val = config.get('args')
136
+ # args = config.get("args", []) does't work since it can yield None
137
+ args_val = config.get("args")
133
138
  args = [] if args_val is None else list(args_val)
134
139
  server_parameters = StdioServerParameters(
135
- command=config.get('command', ''),
140
+ command=config.get("command", ""),
136
141
  args=args,
137
142
  env=env,
138
- cwd=config.get('cwd', None)
143
+ cwd=config.get("cwd", None)
139
144
  )
140
145
 
141
146
  # Initialize stdio client and register it with exit stack for
@@ -147,13 +152,14 @@ async def spawn_mcp_server_and_get_transport(
147
152
  # `errlog: TextIO`. I once included `stderr: int` for
148
153
  # compatibility with the TypeScript version, but decided to
149
154
  # 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 {}
155
+ errlog_val = (cast(McpServerCommandBasedConfig, server_config)
156
+ .get("errlog"))
157
+ kwargs = {"errlog": errlog_val} if errlog_val is not None else {}
152
158
  transport = await exit_stack.enter_async_context(
153
159
  stdio_client(server_parameters, **kwargs)
154
160
  )
155
161
  except Exception as e:
156
- logger.error(f'Error spawning MCP server: {str(e)}')
162
+ logger.error(f"Error spawning MCP server: {str(e)}")
157
163
  raise
158
164
 
159
165
  return transport
@@ -165,8 +171,7 @@ async def get_mcp_server_tools(
165
171
  exit_stack: AsyncExitStack,
166
172
  logger: logging.Logger = logging.getLogger(__name__)
167
173
  ) -> list[BaseTool]:
168
- """
169
- Retrieves and converts MCP server tools to LangChain format.
174
+ """Retrieves and converts MCP server tools to LangChain format.
170
175
 
171
176
  Args:
172
177
  server_name: Server instance name to use for better logging
@@ -213,8 +218,8 @@ async def get_mcp_server_tools(
213
218
 
214
219
  # Define adapter class to convert MCP tool to LangChain format
215
220
  class McpToLangChainAdapter(BaseTool):
216
- name: str = tool.name or 'NO NAME'
217
- description: str = tool.description or ''
221
+ name: str = tool.name or "NO NAME"
222
+ description: str = tool.description or ""
218
223
  # Convert JSON schema to Pydantic model for argument validation
219
224
  args_schema: type[BaseModel] = jsonschema_to_pydantic(
220
225
  fix_schema(tool.inputSchema) # Apply schema conversion
@@ -223,31 +228,40 @@ async def get_mcp_server_tools(
223
228
 
224
229
  def _run(self, **kwargs: Any) -> NoReturn:
225
230
  raise NotImplementedError(
226
- 'MCP tools only support async operations'
231
+ "MCP tools only support async operations"
227
232
  )
228
233
 
229
234
  async def _arun(self, **kwargs: Any) -> Any:
230
- """
231
- Asynchronously executes the tool with given arguments.
235
+ """Asynchronously executes the tool with given arguments.
236
+
232
237
  Logs input/output and handles errors.
238
+
239
+ Args:
240
+ **kwargs: Arguments to be passed to the MCP tool
241
+
242
+ Returns:
243
+ Formatted response from the MCP tool as a string
244
+
245
+ Raises:
246
+ ToolException: If the tool execution fails
233
247
  """
234
248
  logger.info(f'MCP tool "{server_name}"/"{tool.name}" '
235
- f'received input: {kwargs}')
249
+ f"received input: {kwargs}")
236
250
 
237
251
  try:
238
252
  result = await session.call_tool(self.name, kwargs)
239
253
 
240
- if hasattr(result, 'isError') and result.isError:
254
+ if hasattr(result, "isError") and result.isError:
241
255
  raise ToolException(
242
- f'Tool execution failed: {result.content}'
256
+ f"Tool execution failed: {result.content}"
243
257
  )
244
258
 
245
- if not hasattr(result, 'content'):
259
+ if not hasattr(result, "content"):
246
260
  return str(result)
247
261
 
248
262
  # The return type of `BaseTool`'s `arun` is `str`.
249
263
  try:
250
- result_content_text = '\n\n'.join(
264
+ result_content_text = "\n\n".join(
251
265
  item.text
252
266
  for item in result.content
253
267
  if isinstance(item, mcp_types.TextContent)
@@ -261,20 +275,20 @@ async def get_mcp_server_tools(
261
275
 
262
276
  except KeyError as e:
263
277
  result_content_text = (
264
- f'Error in parsing result.content: {str(e)}; '
265
- f'contents: {repr(result.content)}'
278
+ f"Error in parsing result.content: {str(e)}; "
279
+ f"contents: {repr(result.content)}"
266
280
  )
267
281
 
268
282
  # Log rough result size for monitoring
269
283
  size = len(result_content_text.encode())
270
284
  logger.info(f'MCP tool "{server_name}"/"{tool.name}" '
271
- f'received result (size: {size})')
285
+ f"received result (size: {size})")
272
286
 
273
287
  # If no text content, return a clear message
274
288
  # describing the situation.
275
289
  result_content_text = (
276
290
  result_content_text or
277
- 'No text content available in response'
291
+ "No text content available in response"
278
292
  )
279
293
 
280
294
  return result_content_text
@@ -282,21 +296,21 @@ async def get_mcp_server_tools(
282
296
  except Exception as e:
283
297
  logger.warn(
284
298
  f'MCP tool "{server_name}"/"{tool.name}" '
285
- f'caused error: {str(e)}'
299
+ f"caused error: {str(e)}"
286
300
  )
287
301
  if self.handle_tool_error:
288
- return f'Error executing MCP tool: {str(e)}'
302
+ return f"Error executing MCP tool: {str(e)}"
289
303
  raise
290
304
 
291
305
  langchain_tools.append(McpToLangChainAdapter())
292
306
 
293
307
  # Log available tools for debugging
294
308
  logger.info(f'MCP server "{server_name}": {len(langchain_tools)} '
295
- f'tool(s) available:')
309
+ f"tool(s) available:")
296
310
  for tool in langchain_tools:
297
- logger.info(f'- {tool.name}')
311
+ logger.info(f"- {tool.name}")
298
312
  except Exception as e:
299
- logger.error(f'Error getting MCP tools: {str(e)}')
313
+ logger.error(f"Error getting MCP tools: {str(e)}")
300
314
  raise
301
315
 
302
316
  return langchain_tools
@@ -304,9 +318,14 @@ async def get_mcp_server_tools(
304
318
 
305
319
  # A very simple pre-configured logger for fallback
306
320
  def init_logger() -> logging.Logger:
321
+ """Creates a simple pre-configured logger.
322
+
323
+ Returns:
324
+ A configured Logger instance
325
+ """
307
326
  logging.basicConfig(
308
327
  level=logging.INFO, # logging.DEBUG,
309
- format='\x1b[90m[%(levelname)s]\x1b[0m %(message)s'
328
+ format="\x1b[90m[%(levelname)s]\x1b[0m %(message)s"
310
329
  )
311
330
  return logging.getLogger()
312
331
 
@@ -331,26 +350,30 @@ async def convert_mcp_to_langchain_tools(
331
350
  configurations, where each configuration contains command, args,
332
351
  and env settings
333
352
  logger: Logger instance to use for logging events and errors.
334
- If None, uses module logger with fallback to a pre-configured
335
- logger when no root handlers exist.
353
+ If None, uses module logger with fallback to a pre-configured
354
+ logger when no root handlers exist.
336
355
 
337
356
  Returns:
338
357
  A tuple containing:
339
- - List of converted LangChain tools from all servers
340
- - Async cleanup function to properly shutdown all server
341
- connections
358
+
359
+ * List of converted LangChain tools from all servers
360
+ * Async cleanup function to properly shutdown all server connections
342
361
 
343
362
  Example:
363
+
344
364
  server_configs = {
345
- 'fetch': {
346
- 'command': 'uvx', 'args': ['mcp-server-fetch']
365
+ "fetch": {
366
+ "command": "uvx", "args": ["mcp-server-fetch"]
347
367
  },
348
- 'weather': {
349
- 'command': 'npx', 'args': ['-y','@h1deya/mcp-server-weather']
368
+ "weather": {
369
+ "command": "npx", "args": ["-y","@h1deya/mcp-server-weather"]
350
370
  }
351
371
  }
372
+
352
373
  tools, cleanup = await convert_mcp_to_langchain_tools(server_configs)
374
+
353
375
  # Use tools...
376
+
354
377
  await cleanup()
355
378
  """
356
379
 
@@ -396,13 +419,13 @@ async def convert_mcp_to_langchain_tools(
396
419
 
397
420
  # Define a cleanup function to properly shut down all servers
398
421
  async def mcp_cleanup() -> None:
399
- """Closes all server connections and cleans up resources"""
422
+ """Closes all server connections and cleans up resources."""
400
423
  await async_exit_stack.aclose()
401
424
 
402
425
  # Log summary of initialized tools
403
- logger.info(f'MCP servers initialized: {len(langchain_tools)} tool(s) '
404
- f'available in total')
426
+ logger.info(f"MCP servers initialized: {len(langchain_tools)} tool(s) "
427
+ f"available in total")
405
428
  for tool in langchain_tools:
406
- logger.debug(f'- {tool.name}')
429
+ logger.debug(f"- {tool.name}")
407
430
 
408
431
  return langchain_tools, mcp_cleanup
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langchain-mcp-tools
3
- Version: 0.2.1
3
+ Version: 0.2.3
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
@@ -11,16 +11,17 @@ License-File: LICENSE
11
11
  Requires-Dist: jsonschema-pydantic>=0.6
12
12
  Requires-Dist: langchain>=0.3.14
13
13
  Requires-Dist: mcp>=1.6.0
14
- Requires-Dist: pyjson5>=1.6.8
15
- Requires-Dist: websockets>=15.0.1
16
14
  Provides-Extra: dev
17
15
  Requires-Dist: dotenv>=0.9.9; extra == "dev"
16
+ Requires-Dist: fastapi>=0.115.12; extra == "dev"
17
+ Requires-Dist: pyjwt>=2.10.1; extra == "dev"
18
18
  Requires-Dist: langchain-anthropic>=0.3.1; extra == "dev"
19
19
  Requires-Dist: langchain-groq>=0.2.3; extra == "dev"
20
20
  Requires-Dist: langchain-openai>=0.3.0; extra == "dev"
21
21
  Requires-Dist: langgraph>=0.2.62; extra == "dev"
22
22
  Requires-Dist: pytest>=8.3.4; extra == "dev"
23
23
  Requires-Dist: pytest-asyncio>=0.25.2; extra == "dev"
24
+ Requires-Dist: websockets>=15.0.1; extra == "dev"
24
25
  Dynamic: license-file
25
26
 
26
27
  # MCP To LangChain Tools Conversion Utility [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/hideya/langchain-mcp-tools-py/blob/main/LICENSE) [![pypi version](https://img.shields.io/pypi/v/langchain-mcp-tools.svg)](https://pypi.org/project/langchain-mcp-tools/)
@@ -30,11 +31,14 @@ This package is intended to simplify the use of
30
31
  server tools with LangChain / Python.
31
32
 
32
33
  [Model Context Protocol (MCP)](https://modelcontextprotocol.io/),
33
- an open source technology
34
+ an open standard
34
35
  [announced by Anthropic](https://www.anthropic.com/news/model-context-protocol),
35
36
  dramatically expands LLM’s scope
36
37
  by enabling external tool and resource integration, including
37
- Google Drive, Slack, Notion, Spotify, Docker, PostgreSQL, and more…
38
+ GitHub, Google Drive, Slack, Notion, Spotify, Docker, PostgreSQL, and more…
39
+
40
+ MCP is likely to become the de facto industry standard as
41
+ [OpenAI has announced its adoption](https://techcrunch.com/2025/03/26/openai-adopts-rival-anthropics-standard-for-connecting-ai-models-to-data).
38
42
 
39
43
  Over 2000 functional components available as MCP servers:
40
44
 
@@ -64,6 +68,11 @@ A typescript equivalent of this utility is available
64
68
  pip install langchain-mcp-tools
65
69
  ```
66
70
 
71
+ ## API docs
72
+
73
+ Can be found [here](https://hideya.github.io/langchain-mcp-tools-py/)
74
+
75
+
67
76
  ## Quick Start
68
77
 
69
78
  A minimal but complete working usage example can be found
@@ -142,8 +151,28 @@ Note that the key `"url"` may be changed in the future to match
142
151
  the MCP server configurations used by Claude for Desktop once
143
152
  it introduces remote server support.
144
153
 
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)
154
+ A usage example can be found [here](https://github.com/hideya/langchain-mcp-tools-py-usage/blob/3bd35d9fb49f4b631fe3d0cc8491d43cbf69693b/src/example.py#L43-L54)
155
+
156
+ ### Authentication Support for SSE Connections
157
+
158
+ A new key `"headers"` has been introduced to pass HTTP headers to the SSE (Server-Sent Events) connection.
159
+ It takes `dict[str, str]` and is primarily intended to support SSE MCP servers
160
+ that require authentication via bearer tokens or other custom headers.
161
+
162
+ ```python
163
+ "sse-server-name": {
164
+ "url": f"http://{sse_server_host}:{sse_server_port}/..."
165
+ "headers": {"Authorization": f"Bearer {bearer_token}"}
166
+ },
167
+ ```
168
+
169
+ The key name `header` is derived from the Python SDK
170
+ [`sse_client()`](https://github.com/modelcontextprotocol/python-sdk/blob/babb477dffa33f46cdc886bc885eb1d521151430/src/mcp/client/sse.py#L24) argument name.
171
+
172
+ A simple example showing how to implement MCP SSE server and client with authentication can be found
173
+ in [sse-auth-test-client.py](https://github.com/hideya/langchain-mcp-tools-py-usage/tree/main/src/sse-auth-test-client.py)
174
+ and in [sse-auth-test-server.py](https://github.com/hideya/langchain-mcp-tools-py-usage/tree/main/src/sse-auth-test-server.py)
175
+ of [this usage examples repo](https://github.com/hideya/langchain-mcp-tools-py-usage).
147
176
 
148
177
  ### Working Directory Configuration for Local MCP Servers
149
178
 
@@ -158,11 +187,12 @@ can be specified with the `"cwd"` key as follows:
158
187
  },
159
188
  ```
160
189
 
161
- The key name `cwd` is derived from Python SDK's `StdioServerParameters`.
190
+ The key name `cwd` is derived from
191
+ Python SDK's [`StdioServerParameters`](https://github.com/modelcontextprotocol/python-sdk/blob/babb477dffa33f46cdc886bc885eb1d521151430/src/mcp/client/stdio/__init__.py#L76-L77).
162
192
 
163
- ### Configuration for Local MCP Server `stderr` Redirection
193
+ ### stderr Redirection for Local MCP Server
164
194
 
165
- A new key `"errlog"` has been introduced in to specify a file-like object
195
+ A new key `"errlog"` has been introduced to specify a file-like object
166
196
  to which local (stdio) MCP server's stderr is redirected.
167
197
 
168
198
  ```python
@@ -171,14 +201,14 @@ to which local (stdio) MCP server's stderr is redirected.
171
201
  mcp_servers[server_name]["errlog"] = log_file
172
202
  ```
173
203
 
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)
204
+ A usage example can be found [here](https://github.com/hideya/langchain-mcp-tools-py-usage/blob/3bd35d9fb49f4b631fe3d0cc8491d43cbf69693b/src/example.py#L88-L108)
176
205
 
177
206
  **NOTE: Why the key name `errlog` was chosen:**
178
207
  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
208
+ SDK's `StdioServerParameters` doesn't include `stderr: int`.
209
+ Instead, it calls [`stdio_client()` with a separate argument
210
+ `errlog: TextIO`](https://github.com/modelcontextprotocol/python-sdk/blob/babb477dffa33f46cdc886bc885eb1d521151430/src/mcp/client/stdio/__init__.py#L96).
211
+ I once included `stderr: int` for
182
212
  compatibility with the TypeScript version, but decided to
183
213
  follow the Python SDK more closely.
184
214
 
@@ -0,0 +1,8 @@
1
+ langchain_mcp_tools/__init__.py,sha256=iatHG2fCpz143wgQUZpyFVilgri4yOh2P0vxr22gguE,114
2
+ langchain_mcp_tools/langchain_mcp_tools.py,sha256=3XfJUW98usqrWmn1RqbVzVr_Z4piv8PLzAm29YVj6z4,15806
3
+ langchain_mcp_tools/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ langchain_mcp_tools-0.2.3.dist-info/licenses/LICENSE,sha256=CRC91e8v116gCpnp7h49oIa6_zjhxqnHFTREeoZFJwA,1072
5
+ langchain_mcp_tools-0.2.3.dist-info/METADATA,sha256=PPZz0kgmD2JQfUntk4D9R1gcm5DZZ_utV6L0YRo3b-M,9049
6
+ langchain_mcp_tools-0.2.3.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
7
+ langchain_mcp_tools-0.2.3.dist-info/top_level.txt,sha256=aR_9V2A1Yt-Bca60KmndmGLUWb2wiM5IOG-Gkaf1dxY,20
8
+ langchain_mcp_tools-0.2.3.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.1.0)
2
+ Generator: setuptools (79.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,8 +0,0 @@
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,,