From 6605070d05de407f184e6c3dd2bfc783846d679b Mon Sep 17 00:00:00 2001 From: Graham Neubig Date: Sat, 20 Dec 2025 09:45:52 -0500 Subject: [PATCH] Fix fastmcp stateless_http deprecation warning (#12108) Co-authored-by: openhands Co-authored-by: Rohit Malhotra --- openhands/server/app.py | 2 +- openhands/server/routes/mcp.py | 4 +-- tests/unit/server/routes/test_mcp_routes.py | 33 +++++++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/openhands/server/app.py b/openhands/server/app.py index d5135f2399..5cee75b163 100644 --- a/openhands/server/app.py +++ b/openhands/server/app.py @@ -36,7 +36,7 @@ from openhands.server.shared import conversation_manager, server_config from openhands.server.types import AppMode from openhands.version import get_version -mcp_app = mcp_server.http_app(path='/mcp') +mcp_app = mcp_server.http_app(path='/mcp', stateless_http=True) def combine_lifespans(*lifespans): diff --git a/openhands/server/routes/mcp.py b/openhands/server/routes/mcp.py index 929c66af5b..2d541d637c 100644 --- a/openhands/server/routes/mcp.py +++ b/openhands/server/routes/mcp.py @@ -25,9 +25,7 @@ from openhands.server.user_auth import ( ) from openhands.storage.data_models.conversation_metadata import ConversationMetadata -mcp_server = FastMCP( - 'mcp', stateless_http=True, mask_error_details=True, dependencies=None -) +mcp_server = FastMCP('mcp', mask_error_details=True) HOST = f'https://{os.getenv("WEB_HOST", "app.all-hands.dev").strip()}' CONVERSATION_URL = HOST + '/conversations/{}' diff --git a/tests/unit/server/routes/test_mcp_routes.py b/tests/unit/server/routes/test_mcp_routes.py index 1a55cc0a39..8677b8c85c 100644 --- a/tests/unit/server/routes/test_mcp_routes.py +++ b/tests/unit/server/routes/test_mcp_routes.py @@ -1,3 +1,4 @@ +import warnings from unittest.mock import AsyncMock, patch import pytest @@ -7,6 +8,38 @@ from openhands.server.routes.mcp import get_conversation_link from openhands.server.types import AppMode +def test_mcp_server_no_stateless_http_deprecation_warning(): + """Test that mcp_server is created without stateless_http deprecation warning. + + This test verifies the fix for the fastmcp deprecation warning: + 'Providing `stateless_http` when creating a server is deprecated. + Provide it when calling `run` or as a global setting instead.' + + The fix moves the stateless_http parameter from FastMCP() constructor + to the http_app() method call. + """ + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always') + + # Import the mcp_server which triggers FastMCP creation + from openhands.server.routes.mcp import mcp_server + + # Check that no deprecation warning about stateless_http was raised + stateless_http_warnings = [ + warning + for warning in w + if issubclass(warning.category, DeprecationWarning) + and 'stateless_http' in str(warning.message) + ] + + assert len(stateless_http_warnings) == 0, ( + f'Unexpected stateless_http deprecation warning: {stateless_http_warnings}' + ) + + # Verify mcp_server was created successfully + assert mcp_server is not None + + @pytest.mark.asyncio async def test_get_conversation_link_non_saas_mode(): """Test get_conversation_link in non-SAAS mode."""