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:
David Kaya
2026-03-25 21:54:06 +01:00
co-authored by Copilot
parent 08a1132d86
commit e5878ba9e8
27 changed files with 2466 additions and 45 deletions
+20
View File
@@ -70,6 +70,23 @@ export interface SaveLspProfileInput {
profile: LspProfileDefinition;
}
export type DiscoveredToolingResolution = 'accept' | 'dismiss';
export interface RescanProjectConfigsInput {
projectId: string;
}
export interface ResolveProjectDiscoveredToolingInput {
projectId: string;
serverIds: string[];
resolution: DiscoveredToolingResolution;
}
export interface ResolveWorkspaceDiscoveredToolingInput {
serverIds: string[];
resolution: DiscoveredToolingResolution;
}
export interface UpdateSessionToolingInput extends SessionToolingSelection {
sessionId: string;
}
@@ -85,7 +102,10 @@ export interface ElectronApi {
loadWorkspace(): Promise<WorkspaceState>;
addProject(): Promise<WorkspaceState>;
removeProject(projectId: string): Promise<WorkspaceState>;
resolveWorkspaceDiscoveredTooling(input: ResolveWorkspaceDiscoveredToolingInput): Promise<WorkspaceState>;
refreshProjectGitContext(projectId?: string): Promise<WorkspaceState>;
rescanProjectConfigs(input: RescanProjectConfigsInput): Promise<WorkspaceState>;
resolveProjectDiscoveredTooling(input: ResolveProjectDiscoveredToolingInput): Promise<WorkspaceState>;
savePattern(input: SavePatternInput): Promise<WorkspaceState>;
deletePattern(patternId: string): Promise<WorkspaceState>;
saveMcpServer(input: SaveMcpServerInput): Promise<WorkspaceState>;