feat(frontend): surface MCP tool permissions per agent — Permissions panel (#82 lot UX/F)
Adds the "Tools MCP IdeA" tab to the project Permissions panel, alongside the existing "Système" (file/command) tab. Lets the user grant/revoke MCP tool capabilities per agent or project-wide default, grouped by domain (Lecture projet, Lecture tickets, Délégation agents, Contexte et mémoire, Tickets, Travail et exécution, Skills) instead of a flat 25-checkbox list, per the UX conception in carnet #82. - domain/ports/adapters (Tauri, HTTP, mock): wire get_mcp_tool_permissions, update_project_mcp_tool_permissions, update_agent_mcp_tool_permissions (already merged backend API, #82 lots B1-B4) onto PermissionGateway. - useMcpToolPermissions: view-model owning the durable MCP tool policy document, distinct from the file/command permissions in usePermissions. - McpToolPermissionsPanel: target selector (Défaut projet + agents with Hérité/Override badges) and grouped editor — inherited agents are read-only until "Créer un override" (prefilled with the effective allowlist), per-row Ajouté/Retiré diffing against the project default, inline confirmation before granting a write tool at project-default level, and unsaved-draft protection on target change. - mcpToolGroups.ts: presentational-only domain grouping and short French labels — the read/write classification itself always comes from the backend-provided catalogue, never hardcoded here. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
111
frontend/src/features/permissions/mcpToolGroups.ts
Normal file
111
frontend/src/features/permissions/mcpToolGroups.ts
Normal file
@ -0,0 +1,111 @@
|
||||
/**
|
||||
* Presentational grouping of the MCP tool catalogue (ticket #82).
|
||||
*
|
||||
* Purely a frontend display concern: which domain a tool "belongs to" for the
|
||||
* grouped/collapsible editor, and its short French label. The read/write
|
||||
* classification stays backend-canonical — always read from the
|
||||
* {@link McpToolCatalogue} the API returns, never re-derived here.
|
||||
*/
|
||||
|
||||
export interface McpToolGroupDef {
|
||||
id: string;
|
||||
label: string;
|
||||
tools: string[];
|
||||
}
|
||||
|
||||
/** Domain groups, in display order (carnet #82 — Conception UX/F). */
|
||||
export const MCP_TOOL_GROUPS: McpToolGroupDef[] = [
|
||||
{
|
||||
id: "readProject",
|
||||
label: "Lecture projet",
|
||||
tools: [
|
||||
"idea_list_agents",
|
||||
"idea_context_read",
|
||||
"idea_memory_read",
|
||||
"idea_skill_read",
|
||||
"idea_workstate_read",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "readTickets",
|
||||
label: "Lecture tickets",
|
||||
tools: [
|
||||
"idea_ticket_read",
|
||||
"idea_ticket_list",
|
||||
"idea_ticket_read_carnet",
|
||||
"idea_sprint_list",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "delegation",
|
||||
label: "Délégation agents",
|
||||
tools: ["idea_ask_agent", "idea_launch_agent", "idea_stop_agent"],
|
||||
},
|
||||
{
|
||||
id: "contextMemory",
|
||||
label: "Contexte et mémoire",
|
||||
tools: ["idea_update_context", "idea_context_propose", "idea_memory_write"],
|
||||
},
|
||||
{
|
||||
id: "tickets",
|
||||
label: "Tickets",
|
||||
tools: [
|
||||
"idea_ticket_create",
|
||||
"idea_ticket_update",
|
||||
"idea_ticket_update_status",
|
||||
"idea_ticket_update_priority",
|
||||
"idea_ticket_update_carnet",
|
||||
"idea_ticket_link",
|
||||
"idea_ticket_unlink",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "work",
|
||||
label: "Travail et exécution",
|
||||
tools: ["idea_run_in_background", "idea_workstate_set"],
|
||||
},
|
||||
{
|
||||
id: "skills",
|
||||
label: "Skills",
|
||||
tools: ["idea_create_skill"],
|
||||
},
|
||||
];
|
||||
|
||||
/** Short, human French label per exact MCP tool name. */
|
||||
export const MCP_TOOL_LABELS: Record<string, string> = {
|
||||
idea_list_agents: "Lister les agents",
|
||||
idea_context_read: "Lire le contexte d'un agent",
|
||||
idea_memory_read: "Lire la mémoire projet",
|
||||
idea_skill_read: "Lire un skill",
|
||||
idea_workstate_read: "Lire l'état de travail",
|
||||
idea_ticket_read: "Lire un ticket",
|
||||
idea_ticket_list: "Lister les tickets",
|
||||
idea_ticket_read_carnet: "Lire le carnet d'un ticket",
|
||||
idea_sprint_list: "Lister les sprints",
|
||||
idea_ask_agent: "Déléguer à un agent",
|
||||
idea_launch_agent: "Lancer un agent",
|
||||
idea_stop_agent: "Arrêter un agent",
|
||||
idea_update_context: "Modifier le contexte d'un agent",
|
||||
idea_context_propose: "Proposer un contexte",
|
||||
idea_memory_write: "Écrire la mémoire projet",
|
||||
idea_workstate_set: "Écrire l'état de travail",
|
||||
idea_create_skill: "Créer un skill",
|
||||
idea_ticket_create: "Créer un ticket",
|
||||
idea_ticket_update: "Modifier un ticket",
|
||||
idea_ticket_update_status: "Modifier le statut d'un ticket",
|
||||
idea_ticket_update_priority: "Modifier la priorité d'un ticket",
|
||||
idea_ticket_update_carnet: "Modifier le carnet d'un ticket",
|
||||
idea_ticket_link: "Lier des tickets",
|
||||
idea_ticket_unlink: "Délier des tickets",
|
||||
idea_run_in_background: "Exécuter une commande en arrière-plan",
|
||||
};
|
||||
|
||||
/** Short human label for `tool`, falling back to the exact name if unmapped. */
|
||||
export function mcpToolLabel(tool: string): string {
|
||||
return MCP_TOOL_LABELS[tool] ?? tool;
|
||||
}
|
||||
|
||||
/** The group a tool belongs to, or `undefined` if not locally mapped. */
|
||||
export function mcpToolGroupId(tool: string): string | undefined {
|
||||
return MCP_TOOL_GROUPS.find((group) => group.tools.includes(tool))?.id;
|
||||
}
|
||||
Reference in New Issue
Block a user