From 3b77dd57d894a75e9a8595b363e7c054e1783040 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sun, 26 Oct 2025 09:58:46 +0000 Subject: [PATCH] fix: Add sys.modules stub fixture for mcp modules in tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add autouse fixture to stub mcp, mcp.client, and mcp.client.streamable_http modules - Revert patch targets to module-local names (crewai.tools.mcp_tool_wrapper.*) - This fixes ModuleNotFoundError in CI where mcp package is not installed - The stub fixture ensures tests can run without requiring the actual mcp package Co-Authored-By: João --- .../tests/tools/test_mcp_tool_wrapper.py | 45 +++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/lib/crewai/tests/tools/test_mcp_tool_wrapper.py b/lib/crewai/tests/tools/test_mcp_tool_wrapper.py index 739957d2d..04ff80054 100644 --- a/lib/crewai/tests/tools/test_mcp_tool_wrapper.py +++ b/lib/crewai/tests/tools/test_mcp_tool_wrapper.py @@ -1,6 +1,8 @@ """Tests for MCPToolWrapper progress and headers support.""" import asyncio +import sys +import types from unittest.mock import AsyncMock, MagicMock, Mock, patch import pytest @@ -10,6 +12,33 @@ from crewai.events.types.tool_usage_events import MCPToolProgressEvent from crewai.tools.mcp_tool_wrapper import MCPToolWrapper +@pytest.fixture(autouse=True) +def stub_mcp_modules(monkeypatch): + """Stub the mcp modules in sys.modules to avoid import errors in CI.""" + mcp = types.ModuleType("mcp") + mcp_client = types.ModuleType("mcp.client") + mcp_streamable_http = types.ModuleType("mcp.client.streamable_http") + + mcp.ClientSession = MagicMock() + + async def fake_streamablehttp_client(*args, **kwargs): + """Mock streamablehttp_client context manager.""" + class MockContextManager: + async def __aenter__(self): + return (AsyncMock(), AsyncMock(), AsyncMock()) + + async def __aexit__(self, *exc): + pass + + return MockContextManager() + + mcp_streamable_http.streamablehttp_client = fake_streamablehttp_client + + monkeypatch.setitem(sys.modules, "mcp", mcp) + monkeypatch.setitem(sys.modules, "mcp.client", mcp_client) + monkeypatch.setitem(sys.modules, "mcp.client.streamable_http", mcp_streamable_http) + + @pytest.fixture def mock_mcp_session(): """Create a mock MCP ClientSession.""" @@ -119,8 +148,8 @@ class TestMCPToolWrapperProgress: mock_result = Mock() mock_result.content = [Mock(text="Test result")] - with patch("mcp.client.streamable_http.streamablehttp_client") as mock_client, \ - patch("mcp.ClientSession") as mock_session_class: + with patch("crewai.tools.mcp_tool_wrapper.streamablehttp_client") as mock_client, \ + patch("crewai.tools.mcp_tool_wrapper.ClientSession") as mock_session_class: mock_session = AsyncMock() mock_session.initialize = AsyncMock() @@ -243,8 +272,8 @@ class TestMCPToolWrapperHeaders: mock_result = Mock() mock_result.content = [Mock(text="Test result")] - with patch("mcp.client.streamable_http.streamablehttp_client") as mock_client, \ - patch("mcp.ClientSession") as mock_session_class: + with patch("crewai.tools.mcp_tool_wrapper.streamablehttp_client") as mock_client, \ + patch("crewai.tools.mcp_tool_wrapper.ClientSession") as mock_session_class: mock_session = AsyncMock() mock_session.initialize = AsyncMock() @@ -277,8 +306,8 @@ class TestMCPToolWrapperHeaders: mock_result = Mock() mock_result.content = [Mock(text="Test result")] - with patch("mcp.client.streamable_http.streamablehttp_client") as mock_client, \ - patch("mcp.ClientSession") as mock_session_class: + with patch("crewai.tools.mcp_tool_wrapper.streamablehttp_client") as mock_client, \ + patch("crewai.tools.mcp_tool_wrapper.ClientSession") as mock_session_class: mock_session = AsyncMock() mock_session.initialize = AsyncMock() @@ -326,8 +355,8 @@ class TestMCPToolWrapperIntegration: mock_result = Mock() mock_result.content = [Mock(text="Test result")] - with patch("mcp.client.streamable_http.streamablehttp_client") as mock_client, \ - patch("mcp.ClientSession") as mock_session_class: + with patch("crewai.tools.mcp_tool_wrapper.streamablehttp_client") as mock_client, \ + patch("crewai.tools.mcp_tool_wrapper.ClientSession") as mock_session_class: mock_session = AsyncMock() mock_session.initialize = AsyncMock()