mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
Co-authored-by: openhands <openhands@all-hands.dev> Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
145 lines
5.2 KiB
Python
145 lines
5.2 KiB
Python
"""Test MCP settings merging functionality."""
|
|
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
|
|
from openhands.core.config.mcp_config import (
|
|
MCPConfig,
|
|
MCPSSEServerConfig,
|
|
MCPStdioServerConfig,
|
|
)
|
|
from openhands.storage.data_models.settings import Settings
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_mcp_settings_merge_config_only():
|
|
"""Test merging when only config.toml has MCP settings."""
|
|
# Mock config.toml with MCP settings
|
|
mock_config_settings = Settings(
|
|
mcp_config=MCPConfig(
|
|
sse_servers=[MCPSSEServerConfig(url='http://config-server.com')]
|
|
)
|
|
)
|
|
|
|
# Frontend settings without MCP config
|
|
frontend_settings = Settings(llm_model='gpt-4')
|
|
|
|
with patch.object(Settings, 'from_config', return_value=mock_config_settings):
|
|
merged_settings = frontend_settings.merge_with_config_settings()
|
|
|
|
# Should use config.toml MCP settings
|
|
assert merged_settings.mcp_config is not None
|
|
assert len(merged_settings.mcp_config.sse_servers) == 1
|
|
assert merged_settings.mcp_config.sse_servers[0].url == 'http://config-server.com'
|
|
assert merged_settings.llm_model == 'gpt-4'
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_mcp_settings_merge_frontend_only():
|
|
"""Test merging when only frontend has MCP settings."""
|
|
# Mock config.toml without MCP settings
|
|
mock_config_settings = Settings(llm_model='claude-3')
|
|
|
|
# Frontend settings with MCP config
|
|
frontend_settings = Settings(
|
|
llm_model='gpt-4',
|
|
mcp_config=MCPConfig(
|
|
sse_servers=[MCPSSEServerConfig(url='http://frontend-server.com')]
|
|
),
|
|
)
|
|
|
|
with patch.object(Settings, 'from_config', return_value=mock_config_settings):
|
|
merged_settings = frontend_settings.merge_with_config_settings()
|
|
|
|
# Should keep frontend MCP settings
|
|
assert merged_settings.mcp_config is not None
|
|
assert len(merged_settings.mcp_config.sse_servers) == 1
|
|
assert merged_settings.mcp_config.sse_servers[0].url == 'http://frontend-server.com'
|
|
assert merged_settings.llm_model == 'gpt-4'
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_mcp_settings_merge_both_present():
|
|
"""Test merging when both config.toml and frontend have MCP settings."""
|
|
# Mock config.toml with MCP settings
|
|
mock_config_settings = Settings(
|
|
mcp_config=MCPConfig(
|
|
sse_servers=[MCPSSEServerConfig(url='http://config-server.com')],
|
|
stdio_servers=[
|
|
MCPStdioServerConfig(
|
|
name='config-stdio', command='config-cmd', args=['arg1']
|
|
)
|
|
],
|
|
)
|
|
)
|
|
|
|
# Frontend settings with different MCP config
|
|
frontend_settings = Settings(
|
|
llm_model='gpt-4',
|
|
mcp_config=MCPConfig(
|
|
sse_servers=[MCPSSEServerConfig(url='http://frontend-server.com')],
|
|
stdio_servers=[
|
|
MCPStdioServerConfig(
|
|
name='frontend-stdio', command='frontend-cmd', args=['arg2']
|
|
)
|
|
],
|
|
),
|
|
)
|
|
|
|
with patch.object(Settings, 'from_config', return_value=mock_config_settings):
|
|
merged_settings = frontend_settings.merge_with_config_settings()
|
|
|
|
# Should merge both with config.toml taking priority (appearing first)
|
|
assert merged_settings.mcp_config is not None
|
|
assert len(merged_settings.mcp_config.sse_servers) == 2
|
|
assert merged_settings.mcp_config.sse_servers[0].url == 'http://config-server.com'
|
|
assert merged_settings.mcp_config.sse_servers[1].url == 'http://frontend-server.com'
|
|
|
|
assert len(merged_settings.mcp_config.stdio_servers) == 2
|
|
assert merged_settings.mcp_config.stdio_servers[0].name == 'config-stdio'
|
|
assert merged_settings.mcp_config.stdio_servers[1].name == 'frontend-stdio'
|
|
|
|
assert merged_settings.llm_model == 'gpt-4'
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_mcp_settings_merge_no_config():
|
|
"""Test merging when config.toml has no MCP settings."""
|
|
# Mock config.toml without MCP settings
|
|
mock_config_settings = None
|
|
|
|
# Frontend settings with MCP config
|
|
frontend_settings = Settings(
|
|
llm_model='gpt-4',
|
|
mcp_config=MCPConfig(
|
|
sse_servers=[MCPSSEServerConfig(url='http://frontend-server.com')]
|
|
),
|
|
)
|
|
|
|
with patch.object(Settings, 'from_config', return_value=mock_config_settings):
|
|
merged_settings = frontend_settings.merge_with_config_settings()
|
|
|
|
# Should keep frontend settings unchanged
|
|
assert merged_settings.mcp_config is not None
|
|
assert len(merged_settings.mcp_config.sse_servers) == 1
|
|
assert merged_settings.mcp_config.sse_servers[0].url == 'http://frontend-server.com'
|
|
assert merged_settings.llm_model == 'gpt-4'
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_mcp_settings_merge_neither_present():
|
|
"""Test merging when neither config.toml nor frontend have MCP settings."""
|
|
# Mock config.toml without MCP settings
|
|
mock_config_settings = Settings(llm_model='claude-3')
|
|
|
|
# Frontend settings without MCP config
|
|
frontend_settings = Settings(llm_model='gpt-4')
|
|
|
|
with patch.object(Settings, 'from_config', return_value=mock_config_settings):
|
|
merged_settings = frontend_settings.merge_with_config_settings()
|
|
|
|
# Should keep frontend settings unchanged
|
|
assert merged_settings.mcp_config is None
|
|
assert merged_settings.llm_model == 'gpt-4'
|