Skip to content

Commit e10865e

Browse files
feat: add handle_tool_error and handle_validation_error to load_mcp_tools
1 parent 5402d73 commit e10865e

File tree

2 files changed

+32
-3
lines changed

2 files changed

+32
-3
lines changed

langchain_mcp_adapters/client.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@
55
"""
66

77
import asyncio
8-
from collections.abc import AsyncIterator
8+
from collections.abc import AsyncIterator, Callable
99
from contextlib import asynccontextmanager
1010
from types import TracebackType
1111
from typing import Any
1212

1313
from langchain_core.documents.base import Blob
1414
from langchain_core.messages import AIMessage, HumanMessage
15-
from langchain_core.tools import BaseTool
15+
from langchain_core.tools import BaseTool, ToolException
1616
from mcp import ClientSession
17+
from pydantic import ValidationError
1718

1819
from langchain_mcp_adapters.callbacks import CallbackContext, Callbacks
1920
from langchain_mcp_adapters.interceptors import ToolCallInterceptor
@@ -55,6 +56,10 @@ def __init__(
5556
callbacks: Callbacks | None = None,
5657
tool_interceptors: list[ToolCallInterceptor] | None = None,
5758
tool_name_prefix: bool = False,
59+
handle_tool_error: bool | str | Callable[[ToolException], str] | None = False,
60+
handle_validation_error: (
61+
bool | str | Callable[[ValidationError], str] | None
62+
) = False,
5863
) -> None:
5964
"""Initialize a `MultiServerMCPClient` with MCP servers connections.
6065
@@ -68,6 +73,8 @@ def __init__(
6873
using an underscore separator (e.g., `"weather_search"` instead of
6974
`"search"`). This helps avoid conflicts when multiple servers have tools
7075
with the same name. Defaults to `False`.
76+
handle_tool_error: Optional error handler for tool execution errors.
77+
handle_validation_error: Optional error handler for validation errors.
7178
7279
!!! example "Basic usage (starting a new session on each tool call)"
7380
@@ -110,6 +117,8 @@ def __init__(
110117
self.callbacks = callbacks or Callbacks()
111118
self.tool_interceptors = tool_interceptors or []
112119
self.tool_name_prefix = tool_name_prefix
120+
self.handle_tool_error = handle_tool_error
121+
self.handle_validation_error = handle_validation_error
113122

114123
@asynccontextmanager
115124
async def session(
@@ -178,6 +187,8 @@ async def get_tools(self, *, server_name: str | None = None) -> list[BaseTool]:
178187
server_name=server_name,
179188
tool_interceptors=self.tool_interceptors,
180189
tool_name_prefix=self.tool_name_prefix,
190+
handle_tool_error=self.handle_tool_error,
191+
handle_validation_error=self.handle_validation_error,
181192
)
182193

183194
all_tools: list[BaseTool] = []
@@ -191,6 +202,8 @@ async def get_tools(self, *, server_name: str | None = None) -> list[BaseTool]:
191202
server_name=name,
192203
tool_interceptors=self.tool_interceptors,
193204
tool_name_prefix=self.tool_name_prefix,
205+
handle_tool_error=self.handle_tool_error,
206+
handle_validation_error=self.handle_validation_error,
194207
)
195208
)
196209
load_mcp_tool_tasks.append(load_mcp_tool_task)

langchain_mcp_adapters/tools.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
TextResourceContents,
3838
)
3939
from mcp.types import Tool as MCPTool
40-
from pydantic import BaseModel, create_model
40+
from pydantic import BaseModel, ValidationError, create_model
4141

4242
from langchain_mcp_adapters.callbacks import CallbackContext, Callbacks, _MCPCallbacks
4343
from langchain_mcp_adapters.interceptors import (
@@ -278,6 +278,10 @@ def convert_mcp_tool_to_langchain_tool(
278278
tool_interceptors: list[ToolCallInterceptor] | None = None,
279279
server_name: str | None = None,
280280
tool_name_prefix: bool = False,
281+
handle_tool_error: bool | str | Callable[[ToolException], str] | None = False,
282+
handle_validation_error: (
283+
bool | str | Callable[[ValidationError], str] | None
284+
) = False,
281285
) -> BaseTool:
282286
"""Convert an MCP tool to a LangChain tool.
283287
@@ -293,6 +297,8 @@ def convert_mcp_tool_to_langchain_tool(
293297
server_name: Name of the server this tool belongs to
294298
tool_name_prefix: If `True` and `server_name` is provided, the tool name will be
295299
prefixed w/ server name (e.g., `"weather_search"` instead of `"search"`)
300+
handle_tool_error: Optional error handler for tool execution errors.
301+
handle_validation_error: Optional error handler for validation errors.
296302
297303
Returns:
298304
a LangChain tool
@@ -430,6 +436,8 @@ async def execute_tool(request: MCPToolCallRequest) -> MCPToolCallResult:
430436
coroutine=call_tool,
431437
response_format="content_and_artifact",
432438
metadata=metadata,
439+
handle_tool_error=handle_tool_error,
440+
handle_validation_error=handle_validation_error,
433441
)
434442

435443

@@ -441,6 +449,10 @@ async def load_mcp_tools(
441449
tool_interceptors: list[ToolCallInterceptor] | None = None,
442450
server_name: str | None = None,
443451
tool_name_prefix: bool = False,
452+
handle_tool_error: bool | str | Callable[[ToolException], str] | None = False,
453+
handle_validation_error: (
454+
bool | str | Callable[[ValidationError], str] | None
455+
) = False,
444456
) -> list[BaseTool]:
445457
"""Load all available MCP tools and convert them to LangChain [tools](https://docs.langchain.com/oss/python/langchain/tools).
446458
@@ -452,6 +464,8 @@ async def load_mcp_tools(
452464
server_name: Name of the server these tools belong to.
453465
tool_name_prefix: If `True` and `server_name` is provided, tool names will be
454466
prefixed w/ server name (e.g., `"weather_search"` instead of `"search"`).
467+
handle_tool_error: Optional error handler for tool execution errors.
468+
handle_validation_error: Optional error handler for validation errors.
455469
456470
Returns:
457471
List of LangChain [tools](https://docs.langchain.com/oss/python/langchain/tools).
@@ -492,6 +506,8 @@ async def load_mcp_tools(
492506
tool_interceptors=tool_interceptors,
493507
server_name=server_name,
494508
tool_name_prefix=tool_name_prefix,
509+
handle_tool_error=handle_tool_error,
510+
handle_validation_error=handle_validation_error,
495511
)
496512
for tool in tools
497513
]

0 commit comments

Comments
 (0)