{"record":{"id":"1349f6bbbbdee913","repo":"BerriAI/litellm","slug":"user-does-not-have-permission-to-test-mcp-server-c","errorCode":null,"errorMessage":"User does not have permission to test MCP server connections. Only PROXY_ADMIN users can perform this action.","messagePattern":"User does not have permission to test MCP server connections\\. Only PROXY_ADMIN users can perform this action\\.","errorType":"http","errorClass":"HTTPException","httpStatus":403,"severity":"error","filePath":"litellm/proxy/_experimental/mcp_server/rest_endpoints.py","lineNumber":1326,"sourceCode":"        except Exception as e:\n            verbose_logger.error(\"Error previewing OpenAPI tools: %s\", e, exc_info=True)\n            return {\n                \"tools\": [],\n                \"error\": True,\n                \"message\": f\"Failed to load OpenAPI spec: {e}\",\n            }\n\n    @router.post(\"/test/connection\", dependencies=[Depends(user_api_key_auth)])\n    async def test_connection(\n        request: Request,\n        new_mcp_server_request: NewMCPServerRequest,\n        user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),\n    ):\n        \"\"\"\n        Test if we can connect to the provided MCP server before adding it\n        \"\"\"\n        if LitellmUserRoles.PROXY_ADMIN != user_api_key_dict.user_role:\n            raise HTTPException(\n                status_code=status.HTTP_403_FORBIDDEN,\n                detail={\n                    \"error\": \"User does not have permission to test MCP server connections. Only PROXY_ADMIN users can perform this action.\"\n                },\n            )\n\n        async def _test_connection_operation(client):\n            async def _noop(session):\n                return \"ok\"\n\n            await client.run_with_session(_noop)\n            return {\"status\": \"ok\"}\n\n        return await _execute_with_mcp_client(\n            new_mcp_server_request,\n            _test_connection_operation,\n            raw_headers=_safe_get_request_headers(request),\n        )","sourceCodeStart":1308,"sourceCodeEnd":1344,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/_experimental/mcp_server/rest_endpoints.py#L1308-L1344","documentation":"POST /mcp-rest/test/connection lets an admin pre-flight connectivity to an MCP server before registering it. Because it makes the proxy connect to arbitrary hosts, it is restricted: any caller whose user_api_key_dict.user_role is not PROXY_ADMIN gets HTTP 403 with this message.","triggerScenarios":"Calling POST /mcp-rest/test/connection with an internal-user, team, or external-tester virtual key; scripts or CI smoke tests that use a non-admin key against this endpoint.","commonSituations":"Teams automating MCP server onboarding with their own keys; dashboards calling the endpoint on behalf of non-admin users; service accounts created for testing.","solutions":["Call the endpoint with a key whose user has the PROXY_ADMIN role.","Grant PROXY_ADMIN to the intended user in the admin UI (Internal Users → edit → role) and retry.","If non-admin onboarding must be supported, expose your own wrapper endpoint that runs with an admin service account."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"async def can_test_connections(client: httpx.AsyncClient) -> bool:\n    info = (await client.get(f\"{base}/key/info\")).json()\n    return info.get(\"key_info\", {}).get(\"user_role\") == \"proxy_admin\"","typeGuard":"def is_proxy_admin_key(key_info: dict) -> bool:\n    return key_info.get(\"user_role\") == \"proxy_admin\"","tryCatchPattern":"except httpx.HTTPStatusError as e:\n    if e.response.status_code == 403 and \"PROXY_ADMIN\" in e.response.text:\n        raise PermissionError(\"test/connection requires a PROXY_ADMIN key\") from e\n    raise","preventionTips":["Check /key/info for user_role == proxy_admin before calling admin-only MCP test endpoints.","Keep a dedicated admin key for onboarding scripts; never reuse team keys for these calls."],"tags":["mcp","authorization","http-403","admin-only"],"backgroundTag":"permission-denied-403","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-24T22:17:12.610Z"}