基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
  • 知识卡片碎片时间过考点
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
    • AI 热点每日 AI 资讯与动向
AI 工作台
简历
旧版
AIHT
内容
精选全部 AI 动态热点榜AI 日报收藏
分类
模型行业编程产品技术观点开源
更多
Agent 接入
返回首页开发者导航
AIHT
精选 / 资讯详情
8.0
热点
AI SCORE
技术实践2026-11-08 08:24

MCP 工具设计:让模型选对并用对

dev.to · AI#MCP#工具调用#接口设计
Editor brief · 编辑速览

文章指出,将 REST 端点逐个包装成 MCP 工具,容易导致模型误选工具或填错参数;关键在于工具职责划分及运行时描述。材料还介绍了 TypeScript SDK 的包拆分、Schema 支持和部署流水线工具示例。

文章思维导图
Knowledge map
拖拽缩放
AI deep read

AI 深度解读

MCP Server 能连通,不代表模型会用。原文讨论的是一个常见落差:把 REST API 的每个端点包装成工具后,模型依然选错工具、填错参数。作者的核心判断是,工具设计要围绕任务展开,描述、参数说明和错误消息都属于接口的一部分。

对准备给编辑器或 coding agent 接内部服务的程序员,这篇的价值在于划清边界:SDK 负责协议和校验,开发者负责让模型理解任务;涉及生产操作时,理解之外还必须有真正的授权。

模型需要的是任务入口,不是端点目录

传统 API 面向开发者,开发者可以读文档、看示例、反复调试。MCP 工具面对的则是运行时读取 JSON Schema 的模型。工具名字相近、参数语义含糊,协议再标准,也无法替你解决选择问题。

作者建议从两三个对应实际任务的工具开始。比如部署场景,先提供「查最近部署」,再提供「回滚部署」,并在描述里交代它们的先后关系。

原文称,TypeScript SDK 的 v2 已是稳定版,对应 2026-07-28 规范,拆成 @modelcontextprotocol/server 和 @modelcontextprotocol/client。Schema 使用 Standard Schema,可搭配 Zod v4、Valibot、ArkType。旧包 @modelcontextprotocol/sdk 属于 v1,仍有修复,并提供迁移指南和 codemod。这些是原文给出的版本信息,本文未独立核验。

下面这段完整示例,把查询范围、参数来源和后续用途一起写进了工具定义:

import { McpServer } from "@modelcontextprotocol/server";
import { serveStdio } from "@modelcontextprotocol/server/stdio";
import * as z from "zod/v4";
import { listDeploys } from "./deploys.js";

function createServer(): McpServer {
  const server = new McpServer({ name: "deploys", version: "1.0.0" });

  server.registerTool(
    "list-recent-deploys",
    {
      title: "List recent deploys",
      description:
        "List the most recent production deploys for one service, newest first. " +
        "Use this before rolling back to find the deploy ID to roll back to.",
      inputSchema: z.object({
        service: z
          .string()
          .describe(
            'Service slug as shown in the dashboard, e.g. "billing-api"',
          ),
        limit: z
          .number()
          .int()
          .min(1)
          .max(20)
          .optional()
          .describe("Defaults to 5"),
      }),
      annotations: { readOnlyHint: true },
    },
    async ({ service, limit }) => {
      const deploys = await listDeploys(service, limit ?? 5);
      if (deploys.length === 0) {
        return {
          content: [
            {
              type: "text",
              text: `No deploys found for "${service}". Check the service slug.`,
            },
          ],
          isError: true,
        };
      }
      return {
        content: [{ type: "text", text: JSON.stringify(deploys, null, 2) }],
      };
    },
  );

  return server;
}

void serveStdio(createServer);
console.error("deploys MCP server running on stdio");

重点看 .describe():它会进入模型看到的 JSON Schema。service 不只是字符串,还是控制台里的服务标识;limit 不只是数字,还必须是 1–20 的整数,省略时由 limit ?? 5 执行默认值。说明默认值和落实默认值,是两件事。

按照原文,SDK 从 inputSchema 派生 JSON Schema,在 handler 执行前校验参数,同时推导 handler 类型。另一个容易踩坑的细节是最后的 console.error:stdio 模式下,stdout 承载 JSON-RPC,随手添加 console.log 可能破坏协议流。

错误消息要帮助重试,描述不能代替授权

模型调用失败后,还会继续读取返回结果。因此,错误消息同样影响下一步行为。

原文举例,limit 超过上限时,SDK 会返回带 isError: true 的工具结果,提示 limit: Too big: expected number to be <=20。模型据此有机会修正参数。业务 handler 也应遵循这个思路:告诉调用方哪里出了问题,以及接下来能检查什么。

示例中的「没有找到部署,请检查服务标识」就比一段 TypeError 更有用。不过,修复提示必须符合真实故障,不能把权限不足、服务不可用都归结为参数错误。

结果若还要交给程序处理,作者建议增加 outputSchema,同时返回 structuredContent 和便于阅读的 content。按原文,SDK 会校验结构化结果,并通过 tools/list 公布输出结构,供客户端校验。

回滚工具则多了一层风险。作者为 rollback-deploy 设置:

  • readOnlyHint: false,表明它会修改状态。
  • destructiveHint: true,表明它具有破坏性。
  • idempotentHint: true,表明它被声明为幂等操作。

其 deployId 参数说明要求从 list-recent-deploys 获取,例如 dpl_8f2c;工具描述还要求用户确认精确的部署 ID。

这些文字和 annotations 都是提示,真正的授权必须在 rollback() 内执行。

宿主可能据此展示确认界面,也可能忽略这些提示。声明幂等也不会自动让业务实现变得幂等,开发者仍需保证重复调用符合声明。

显式传递状态,也先判断是否需要 MCP

原文称,2026-07-28 规范移除了 Streamable HTTP 中的协议级会话、Mcp-Session-Id 请求头以及 initialize 握手,每次请求自行携带协议版本和客户端能力。

跨调用需要保留的状态,应通过显式句柄传递。这里的句柄可以理解为一个后续操作能引用的标识:查询返回 deployId,回滚再接收它,依赖关系就摆在参数里。

原文还提到,规范要求服务端 SHOULD 以确定顺序返回 tools/list,有助于客户端缓存和 LLM 提示缓存命中。因此不要让工具列表的顺序取决于无序 map。

但作者并不主张所有项目都接 MCP。如果只有自己的应用调用模型,直接使用供应商 API 的 function calling,代码和进程都更少。需要让编辑器、桌面助手、coding agent 共用一套工具时,MCP 的复用价值才更明确。

我的判断

我认同把描述当作接口设计来审查。参数能通过类型校验,只能说明形状合法,不能证明模型选对了服务或部署目标。任务边界、参数来源和失败提示,确实值得与 handler 一起评审。

但「描述就是整个 API」更像强调重点的标题。实际接口还包含权限、输出契约、幂等性和宿主行为。原文给了示例,没有提供工具选择准确率、重试成功率,也没有与「每个端点一个工具」做对照实验,因此效果判断属于经验之谈。

版本相关内容尤其需要谨慎。原文涉及 SDK 包拆分和协议握手变化,落地前应确认项目实际使用的 SDK 与宿主支持情况,不能仅凭文章替换现有初始化流程。

能拿来做什么

  • 给 Node 服务封装 MCP 时,先选两三个完整任务,为每个工具写清使用时机、参数来源和执行影响,再接业务函数。
  • 检查现有工具的报错,优先补上可执行的修复提示;涉及程序消费的结果,再增加明确的输出契约。
  • 做部署或回滚工具时,在业务函数里落实授权,并核对幂等声明是否符合实现。
  • 用 npx @modelcontextprotocol/inspector npx tsx src/index.ts 检查工具注册和调用结果;如果只有自家应用使用模型,也先评估 function calling 是否已经够用。
Original source

本文由 AI 通读原文后重新编写,观点部分为站内判断,细节以原文为准,来源 dev.to · AI,原文版权归原作者所有。

阅读原文
上一篇
Claude Code 反复改错,可能是旧记忆作祟
下一篇
用 Rust 策略约束 AI 支付代理

资讯速览

dev.to · AI · 2026-11-08 08:24

AI 评分 8.0 / 10

相关标签

#MCP#工具调用#接口设计

继续阅读

  • AI 图片存储的关键是权限与生命周期
  • Claude Code 反复改错,可能是旧记忆作祟
  • 用 Rust 策略约束 AI 支付代理
  • 用驱动技能串起规格到交付的开发流程
  • AI代码审查应看缺陷拦截效果