Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
08dcdc0
feat: MCP settings paget pu
adityathebe Apr 6, 2026
3b771f0
chore: remove playbook and view table for MCP
adityathebe Apr 6, 2026
8574f7c
chore: refactor file paths
adityathebe Apr 6, 2026
7371529
fix(permissions): fix SubjectSelectorModal bugs and UX issues
adityathebe Apr 6, 2026
1c133c0
fix(permissions): improve PermissionAccessCard UX and correctness
adityathebe Apr 6, 2026
d65d333
feat(mcp): redesign overview subject access controls
adityathebe Apr 6, 2026
6e4d24c
fix(mcp): use playbook object selectors and dedupe overrides
adityathebe Apr 6, 2026
c02acb5
fix(mcp): centralize and enforce mcp settings source
adityathebe Apr 6, 2026
52b637a
fix(mcp): resolve ambiguous view-name permission matching
adityathebe Apr 6, 2026
3a3d0d7
chore: refactor access card -> permission matching
adityathebe Apr 6, 2026
7e321fa
fix(mcp): centralize tab-body loading and avoid blank switch
adityathebe Apr 7, 2026
47c2292
fix(mcp): cap card subjects and scope queries to mcp source
adityathebe Apr 7, 2026
f1da0c9
feat(mcp): show effective access verdicts in subject viewer
adityathebe Apr 7, 2026
6d366b1
modify subject selector access modal
adityathebe Apr 7, 2026
ed701bc
remove card design
adityathebe Apr 7, 2026
10a6a54
feat(permissions): compact MCP access rows and add switch sizes
adityathebe Apr 7, 2026
ce68b99
feat(mcp): move subject selector to sticky side panel
adityathebe Apr 7, 2026
1374bd0
fix: mcp overview page
adityathebe Apr 7, 2026
50e48db
fix: width of cards
adityathebe Apr 7, 2026
22ab392
fix: type error in test
adityathebe Apr 7, 2026
df187c5
fix: review
adityathebe Apr 7, 2026
f9c3b86
chore: refactor
adityathebe Apr 7, 2026
9817527
feat: Display setup MCP token button in mcp settings
adityathebe Apr 7, 2026
cf3810d
fix(permissions): address PR review issues in MCP permission UI
adityathebe Apr 7, 2026
3e2fd4b
fix(permissions): handle missing subjects and always refetch overrides
adityathebe Apr 7, 2026
e0ef0f4
fix: show MCP token creation error inside the modal
adityathebe Apr 8, 2026
5e7c4c6
Add playbook permission access check modal with shared resource selector
adityathebe Apr 9, 2026
b651f60
fix(permissions): allow mouse selection in access-check modal
adityathebe Apr 9, 2026
88789b4
refactor(permissions): centralize subject avatar rendering
adityathebe Apr 9, 2026
cf23edc
fix: highlight selected rows
adityathebe Apr 9, 2026
b0684f4
feat: grouping playbooks by category
adityathebe Apr 9, 2026
53b6046
fix(mcp-permissions): improve subject selector switch feedback
adityathebe Apr 9, 2026
665d568
feat(mcp): add check access tab with conditional resources
adityathebe Apr 9, 2026
2d31026
feat(permissions): support access-token subjects in selector UI
adityathebe Apr 9, 2026
39931ea
fix(mcp): reduce subject avatar size in overview list
adityathebe Apr 9, 2026
65b7987
feat: Subject -> mcp settings
adityathebe Apr 10, 2026
77a5fa9
parity between playbooks and users page
adityathebe Apr 10, 2026
6ee4764
feat(permissions): add effective access checks across MCP tabs
adityathebe Apr 13, 2026
76c82b6
fix(mcp): reuse tokens table on overview without layout gap
adityathebe Apr 13, 2026
963cc7e
fix(permissions): align selector panel bulk-lock UX
adityathebe Apr 13, 2026
d3566b2
fix(permissions): match effective access and mode control widths
adityathebe Apr 13, 2026
9fa7671
sorting
adityathebe Apr 13, 2026
bba56ba
sorting animation
adityathebe Apr 13, 2026
dabc0ff
change sort menu
adityathebe Apr 13, 2026
975c199
feat(permissions): add subject sort controls with direction toggle
adityathebe Apr 13, 2026
d320fee
feat(permissions): split resource selector lists by type
adityathebe Apr 13, 2026
8d8bf56
perf(permissions): localize list sorting to reduce flicker
adityathebe Apr 13, 2026
edcf937
feat(permissions): add subjects tab with shared subject panel
adityathebe Apr 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 102 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-separator": "^1.1.8",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-tooltip": "^1.2.8",
"@radix-ui/react-use-controllable-state": "^1.2.2",
"@storybook/client-api": "^7.6.17",
Expand Down
72 changes: 72 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ import { UserAccessStateContextProvider } from "./context/UserAccessContext/User
import { tables } from "./context/UserAccessContext/permissions";

import { PermissionsPage } from "./pages/Settings/PermissionsPage";
import { PermissionsSubjectsPage } from "./pages/Settings/PermissionsSubjectsPage";
import McpOverviewPage from "./pages/Settings/mcp/McpOverviewPage";
import McpPlaybooksPage from "./pages/Settings/mcp/McpPlaybooksPage";
import McpViewsPage from "./pages/Settings/mcp/McpViewsPage";
import McpSubjectAccessPage from "./pages/Settings/mcp/McpSubjectAccessPage";
import McpCheckAccessPage from "./pages/Settings/mcp/McpCheckAccessPage";
import ScopesPage from "./pages/Settings/ScopesPage";
import { features } from "./services/permissions/features";
import { getViewsForSidebar, ViewSummary } from "./api/services/views";
Expand Down Expand Up @@ -427,6 +433,15 @@ const settingsNav: SettingsNavigationItems = {
featureName: features["settings.job_history"],
resourceName: tables.database
},
{
name: "MCP",
href: "/settings/mcp",
icon: ({ className }: { className: string }) => (
<Icon name="mcp" className={`${className} [&_path]:!fill-white`} />
),
featureName: features["settings.mcp"],
resourceName: tables.database
},
{
name: "Feature Flags",
href: "/settings/feature-flags",
Expand Down Expand Up @@ -735,6 +750,14 @@ export function IncidentManagerRoutes({ sidebar }: { sidebar: ReactNode }) {
"read"
)}
/>
<Route
path="permissions/subjects"
element={withAuthorizationAccessCheck(
<PermissionsSubjectsPage />,
tables.permissions,
"read"
)}
/>
<Route
path="scopes"
element={withAuthorizationAccessCheck(
Expand Down Expand Up @@ -841,6 +864,55 @@ export function IncidentManagerRoutes({ sidebar }: { sidebar: ReactNode }) {
/>
</Route>

<Route path="mcp">
<Route index element={<Navigate to="/settings/mcp/overview" />} />
<Route
path="overview"
element={withAuthorizationAccessCheck(
<McpOverviewPage />,
tables.database,
"write",
true
)}
/>
<Route
path="playbooks"
element={withAuthorizationAccessCheck(
<McpPlaybooksPage />,
tables.database,
"write",
true
)}
/>
<Route
path="views"
element={withAuthorizationAccessCheck(
<McpViewsPage />,
tables.database,
"write",
true
)}
/>
<Route
path="subject-access"
element={withAuthorizationAccessCheck(
<McpSubjectAccessPage />,
tables.database,
"write",
true
)}
/>
<Route
path="check-access"
element={withAuthorizationAccessCheck(
<McpCheckAccessPage />,
tables.database,
"write",
true
)}
/>
</Route>

{settingsNav.submenu
.filter((v) => (v as SchemaResourceType).table)
.map((x) => {
Expand Down
93 changes: 92 additions & 1 deletion src/api/services/permissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,15 @@ export type FetchPermissionsInput = {
connectionId?: string;
subject?: string;
action?: string;
subject_type?: "playbook" | "team" | "person" | "notification" | "component";
direction?: "inbound" | "outbound";
subject_type?:
| "playbook"
| "team"
| "person"
| "notification"
| "component"
| "role"
| "access_token_person";
};

function composeQueryParamForFetchPermissions({
Expand Down Expand Up @@ -149,3 +156,87 @@ export function recheckPermission(id: string) {
error: null
});
}

// Source marker used by the MCP Settings UI for permissions it creates/manages.
export const MCP_SETTINGS_PERMISSION_SOURCE = "mcp_settings" as const;

export async function fetchMcpRunPermissions() {
const response = await IncidentCommander.get<PermissionsSummary[] | null>(
`/permissions_summary?select=*&action=eq.mcp:run&source=eq.${MCP_SETTINGS_PERMISSION_SOURCE}&deleted_at=is.null&limit=5000`
);

return response.data ?? [];
}

export async function fetchMcpUserPermissions() {
const response = await IncidentCommander.get<PermissionsSummary[] | null>(
`/permissions_summary?select=*&action=eq.mcp:use&object=eq.mcp&source=eq.${MCP_SETTINGS_PERMISSION_SOURCE}&deleted_at=is.null&limit=5000`
);

return response.data ?? [];
Comment thread
adityathebe marked this conversation as resolved.
}

export type PermissionSubject = {
id: string;
name: string;
type:
| "team"
| "permission_subject_group"
| "person"
| "role"
| "access_token_person";
owner?: string | null;
};

export async function fetchPermissionSubjectsPaginated({
search = "",
pageIndex = 0,
pageSize = 20
}: {
search?: string;
pageIndex?: number;
pageSize?: number;
}) {
const query = search.trim();

let url = "/permission_subjects?select=id,name,type,owner&order=name.asc";
url += `&limit=${pageSize}&offset=${pageIndex * pageSize}`;

if (query) {
url += `&name=ilike.*${encodeURIComponent(query)}*`;
}

return resolvePostGrestRequestWithPagination<PermissionSubject[]>(
IncidentCommander.get(url, {
headers: {
Prefer: "count=exact"
}
})
);
}

export async function fetchPermissionSubjectsByIds(ids: string[]) {
if (ids.length === 0) {
return [];
}
const response = await IncidentCommander.get<PermissionSubject[] | null>(
`/permission_subjects?select=id,name,type,owner&id=in.(${ids.join(",")})&limit=${ids.length}`
);
return response.data ?? [];
}

async function fetchPermissionSubjectsWithOrder(order: string) {
const response = await IncidentCommander.get<PermissionSubject[] | null>(
`/permission_subjects?select=id,name,type,owner&order=${order}&limit=5000`
);

return response.data ?? [];
}

export async function fetchPermissionSubjects() {
return fetchPermissionSubjectsWithOrder("name.asc");
}

export async function fetchAllPermissionSubjects() {
return fetchPermissionSubjectsWithOrder("type.asc,name.asc");
}
2 changes: 1 addition & 1 deletion src/api/services/playbooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export async function getAllPlaybooksSpecs() {

export async function getAllPlaybookNames() {
const res = await IncidentCommander.get<PlaybookNames[] | null>(
`/playbook_names?select=id,name,title,icon,category&order=title.asc`
`/playbook_names?select=id,name,namespace,title,icon,category,description&order=title.asc`
);
return res.data ?? [];
}
Expand Down
Loading
Loading