Skip to content

Commit 15b4d00

Browse files
feat: add handle_tool_error and handle_validation_error to load_mcp_tools
1 parent 7eb4098 commit 15b4d00

File tree

2 files changed

+49
-7
lines changed

2 files changed

+49
-7
lines changed

langchain_mcp_adapters/client.py

Lines changed: 26 additions & 5 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.prompts import load_mcp_prompt
1920
from langchain_mcp_adapters.resources import load_mcp_resources
@@ -125,12 +126,22 @@ async def session(
125126
await session.initialize()
126127
yield session
127128

128-
async def get_tools(self, *, server_name: str | None = None) -> list[BaseTool]:
129+
async def get_tools(
130+
self,
131+
*,
132+
server_name: str | None = None,
133+
handle_tool_error: bool | str | Callable[[ToolException], str] | None = False,
134+
handle_validation_error: (
135+
bool | str | Callable[[ValidationError], str] | None
136+
) = False,
137+
) -> list[BaseTool]:
129138
"""Get a list of all tools from all connected servers.
130139
131140
Args:
132141
server_name: Optional name of the server to get tools from.
133142
If None, all tools from all servers will be returned (default).
143+
handle_tool_error: Optional error handler for tool execution errors.
144+
handle_validation_error: Optional error handler for validation errors.
134145
135146
NOTE: a new session will be created for each tool call
136147
@@ -145,13 +156,23 @@ async def get_tools(self, *, server_name: str | None = None) -> list[BaseTool]:
145156
f"expected one of '{list(self.connections.keys())}'"
146157
)
147158
raise ValueError(msg)
148-
return await load_mcp_tools(None, connection=self.connections[server_name])
159+
return await load_mcp_tools(
160+
None,
161+
connection=self.connections[server_name],
162+
handle_tool_error=handle_tool_error,
163+
handle_validation_error=handle_validation_error,
164+
)
149165

150166
all_tools: list[BaseTool] = []
151167
load_mcp_tool_tasks = []
152168
for connection in self.connections.values():
153169
load_mcp_tool_task = asyncio.create_task(
154-
load_mcp_tools(None, connection=connection)
170+
load_mcp_tools(
171+
None,
172+
connection=connection,
173+
handle_tool_error=handle_tool_error,
174+
handle_validation_error=handle_validation_error,
175+
)
155176
)
156177
load_mcp_tool_tasks.append(load_mcp_tool_task)
157178
tools_list = await asyncio.gather(*load_mcp_tool_tasks)

langchain_mcp_adapters/tools.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
tools, handle tool execution, and manage tool conversion between the two formats.
55
"""
66

7+
from collections.abc import Callable
78
from typing import Any, cast, get_args
89

910
from langchain_core.tools import (
@@ -18,7 +19,7 @@
1819
from mcp.server.fastmcp.utilities.func_metadata import ArgModelBase, FuncMetadata
1920
from mcp.types import CallToolResult, EmbeddedResource, ImageContent, TextContent
2021
from mcp.types import Tool as MCPTool
21-
from pydantic import BaseModel, create_model
22+
from pydantic import BaseModel, ValidationError, create_model
2223

2324
from langchain_mcp_adapters.sessions import Connection, create_session
2425

@@ -102,6 +103,10 @@ def convert_mcp_tool_to_langchain_tool(
102103
tool: MCPTool,
103104
*,
104105
connection: Connection | None = None,
106+
handle_tool_error: bool | str | Callable[[ToolException], str] | None = False,
107+
handle_validation_error: (
108+
bool | str | Callable[[ValidationError], str] | None
109+
) = False,
105110
) -> BaseTool:
106111
"""Convert an MCP tool to a LangChain tool.
107112
@@ -112,6 +117,8 @@ def convert_mcp_tool_to_langchain_tool(
112117
tool: MCP tool to convert
113118
connection: Optional connection config to use to create a new session
114119
if a `session` is not provided
120+
handle_tool_error: Optional error handler for tool execution errors.
121+
handle_validation_error: Optional error handler for validation errors.
115122
116123
Returns:
117124
a LangChain tool
@@ -143,19 +150,27 @@ async def call_tool(
143150
coroutine=call_tool,
144151
response_format="content_and_artifact",
145152
metadata=tool.annotations.model_dump() if tool.annotations else None,
153+
handle_tool_error=handle_tool_error,
154+
handle_validation_error=handle_validation_error,
146155
)
147156

148157

149158
async def load_mcp_tools(
150159
session: ClientSession | None,
151160
*,
152161
connection: Connection | None = None,
162+
handle_tool_error: bool | str | Callable[[ToolException], str] | None = False,
163+
handle_validation_error: (
164+
bool | str | Callable[[ValidationError], str] | None
165+
) = False,
153166
) -> list[BaseTool]:
154167
"""Load all available MCP tools and convert them to LangChain tools.
155168
156169
Args:
157170
session: The MCP client session. If None, connection must be provided.
158171
connection: Connection config to create a new session if session is None.
172+
handle_tool_error: Optional error handler for tool execution errors.
173+
handle_validation_error: Optional error handler for validation errors.
159174
160175
Returns:
161176
List of LangChain tools. Tool annotations are returned as part
@@ -177,7 +192,13 @@ async def load_mcp_tools(
177192
tools = await _list_all_tools(session)
178193

179194
return [
180-
convert_mcp_tool_to_langchain_tool(session, tool, connection=connection)
195+
convert_mcp_tool_to_langchain_tool(
196+
session,
197+
tool,
198+
connection=connection,
199+
handle_tool_error=handle_tool_error,
200+
handle_validation_error=handle_validation_error,
201+
)
181202
for tool in tools
182203
]
183204

0 commit comments

Comments
 (0)