Skip to main content

MCP Module Overview

The MCP (Model Context Protocol) module manages connections to external MCP servers, tool discovery, format conversion, and call execution. This module uses a layered architecture with the core in the main process, exposed to the renderer process via IPC.

Architecture Diagram

graph TB
subgraph Renderer["Renderer Process"]
McpPage["McpServersPage"]
McpForm["McpServerForm"]
McpManage["McpManageDialog"]
UseMcp["useMcpMode Hook"]
UseMgmt["useMcpManagement Hook"]
end

subgraph Main["Main Process"]
McpRouter["McpRouter<br/>(IPC Routing)"]
McpService["McpService<br/>(Connection Pool)"]
ToolsLoader["ToolsLoader<br/>(Format Conversion)"]
DepCheck["DependencyCheckService<br/>(Dependency Check)"]

subgraph Transports["Transport Layer"]
Stdio["StdioClientTransport"]
SSE["SSEClientTransport"]
HTTP["StreamableHTTPClientTransport"]
end

subgraph TinyElf["TinyElf Engine"]
McpAdapter["McpToolAdapter<br/>(ITool Wrapping)"]
DirectAdapter["DirectMcpToolAdapter<br/>(Built-in Servers)"]
Tracker["McpProcessTracker<br/>(Process Tracking)"]
end
end

subgraph Worker["Worker Thread"]
McpWorker["mcp.worker.ts<br/>(CLI Bridging)"]
end

subgraph External["External"]
MCP1["MCP Server A<br/>(stdio)"]
MCP2["MCP Server B<br/>(SSE/HTTP)"]
ClaudeCLI["claude CLI"]
end

McpPage -->|IPC| McpRouter
McpRouter --> McpService
McpRouter --> DepCheck
McpService --> Stdio
McpService --> SSE
McpService --> HTTP
Stdio --> MCP1
SSE --> MCP2
HTTP --> MCP2
McpService --> ToolsLoader
McpService --> McpAdapter
McpAdapter --> McpService
DirectAdapter --> MCP1
Tracker --> DirectAdapter
McpWorker --> ClaudeCLI

Key Files

FilePathResponsibility
McpService.tsdesktop/app/main/services/capabilities/tools/mcp-users/Connection pool management, client lifecycle, tool caching
ToolsLoader.tsdesktop/app/main/services/capabilities/tools/mcp-users/Convert MCP tools to OpenAI/Anthropic/Gemini formats
DependencyCheckService.tsdesktop/app/main/services/capabilities/tools/mcp-users/Command-line dependency detection and auto-installation
McpRouter.tsdesktop/app/main/services/routers/IPC routing registration, parameter validation
McpToolAdapter.tsdesktop/app/main/services/agent-core/engine/tinyelf/tools/Adapter from MCPTool to ITool
McpProcessTracker.tsdesktop/app/main/services/agent-core/engine/tinyelf/tools/Child process PID tracking and cleanup
mcp.worker.tsdesktop/app/main/workers/Worker thread, CLI bridging
mcp-types.tsdesktop/app/shared/contracts/Shared type definitions
mcp-presets.tsdesktop/app/shared/Official MCP server presets
mcp-detector.tsdesktop/app/main/lib/utils/MCP configuration detection utility
McpServersPage.tsxrenderer/src/pages/MCP server management page
McpServerForm.tsxrenderer/src/features/settings/components/tabs/tools-tab/Add/edit form
McpManageDialog.tsxrenderer/src/features/marketplace/components/mcp/Agent association management
useMcpMode.tsrenderer/src/features/marketplace/hooks/mcp/MCP mode and tool selection Hook
useMcpManagement.tsrenderer/src/features/settings/components/tabs/tools-tab/hooks/CRUD management Hook

IPC Channels

All MCP-related IPC channels are registered via McpRouter using secureHandle for authentication:

ChannelDirectionParametersReturnDescription
mcp:listR→MNoneMcpServerRecord[]List all servers
mcp:addR→MMcpServerInputMcpActionResultAdd server
mcp:addJsonR→MMcpServerJsonInputMcpActionResultBatch add from JSON
mcp:removeR→MMcpServerRemoveInputMcpActionResultRemove server
mcp:updateR→M{ id, updates }McpActionResultUpdate server config
mcp:testR→MMcpServerRemoveInputMcpTestResultTest connection
mcp:discoverR→MMcpServerRemoveInputMcpDiscoverResultDiscover tools/resources/prompts
mcp:list-server-toolsR→M{ serverId }MCPTool[]List single server tools
mcp:list-all-toolsR→MNoneMCPTool[]List all active server tools
mcp:call-toolR→M{ serverId, toolName, args, callId }MCPCallToolResponseCall tool
mcp:check-dependencyR→M{ command }DependencyCheckResultCheck dependency
mcp:install-dependencyR→M{ command }DependencyInstallResultInstall dependency

Core Types

type McpServerTransport = 'stdio' | 'http' | 'sse';
type McpServerScope = 'user' | 'local';
type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'error';
type McpMode = 'disabled' | 'auto' | 'manual';

interface McpServerRecord {
id: string;
name: string;
scope: McpServerScope;
type: McpServerTransport;
config: McpServerConfig;
isActive?: boolean;
isTrusted?: boolean;
disabledTools?: string[];
installSource?: 'builtin' | 'manual' | 'protocol' | 'unknown';
createdAt?: number;
updatedAt?: number;
}

interface MCPTool {
id: string; // mcp__serverName__toolName
serverId: string;
serverName: string;
name: string;
description?: string;
inputSchema: Record<string, any>;
type: 'mcp';
}

Inter-Module Dependencies

graph LR
McpRouter --> McpService
McpRouter --> DependencyCheckService
McpService --> ConfigStore["Electron Store<br/>(mcp-config)"]
McpService --> MCP_SDK["@modelcontextprotocol/sdk"]
ToolsLoader --> McpService
McpToolAdapter --> McpService
CompletionService["CompletionService"] --> ToolsLoader
TinyElfEngine --> McpToolAdapter
TinyElfEngine --> DirectMcpToolAdapter

Data Flow

Tool Loading Flow

User initiates chat

CompletionService calls setupMcpTools()

fetchMcpTools() determines which servers to load based on MCP mode
↓ (auto: all active servers / manual: selected servers)
McpService.listServerTools() / listAllActiveServerTools()
↓ (check cache → hit: return / miss: initClient + listTools)
ToolsLoader converts to target format (OpenAI / Anthropic / Gemini)

Tool definitions injected into LLM request

Tool Call Flow

LLM returns tool_call (name = mcp__server__tool)

Parse server ID and tool name

McpService.callTool(serverId, toolName, args, callId)

initClient() ensures connection → client.callTool()

Return MCPCallToolResponse (isError, content[])

Result passed back to LLM for continued conversation