MCP を拡張する方法
このページでは 2 つの拡張ガイドを提供します。1 つは Elftia に新しい MCP トランスポートタイプを追加する方法、もう 1 つは Elftia と連携するカスタム MCP サーバーを作成する方法です。
ガイド 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 の type enum を拡張 |
| 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 files | 新しいトランスポートタイプの表示名を追加 |
ステップ 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;
// Add new fields if needed
wsProtocol?: string;
};
ステップ 2: トランスポート層を実装する
McpService.ts の createTransport() メソッドに新しい case 分岐を追加します。
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}`);
}
}
要件: トランスポート実装は MCP SDK の Transport インターフェイスに準拠し、Client.connect() と連携して動作する必要があります。
ステップ 3: IPC バリデーションを更新する
McpRouter.ts の Zod schema を拡張します。
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 サーバーを作成する
Elftia と連携する MCP サーバーを作成するには、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 として保存し、Elftia で Stdio サーバーを追加します。
| フィールド | 値 |
|---|---|
| Name | my-custom-server |
| Transport Type | Stdio |
| Command | node |
| Arguments | /path/to/my-server.js |
ツール定義仕様
Elftia の MCP ツールには次の要件があります。
| 要件 | 説明 |
|---|---|
| Name | 必須です。ツール ID(mcp__server__name)の生成に使用されます |
| Description | 強く推奨されます。LLM は、いつ呼び出すかを判断するために説明に依存します |
| inputSchema | 有効な JSON Schema で、type: 'object' である必要があります |
| Return format | content 配列です。各項目には type と対応するデータが含まれます |
返却コンテンツタイプ
// Text return
{ type: 'text', text: 'Result text' }
// Image return
{ type: 'image', mimeType: 'image/png', data: '<base64-encoded>' }
// Audio return
{ type: 'audio', mimeType: 'audio/wav', data: '<base64-encoded>' }
注記: Elftia の McpToolAdapter は画像と音声をプレースホルダーテキスト([Image: mime])に変換し、実際のバイナリデータは ToolCallDisplay コンポーネントがレンダリング用に処理します。
タイムアウトに関する考慮事項
Elftia は MCP ツール呼び出しに 120 秒のタイムアウト を設定しています。ツールがより長時間の操作を実行する可能性がある場合は、次を推奨します。
- 非同期処理を実装し、まずタスク ID を返してポーリングインターフェイスを提供する
- ツールの説明に想定される待ち時間を記載する
- ストリーミング返却の使用を検討する(トランスポート層が対応している場合)
npm パッケージの公開
MCP サーバーを npm パッケージとして公開したい場合(npx によるワンクリック起動をサポートする場合)は、次のようにします。
-
package.jsonにbinフィールドを設定します。{"name": "@yourorg/mcp-server-example","bin": {"mcp-server-example": "./dist/index.js"}} -
エントリファイルに shebang があることを確認します。
#!/usr/bin/env node -
ユーザーは Elftia で次のように設定します。
Field Value Command npxArguments -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 | Yes | 一意の識別子 |
name | Yes | 表示名 |
provider | Yes | プロバイダー識別子 |
category | Yes | カテゴリ: search / vision / web-reading / code-repo / general |
description | Yes | 機能説明 |
tools | Yes | 提供されるツール名の一覧 |
transportType | No | stdio(デフォルト)/ http |
command | For Stdio | 起動コマンド |
args | For Stdio | コマンド引数 |
url | For HTTP | リモート URL |
requiresApiKey | Yes | API Key が必要かどうか |
apiKeyEnvVar | No | API Key 用の環境変数名 |
linkedProviderIds | No | 関連付けられた LLM プロバイダー ID(Key を自動取得) |
extraEnv | No | 追加の固定環境変数 |
documentationUrl | No | ドキュメントリンク |
DependencyCheckService の拡張
MCP サーバーが標準ではないコマンドラインツールに依存している場合は、DependencyCheckService の installCommand() メソッドを拡張できます。
ファイルパス: 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; Others: Download page |
uv / uvx | 公式インストールスクリプト(Windows: PowerShell; Unix: curl + sh) |
関連ファイル
- 接続プール管理 — 接続がどのように確立されるかを理解する
- ツール形式アダプター — ツール形式の変換を理解する
- Worker アーキテクチャ — CLI ブリッジ方式
- モジュール概要 — 全体アーキテクチャ