From 760bef1ab8913bba2b9291594a8405167d642a76 Mon Sep 17 00:00:00 2001 From: Edward Park Date: Fri, 7 Aug 2026 22:48:05 -0700 Subject: [PATCH] fix: distinguish public route authorization failures --- .../fastmcp/cli/deploy/horizon_client.py | 2 +- tests/cli/deploy/test_horizon_client.py | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/fastmcp_slim/fastmcp/cli/deploy/horizon_client.py b/fastmcp_slim/fastmcp/cli/deploy/horizon_client.py index 26b609e6d..f3f01553c 100644 --- a/fastmcp_slim/fastmcp/cli/deploy/horizon_client.py +++ b/fastmcp_slim/fastmcp/cli/deploy/horizon_client.py @@ -210,7 +210,7 @@ class HorizonClient: except httpx2.RequestError as exc: raise HorizonUnavailableError("The Horizon API is unavailable") from exc - if response.status_code == 401: + if authenticated and response.status_code == 401: raise HorizonUnauthorizedError("The Horizon credential is not valid") return response diff --git a/tests/cli/deploy/test_horizon_client.py b/tests/cli/deploy/test_horizon_client.py index 1b7fa0b30..a0f065400 100644 --- a/tests/cli/deploy/test_horizon_client.py +++ b/tests/cli/deploy/test_horizon_client.py @@ -213,6 +213,23 @@ async def test_protected_routes_require_a_credential() -> None: await client.get_current_user() +async def test_protected_routes_report_a_rejected_credential() -> None: + async with HorizonClient( + api_key="fmcp_invalid", + transport=mock_transport(lambda request: httpx2.Response(401)), + ) as client: + with pytest.raises(HorizonUnauthorizedError): + await client.get_current_user() + + +async def test_public_routes_do_not_report_a_missing_credential() -> None: + async with HorizonClient( + transport=mock_transport(lambda request: httpx2.Response(401)) + ) as client: + with pytest.raises(HorizonResponseError): + await client.create_device_authorization() + + async def test_invalid_responses_do_not_include_response_bodies() -> None: secret_body = "fmcp_response_secret" async with HorizonClient(