Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/agents/mcp/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -1443,8 +1443,8 @@ async def list_tools(
transport_cause: Exception | None = None
try:
tools: list[MCPTool]
# Return from cache if caching is enabled, we have tools, and the cache is not dirty
if self.cache_tools_list and not self._cache_dirty and self._tools_list:
# Return from cache if caching is enabled, the cache is populated, and it is not dirty
if self.cache_tools_list and not self._cache_dirty and self._tools_list is not None:
tools = self._tools_list
else:
tools = []
Expand Down
27 changes: 27 additions & 0 deletions tests/mcp/test_caching.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,33 @@ async def test_server_caching_works(
assert result_tools == tools


@pytest.mark.asyncio
@patch("mcp.client.stdio.stdio_client", return_value=DummyStreamsContextManager())
@patch("mcp.client.session.ClientSession.initialize", new_callable=AsyncMock, return_value=None)
@patch("mcp.client.session.ClientSession.list_tools")
async def test_server_caching_works_with_empty_tools(
mock_list_tools: AsyncMock, mock_initialize: AsyncMock, mock_stdio_client
):
"""An empty tools list is a populated cache and must not be fetched again."""
server = MCPServerStdio(
params={
"command": tee,
},
cache_tools_list=True,
)
mock_list_tools.return_value = ListToolsResult(tools=[])

async with server:
first_result = await server.list_tools()
assert first_result == []
assert server.cached_tools == []

second_result = await server.list_tools()
assert second_result == []

assert mock_list_tools.call_count == 1


@pytest.mark.asyncio
@patch("mcp.client.stdio.stdio_client", return_value=DummyStreamsContextManager())
@patch("mcp.client.session.ClientSession.initialize", new_callable=AsyncMock, return_value=None)
Expand Down