{"record":{"id":"6997dc13a00c3b54","repo":"BerriAI/litellm","slug":"user-does-not-have-permission-to-view-mcp-server-w","errorCode":null,"errorMessage":"User does not have permission to view mcp server with id {server_id}. You can only view mcp servers that you have access to.","messagePattern":"User does not have permission to view mcp server with id (.+?)\\. You can only view mcp servers that you have access to\\.","errorType":"http","errorClass":"HTTPException","httpStatus":403,"severity":"error","filePath":"litellm/proxy/management_endpoints/mcp_management_endpoints.py","lineNumber":1480,"sourceCode":"            )\n\n        # Implement authz restriction from requested user\n        is_admin_view: Final = _user_has_admin_view(user_api_key_dict)\n        is_restricted_virtual_key: Final = _is_restricted_virtual_key_request(user_api_key_dict)\n\n        if not is_admin_view:\n            # Perform authz check BEFORE any health check (avoid side-effects for\n            # unauthorized callers).\n            if from_db:\n                mcp_server_records: Final = await get_all_mcp_servers_for_user(prisma_client, user_api_key_dict)\n                exists = does_mcp_server_exist(mcp_server_records, server_id)\n            else:\n                # Registry/config server: use same access logic as list endpoint\n                allowed_server_ids: Final = await global_mcp_server_manager.get_allowed_mcp_servers(user_api_key_dict)\n                exists = mcp_server.server_id in allowed_server_ids\n\n            if not exists:\n                raise HTTPException(\n                    status_code=status.HTTP_403_FORBIDDEN,\n                    detail={\n                        \"error\": (\n                            f\"User does not have permission to view mcp server with id {server_id}. \"\n                            \"You can only view mcp servers that you have access to.\"\n                        )\n                    },\n                )\n\n        # At this point caller is authorized to view the server.\n        if from_db:\n            await global_mcp_server_manager.add_server(mcp_server)\n\n        # Perform health check on the server using server manager\n        try:\n            health_result: Final = await global_mcp_server_manager.health_check_server(server_id)\n            # Update the server object with health check results\n            mcp_server.status = health_result.status if health_result.status else \"unknown\"","sourceCodeStart":1462,"sourceCodeEnd":1498,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/management_endpoints/mcp_management_endpoints.py#L1462-L1498","documentation":"Returned (403) by the single MCP server fetch endpoint when the caller is not an admin-view user and the server is absent from their permitted set: for DB servers it checks get_all_mcp_servers_for_user, for registry/config servers the get_allowed_mcp_servers list. Authorization is deliberately checked before any health check so unauthorized callers cannot trigger server side-effects.","triggerScenarios":"GET /v1/mcp/server/{server_id} with a virtual key whose team/key was never granted that MCP server; a user viewing a server that belongs to another team; a non-admin key checking a server that exists but is not attached to the key, its team, or its organization.","commonSituations":"Team-scoped virtual keys used to inspect servers owned by a different team; server added to the proxy but not to any team's mcp_servers; admin assumes a regular user key can see everything admins see.","solutions":["Grant access: attach the MCP server to the team (team mcp_servers / allowed servers setting) or to the virtual key that is calling.","Use the key's own list endpoint to see which servers it can view, and only fetch those.","Use a proxy-admin key (or the master key) when an unrestricted admin view is intended."],"exampleFix":"# before: fetching a server the key cannot see\nrequests.get(f\"{PROXY}/v1/mcp/server/{server_id}\", headers={\"Authorization\": f\"Bearer {TEAM_KEY}\"})\n\n# after: only fetch servers present in this key's visible list\nvisible = requests.get(f\"{PROXY}/v1/mcp/server\", headers={\"Authorization\": f\"Bearer {TEAM_KEY}\"}).json()\nids = {s[\"server_id\"] for s in visible[\"servers\"]}\nif server_id in ids:\n    requests.get(f\"{PROXY}/v1/mcp/server/{server_id}\", headers={\"Authorization\": f\"Bearer {TEAM_KEY}\"})","handlingStrategy":"validation","validationCode":"visible = requests.get(f\"{PROXY}/v1/mcp/server\", headers={\"Authorization\": f\"Bearer {TEAM_KEY}\"}).json()[\"servers\"]\nif server_id not in {s[\"server_id\"] for s in visible}:\n    raise PermissionError(f\"{server_id} not granted to this key; attach it to the team first\")","typeGuard":null,"tryCatchPattern":"try:\n    fetch(server_id)\nexcept HTTPError as e:\n    if e.response.status_code == 403:\n        # surface 'request access' message instead of a raw failure\n        raise PermissionError(\"ask admin to grant this MCP server to your team\")\n    raise","preventionTips":["Fetch only servers present in the caller's own list response.","When provisioning a server, attach it to the teams that need it in the same change.","Use admin keys only for admin workflows, never as a workaround baked into user code."],"tags":["litellm","mcp","forbidden","authorization","teams"],"backgroundTag":"authorization-forbidden","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}