mirror of
https://github.com/davidkaya/aryx.git
synced 2026-08-30 06:27:13 +02:00
feat: auto-discover MCP servers from project and user config files
Scan .vscode/mcp.json, .mcp.json, .copilot/mcp.json (project-level) and ~/.copilot/mcp.json (user-level) for MCP server definitions. Discovered servers require explicit user acceptance before activation. Backend: - Add ConfigScannerRegistry with per-format scanners and substitution - Add discovered tooling domain model with fingerprint-based change detection - Integrate scanning into workspace load, project add, and project selection - Merge accepted discovered MCPs into effective runtime tooling - Extend sidecar contracts with env/headers for real-world MCP configs - Add IPC channels for accept/dismiss/rescan operations Frontend: - Add DiscoveredToolingModal for reviewing pending MCP servers - Auto-show modal when pending discoveries exist on load or project switch - Add amber badge on sidebar project headers for pending discoveries - Add discovered MCP section in Settings panel with accept/dismiss/rescan - Group InlinePills tool dropdown by Workspace MCP / User MCP / Project MCP - Pass effective project tooling (including accepted discoveries) to ChatPane Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -225,6 +225,10 @@ export function InlineToolsPill({
|
||||
const enabledCount = selection.enabledMcpServerIds.length + selection.enabledLspProfileIds.length;
|
||||
const totalCount = mcpServers.length + lspProfiles.length;
|
||||
|
||||
const workspaceMcpServers = mcpServers.filter((s) => !s.id.startsWith('discovered_'));
|
||||
const discoveredUserMcpServers = mcpServers.filter((s) => s.id.startsWith('discovered_user_'));
|
||||
const discoveredProjectMcpServers = mcpServers.filter((s) => s.id.startsWith('discovered_project_'));
|
||||
|
||||
return (
|
||||
<div className="relative" ref={ref}>
|
||||
<button
|
||||
@@ -246,26 +250,29 @@ export function InlineToolsPill({
|
||||
|
||||
{open && !disabled && (
|
||||
<div className="absolute bottom-full left-0 z-40 mb-1.5 w-64 overflow-y-auto rounded-lg border border-zinc-700 bg-zinc-900 py-1 shadow-2xl">
|
||||
{mcpServers.length > 0 && (
|
||||
<div>
|
||||
<div className="px-3 pb-1 pt-2 text-[9px] font-semibold uppercase tracking-wider text-zinc-600">
|
||||
MCP Servers
|
||||
</div>
|
||||
{mcpServers.map((server) => (
|
||||
<PopoverToggleRow
|
||||
detail={server.transport === 'local' ? server.command : server.url}
|
||||
enabled={selection.enabledMcpServerIds.includes(server.id)}
|
||||
key={server.id}
|
||||
label={server.name}
|
||||
onToggle={() =>
|
||||
onToggle({
|
||||
...selection,
|
||||
enabledMcpServerIds: toggleInArray(selection.enabledMcpServerIds, server.id),
|
||||
})
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
{workspaceMcpServers.length > 0 && (
|
||||
<McpServerGroup
|
||||
label="Workspace MCP"
|
||||
onToggle={onToggle}
|
||||
selection={selection}
|
||||
servers={workspaceMcpServers}
|
||||
/>
|
||||
)}
|
||||
{discoveredUserMcpServers.length > 0 && (
|
||||
<McpServerGroup
|
||||
label="User MCP"
|
||||
onToggle={onToggle}
|
||||
selection={selection}
|
||||
servers={discoveredUserMcpServers}
|
||||
/>
|
||||
)}
|
||||
{discoveredProjectMcpServers.length > 0 && (
|
||||
<McpServerGroup
|
||||
label="Project MCP"
|
||||
onToggle={onToggle}
|
||||
selection={selection}
|
||||
servers={discoveredProjectMcpServers}
|
||||
/>
|
||||
)}
|
||||
{lspProfiles.length > 0 && (
|
||||
<div>
|
||||
@@ -294,6 +301,40 @@ export function InlineToolsPill({
|
||||
);
|
||||
}
|
||||
|
||||
function McpServerGroup({
|
||||
label,
|
||||
servers,
|
||||
selection,
|
||||
onToggle,
|
||||
}: {
|
||||
label: string;
|
||||
servers: ReadonlyArray<McpServerDefinition>;
|
||||
selection: SessionToolingSelection;
|
||||
onToggle: (selection: SessionToolingSelection) => void;
|
||||
}) {
|
||||
return (
|
||||
<div>
|
||||
<div className="px-3 pb-1 pt-2 text-[9px] font-semibold uppercase tracking-wider text-zinc-600">
|
||||
{label}
|
||||
</div>
|
||||
{servers.map((server) => (
|
||||
<PopoverToggleRow
|
||||
detail={server.transport === 'local' ? server.command : server.url}
|
||||
enabled={selection.enabledMcpServerIds.includes(server.id)}
|
||||
key={server.id}
|
||||
label={server.name}
|
||||
onToggle={() =>
|
||||
onToggle({
|
||||
...selection,
|
||||
enabledMcpServerIds: toggleInArray(selection.enabledMcpServerIds, server.id),
|
||||
})
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/* ── InlineApprovalPill ────────────────────────────────────── */
|
||||
|
||||
const approvalKindOrder: ApprovalToolKind[] = ['builtin', 'mcp', 'lsp', 'mixed'];
|
||||
|
||||
Reference in New Issue
Block a user