From 4ac025da09a9fca02007989b948412c56ed233bd Mon Sep 17 00:00:00 2001 From: Zamil Majdy Date: Tue, 10 Feb 2026 22:22:38 +0400 Subject: [PATCH] fix(backend/mcp): Fix test_routes.py tests and refine exception handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - discover_tools: Keep generic Exception catch → 502 for MCP connectivity errors - mcp_oauth_callback: Add targeted exception handler for token exchange → 400 - test_routes: Fix discover_auth_server_metadata mock for no-OAuth-support case - oauth.py: Auto-formatting only --- .../backend/backend/api/features/mcp/routes.py | 17 ++++++++++++++--- .../backend/api/features/mcp/test_routes.py | 1 + .../backend/backend/blocks/mcp/oauth.py | 8 ++------ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/autogpt_platform/backend/backend/api/features/mcp/routes.py b/autogpt_platform/backend/backend/api/features/mcp/routes.py index a038073c49..2c2d9f064c 100644 --- a/autogpt_platform/backend/backend/api/features/mcp/routes.py +++ b/autogpt_platform/backend/backend/api/features/mcp/routes.py @@ -120,6 +120,11 @@ async def discover_tools( raise fastapi.HTTPException(status_code=502, detail=str(e)) except MCPClientError as e: raise fastapi.HTTPException(status_code=502, detail=str(e)) + except Exception as e: + raise fastapi.HTTPException( + status_code=502, + detail=f"Failed to connect to MCP server: {e}", + ) return DiscoverToolsResponse( tools=[ @@ -316,9 +321,15 @@ async def mcp_oauth_callback( resource_url=meta.get("resource_url"), ) - credentials = await handler.exchange_code_for_tokens( - request.code, valid_state.scopes, valid_state.code_verifier - ) + try: + credentials = await handler.exchange_code_for_tokens( + request.code, valid_state.scopes, valid_state.code_verifier + ) + except Exception as e: + raise fastapi.HTTPException( + status_code=400, + detail=f"OAuth token exchange failed: {e}", + ) # Enrich credential metadata for future lookup and token refresh if credentials.metadata is None: diff --git a/autogpt_platform/backend/backend/api/features/mcp/test_routes.py b/autogpt_platform/backend/backend/api/features/mcp/test_routes.py index 92cc2f332b..1006bb774e 100644 --- a/autogpt_platform/backend/backend/api/features/mcp/test_routes.py +++ b/autogpt_platform/backend/backend/api/features/mcp/test_routes.py @@ -239,6 +239,7 @@ class TestOAuthLogin: with patch("backend.api.features.mcp.routes.MCPClient") as MockClient: instance = MockClient.return_value instance.discover_auth = AsyncMock(return_value=None) + instance.discover_auth_server_metadata = AsyncMock(return_value=None) response = client.post( "/oauth/login", diff --git a/autogpt_platform/backend/backend/blocks/mcp/oauth.py b/autogpt_platform/backend/backend/blocks/mcp/oauth.py index f49444b4a7..2228336cd3 100644 --- a/autogpt_platform/backend/backend/blocks/mcp/oauth.py +++ b/autogpt_platform/backend/backend/blocks/mcp/oauth.py @@ -110,9 +110,7 @@ class MCPOAuthHandler(BaseOAuthHandler): ) if "access_token" not in tokens: - raise RuntimeError( - "OAuth token response missing 'access_token' field" - ) + raise RuntimeError("OAuth token response missing 'access_token' field") now = int(time.time()) expires_in = tokens.get("expires_in") @@ -164,9 +162,7 @@ class MCPOAuthHandler(BaseOAuthHandler): ) if "access_token" not in tokens: - raise RuntimeError( - "OAuth refresh response missing 'access_token' field" - ) + raise RuntimeError("OAuth refresh response missing 'access_token' field") now = int(time.time()) expires_in = tokens.get("expires_in")