Расширение MCP
На этой странице представлены два руководства: первое — по добавлению новых типов транспорта MCP в Elftia, второе — по написанию пользовательских MCP-серверов, совместимых с Elftia.
Руководство 1: Добавление новых типов транспорта
Если вам нужна поддержка методов передачи данных, отличных от Stdio/SSE/HTTP (например, WebSocket, gRPC и т. д.), необходимо изменить следующие файлы.
Чек-лист изменений
| Шаг | Файл | Изменения |
|---|---|---|
| 1 | packages/desktop/app/shared/contracts/mcp-types.ts | Расширить тип McpServerTransport |
| 2 | packages/desktop/app/main/services/capabilities/tools/mcp-users/McpService.ts | Добавить новую ветку в createTransport() |
| 3 | packages/desktop/app/main/services/routers/McpRouter.ts | Расширить перечисление типов в mcpAddSchema |
| 4 | packages/renderer/src/features/settings/components/tabs/tools-tab/types.ts | Обновить типы фронтенда |
| 5 | packages/renderer/src/features/settings/components/tabs/tools-tab/McpServerForm.tsx | Добавить параметры формы |
| 6 | Файлы i18n | Добавить отображаемые имена для нового типа транспорта |
Шаг 1: Расширение типов
Добавить новое значение типа транспорта в mcp-types.ts:
export type McpServerTransport = 'stdio' | 'http' | 'sse' | 'websocket';
Также проверить, требуются ли новые поля в McpServerConfig:
export type McpServerConfig = {
command?: string;
args?: string[];
env?: Record<string, string>;
url?: string;
headers?: Record<string, string>;
transport?: string;
// Добавить новые поля при необходимости
wsProtocol?: string;
};
Шаг 2: Реализация транспортного уровня
Добавить новую ветку case в метод createTransport() в McpService.ts:
private async createTransport(server: McpServerRecord) {
switch (server.type) {
case 'stdio':
// ...
case 'sse':
// ...
case 'http':
// ...
case 'websocket':
if (!server.config.url) {
throw new Error('WebSocket server requires url');
}
// Use your WebSocket transport implementation
return new WebSocketClientTransport(
new URL(server.config.url),
{ headers: server.config.headers || {} }
);
default:
throw new Error(`Unsupported transport type: ${server.type}`);
}
}
Требование: реализация транспорта должна соответствовать интерфейсу Transport из MCP SDK и быть совместима с Client.connect().
Шаг 3: Обновление IPC-валидации
Расширить Zod-схему в McpRouter.ts:
const mcpAddSchema = z.object({
// ...
type: z.enum(['stdio', 'http', 'sse', 'websocket']),
// ...
});
Шаги 4–5: Обновление фронтенда
Добавить параметры в селектор типа транспорта в McpServerForm.tsx:
options={[
{ value: 'stdio', label: t('...stdio') },
{ value: 'sse', label: t('...sse') },
{ value: 'http', label: t('...http') },
{ value: 'websocket', label: t('...websocket') },
]}
В зависимости от требований нового типа транспорта добавьте соответствующие поля конфигурационной формы (URL, выбор протокола и т. д.).
Шаг 6: Интернационализация
Добавить отображаемые имена для нового типа транспорта в locales/{en,zh,ja}/settings/tools.json.
Руководство 2: Написание пользовательских MCP-серверов
Написание MCP-сервера, совместимого с Elftia, требует соблюдения спецификации протокола MCP.
Минимальный Stdio-сервер (Node.js)
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const server = new Server(
{ name: 'my-custom-server', version: '1.0.0' },
{
capabilities: {
tools: {}
}
}
);
// Register tool list
server.setRequestHandler('tools/list', async () => ({
tools: [
{
name: 'hello',
description: 'Return a greeting',
inputSchema: {
type: 'object',
properties: {
name: { type: 'string', description: 'Name to greet' }
},
required: ['name']
}
}
]
}));
// Handle tool calls
server.setRequestHandler('tools/call', async (request) => {
if (request.params.name === 'hello') {
const name = request.params.arguments?.name ?? 'World';
return {
content: [
{ type: 'text', text: `Hello, ${name}!` }
]
};
}
return {
content: [{ type: 'text', text: 'Unknown tool' }],
isError: true
};
});
// Start
const transport = new StdioServerTransport();
await server.connect(transport);
Использование в Elftia
Сохраните приведённый выше сервер как my-server.js и добавьте Stdio-сервер в Elftia:
| Поле | Значение |
|---|---|
| Имя | my-custom-server |
| Тип транспорта | Stdio |
| Команда | node |
| Аргументы | /path/to/my-server.js |
Спецификация определения инструментов
Elftia предъявляет следующие требования к инструментам MCP:
| Требование | Описание |
|---|---|
| Имя | Обязательно; используется для генерации ID инструмента (mcp__server__name) |
| Описание | Настоятельно рекомендуется; LLM опирается на описание, чтобы решить, когда вызвать инструмент |
| inputSchema | Должна быть валидной JSON Schema с type: 'object' |
| Формат возврата | Массив content, каждый элемент содержит type и соответствующие данные |
Типы возвращаемого содержимого
// Текстовый возврат
{ type: 'text', text: 'Result text' }
// Возврат изображения
{ type: 'image', mimeType: 'image/png', data: '<base64-encoded>' }
// Аудиовозврат
{ type: 'audio', mimeType: 'audio/wav', data: '<base64-encoded>' }
Примечание: McpToolAdapter в Elftia преобразует изображения и аудио в текст-заглушку ([Image: mime]), а фактические бинарные данные отображает компонент ToolCallDisplay.
Учёт тайм-аутов
Elftia устанавливает тайм-аут 120 секунд для вызовов инструментов MCP. Если ваш инструмент может выполнять длительные операции, рекомендуется:
- Реализовать асинхронную обработку: сначала вернуть ID задачи, а затем предоставить интерфейс для опроса
- Указать возможное время ожидания в описании инструмента
- Рассмотреть использование потоковых ответов (если транспортный уровень поддерживает)
Публикация пакета npm
Если вы хотите опубликовать MCP-сервер как npm-пакет (с поддержкой запуска одной командой через npx):
-
Задайте поле
binвpackage.json:{"name": "@yourorg/mcp-server-example","bin": {"mcp-server-example": "./dist/index.js"}} -
Убедитесь, что входной файл содержит shebang:
#!/usr/bin/env node -
Пользователь настраивает в Elftia следующим образом:
Поле Значение Команда npxАргументы -y,@yourorg/mcp-server-example
Добавление в официальные пресеты
Если вы хотите, чтобы ваш MCP-сервер появился в официальном списке пресетов Elftia, добавьте конфигурацию в packages/desktop/app/shared/mcp-presets.ts:
export const OFFICIAL_MCP_PRESETS: OfficialMcpPreset[] = [
// Existing presets...
{
id: 'your-server-id',
name: 'Your Server Name',
provider: 'your-org',
category: 'general', // search | vision | web-reading | code-repo | general
description: 'Server feature description',
tools: ['tool1', 'tool2'],
command: 'npx',
args: ['-y', '@yourorg/mcp-server@latest'],
requiresApiKey: true,
apiKeyEnvVar: 'YOUR_API_KEY',
linkedProviderIds: ['provider-id'],
documentationUrl: 'https://docs.example.com',
icon: 'icon-name',
},
];
Описание полей пресета:
| Поле | Обязательно | Описание |
|---|---|---|
id | Да | Уникальный идентификатор |
name | Да | Отображаемое имя |
provider | Да | Идентификатор провайдера |
category | Да | Категория: search / vision / web-reading / code-repo / general |
description | Да | Описание функциональности |
tools | Да | Список предоставляемых имён инструментов |
transportType | Нет | stdio (по умолчанию) / http |
command | Для Stdio | Команда запуска |
args | Для Stdio | Аргументы команды |
url | Для HTTP | Удалённый URL |
requiresApiKey | Да | Требуется ли API Key |
apiKeyEnvVar | Нет | Имя переменной среды для API Key |
linkedProviderIds | Нет | Идентификаторы связанных LLM-провайдеров (автоматическое получение ключа) |
extraEnv | Нет | Дополнительные фиксированные переменные среды |
documentationUrl | Нет | Ссылка на документацию |
Расширение DependencyCheckService
Если ваш MCP-сервер зависит от нестандартных инструментов командной строки, можно расширить метод installCommand() в DependencyCheckService:
Путь к файлу: packages/desktop/app/main/services/capabilities/tools/mcp-users/DependencyCheckService.ts
async installCommand(command: string): Promise<DependencyInstallResult> {
// ...
if (command === 'your-tool') {
return await this.installYourTool(command);
}
// ...
}
Поддерживаемая автоматическая установка:
| Команда | Способ установки |
|---|---|
npx / npm / node | Windows: winget; macOS: Homebrew; другие: страница загрузки |
uv / uvx | Официальный скрипт установки (Windows: PowerShell; Unix: curl + sh) |
Связанные файлы
- Управление пулом подключений — понять, как устанавливаются подключения
- Адаптеры форматов инструментов — понять преобразование форматов инструментов
- Архитектура Worker — метод CLI-связки
- Обзор модуля — общая архитектура