Skip to content

Commit 91f2e09

Browse files
author
Travis Matthews
committed
chore: add unit tests for exception handling
1 parent 5e0953d commit 91f2e09

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

src/mcp/server/fastmcp/tools/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ async def run(
107107
result = self.fn_metadata.convert_result(result)
108108

109109
return result
110-
except httpx.HTTPStatusException as e:
110+
except httpx.HTTPStatusError as e:
111111
try:
112112
error_detail = e.response.json()
113113
except:

tests/server/fastmcp/test_tool_manager.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,55 @@ def name_shrimp(tank: MyShrimpTank, ctx: Context) -> list[str]:
313313
)
314314
assert result == ["rex", "gertrude"]
315315

316+
@pytest.mark.anyio
317+
async def test_tool_run_httpx_json_error(self):
318+
"""Test Tool.run() handling HTTPStatusError with JSON response."""
319+
import httpx
320+
from unittest.mock import Mock
321+
322+
def tool_with_httpx_error(x: int) -> str:
323+
mock_response = Mock()
324+
mock_response.status_code = 404
325+
mock_response.json.return_value = {"error": "Not found", "code": "RESOURCE_NOT_FOUND"}
326+
raise httpx.HTTPStatusError("Not found", request=Mock(), response=mock_response)
327+
328+
manager = ToolManager()
329+
tool = manager.add_tool(tool_with_httpx_error)
330+
331+
with pytest.raises(ToolError, match="Error executing tool tool_with_httpx_error: [404]"):
332+
await tool.run({"x": 42})
333+
334+
@pytest.mark.anyio
335+
async def test_tool_run_httpx_text_error(self):
336+
"""Test Tool.run() handling HTTPStatusError with text response."""
337+
import httpx
338+
from unittest.mock import Mock
339+
340+
def tool_with_httpx_text_error(x: int) -> str:
341+
mock_response = Mock()
342+
mock_response.status_code = 500
343+
mock_response.json.side_effect = Exception("Not JSON")
344+
mock_response.text = "Internal Server Error"
345+
raise httpx.HTTPStatusError("Server error", request=Mock(), response=mock_response)
346+
347+
manager = ToolManager()
348+
tool = manager.add_tool(tool_with_httpx_text_error)
349+
350+
with pytest.raises(ToolError, match="Error executing tool tool_with_httpx_text_error: [500] Internal Server Error"):
351+
await tool.run({"x": 42})
352+
353+
@pytest.mark.anyio
354+
async def test_tool_run_generic_exception(self):
355+
"""Test Tool.run() handling generic exceptions."""
356+
def tool_with_error(x: int) -> str:
357+
raise ValueError("Something went wrong")
358+
359+
manager = ToolManager()
360+
tool = manager.add_tool(tool_with_error)
361+
362+
with pytest.raises(ToolError, match="Error executing tool tool_with_error: Something went wrong"):
363+
await tool.run({"x": 42})
364+
316365

317366
class TestToolSchema:
318367
@pytest.mark.anyio

0 commit comments

Comments
 (0)