DSH Quality
进阶
8 分钟阅读

给 dsh 接入 MCP server 或自定义 tool

两条路径让模型获得真实能力:用 ctx.tools.register 注册自定义 tool,或把现成 MCP server 包成 dsh 插件。

最后更新:2026-08-19

Tool 与 command:谁调用谁

command 由用户在 UI 里触发;tool 由模型自己决定需要时调用。想让 agent 自主行动,就注册 tool。

路径 A — 注册自定义 tool

最小注册节点:

ts
ctx.tools.register({
  name: 'read_local_file',
  description: 'Read a text file from the workspace',
  parameters: {
    type: 'object',
    properties: {
      path: { type: 'string', description: 'Relative path' },
    },
    required: ['path'],
  },
  async execute(args) {
    try {
      return { ok: true, content: await fs.readFile(args.path, 'utf8') };
    } catch (err) {
      // 错误必须回传给模型,不能吞掉
      return { ok: false, error: String(err) };
    }
  },
});

三个细节很关键:清晰的 description(它决定模型选不选这个 tool)、严格的 JSON Schema parameters、以及结构化错误返回(让模型能恢复并重试)。

路径 B — 包一个现成 MCP server

MCP (Model Context Protocol) server 通过 stdio 或 HTTP 暴露工具。与其重新实现,不如在插件里启动 server 并把它的工具注册到 ctx

ts
import { startMcpClient } from '@dsh/mcp';

export async function apply(ctx) {
  const client = await startMcpClient({
    command: 'npx',
    args: ['-y', '@modelcontextprotocol/server-filesystem', './'],
  });
  const tools = await client.listTools();
  for (const tool of tools) {
    ctx.tools.register({
      name: `mcp_${tool.name}`,
      description: tool.description,
      parameters: tool.inputSchema,
      execute: (args) => client.callTool(tool.name, args),
    });
  }
}

远程 server 只需传 url 代替 command/args。无论哪种方式,模型的工具箱里都多了一个工具,协议层完全不用模型操心。

端到端验证

启动 dsh,开一个会话,让模型做一件需要工具的事(比如"package.json 里有什么?")。观察模型自主调用 read_local_file(或 mcp_filesystem_*),然后基于结果作答。

相关拆解

真实插件在更大规模上展示了同一模式:modlens 把结构化视觉证据作为 tool 结果返回,dsh-at-file 用 Codex 风格的 @file 引用扩展输入通道。