langchain-mcp-tools 0.2.2__py3-none-any.whl → 0.2.4__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.
@@ -3,4 +3,7 @@ from .langchain_mcp_tools import (
3
3
  convert_mcp_to_langchain_tools,
4
4
  McpServerCleanupFn,
5
5
  McpServersConfig,
6
+ McpServerCommandBasedConfig,
7
+ McpServerUrlBasedConfig,
8
+ SingleMcpServerConfig,
6
9
  )
@@ -32,12 +32,37 @@ 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
+ """Configuration for an MCP server launched via command line.
42
+
43
+ This configuration is used for local MCP servers that are started as child
44
+ processes using the stdio client. It defines the command to run, optional
45
+ arguments, environment variables, working directory, and error logging
46
+ options.
47
+
48
+ Attributes:
49
+ command: The executable command to run (e.g., "npx", "uvx", "python").
50
+ args: Optional list of command-line arguments to pass to the command.
51
+ env: Optional dictionary of environment variables to set for the
52
+ process.
53
+ cwd: Optional working directory where the command will be executed.
54
+ errlog: Optional file-like object for redirecting the server's stderr
55
+ output.
56
+
57
+ Example:
58
+ {
59
+ "command": "npx",
60
+ "args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
61
+ "env": {"NODE_ENV": "production"},
62
+ "cwd": "/path/to/working/directory",
63
+ "errlog": open("server.log", "w")
64
+ }
65
+ """
41
66
  command: str
42
67
  args: NotRequired[list[str] | None]
43
68
  env: NotRequired[dict[str, str] | None]
@@ -46,21 +71,88 @@ class McpServerCommandBasedConfig(TypedDict):
46
71
 
47
72
 
48
73
  class McpServerUrlBasedConfig(TypedDict):
74
+ """Configuration for a remote MCP server accessed via URL.
75
+
76
+ This configuration is used for remote MCP servers that are accessed via
77
+ HTTP/HTTPS (Server-Sent Events) or WebSocket connections. It defines the
78
+ URL to connect to and optional HTTP headers for authentication.
79
+
80
+ Attributes:
81
+ url: The URL of the remote MCP server. For SSE servers,
82
+ use http:// or https:// prefix. For WebSocket servers,
83
+ use ws:// or wss:// prefix.
84
+ headers: Optional dictionary of HTTP headers to include in the request,
85
+ typically used for authentication (e.g., bearer tokens).
86
+
87
+ Example for SSE server:
88
+ {
89
+ "url": "https://example.com/mcp/sse",
90
+ "headers": {"Authorization": "Bearer token123"}
91
+ }
92
+
93
+ Example for WebSocket server:
94
+ {
95
+ "url": "wss://example.com/mcp/ws"
96
+ }
97
+ """
49
98
  url: str
50
99
  headers: NotRequired[dict[str, str] | None]
51
100
 
52
101
 
53
- McpServerConfig = McpServerCommandBasedConfig | McpServerUrlBasedConfig
54
-
55
- McpServersConfig = dict[str, McpServerConfig]
102
+ # Type for a single MCP server configuration, which can be either
103
+ # command-based or URL-based.
104
+ SingleMcpServerConfig = McpServerCommandBasedConfig | McpServerUrlBasedConfig
105
+ """Configuration for a single MCP server, either command-based or URL-based.
106
+
107
+ This type represents the configuration for a single MCP server, which can
108
+ be either:
109
+ 1. A local server launched via command line (McpServerCommandBasedConfig)
110
+ 2. A remote server accessed via URL (McpServerUrlBasedConfig)
111
+
112
+ The type is determined by the presence of either the "command" key
113
+ (for command-based) or the "url" key (for URL-based).
114
+ """
115
+
116
+ # Configuration dictionary for multiple MCP servers
117
+ McpServersConfig = dict[str, SingleMcpServerConfig]
118
+ """Configuration dictionary for multiple MCP servers.
119
+
120
+ A dictionary mapping server names (as strings) to their respective
121
+ configurations. Each server name acts as a logical identifier used for logging
122
+ and debugging. The configuration for each server can be either command-based
123
+ or URL-based.
124
+
125
+ Example:
126
+ {
127
+ "filesystem": {
128
+ "command": "npx",
129
+ "args": ["-y", "@modelcontextprotocol/server-filesystem", "."]
130
+ },
131
+ "fetch": {
132
+ "command": "uvx",
133
+ "args": ["mcp-server-fetch"]
134
+ },
135
+ "remote-server": {
136
+ "url": "https://example.com/mcp/sse",
137
+ "headers": {"Authorization": "Bearer token123"}
138
+ }
139
+ }
140
+ """
56
141
 
57
142
 
58
143
  def fix_schema(schema: dict) -> dict:
59
- """Converts JSON Schema 'type': ['string', 'null'] to 'anyOf' format"""
144
+ """Converts JSON Schema "type": ["string", "null"] to "anyOf" format.
145
+
146
+ Args:
147
+ schema: A JSON schema dictionary
148
+
149
+ Returns:
150
+ Modified schema with converted type formats
151
+ """
60
152
  if isinstance(schema, dict):
61
- if 'type' in schema and isinstance(schema['type'], list):
62
- schema['anyOf'] = [{'type': t} for t in schema['type']]
63
- del schema['type'] # Remove 'type' and standardize to 'anyOf'
153
+ if "type" in schema and isinstance(schema["type"], list):
154
+ schema["anyOf"] = [{"type": t} for t in schema["type"]]
155
+ del schema["type"] # Remove "type" and standardize to "anyOf"
64
156
  for key, value in schema.items():
65
157
  schema[key] = fix_schema(value) # Apply recursively
66
158
  return schema
@@ -76,12 +168,11 @@ Transport: TypeAlias = tuple[
76
168
 
77
169
  async def spawn_mcp_server_and_get_transport(
78
170
  server_name: str,
79
- server_config: McpServerConfig,
171
+ server_config: SingleMcpServerConfig,
80
172
  exit_stack: AsyncExitStack,
81
173
  logger: logging.Logger = logging.getLogger(__name__)
82
174
  ) -> Transport:
83
- """
84
- Spawns an MCP server process and establishes communication channels.
175
+ """Spawns an MCP server process and establishes communication channels.
85
176
 
86
177
  Args:
87
178
  server_name: Server instance name to use for better logging
@@ -97,19 +188,20 @@ async def spawn_mcp_server_and_get_transport(
97
188
  """
98
189
  try:
99
190
  logger.info(f'MCP server "{server_name}": '
100
- f'initializing with: {server_config}')
191
+ f"initializing with: {server_config}")
101
192
 
102
- url_str = str(server_config.get('url')) # None becomes 'None'
103
- headers = server_config.get("headers", None)
193
+ url_str = str(server_config.get("url")) # None becomes "None"
194
+ headers = (cast(McpServerUrlBasedConfig, server_config)
195
+ .get("headers", None))
104
196
  # no exception thrown even for a malformed URL
105
197
  url_scheme = urlparse(url_str).scheme
106
198
 
107
- if url_scheme in ('http', 'https'):
199
+ if url_scheme in ("http", "https"):
108
200
  transport = await exit_stack.enter_async_context(
109
201
  sse_client(url_str, headers=headers)
110
202
  )
111
203
 
112
- elif url_scheme in ('ws', 'wss'):
204
+ elif url_scheme in ("ws", "wss"):
113
205
  transport = await exit_stack.enter_async_context(
114
206
  websocket_client(url_str)
115
207
  )
@@ -119,21 +211,21 @@ async def spawn_mcp_server_and_get_transport(
119
211
  # To avoid confusion, it was decided to automatically append it
120
212
  # to the env if not explicitly set by the config.
121
213
  config = cast(McpServerCommandBasedConfig, server_config)
122
- # env = config.get('env', {}) does't work since it can yield None
123
- env_val = config.get('env')
214
+ # env = config.get("env", {}) does't work since it can yield None
215
+ env_val = config.get("env")
124
216
  env = {} if env_val is None else dict(env_val)
125
- if 'PATH' not in env:
126
- env['PATH'] = os.environ.get('PATH', '')
217
+ if "PATH" not in env:
218
+ env["PATH"] = os.environ.get("PATH", "")
127
219
 
128
220
  # Use stdio client for commands
129
- # args = config.get('args', []) does't work since it can yield None
130
- args_val = config.get('args')
221
+ # args = config.get("args", []) does't work since it can yield None
222
+ args_val = config.get("args")
131
223
  args = [] if args_val is None else list(args_val)
132
224
  server_parameters = StdioServerParameters(
133
- command=config.get('command', ''),
225
+ command=config.get("command", ""),
134
226
  args=args,
135
227
  env=env,
136
- cwd=config.get('cwd', None)
228
+ cwd=config.get("cwd", None)
137
229
  )
138
230
 
139
231
  # Initialize stdio client and register it with exit stack for
@@ -145,13 +237,14 @@ async def spawn_mcp_server_and_get_transport(
145
237
  # `errlog: TextIO`. I once included `stderr: int` for
146
238
  # compatibility with the TypeScript version, but decided to
147
239
  # follow the Python SDK more closely.
148
- errlog_val = server_config.get('errlog')
149
- kwargs = {'errlog': errlog_val} if errlog_val is not None else {}
240
+ errlog_val = (cast(McpServerCommandBasedConfig, server_config)
241
+ .get("errlog"))
242
+ kwargs = {"errlog": errlog_val} if errlog_val is not None else {}
150
243
  transport = await exit_stack.enter_async_context(
151
244
  stdio_client(server_parameters, **kwargs)
152
245
  )
153
246
  except Exception as e:
154
- logger.error(f'Error spawning MCP server: {str(e)}')
247
+ logger.error(f"Error spawning MCP server: {str(e)}")
155
248
  raise
156
249
 
157
250
  return transport
@@ -163,8 +256,7 @@ async def get_mcp_server_tools(
163
256
  exit_stack: AsyncExitStack,
164
257
  logger: logging.Logger = logging.getLogger(__name__)
165
258
  ) -> list[BaseTool]:
166
- """
167
- Retrieves and converts MCP server tools to LangChain format.
259
+ """Retrieves and converts MCP server tools to LangChain format.
168
260
 
169
261
  Args:
170
262
  server_name: Server instance name to use for better logging
@@ -211,8 +303,8 @@ async def get_mcp_server_tools(
211
303
 
212
304
  # Define adapter class to convert MCP tool to LangChain format
213
305
  class McpToLangChainAdapter(BaseTool):
214
- name: str = tool.name or 'NO NAME'
215
- description: str = tool.description or ''
306
+ name: str = tool.name or "NO NAME"
307
+ description: str = tool.description or ""
216
308
  # Convert JSON schema to Pydantic model for argument validation
217
309
  args_schema: type[BaseModel] = jsonschema_to_pydantic(
218
310
  fix_schema(tool.inputSchema) # Apply schema conversion
@@ -221,31 +313,40 @@ async def get_mcp_server_tools(
221
313
 
222
314
  def _run(self, **kwargs: Any) -> NoReturn:
223
315
  raise NotImplementedError(
224
- 'MCP tools only support async operations'
316
+ "MCP tools only support async operations"
225
317
  )
226
318
 
227
319
  async def _arun(self, **kwargs: Any) -> Any:
228
- """
229
- Asynchronously executes the tool with given arguments.
320
+ """Asynchronously executes the tool with given arguments.
321
+
230
322
  Logs input/output and handles errors.
323
+
324
+ Args:
325
+ **kwargs: Arguments to be passed to the MCP tool
326
+
327
+ Returns:
328
+ Formatted response from the MCP tool as a string
329
+
330
+ Raises:
331
+ ToolException: If the tool execution fails
231
332
  """
232
333
  logger.info(f'MCP tool "{server_name}"/"{tool.name}" '
233
- f'received input: {kwargs}')
334
+ f"received input: {kwargs}")
234
335
 
235
336
  try:
236
337
  result = await session.call_tool(self.name, kwargs)
237
338
 
238
- if hasattr(result, 'isError') and result.isError:
339
+ if hasattr(result, "isError") and result.isError:
239
340
  raise ToolException(
240
- f'Tool execution failed: {result.content}'
341
+ f"Tool execution failed: {result.content}"
241
342
  )
242
343
 
243
- if not hasattr(result, 'content'):
344
+ if not hasattr(result, "content"):
244
345
  return str(result)
245
346
 
246
347
  # The return type of `BaseTool`'s `arun` is `str`.
247
348
  try:
248
- result_content_text = '\n\n'.join(
349
+ result_content_text = "\n\n".join(
249
350
  item.text
250
351
  for item in result.content
251
352
  if isinstance(item, mcp_types.TextContent)
@@ -259,20 +360,20 @@ async def get_mcp_server_tools(
259
360
 
260
361
  except KeyError as e:
261
362
  result_content_text = (
262
- f'Error in parsing result.content: {str(e)}; '
263
- f'contents: {repr(result.content)}'
363
+ f"Error in parsing result.content: {str(e)}; "
364
+ f"contents: {repr(result.content)}"
264
365
  )
265
366
 
266
367
  # Log rough result size for monitoring
267
368
  size = len(result_content_text.encode())
268
369
  logger.info(f'MCP tool "{server_name}"/"{tool.name}" '
269
- f'received result (size: {size})')
370
+ f"received result (size: {size})")
270
371
 
271
372
  # If no text content, return a clear message
272
373
  # describing the situation.
273
374
  result_content_text = (
274
375
  result_content_text or
275
- 'No text content available in response'
376
+ "No text content available in response"
276
377
  )
277
378
 
278
379
  return result_content_text
@@ -280,21 +381,21 @@ async def get_mcp_server_tools(
280
381
  except Exception as e:
281
382
  logger.warn(
282
383
  f'MCP tool "{server_name}"/"{tool.name}" '
283
- f'caused error: {str(e)}'
384
+ f"caused error: {str(e)}"
284
385
  )
285
386
  if self.handle_tool_error:
286
- return f'Error executing MCP tool: {str(e)}'
387
+ return f"Error executing MCP tool: {str(e)}"
287
388
  raise
288
389
 
289
390
  langchain_tools.append(McpToLangChainAdapter())
290
391
 
291
392
  # Log available tools for debugging
292
393
  logger.info(f'MCP server "{server_name}": {len(langchain_tools)} '
293
- f'tool(s) available:')
394
+ f"tool(s) available:")
294
395
  for tool in langchain_tools:
295
- logger.info(f'- {tool.name}')
396
+ logger.info(f"- {tool.name}")
296
397
  except Exception as e:
297
- logger.error(f'Error getting MCP tools: {str(e)}')
398
+ logger.error(f"Error getting MCP tools: {str(e)}")
298
399
  raise
299
400
 
300
401
  return langchain_tools
@@ -302,19 +403,36 @@ async def get_mcp_server_tools(
302
403
 
303
404
  # A very simple pre-configured logger for fallback
304
405
  def init_logger() -> logging.Logger:
406
+ """Creates a simple pre-configured logger.
407
+
408
+ Returns:
409
+ A configured Logger instance
410
+ """
305
411
  logging.basicConfig(
306
412
  level=logging.INFO, # logging.DEBUG,
307
- format='\x1b[90m[%(levelname)s]\x1b[0m %(message)s'
413
+ format="\x1b[90m[%(levelname)s]\x1b[0m %(message)s"
308
414
  )
309
415
  return logging.getLogger()
310
416
 
311
417
 
312
418
  # Type hint for cleanup function
313
419
  McpServerCleanupFn = Callable[[], Awaitable[None]]
420
+ """Type for the async cleanup function returned by
421
+ convert_mcp_to_langchain_tools.
422
+
423
+ This represents an asynchronous function that takes no arguments and returns
424
+ nothing. It's used to properly shut down all MCP server connections and clean
425
+ up resources when the tools are no longer needed.
426
+
427
+ Example usage:
428
+ tools, cleanup = await convert_mcp_to_langchain_tools(server_configs)
429
+ # Use tools...
430
+ await cleanup() # Clean up resources when done
431
+ """
314
432
 
315
433
 
316
434
  async def convert_mcp_to_langchain_tools(
317
- server_configs: dict[str, McpServerConfig],
435
+ server_configs: McpServersConfig,
318
436
  logger: logging.Logger | None = None
319
437
  ) -> tuple[list[BaseTool], McpServerCleanupFn]:
320
438
  """Initialize multiple MCP servers and convert their tools to
@@ -329,26 +447,30 @@ async def convert_mcp_to_langchain_tools(
329
447
  configurations, where each configuration contains command, args,
330
448
  and env settings
331
449
  logger: Logger instance to use for logging events and errors.
332
- If None, uses module logger with fallback to a pre-configured
333
- logger when no root handlers exist.
450
+ If None, uses module logger with fallback to a pre-configured
451
+ logger when no root handlers exist.
334
452
 
335
453
  Returns:
336
454
  A tuple containing:
337
- - List of converted LangChain tools from all servers
338
- - Async cleanup function to properly shutdown all server
339
- connections
455
+
456
+ * List of converted LangChain tools from all servers
457
+ * Async cleanup function to properly shutdown all server connections
340
458
 
341
459
  Example:
460
+
342
461
  server_configs = {
343
- 'fetch': {
344
- 'command': 'uvx', 'args': ['mcp-server-fetch']
462
+ "fetch": {
463
+ "command": "uvx", "args": ["mcp-server-fetch"]
345
464
  },
346
- 'weather': {
347
- 'command': 'npx', 'args': ['-y','@h1deya/mcp-server-weather']
465
+ "weather": {
466
+ "command": "npx", "args": ["-y","@h1deya/mcp-server-weather"]
348
467
  }
349
468
  }
469
+
350
470
  tools, cleanup = await convert_mcp_to_langchain_tools(server_configs)
471
+
351
472
  # Use tools...
473
+
352
474
  await cleanup()
353
475
  """
354
476
 
@@ -394,13 +516,13 @@ async def convert_mcp_to_langchain_tools(
394
516
 
395
517
  # Define a cleanup function to properly shut down all servers
396
518
  async def mcp_cleanup() -> None:
397
- """Closes all server connections and cleans up resources"""
519
+ """Closes all server connections and cleans up resources."""
398
520
  await async_exit_stack.aclose()
399
521
 
400
522
  # Log summary of initialized tools
401
- logger.info(f'MCP servers initialized: {len(langchain_tools)} tool(s) '
402
- f'available in total')
523
+ logger.info(f"MCP servers initialized: {len(langchain_tools)} tool(s) "
524
+ f"available in total")
403
525
  for tool in langchain_tools:
404
- logger.debug(f'- {tool.name}')
526
+ logger.debug(f"- {tool.name}")
405
527
 
406
528
  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.2
3
+ Version: 0.2.4
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,20 +11,31 @@ 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/)
27
28
 
29
+ ## NOTE
30
+
31
+ LangChain's official **LangChain MCP Adapters** library has been released at:
32
+ - pypi: https://pypi.org/project/langchain-mcp-adapters/
33
+ - github: https://github.com/langchain-ai/langchain-mcp-adapters
34
+
35
+ You may want to consider using the above if you don't have specific needs for using this library...
36
+
37
+ ## Introduction
38
+
28
39
  This package is intended to simplify the use of
29
40
  [Model Context Protocol (MCP)](https://modelcontextprotocol.io/)
30
41
  server tools with LangChain / Python.
@@ -67,6 +78,11 @@ A typescript equivalent of this utility is available
67
78
  pip install langchain-mcp-tools
68
79
  ```
69
80
 
81
+ ## API docs
82
+
83
+ Can be found [here](https://hideya.github.io/langchain-mcp-tools-py/)
84
+
85
+
70
86
  ## Quick Start
71
87
 
72
88
  A minimal but complete working usage example can be found
@@ -145,9 +161,9 @@ Note that the key `"url"` may be changed in the future to match
145
161
  the MCP server configurations used by Claude for Desktop once
146
162
  it introduces remote server support.
147
163
 
148
- A usage example can be found [here](https://github.com/hideya/langchain-mcp-tools-py-usage/blob/cf96ddc43750708ef3b244bad95714f0f2fe1d28/src/example.py#L43-L54)
164
+ A usage example can be found [here](https://github.com/hideya/langchain-mcp-tools-py-usage/blob/3bd35d9fb49f4b631fe3d0cc8491d43cbf69693b/src/example.py#L43-L54)
149
165
 
150
- ### Passing HTTP Headers to SSE Connection
166
+ ### Authentication Support for SSE Connections
151
167
 
152
168
  A new key `"headers"` has been introduced to pass HTTP headers to the SSE (Server-Sent Events) connection.
153
169
  It takes `dict[str, str]` and is primarily intended to support SSE MCP servers
@@ -163,6 +179,11 @@ that require authentication via bearer tokens or other custom headers.
163
179
  The key name `header` is derived from the Python SDK
164
180
  [`sse_client()`](https://github.com/modelcontextprotocol/python-sdk/blob/babb477dffa33f46cdc886bc885eb1d521151430/src/mcp/client/sse.py#L24) argument name.
165
181
 
182
+ A simple example showing how to implement MCP SSE server and client with authentication can be found
183
+ in [sse-auth-test-client.py](https://github.com/hideya/langchain-mcp-tools-py-usage/tree/main/src/sse-auth-test-client.py)
184
+ and in [sse-auth-test-server.py](https://github.com/hideya/langchain-mcp-tools-py-usage/tree/main/src/sse-auth-test-server.py)
185
+ of [this usage examples repo](https://github.com/hideya/langchain-mcp-tools-py-usage).
186
+
166
187
  ### Working Directory Configuration for Local MCP Servers
167
188
 
168
189
  The working directory that is used when spawning a local (stdio) MCP server
@@ -179,7 +200,7 @@ can be specified with the `"cwd"` key as follows:
179
200
  The key name `cwd` is derived from
180
201
  Python SDK's [`StdioServerParameters`](https://github.com/modelcontextprotocol/python-sdk/blob/babb477dffa33f46cdc886bc885eb1d521151430/src/mcp/client/stdio/__init__.py#L76-L77).
181
202
 
182
- ### Configuration for Local MCP Server `stderr` Redirection
203
+ ### stderr Redirection for Local MCP Server
183
204
 
184
205
  A new key `"errlog"` has been introduced to specify a file-like object
185
206
  to which local (stdio) MCP server's stderr is redirected.
@@ -190,8 +211,7 @@ to which local (stdio) MCP server's stderr is redirected.
190
211
  mcp_servers[server_name]["errlog"] = log_file
191
212
  ```
192
213
 
193
- A usage example can be found [here](
194
- https://github.com/hideya/langchain-mcp-tools-py-usage/blob/cf96ddc43750708ef3b244bad95714f0f2fe1d28/src/example.py#L91-L108)
214
+ A usage example can be found [here](https://github.com/hideya/langchain-mcp-tools-py-usage/blob/3bd35d9fb49f4b631fe3d0cc8491d43cbf69693b/src/example.py#L88-L108)
195
215
 
196
216
  **NOTE: Why the key name `errlog` was chosen:**
197
217
  Unlike TypeScript SDK's `StdioServerParameters`, the Python
@@ -0,0 +1,8 @@
1
+ langchain_mcp_tools/__init__.py,sha256=CYyhniRN10ktRD1z06JyBoeo_m72Q8OIbqHjh-OGoFA,197
2
+ langchain_mcp_tools/langchain_mcp_tools.py,sha256=LximGy_0QYKuwsKFr5SvUwMZ7475CIJWxLtNDq68b-g,19377
3
+ langchain_mcp_tools/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ langchain_mcp_tools-0.2.4.dist-info/licenses/LICENSE,sha256=CRC91e8v116gCpnp7h49oIa6_zjhxqnHFTREeoZFJwA,1072
5
+ langchain_mcp_tools-0.2.4.dist-info/METADATA,sha256=RJ00zZEh3UCSe6S6B_aaD4YZRiYd3SemWQrPrO9BM8M,9377
6
+ langchain_mcp_tools-0.2.4.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
7
+ langchain_mcp_tools-0.2.4.dist-info/top_level.txt,sha256=aR_9V2A1Yt-Bca60KmndmGLUWb2wiM5IOG-Gkaf1dxY,20
8
+ langchain_mcp_tools-0.2.4.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.1.0)
2
+ Generator: setuptools (79.0.1)
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=txbtjl7BAjZu1ccNUNhLkLd3HNdCSfKeyTCDX_0PUR0,15078
3
- langchain_mcp_tools/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- langchain_mcp_tools-0.2.2.dist-info/licenses/LICENSE,sha256=CRC91e8v116gCpnp7h49oIa6_zjhxqnHFTREeoZFJwA,1072
5
- langchain_mcp_tools-0.2.2.dist-info/METADATA,sha256=hxlEr_nyHbnjLMzhxYOsT_rZQ8-j4rTi7EDDUxyvb-A,8458
6
- langchain_mcp_tools-0.2.2.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
7
- langchain_mcp_tools-0.2.2.dist-info/top_level.txt,sha256=aR_9V2A1Yt-Bca60KmndmGLUWb2wiM5IOG-Gkaf1dxY,20
8
- langchain_mcp_tools-0.2.2.dist-info/RECORD,,