feat(infrastructure,backend,app-tauri,frontend): tools MCP workspace natifs read-only idea_workspace_map/list/read/search, activés par défaut et configurables dans les permissions MCP et les templates — #341 (QA verte)

This commit is contained in:
2026-09-12 19:17:09 +02:00
parent ea42d95f2e
commit 7b712f2b62
16 changed files with 1503 additions and 80 deletions

View File

@ -12,6 +12,7 @@ import type {
} from "@/domain";
import {
mcpToolGroupLabel,
mcpToolGroupDescription,
mcpToolGroupsForCatalogue,
mcpToolLabel,
} from "@/features/permissions/mcpToolGroups";
@ -72,6 +73,9 @@ export function TemplateEditor({
const [allowedTools, setAllowedTools] = useState<string[]>(
template?.mcpToolPermissions?.allowedTools ?? [],
);
const [mcpOverrideActive, setMcpOverrideActive] = useState(
template?.mcpToolPermissions != null,
);
const [tab, setTab] = useState<EditorTab>("edit");
const toolGroups = useMemo(
() => mcpToolGroupsForCatalogue(mcpCatalogue),
@ -103,8 +107,9 @@ export function TemplateEditor({
defaultAgentName: defaultAgentName.trim() || null,
defaultContactable,
systemPermissions: network ? { network } : null,
mcpToolPermissions:
allowedTools.length > 0 ? { allowedTools: [...allowedTools] } : null,
mcpToolPermissions: mcpOverrideActive
? { allowedTools: [...allowedTools] }
: null,
});
}
@ -299,39 +304,65 @@ export function TemplateEditor({
<h3 className="text-xs font-medium text-muted">
{tr("Permissions des outils MCP IdeA", "IdeA MCP tool permissions")}
</h3>
<span className="text-xs text-faint">{allowedTools.length} {tr("autorisé(s)", "allowed")}</span>
<span className="text-xs text-faint">
{mcpOverrideActive
? `${allowedTools.length} ${tr("autorisé(s)", "allowed")}`
: tr("Héritage du projet", "Project inheritance")}
</span>
</div>
<label className="flex items-start gap-2 text-sm text-content">
<input
type="checkbox"
aria-label={tr("Hériter des outils MCP du projet", "Inherit project MCP tools")}
checked={!mcpOverrideActive}
onChange={(event) => setMcpOverrideActive(!event.target.checked)}
disabled={busy}
className="mt-0.5 h-4 w-4 shrink-0 accent-primary"
/>
<span className="flex flex-col gap-0.5">
<span>{tr("Hériter des outils MCP du projet", "Inherit project MCP tools")}</span>
<span className="text-xs text-muted">
{tr("Le modèle utilise les outils autorisés par le projet.", "The template uses the tools allowed by the project.")}
</span>
</span>
</label>
{allMcpTools.length === 0 ? (
<p className="text-sm text-muted">{tr("Aucun outil MCP IdeA disponible.", "No IdeA MCP tool available.")}</p>
) : (
<>
{allowedTools.length === 0 && (
{mcpOverrideActive && allowedTools.length === 0 && (
<p className="text-sm text-muted">
{tr("Aucun outil MCP IdeA autorisé.", "No IdeA MCP tool allowed.")}
</p>
)}
<div className="grid gap-3 md:grid-cols-2 xl:grid-cols-3">
{toolGroups.map((group) => (
<div key={group.id} className="flex min-w-0 flex-col gap-2">
<h4 className="text-xs font-semibold text-content">{mcpToolGroupLabel(group, tr)}</h4>
{group.tools.map((tool) => (
<label
key={tool}
className="flex min-w-0 items-center gap-2 text-sm text-content/90"
>
<input
type="checkbox"
aria-label={`${tr("Outil MCP du modèle", "Template MCP tool")} ${tool}`}
checked={allowed.has(tool)}
onChange={() => toggleTool(tool)}
disabled={busy}
className="h-4 w-4 shrink-0 accent-primary"
/>
<span className="truncate">{mcpToolLabel(tool, tr)}</span>
</label>
))}
</div>
))}
{toolGroups.map((group) => {
const description = mcpToolGroupDescription(group, tr);
return (
<div key={group.id} className="flex min-w-0 flex-col gap-2">
<div className="flex flex-col gap-0.5">
<h4 className="text-xs font-semibold text-content">{mcpToolGroupLabel(group, tr)}</h4>
{description && <p className="text-xs text-muted">{description}</p>}
</div>
{group.tools.map((tool) => (
<label
key={tool}
className="flex min-w-0 items-center gap-2 text-sm text-content/90"
>
<input
type="checkbox"
aria-label={`${tr("Outil MCP du modèle", "Template MCP tool")} ${tool}`}
checked={allowed.has(tool)}
onChange={() => toggleTool(tool)}
disabled={busy || !mcpOverrideActive}
className="h-4 w-4 shrink-0 accent-primary"
/>
<span className="truncate">{mcpToolLabel(tool, tr)}</span>
</label>
))}
</div>
);
})}
</div>
</>
)}