跳到主要内容

如何扩展 MCP

本页提供两个扩展指南:一是在 Elftia 中添加新的 MCP 传输类型,二是编写能与 Elftia 配合使用的自定义 MCP 服务器。

指南一:添加新的传输类型

如果需要支持 Stdio/SSE/HTTP 以外的传输方式(如 WebSocket、gRPC 等),需要修改以下文件。

修改清单

步骤文件修改内容
1packages/desktop/app/shared/contracts/mcp-types.ts扩展 McpServerTransport 类型
2packages/desktop/app/main/services/capabilities/tools/mcp-users/McpService.tscreateTransport() 添加新分支
3packages/desktop/app/main/services/routers/McpRouter.tsmcpAddSchema 中扩展 type 枚举
4packages/renderer/src/features/settings/components/tabs/tools-tab/types.ts更新前端类型
5packages/renderer/src/features/settings/components/tabs/tools-tab/McpServerForm.tsx添加表单选项
6国际化文件添加新传输类型的显示名称

步骤 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:实现传输层

McpService.tscreateTransport() 方法中添加新的 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');
}
// 使用你的 WebSocket 传输实现
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 中添加新传输类型的显示名称。

指南二:编写自定义 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: {}
}
}
);

// 注册工具列表
server.setRequestHandler('tools/list', async () => ({
tools: [
{
name: 'hello',
description: '返回问候语',
inputSchema: {
type: 'object',
properties: {
name: { type: 'string', description: '要问候的名字' }
},
required: ['name']
}
}
]
}));

// 处理工具调用
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
};
});

// 启动
const transport = new StdioServerTransport();
await server.connect(transport);

在 Elftia 中使用

将上述服务器保存为 my-server.js,在 Elftia 中添加 Stdio 服务器:

字段
名称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: '结果文本' }

// 图片返回
{ type: 'image', mimeType: 'image/png', data: '<base64-encoded>' }

// 音频返回
{ type: 'audio', mimeType: 'audio/wav', data: '<base64-encoded>' }

注意:Elftia 的 McpToolAdapter 将图片和音频转换为占位符文本([Image: mime]),实际的二进制数据由 ToolCallDisplay 组件处理渲染。

超时注意事项

Elftia 对 MCP 工具调用设有 120 秒超时。如果你的工具可能执行较长时间的操作,建议:

  • 实现异步处理,先返回任务 ID 再提供轮询接口
  • 在工具描述中注明可能的等待时间
  • 考虑使用流式返回(如果传输层支持)

npm 包发布

如果要将 MCP 服务器作为 npm 包发布(支持 npx 一键启动):

  1. package.json 中设置 bin 字段:

    {
    "name": "@yourorg/mcp-server-example",
    "bin": {
    "mcp-server-example": "./dist/index.js"
    }
    }
  2. 确保入口文件有 shebang:

    #!/usr/bin/env node
  3. 用户在 Elftia 中配置:

    字段
    命令npx
    参数-y , @yourorg/mcp-server-example

添加到官方预设

如果你的 MCP 服务器希望出现在 Elftia 的官方预设列表中,需要在 packages/desktop/app/shared/mcp-presets.ts 中添加配置:

export const OFFICIAL_MCP_PRESETS: OfficialMcpPreset[] = [
// 现有预设...
{
id: 'your-server-id',
name: 'Your Server Name',
provider: 'your-org',
category: 'general', // search | vision | web-reading | code-repo | general
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提供的工具名列表
transportTypestdio(默认)/ http
commandStdio 需要启动命令
argsStdio 需要命令参数
urlHTTP 需要远程 URL
requiresApiKey是否需要 API Key
apiKeyEnvVarAPI Key 的环境变量名
linkedProviderIds关联的 LLM 提供商 ID(自动获取 Key)
extraEnv额外固定环境变量
documentationUrl文档链接

DependencyCheckService 扩展

如果你的 MCP 服务器依赖非标准命令行工具,可以扩展 DependencyCheckServiceinstallCommand() 方法:

文件路径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 / nodeWindows: winget; macOS: Homebrew; 其他: 下载页面
uv / uvx官方安装脚本(Windows: PowerShell; Unix: curl + sh)

相关文件