Skip to content

Commit 388ecc2

Browse files
authored
Handle McpError from MCP tool calls (#1999)
1 parent a953d34 commit 388ecc2

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

pydantic_ai_slim/pydantic_ai/mcp.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import httpx
1616
from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
1717
from mcp.client.streamable_http import GetSessionIdCallback, streamablehttp_client
18+
from mcp.shared.exceptions import McpError
1819
from mcp.shared.message import SessionMessage
1920
from mcp.types import (
2021
AudioContent,
@@ -127,7 +128,10 @@ async def call_tool(
127128
Raises:
128129
ModelRetry: If the tool call fails.
129130
"""
130-
result = await self._client.call_tool(self.get_unprefixed_tool_name(tool_name), arguments)
131+
try:
132+
result = await self._client.call_tool(self.get_unprefixed_tool_name(tool_name), arguments)
133+
except McpError as e:
134+
raise ModelRetry(e.error.message)
131135

132136
content = [self._map_tool_result_part(part) for part in result.content]
133137

tests/test_mcp.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22

33
import re
44
from pathlib import Path
5+
from unittest.mock import AsyncMock, patch
56

67
import pytest
78
from inline_snapshot import snapshot
89

910
from pydantic_ai.agent import Agent
10-
from pydantic_ai.exceptions import UserError
11+
from pydantic_ai.exceptions import ModelRetry, UserError
1112
from pydantic_ai.messages import (
1213
BinaryContent,
1314
ModelRequest,
@@ -23,6 +24,8 @@
2324
from .conftest import IsDatetime, IsStr, try_import
2425

2526
with try_import() as imports_successful:
27+
from mcp import ErrorData, McpError
28+
2629
from pydantic_ai.mcp import MCPServerSSE, MCPServerStdio
2730
from pydantic_ai.models.google import GoogleModel
2831
from pydantic_ai.models.openai import OpenAIModel
@@ -932,3 +935,18 @@ async def test_tool_returning_multiple_items(allow_model_requests: None, agent:
932935
),
933936
]
934937
)
938+
939+
940+
async def test_mcp_server_raises_mcp_error(allow_model_requests: None, agent: Agent) -> None:
941+
server = agent._mcp_servers[0] # pyright: ignore[reportPrivateUsage]
942+
943+
mcp_error = McpError(error=ErrorData(code=400, message='Test MCP error conversion'))
944+
945+
async with agent.run_mcp_servers():
946+
with patch.object(
947+
server._client, # pyright: ignore[reportPrivateUsage]
948+
'call_tool',
949+
new=AsyncMock(side_effect=mcp_error),
950+
):
951+
with pytest.raises(ModelRetry, match='Test MCP error conversion'):
952+
await server.call_tool('test_tool', {})

0 commit comments

Comments
 (0)