diff --git a/openhands/server/routes/mcp.py b/openhands/server/routes/mcp.py index 2d541d637c..df7c978de6 100644 --- a/openhands/server/routes/mcp.py +++ b/openhands/server/routes/mcp.py @@ -32,12 +32,15 @@ CONVERSATION_URL = HOST + '/conversations/{}' async def get_conversation_link( - service: GitService, conversation_id: str, body: str + service: GitService, conversation_id: str | None, body: str ) -> str: """Appends a followup link, in the PR body, to the OpenHands conversation that opened the PR""" if server_config.app_mode != AppMode.SAAS: return body + if not conversation_id: + return body + user = await service.get_user() username = user.login conversation_url = CONVERSATION_URL.format(conversation_id) diff --git a/tests/unit/server/routes/test_mcp_routes.py b/tests/unit/server/routes/test_mcp_routes.py index 3f5fb68e80..54c1a8a43c 100644 --- a/tests/unit/server/routes/test_mcp_routes.py +++ b/tests/unit/server/routes/test_mcp_routes.py @@ -123,3 +123,29 @@ async def test_get_conversation_link_empty_body(): # Verify that get_user was called mock_service.get_user.assert_called_once() + + +@pytest.mark.asyncio +async def test_get_conversation_link_none_conversation_id(): + """Test get_conversation_link returns body unchanged when conversation_id is None.""" + mock_service = AsyncMock(spec=GitService) + + with patch('openhands.server.routes.mcp.server_config') as mock_config: + mock_config.app_mode = AppMode.SAAS + + body = 'This is the PR body.' + + # Test with None conversation_id + result = await get_conversation_link( + service=mock_service, conversation_id=None, body=body + ) + assert result == body + + # Test with empty string conversation_id + result = await get_conversation_link( + service=mock_service, conversation_id='', body=body + ) + assert result == body + + # Verify get_user was never called (early return) + mock_service.get_user.assert_not_called()