Add MCP support (#1028)

This commit is contained in:
Will Chen
2025-09-19 15:43:39 -07:00
committed by GitHub
parent 7b160b7d0b
commit 6d3c397d40
39 changed files with 3865 additions and 650 deletions

View File

@@ -63,6 +63,8 @@ import type {
PromptDto,
CreatePromptParamsDto,
UpdatePromptParamsDto,
McpServerUpdate,
CreateMcpServer,
} from "./ipc_types";
import type { Template } from "../shared/templates";
import type {
@@ -119,11 +121,13 @@ export class IpcClient {
onError: (error: string) => void;
}
>;
private mcpConsentHandlers: Map<string, (payload: any) => void>;
private constructor() {
this.ipcRenderer = (window as any).electron.ipcRenderer as IpcRenderer;
this.chatStreams = new Map();
this.appStreams = new Map();
this.helpStreams = new Map();
this.mcpConsentHandlers = new Map();
// Set up listeners for stream events
this.ipcRenderer.on("chat:response:chunk", (data) => {
if (
@@ -238,6 +242,12 @@ export class IpcClient {
this.helpStreams.delete(sessionId);
}
});
// MCP tool consent request from main
this.ipcRenderer.on("mcp:tool-consent-request", (payload) => {
const handler = this.mcpConsentHandlers.get("consent");
if (handler) handler(payload);
});
}
public static getInstance(): IpcClient {
@@ -814,6 +824,67 @@ export class IpcClient {
return result.version as string;
}
// --- MCP Client Methods ---
public async listMcpServers() {
return this.ipcRenderer.invoke("mcp:list-servers");
}
public async createMcpServer(params: CreateMcpServer) {
return this.ipcRenderer.invoke("mcp:create-server", params);
}
public async updateMcpServer(params: McpServerUpdate) {
return this.ipcRenderer.invoke("mcp:update-server", params);
}
public async deleteMcpServer(id: number) {
return this.ipcRenderer.invoke("mcp:delete-server", id);
}
public async listMcpTools(serverId: number) {
return this.ipcRenderer.invoke("mcp:list-tools", serverId);
}
// Removed: upsertMcpTools and setMcpToolActive tools are fetched dynamically at runtime
public async getMcpToolConsents() {
return this.ipcRenderer.invoke("mcp:get-tool-consents");
}
public async setMcpToolConsent(params: {
serverId: number;
toolName: string;
consent: "ask" | "always" | "denied";
}) {
return this.ipcRenderer.invoke("mcp:set-tool-consent", params);
}
public onMcpToolConsentRequest(
handler: (payload: {
requestId: string;
serverId: number;
serverName: string;
toolName: string;
toolDescription?: string | null;
inputPreview?: string | null;
}) => void,
) {
this.mcpConsentHandlers.set("consent", handler as any);
return () => {
this.mcpConsentHandlers.delete("consent");
};
}
public respondToMcpConsentRequest(
requestId: string,
decision: "accept-once" | "accept-always" | "decline",
) {
this.ipcRenderer.invoke("mcp:tool-consent-response", {
requestId,
decision,
});
}
// Get proposal details
public async getProposal(chatId: number): Promise<ProposalResult | null> {
try {