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
Original file line number Diff line number Diff line change
Expand Up @@ -78,102 +78,63 @@ def create_mock_mcp_tool(tool_name: str):
return MockTool()


MCP_ENV_CASES = [
pytest.param(
{"EXTERNAL_MCP_URL": "https://mcp-server.example.com/mcp"},
"https://mcp-server.example.com/mcp",
id="external-url",
),
pytest.param(
{"MCP_DEPLOYMENT_ID": "abc123def456789012345678"},
None,
id="datarobot-deployment",
),
]


class TestMyAgentMCPIntegration:
"""Test MCP tool integration for CrewAI agents."""

def test_agent_loads_mcp_tools_from_external_url_in_invoke(
self, crewai_common_mocks
@pytest.mark.parametrize("env_patch,expected_adapter_url", MCP_ENV_CASES)
def test_agent_loads_mcp_tools_in_invoke(
self, crewai_common_mocks, env_patch, expected_adapter_url
):
"""Test that agent loads MCP tools from EXTERNAL_MCP_URL when invoke() is called."""
"""Test that agent loads MCP tools from configured environment settings."""

mock_tools = crewai_common_mocks.default_tools
mock_adapter_class = crewai_common_mocks.adapter_class

test_url = "https://mcp-server.example.com/mcp"
with patch.dict(os.environ, {"EXTERNAL_MCP_URL": test_url}, clear=True):
agent = MyAgent(api_key="test_key", api_base="test_base", verbose=True)
with patch.dict(os.environ, env_patch, clear=True):
api_key = "test-api-key"
api_base = "https://app.datarobot.com/api/v2"
agent = MyAgent(api_key=api_key, api_base=api_base, verbose=True)

# Create completion params
completion_params = {
"messages": [{"role": "user", "content": "test prompt"}],
}

# Call invoke - this should trigger MCP tool loading
try:
asyncio.run(agent.invoke(completion_params))
except (StopIteration, AttributeError, TypeError):
# Expected when crew is mocked
pass

# Verify MCPServerAdapter received the rendered server configuration
mock_adapter_class.assert_called_once()
mock_adapter_class.assert_called_once()
if expected_adapter_url:
adapter_setting = mock_adapter_class.call_args[0][0]
assert adapter_setting["url"] == test_url
assert adapter_setting["url"] == expected_adapter_url
assert adapter_setting["transport"] == "streamable-http"

# Verify set_mcp_tools was called with the tools from MCP server
assert agent.mcp_tools == mock_tools

# Verify mcp_tools property was accessed (by agent_planner, agent_writer, agent_editor)
# We can verify this by checking that the agents were created with the tools
planner = agent.agent_planner
writer = agent.agent_writer
editor = agent.agent_editor
assert agent.mcp_tools == mock_tools

# Verify all agents have the expected MCP tools
expected_tool_names = [tool.name for tool in mock_tools]
for agent_with_tools in (planner, writer, editor):
assert len(agent_with_tools.tools) == len(expected_tool_names)
assert [
tool.name for tool in agent_with_tools.tools
] == expected_tool_names

def test_agent_loads_mcp_tools_from_datarobot_deployment_in_invoke(
self, crewai_common_mocks
):
"""Test that agent loads MCP tools from MCP_DEPLOYMENT_ID when invoke() is called."""
mock_tool = create_mock_mcp_tool("test_mcp_tool")
mock_tools = [mock_tool]
crewai_common_mocks.set_adapter_tools(mock_tools)

deployment_id = "abc123def456789012345678"
api_base = "https://app.datarobot.com/api/v2"
api_key = "test-api-key"

with patch.dict(
os.environ,
{
"MCP_DEPLOYMENT_ID": deployment_id,
"DATAROBOT_ENDPOINT": api_base,
"DATAROBOT_API_TOKEN": api_key,
},
clear=True,
):
agent = MyAgent(api_key=api_key, api_base=api_base, verbose=True)

# Create completion params
completion_params = {
"messages": [{"role": "user", "content": "test prompt"}],
}

# Call invoke - this should trigger MCP tool loading
try:
asyncio.run(agent.invoke(completion_params))
except (StopIteration, AttributeError, TypeError):
# Expected when crew is mocked
pass

# Verify set_mcp_tools was called with the tools from MCP server
assert agent.mcp_tools == mock_tools

# Verify agents have MCP tools
planner = agent.agent_planner
writer = agent.agent_writer
editor = agent.agent_editor
planner = agent.agent_planner
writer = agent.agent_writer
editor = agent.agent_editor

assert len(planner.tools) == 1 # 1 MCP tool
assert len(writer.tools) == 1 # 1 MCP tool
assert len(editor.tools) == 1 # 1 MCP tool
expected_tool_names = [tool.name for tool in mock_tools]
for agent_with_tools in (planner, writer, editor):
assert len(agent_with_tools.tools) == len(expected_tool_names)
assert [tool.name for tool in agent_with_tools.tools] == expected_tool_names

@patch("datarobot_genai.crewai.base.mcp_tools_context")
def test_agent_works_without_mcp_tools(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,55 +98,36 @@ def langgraph_common_mocks():
)


LANGGRAPH_MCP_ENV_CASES = [
pytest.param(
{
"EXTERNAL_MCP_URL": "https://mcp-server.example.com/mcp",
},
id="external-url",
),
pytest.param(
{"MCP_DEPLOYMENT_ID": "abc123def456789012345678"},
id="datarobot-deployment",
),
]


class TestMyAgentLangGraphMCPIntegration:
"""Test MCP tool integration for LangGraph agents."""

def test_agent_loads_mcp_tools_from_external_url_in_invoke(
self, langgraph_common_mocks
):
mock_tools = langgraph_common_mocks.default_tools
@pytest.mark.parametrize("env_patch", LANGGRAPH_MCP_ENV_CASES)
def test_agent_loads_mcp_tools_in_invoke(self, langgraph_common_mocks, env_patch):
mock_context = langgraph_common_mocks.mcp_context

test_url = "https://mcp-server.example.com/mcp"
with patch.dict(os.environ, {"EXTERNAL_MCP_URL": test_url}, clear=True):
agent = MyAgent(api_key="test_key", api_base="test_base", verbose=True)

completion_params = {
"messages": [{"role": "user", "content": "test prompt"}]
}

try:
asyncio.run(agent.invoke(completion_params))
except (StopIteration, AttributeError, TypeError, ValueError):
pass

mock_context.assert_called_once_with(
api_base="test_base", api_key="test_key"
expected_tools = langgraph_common_mocks.default_tools

with patch.dict(os.environ, env_patch, clear=True):
api_key = "test-api-key"
api_base = "https://app.datarobot.com/api/v2"
agent = MyAgent(
api_key=api_key,
api_base=api_base,
verbose=True,
)
assert agent.mcp_tools == mock_tools

def test_agent_loads_mcp_tools_from_datarobot_deployment_in_invoke(
self, langgraph_common_mocks
):
mock_tool = create_mock_mcp_tool("test_mcp_tool")
mock_tools = [mock_tool]
langgraph_common_mocks.set_mcp_tools(mock_tools)
mock_context = langgraph_common_mocks.mcp_context

deployment_id = "abc123def456789012345678"
api_base = "https://app.datarobot.com/api/v2"
api_key = "test-api-key"

with patch.dict(
os.environ,
{
"MCP_DEPLOYMENT_ID": deployment_id,
"DATAROBOT_ENDPOINT": api_base,
"DATAROBOT_API_TOKEN": api_key,
},
clear=True,
):
agent = MyAgent(api_key=api_key, api_base=api_base, verbose=True)

completion_params = {
"messages": [{"role": "user", "content": "test prompt"}]
Expand All @@ -157,8 +138,8 @@ class TestMyAgentLangGraphMCPIntegration:
except (StopIteration, AttributeError, TypeError, ValueError):
pass

mock_context.assert_called_once_with(api_base=api_base, api_key=api_key)
assert agent.mcp_tools == mock_tools
mock_context.assert_called_once_with(api_base=api_base, api_key=api_key)
assert agent.mcp_tools == expected_tools

def test_agent_works_without_mcp_tools(self, langgraph_common_mocks):
langgraph_common_mocks.set_mcp_tools([])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,104 +84,57 @@ def llamaindex_common_mocks():
)


LLAMAINDEX_MCP_ENV_CASES = [
pytest.param(
{"EXTERNAL_MCP_URL": "https://mcp-server.example.com/mcp"},
id="external-url",
),
pytest.param(
{"MCP_DEPLOYMENT_ID": "abc123def456789012345678"},
id="datarobot-deployment",
),
]


class TestMyAgentMCPIntegration:
"""Test MCP tool integration for LlamaIndex agents."""

def test_agent_loads_mcp_tools_from_external_url_in_invoke(
self, llamaindex_common_mocks
):
"""Test that agent loads MCP tools from EXTERNAL_MCP_URL when invoke() is called."""
@pytest.mark.parametrize("env_patch", LLAMAINDEX_MCP_ENV_CASES)
def test_agent_loads_mcp_tools_in_invoke(self, llamaindex_common_mocks, env_patch):
"""Test that agent loads MCP tools from configured environment settings."""
mock_tools = llamaindex_common_mocks.default_tools
mock_load_mcp_tools = llamaindex_common_mocks.load_mcp_tools

test_url = "https://mcp-server.example.com/mcp"
with patch.dict(os.environ, {"EXTERNAL_MCP_URL": test_url}, clear=True):
agent = MyAgent(api_key="test_key", api_base="test_base", verbose=True)

# Create completion params
completion_params = {
"messages": [{"role": "user", "content": "test prompt"}],
}

# Call invoke - this should trigger MCP tool loading
try:
asyncio.run(agent.invoke(completion_params))
except (StopIteration, AttributeError, TypeError):
# Expected when workflow is mocked
pass

# Verify load_mcp_tools was called with correct parameters
mock_load_mcp_tools.assert_called_once_with(
api_base="test_base", api_key="test_key"
with patch.dict(os.environ, env_patch, clear=True):
api_key = "test-api-key"
api_base = "https://app.datarobot.com/api/v2"
agent = MyAgent(
api_key=api_key,
api_base=api_base,
verbose=True,
)

# Verify set_mcp_tools was called with the tools from MCP server
assert agent.mcp_tools == mock_tools

# Verify mcp_tools property was accessed (by agent_planner, agent_writer, agent_editor)
# We can verify this by checking that the agents were created with the tools
planner = agent.agent_planner
writer = agent.agent_writer
editor = agent.agent_editor

# Verify all agents have MCP tools
assert len(planner.tools) == 3 # record_notes + 2 MCP tools
assert len(writer.tools) == 3 # write_report + 2 MCP tools
assert len(editor.tools) == 3 # review_report + 2 MCP tools

def test_agent_loads_mcp_tools_from_datarobot_deployment_in_invoke(
self, llamaindex_common_mocks
):
"""Test that agent loads MCP tools from MCP_DEPLOYMENT_ID when invoke() is called."""
# Create mock MCP tools
mock_tool = create_mock_mcp_tool("test_mcp_tool")
mock_tools = [mock_tool]
llamaindex_common_mocks.set_mcp_tools(mock_tools)
mock_load_mcp_tools = llamaindex_common_mocks.load_mcp_tools

deployment_id = "abc123def456789012345678"
api_base = "https://app.datarobot.com/api/v2"
api_key = "test-api-key"

with patch.dict(
os.environ,
{
"MCP_DEPLOYMENT_ID": deployment_id,
"DATAROBOT_ENDPOINT": api_base,
"DATAROBOT_API_TOKEN": api_key,
},
clear=True,
):
agent = MyAgent(api_key=api_key, api_base=api_base, verbose=True)

# Create completion params
completion_params = {
"messages": [{"role": "user", "content": "test prompt"}],
}

# Call invoke - this should trigger MCP tool loading
try:
asyncio.run(agent.invoke(completion_params))
except (StopIteration, AttributeError, TypeError):
# Expected when workflow is mocked
pass

# Verify load_mcp_tools was called with correct parameters
mock_load_mcp_tools.assert_called_once_with(
api_base=api_base, api_key=api_key
)
mock_load_mcp_tools.assert_called_once_with(api_base=api_base, api_key=api_key)
assert agent.mcp_tools == mock_tools

# Verify set_mcp_tools was called with the tools from MCP server
assert agent.mcp_tools == mock_tools

# Verify agents have MCP tools
planner = agent.agent_planner
writer = agent.agent_writer
editor = agent.agent_editor
planner = agent.agent_planner
writer = agent.agent_writer
editor = agent.agent_editor

assert len(planner.tools) == 2 # record_notes + 1 MCP tool
assert len(writer.tools) == 2 # write_report + 1 MCP tool
assert len(editor.tools) == 2 # review_report + 1 MCP tool
# record_notes/write_report/review_report plus 2 MCP tools
assert len(planner.tools) == 3
assert len(writer.tools) == 3
assert len(editor.tools) == 3

def test_agent_works_without_mcp_tools(self, llamaindex_common_mocks):
"""Test that agent works correctly when no MCP tools are available."""
Expand Down
Loading