Worker-поток
mcp.worker.ts — это независимый Worker-поток, предоставляющий мостовой слой для управления MCP-серверами через CLI claude. Он дополняет McpService (подход прямого подключения через SDK), поддерживая чтение записей MCP-серверов из конфигурационных файлов Claude и выполнение операций добавления/удаления/тестирования через CLI.
Путь к файлу: packages/desktop/app/main/workers/mcp.worker.ts
Архитектурная схема
graph LR
subgraph Main["Главный процесс"]
Router["McpRouter / Caller"]
end
subgraph Worker["Worker-поток"]
Port["MessagePort"]
McpWorkerClass["McpWorker"]
end
subgraph 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.
Поддерживаемые операции
| Action | Метод | Команда 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 > по умолчанию '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}
Области видимости (Scopes):
user— Глобально настроенные серверы (верхний уровеньmcpServers)local— Серверы уровня проекта (projects[path].mcpServers)
add — Добавление сервера
Добавление серверов через команду CLI claude mcp add:
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
Извлечение JSON-объекта из вывода CLI:
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[] {
// Поддержка массивов строк и массивов объектов
// string → { name: string }
// { name, description } → McpToolInfo
}
Разбор идентификаторов серверов
Идентификаторы серверов в Worker используют формат scope:name (отличается от UUID-формата McpService):
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
- Определяет успех/неудачу по коду завершения процесса
- Поддерживает указание рабочего каталога (
cwd) для операций с локальной областью видимости
Взаимосвязь Worker и McpService
| Характеристика | McpService (прямое подключение через SDK) | mcp.worker (CLI-мост) |
|---|---|---|
| Метод подключения | Прямое использование MCP SDK | Через CLI claude |
| Модель процесса | Внутри главного процесса | Независимый 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 {
// Обработка запроса...
port.postMessage({ id: message.id, result: ... });
} catch (error) {
port.postMessage({
id: message.id,
error: error instanceof Error ? error.message : String(error)
});
}
});
Все исключения перехватываются и преобразуются в ответы с ошибкой без завершения работы Worker-потока.
Связанные файлы
- Управление пулом подключений — Реализация прямого подключения McpService через SDK
- Адаптеры форматов инструментов — Преобразование форматов инструментов
- Обзор модуля — Общая архитектура