Shows the owning team alias resolved from team_id. Global servers
(team_id=null) display "Global". Header includes info icon explaining
that only servers from teams with mcp:read permission are visible.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The list endpoint returns an empty list (not 403) when a user has no
MCP servers available. For internal users, show a message suggesting
they may need mcp:read permission or team MCP server assignments.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace "Missing required authentication parameters" with a loading
state. When the MCP servers fetch fails (e.g. 403), show a clear
error message with steps on how to get mcp:read permission.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a proxy admin deleted an MCP server, team_id was None so
remove_mcp_server_from_team was skipped, leaving stale server IDs
in the team's ObjectPermissionTable. Now fetches the server's
team_id before deletion to ensure cleanup.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
_invalidate_team_cache only cleared the team object cache but not the
ObjectPermissionTable cache. After add_mcp_server_to_team, the team
was re-fetched from DB but its object_permission was served from stale
cache, causing newly created servers to not appear in the list.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move team_id clear-to-null and ObjectPermissionTable sync before
registry reload so the cache reflects the new ownership state.
Also update the response object when clearing team_id to null.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Make search_tools String[]? (nullable) in all 3 schema.prisma files
so Prisma preserves NULL from DB instead of coercing to []
- Remove get_permitted_search_tool_names (dead code — never called
from any production path) and its tests
- Add -> bool return type annotation to _can_object_call_search_tools
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Revert MCP management endpoint changes: team-scoped CRUD depends on
check_member_permission, add_mcp_server_to_team, remove_mcp_server_from_team
which exist only in the base branch, not main. Importing them crashes
all MCP endpoints on main.
- Revert ObjectPermissionTable default changes for pre-existing fields
(mcp_servers, mcp_access_groups, vector_stores, agents, agent_access_groups)
back to [] to avoid backwards-incompatible behavior change. Only
search_tools (new field) uses None default.
- Restore vector store access check: [] = allow all (existing behavior)
- Restore vector store test assertion
- Revert common_utils.py inline import changes (infrastructure not in scope)
- Add ValueError fallback to get_search_tool_access_error_type_for_object
for unrecognized object_type values
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Migration: remove DEFAULT ARRAY[]::TEXT[] so existing rows get NULL
(NULL = all access) instead of [] (no access)
- Schema: remove @default([]) for search_tools in all 3 schema.prisma files
- Use cached get_object_permission instead of raw DB queries in
search_tool_access_check and _get_allowed_search_tool_names
- Reject requests with missing search_tool_name (400) instead of
silently bypassing access control
- Fix vector store test: [] now correctly denies access (not allows)
- Update search_tool_access_check tests to mock get_object_permission
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Change all ObjectPermissionTable array field defaults from [] to None
(None = all access / no restriction, [] = no access)
- Update vector store access check: [] now denies access instead of allowing all
- Add team-scoped MCP server management (create/update/delete) with
granular permissions (mcp:create, mcp:update, mcp:delete)
- Auto-assign created servers to team's ObjectPermissionTable
- Auto-remove deleted servers from team's ObjectPermissionTable
- Fix unreachable special MCP server name guard in add_mcp_server
- Fix server_id validation ordering in edit_mcp_server
- Fix description typo on PUT /server endpoint
- Move inline imports to module level in common_utils.py (CLAUDE.md)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix double error handling in getTeamPermissionsCall: return empty data
on HTTP error instead of calling handleError + throwing, preventing
duplicate error notifications
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix double error handling in getTeamPermissionsCall: return empty data
on HTTP error instead of calling handleError + throwing, preventing
duplicate error notifications
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix unknown permissions duplication: seed selected state with only known
permissions so existingUnknown and selected are disjoint on save
- Disable Add MCP Server button for non-admins without a team selected,
show tooltip explaining they need to select a team first
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Separate save failure from refresh failure: close drawer after successful
save even if teamInfoCall refresh fails
- Preserve unknown permissions not in availablePermissions when saving,
preventing silent drops of permissions from newer backend versions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Type onUpdate as () => Promise<void> and await it before closing drawer
- Replace accessToken! assertion with explicit null guard
- Gate fetchAvailableTeamMemberPermissions behind canEditTeam check
- Pass team_id for admins too when a team is selected in the filter
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add UI support for the MCP team management permissions introduced in PR #24266.
- Add MemberPermissionsDrawer component (Ant Design Drawer) for managing
per-member MCP permissions (mcp:read, mcp:create, mcp:update, mcp:delete)
- Add permissions button to team member table actions column
- Fetch available permissions from GET /team/available_permissions
- Pass extra_permissions in team member update API calls
- Allow all users to create MCP servers directly (backend enforces permissions)
- Pass team_id when non-admin users create MCP servers
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move callbacks outside try/catch so only mutation errors are caught,
not errors from onVersionCreated/onVersionStatusUpdated callbacks
- Replace policyName! non-null assertion with DISABLED_POLICY_KEY
sentinel to avoid undefined in cache keys when query is disabled
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add PolicyVersionsData type for select output; specify TData generic
so consumers get Policy[] (not Policy[] | undefined) for versions
- Remove empty-string queryKey fallback — use policyName! since
enabled:false prevents fetch when policyName is null
- Add cache invalidation tests for both mutation hooks
- Add explanatory comment for ?? [] fallback in component
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Make PolicyVersionsResponse.versions optional (Policy[] | undefined)
to match real API shape — select fallback handles normalization
- Add policyName guard to useUpdatePolicyVersionStatus mutationFn
to fail loudly instead of silently skipping cache invalidation
- Add test for null policyName in updateStatus mutation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Wrap mutateAsync calls in try/catch to swallow re-thrown errors
(notifications already handled by onError in mutation hooks)
- Use isLoading instead of isPending for version loading state —
isPending is true when query is disabled with no cache, isLoading
is only true during active fetches (matches original behavior)
- Add isLoading assertions to disabled-state tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move extra_permissions validation before budget upsert to prevent
partial DB writes on validation failure
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Revert PUT /v1/mcp/server status code to 202 (backwards-compatible)
- Strengthen Member.extra_permissions validator to check VALID_PERMISSIONS
- Invalidate team cache after add/remove_mcp_server_to_team
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Handle ValueError on team-link failure as 400 (orphaned server fix)
- Wrap delete's remove_from_team in try/except (prevent 500 after
successful delete)
- Revert DELETE status code to 202 (backwards-compatible)
- Add extra_permissions to TeamMemberUpdateResponse
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Wrap add/remove_mcp_server_to_team in DB transactions (race condition fix)
- Consolidate role + extra_permissions into single DB write (atomicity)
- Remove silent try/except on team linking (surface errors to caller)
- Add email fallback to _find_member_in_team (email-only members)
- Add None guard on payload.server_id in update endpoint
- Add field_validator on Member.extra_permissions (resource:action format)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ensures permission changes take effect immediately instead of waiting
for cache TTL expiry.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Allow team admins and permissioned members to manage MCP servers scoped
to their team, laying groundwork for full Permission Strings RBAC.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace useEffect + useState fetch pattern for policy version management
with React Query hooks (useQuery + useMutation), following established
codebase conventions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The special name check (all_team_servers, all_proxy_servers) was an elif
after the server_id-is-not-None check, making it unreachable since special
names are non-None strings. Split into separate if blocks so the special
name guard runs before the duplicate-ID check.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>