Worker スレッド
mcp.worker.ts は独立した Worker スレッドであり、claude CLI を通じて MCP サーバーを管理するためのブリッジレイヤーを提供します。McpService(SDK 直接接続方式)を補完し、Claude 設定ファイルから MCP サーバーレコードを読み取り、CLI 経由で追加/削除/テスト操作を実行できるようにします。
ファイルパス: packages/desktop/app/main/workers/mcp.worker.ts
アーキテクチャ図
graph LR
subgraph Main["Main Process"]
Router["McpRouter / Caller"]
end
subgraph Worker["Worker Thread"]
Port["MessagePort"]
McpWorkerClass["McpWorker"]
end
subgraph External["External"]
ClaudeCLI["claude CLI"]
ConfigFile["~/.claude/config.json"]
end
Router -->|postMessage| Port
Port -->|message event| McpWorkerClass
McpWorkerClass -->|spawn| ClaudeCLI
McpWorkerClass -->|readFile| ConfigFile
McpWorkerClass -->|postMessage| Port
Port -->|result/error| Router
通信プロトコル
リクエスト形式
type WorkerAction =
| { id: number; action: 'list' }
| { id: number; action: 'add'; payload: McpServerInput }
| { id: number; action: 'addJson'; payload: McpServerJsonInput }
| { id: number; action: 'remove'; payload: McpServerRemoveInput }
| { id: number; action: 'test'; payload: McpServerRemoveInput }
| { id: number; action: 'discover'; payload: McpServerRemoveInput };
レスポンス形式
type WorkerResponse =
| { id: number; result: unknown }
| { id: number; error: string };
各リクエストは id フィールドによってレスポンスと対応付けられます。
対応操作
| アクション | メソッド | CLI コマンド | 説明 |
|---|---|---|---|
list | list() | なし(ファイルを直接読み取り) | config.json からサーバー一覧を読み取る |
add | add() | claude mcp add | サーバーを追加する |
addJson | addJson() | claude mcp add-json | JSON から一括追加する |
remove | remove() | claude mcp remove | サーバーを削除する |
test | test() | claude mcp test | 接続をテストする |
discover | discover() | claude mcp inspect | ツール/リソース/プロンプトを検出する |
list — 設定ファイルの読み取り
list() は CLI を呼び出さず、~/.claude/config.json ファイルを直接読み取ります。
private async readClaudeConfig(): Promise<ClaudeConfig | null> {
const configPath = path.join(os.homedir(), '.claude', 'config.json');
const content = await fsp.readFile(configPath, 'utf8');
return JSON.parse(content);
}
設定ファイル構造
interface ClaudeConfig {
mcpServers?: Record<string, McpServerConfig & Record<string, unknown>>;
projects?: Record<string, {
mcpServers?: Record<string, McpServerConfig & Record<string, unknown>>;
}>;
}
サーバーレコードのマッピング
config.json から読み取ったレコードは、内部形式へ変換する必要があります。
private toServerRecord(input): McpServerRecord {
// Transport type inference: transport > type > default 'stdio'
const transport = config.transport ?? config.type ?? 'stdio';
return {
id: `${scope}:${projectPath ?? 'global'}:${name}`,
name,
scope,
type: transport,
projectPath,
status: 'configured',
config
};
}
ID 形式: {scope}:{projectPath|global}:{name}
スコープ:
user— グローバルに設定されたサーバー(トップレベルのmcpServers)local— プロジェクトレベルで設定されたサーバー(projects[path].mcpServers)
add — サーバーの追加
claude mcp add CLI コマンドでサーバーを追加します。
Stdio サーバー
claude mcp add --scope user my-server \
-e API_KEY=xxx \
npx -y @example/mcp-server
パラメーター構築:
['mcp', 'add', '--scope', scope, name]envを反復処理し、-e KEY=VALUEパラメーターを追加commandとargsを追加
SSE/HTTP サーバー
claude mcp add --scope user my-server \
--transport sse \
--header "Authorization: Bearer token" \
https://api.example.com/mcp
パラメーター構築:
['mcp', 'add', '--scope', scope, name]--transport sse|http- URL
headersを反復処理し、--header "Key: Value"パラメーターを追加
discover — 機能の検出
claude mcp inspect コマンドを使用して、JSON 形式の機能インベントリを取得します。
claude mcp inspect --scope user my-server --format json
JSON 抽出
CLI 出力から JSON オブジェクトを抽出します。
private extractJson(output: string) {
const match = /\{[\s\S]*\}/.exec(output);
if (!match) return null;
return JSON.parse(match[0]);
}
結果の正規化
ツール/リソース/プロンプトのリストは McpToolInfo[] 形式に標準化されます。
private normalizeToolList(value: any): McpToolInfo[] {
// Support string arrays and object arrays
// string → { name: string }
// { name, description } → McpToolInfo
}
サーバー識別子の解析
Worker 内のサーバー識別子は scope:name 形式を使用します(McpService の UUID 形式とは異なります)。
private parseServerIdentifier(id?: string, scope?: string) {
const [prefix, ...rest] = id.split(':');
const name = rest.length ? rest.join(':') : prefix;
const normalizedScope = rest.length
? prefix as 'user' | 'local'
: scope ?? 'user';
return { scope: normalizedScope, name };
}
例:
user:my-server→{ scope: 'user', name: 'my-server' }local:/path/to/project:db-server→{ scope: 'local', name: '/path/to/project:db-server' }my-server(プレフィックスなし)→{ scope: 'user', name: 'my-server' }
CLI 実行
すべての CLI 操作は runClaude() メソッド経由で実行されます。
private async runClaude(
args: string[],
options: { cwd?: string } = {}
): Promise<{ success: boolean; stdout: string; stderr: string }>
child_process.spawnを使用してclaudeプロセスを開始する- stdout と stderr を収集する
- プロセスの終了コードで成功/失敗を判定する
- local スコープ操作向けに作業ディレクトリ(
cwd)の指定に対応する
Worker と McpService の関係
| 機能 | McpService(SDK 直接) | mcp.worker(CLI ブリッジ) |
|---|---|---|
| 接続方式 | MCP SDK を直接使用 | claude CLI 経由 |
| プロセスモデル | メインプロセス内 | 独立した Worker スレッド |
| 設定ソース | Electron Store (mcp-config) | ~/.claude/config.json |
| ツール呼び出し | 対応 | 非対応 |
| 目的 | ランタイム接続とツール呼び出し | 設定管理と CLI 互換性 |
| リアルタイム性 | リアルタイム接続 | オンデマンド操作 |
注: 現在のバージョンでは、McpService(SDK 直接接続)が主要なランタイム実装です。Worker は補助として機能し、Claude CLI との設定相互運用性を提供します。両者が管理する設定は独立しています(Electron Store と ~/.claude/config.json に別々に保存されます)。
エラーハンドリング
Worker スレッド内のエラーは、メッセージプロトコル経由で送信されます。
port.on('message', async (message: WorkerAction) => {
try {
// Handle request...
port.postMessage({ id: message.id, result: ... });
} catch (error) {
port.postMessage({
id: message.id,
error: error instanceof Error ? error.message : String(error)
});
}
});
すべての例外は捕捉され、Worker スレッドをクラッシュさせることなくエラーレスポンスへ変換されます。
関連ファイル
- 接続プール管理 — McpService SDK 直接接続実装
- ツール形式アダプター — ツール形式変換
- モジュール概要 — 全体アーキテクチャ