diff --git a/src/mcp/client/session_group.py b/src/mcp/client/session_group.py index a544cecbe8..03f6786c24 100644 --- a/src/mcp/client/session_group.py +++ b/src/mcp/client/session_group.py @@ -414,11 +414,6 @@ async def _aggregate_components(self, server_info: types.Implementation, session except MCPError as err: # pragma: no cover logging.warning(f"Could not fetch tools: {err}") - # Clean up exit stack for session if we couldn't retrieve anything - # from the server. - if not any((prompts_temp, resources_temp, tools_temp)): - del self._session_exit_stacks[session] # pragma: no cover - # Check for duplicates. matching_prompts = prompts_temp.keys() & self._prompts.keys() if matching_prompts: diff --git a/tests/client/test_session_group.py b/tests/client/test_session_group.py index b75d22b7a0..4a5f70d45a 100644 --- a/tests/client/test_session_group.py +++ b/tests/client/test_session_group.py @@ -402,3 +402,27 @@ async def test_client_session_group_establish_session_parameterized( # 3. Assert returned values assert returned_server_info is mock_initialize_result.server_info assert returned_session is mock_entered_session + + +@pytest.mark.anyio +async def test_client_session_group_connect_empty_components_server(): + """Test connecting a server that exposes no components (tools, prompts, or resources).""" + mock_server_info = mock.Mock(spec=types.Implementation) + mock_server_info.name = "EmptyServer" + mock_session = mock.AsyncMock(spec=mcp.ClientSession) + mock_session.list_tools.return_value = mock.AsyncMock(tools=[]) + mock_session.list_resources.return_value = mock.AsyncMock(resources=[]) + mock_session.list_prompts.return_value = mock.AsyncMock(prompts=[]) + + group = ClientSessionGroup() + # Should not raise KeyError when aggregating empty components + await group.connect_with_session(mock_server_info, mock_session) + + assert mock_session in group._sessions + assert group.tools == {} + assert group.resources == {} + assert group.prompts == {} + + # Disconnecting should also succeed cleanly + await group.disconnect_from_server(mock_session) + assert mock_session not in group._sessions