diff --git a/schema.prisma b/schema.prisma index 8a06d86b829..083b5a5156e 100644 --- a/schema.prisma +++ b/schema.prisma @@ -331,7 +331,7 @@ model LiteLLM_MCPToolsetTable { tools Json @default("[]") // [{server_id: string, tool_name: string}] created_at DateTime @default(now()) created_by String? - updated_at DateTime @updatedAt + updated_at DateTime @default(now()) @updatedAt updated_by String? } diff --git a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_toolset_scope.py b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_toolset_scope.py index 4dfd33cbbd4..c9732a53a70 100644 --- a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_toolset_scope.py +++ b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_toolset_scope.py @@ -59,7 +59,8 @@ class TestApplyToolsetScope: assert op.mcp_tool_permissions == toolset_perms @pytest.mark.asyncio - async def test_creates_object_permission_when_none(self): + async def test_admin_creates_object_permission_when_none(self): + """Admin key with object_permission=None can access any toolset.""" from litellm.proxy._experimental.mcp_server.server import _apply_toolset_scope toolset_perms = {"server-a": ["tool1"]} @@ -68,7 +69,11 @@ class TestApplyToolsetScope: "global_mcp_server_manager.resolve_toolset_tool_permissions", new=AsyncMock(return_value=toolset_perms), ): - auth = UserAPIKeyAuth(api_key="sk-test", object_permission=None) + auth = UserAPIKeyAuth( + api_key="sk-test", + user_role=LitellmUserRoles.PROXY_ADMIN, + object_permission=None, + ) result = await _apply_toolset_scope(auth, "toolset-123") op = result.object_permission @@ -76,6 +81,18 @@ class TestApplyToolsetScope: assert op.mcp_servers == ["server-a"] assert op.mcp_tool_permissions == toolset_perms + @pytest.mark.asyncio + async def test_non_admin_no_object_permission_raises_403(self): + """Non-admin key with object_permission=None is denied (no grants configured).""" + from fastapi import HTTPException + + from litellm.proxy._experimental.mcp_server.server import _apply_toolset_scope + + auth = UserAPIKeyAuth(api_key="sk-test", object_permission=None) + with pytest.raises(HTTPException) as exc_info: + await _apply_toolset_scope(auth, "toolset-123") + assert exc_info.value.status_code == 403 + class TestFetchMCPToolsetsAccess: """Tests for GET /v1/mcp/toolset access control."""