メインコンテンツまでスキップ

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 コマンド説明
listlist()なし(ファイルを直接読み取り)config.json からサーバー一覧を読み取る
addadd()claude mcp addサーバーを追加する
addJsonaddJson()claude mcp add-jsonJSON から一括追加する
removeremove()claude mcp removeサーバーを削除する
testtest()claude mcp test接続をテストする
discoverdiscover()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

パラメーター構築:

  1. ['mcp', 'add', '--scope', scope, name]
  2. env を反復処理し、-e KEY=VALUE パラメーターを追加
  3. commandargs を追加

SSE/HTTP サーバー

claude mcp add --scope user my-server \
--transport sse \
--header "Authorization: Bearer token" \
https://api.example.com/mcp

パラメーター構築:

  1. ['mcp', 'add', '--scope', scope, name]
  2. --transport sse|http
  3. URL
  4. 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 スレッドをクラッシュさせることなくエラーレスポンスへ変換されます。

関連ファイル