news 2026/9/13 2:40:30

MCP工具定义实战:JSON Schema在具身智能Agent中的应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MCP工具定义实战:JSON Schema在具身智能Agent中的应用

做具身智能方向的工程落地,这两年绕不开一个话题:MCP(Model Context Protocol)的工具定义规范。尤其当你需要让大模型去调用机械臂、传感器、仿真环境这些真实世界的工具时,工具的JSON定义写得好不好,直接决定Agent能不能用起来,以及用起来之后稳不稳。标题里写成“Jason格式”其实是个很经典的笔误,JSON的全称是JavaScript Object Notation,跟人名Jason没有任何关系,但搜索引擎里这么搜的人特别多,可见这个格式的命名确实容易让人记混。

MCP的工具定义标准,简单说就是:你给大模型一份“工具说明书”,说明书里写清楚这个工具叫什么、有什么用、参数怎么填。这份说明书用JSON格式描述,而其中最核心的部分是JSON Schema——一种用来描述JSON数据结构的规范。这篇文章我不打算泛泛讲概念,而是直接拆解一份真实可用的工具定义长什么样,每个字段为什么存在、怎么填才能让大模型少犯傻,以及我在具身智能项目里实际踩过的坑。内容适合三类人:正在做智能体(Agent)应用开发的工程师、准备接MCP协议的工具开发者,以及刚接触具身智能、想搞清楚大模型怎么控制真实硬件的新手。

1. 为什么MCP的工具定义非得用JSON

1.1 MCP里“工具”到底是干什么的

MCP是Anthropic在2024年底提出并开源的模型上下文协议,目的很直接:让大语言模型能标准化地连接外部数据源和工具。你可以把MCP理解成大模型世界的“USB接口”——鼠标键盘显示器各有各的协议,但插上USB就能统一工作。在MCP体系里,工具(Tool)是模型可以主动调用的函数,比如查询数据库、操作文件系统、控制机械臂、读传感器数据。

关键点在于:大模型本身不会“知道”你的工具怎么用。它只是读取你提供的工具定义文本,然后根据这些文本决定“要不要调用这个工具”以及“参数应该传什么”。所以工具定义的质量,直接决定了模型调用的准确率。写工具定义这件事,本质上是在做大模型的“外部提示词工程”——你写在JSON里的每一个描述字段,都会被模型当成决策依据。

1.2 为什么选JSON而不是别的格式

市面上的结构化描述格式不少:XML、YAML、Protobuf,但MCP最终选了JSON,或者说更准确地选了JSON Schema,原因是多方面的。

JSON的跨语言支持几乎是零成本的。Python、TypeScript、Java、C++、Rust,几乎每种语言都有内置或成熟的JSON解析库,不需要额外生成代码、不需要编译器介入。对于MCP这种要接成千上万种不同技术栈工具的场景来说,这是最现实的兼容性方案。

JSON Schema本身是一种“自描述”的规范。你写出来的工具参数约束,既可以被人类阅读,也可以被程序校验,更重要的是可以被大模型理解。模型训练语料里JSON Schema的样本实在太多了,模型对它的语义理解天然优于XML或自定义格式。我自己测试过同一个工具定义分别用JSON Schema和自然语言描述,模型对前者的参数生成准确率明显更高。

从工程角度看,JSON还有几个隐性优势:无状态、可序列化、容易持久化和传输。MCP的传输层基于JSON-RPC,工具定义本身就是JSON-RPC消息体的一部分,直接用JSON描述工具可以减少一次格式转换,减少出错面。

1.3 工具定义在MCP协议中的位置

搞清楚工具定义在MCP协议里的位置,对理解它的结构有帮助。MCP的通信模型是客户端(Client)与服务器(Server)之间的JSON-RPC消息交互。当客户端启动并初始化会话后,会发送一个tools/list请求,服务器返回一个工具列表,这个列表里的每一项就是一个工具定义对象。当模型决定调用某个工具时,客户端再发送tools/call请求,服务器执行具体逻辑并把结果返回。

所以工具定义是“模型的行动指南”。服务器的代码逻辑写得再漂亮,如果工具定义没写好,模型就不知道什么时候调用、怎么传参数,再好的功能也白搭。这也是我强调“工具定义先于代码实现”的原因——在写任何业务逻辑之前,先把工具定义打磨好,后面几乎不会返工。

2. JSON Schema核心字段逐个拆解

2.1 工具定义的整体结构

一个标准的MCP工具定义长这样:

{ "name": "move_arm_to_pose", "description": "控制机械臂末端运动到指定笛卡尔坐标位置,常用于抓取、放置、轨迹规划等操作。", "inputSchema": { "type": "object", "properties": { "x": { "type": "number", "description": "目标X坐标,单位毫米,相对于机械臂基座坐标系。" }, "y": { "type": "number", "description": "目标Y坐标,单位毫米,相对于机械臂基座坐标系。" }, "z": { "type": "number", "description": "目标Z坐标,单位毫米,相对于机械臂基座坐标系。" }, "speed": { "type": "number", "description": "运动速度比例,范围0.1到1.0,1.0为最大速度。", "default": 0.5, "minimum": 0.1, "maximum": 1.0 } }, "required": ["x", "y", "z"] } }

这个结构分三层:最外层是工具本身的信息(namedescription),第二层是inputSchema(输入参数约束),第三层是JSON Schema内部的具体字段定义。后续新版本MCP还扩展了outputSchemaannotations等字段,但namedescriptioninputSchema这三个是绝对核心。

2.2 name和description:给模型看的“第一印象”

name是工具的唯一标识,必须全局唯一。命名规范建议全小写加下划线,比如move_arm_to_poseread_sensor_data。我见过有人用驼峰命名(moveArmToPose),大模型通常也能识别,但小写下划线是工具调用领域最通用的惯例,保持一致最稳妥。

description的作用可能比你想象中重要得多。它不只是给人看的注释,更是大模型决定“何时使用这个工具”的关键依据。模型在接到用户问题后,会遍历所有工具的描述,根据语义相关度决定调用哪个。描述写得越具体、越明确,模型的决策越准确。如果只是写“移动机械臂”,模型可能搞不清楚这个工具和控制单个关节的工具有什么区别;但如果写好“用于将机械臂末端移动到指定笛卡尔坐标位置,常用于抓取、放置、轨迹规划”,模型就能根据任务上下文做出合理判断。

2.3 inputSchema里的properties:参数的定义方式

inputSchematype固定为object,表示这个工具接收一个JSON对象作为参数。对象的每一个字段在properties中定义,每个字段又包含自己的typedescription,以及可选的约束条件。

常用的type类型有这几种:

  • string:字符串,适合名称、ID、路径等文本信息
  • number:数字(整数和小数都可以)
  • integer:整数,适合计数、索引
  • boolean:布尔值,适合开关类参数
  • array:数组,适合批量数据
  • object:嵌套对象,适合结构化的复合参数

每个字段的description同样重要。大模型通过description来理解这个参数的含义、单位、取值范围。我在实际项目中遇到过很多次:不给单位,模型就把毫米当成米;不给坐标系,模型就按自己的理解传值。这些坑几乎都可以通过写清楚description来规避。

2.4 required、default、enum与约束条件

required是一个数组,列出调用工具时必须提供的字段。不需要把所有参数都设为必填,能给出合理默认值的就让模型少传一个参数,降低出错概率。

default字段为参数提供默认值。当模型没传这个参数时,服务器端可以自动使用默认值。比如速度、超时时间这类参数,给一个安全默认值非常实用。

enum用来限制参数的取值集合。比如控制模式只有"position""velocity""force"三种,写成enum后模型就只能从这三个值里选,从根源上杜绝乱传值。

"mode": { "type": "string", "description": "控制模式:位置控制、速度控制、力控。", "enum": ["position", "velocity", "force"] }

minimummaximum用于数值范围约束,minLengthmaxLength用于字符串长度约束,pattern用于正则匹配。这些约束不光是给人看的,更是可以直接在服务器端做输入校验的依据。

2.5 嵌套对象与数组:处理复合参数

有些工具的参数天然是复合结构。比如要控制机械臂走一段轨迹,你需要的不是单个坐标,而是一组坐标点加时间戳。这时候就需要嵌套结构:

{ "name": "plan_trajectory", "description": "规划并执行机械臂末端轨迹。", "inputSchema": { "type": "object", "properties": { "waypoints": { "type": "array", "description": "轨迹途经点列表,至少包含起点和终点。", "items": { "type": "object", "properties": { "x": { "type": "number", "description": "X坐标(毫米)" }, "y": { "type": "number", "description": "Y坐标(毫米)" }, "z": { "type": "number", "description": "Z坐标(毫米)" } }, "required": ["x", "y", "z"] }, "minItems": 2 } }, "required": ["waypoints"] } }

这里array类型的字段用items来定义数组元素的schema,minItems控制最少元素数量。嵌套层级理论上不限,但建议最多三层——层级太深会显著增加模型生成合法参数的难度,也增加JSON Schema校验的复杂度。

2.6 条件约束:oneOf、anyOf、allOf

这三个是JSON Schema中处理“条件分支”的关键字,但在MCP工具定义中使用频率相对较低。什么场景会用到呢?比如一个工具既可以按坐标控制也可以按关节角控制,两种模式参数结构差异很大:

"inputSchema": { "type": "object", "oneOf": [ { "properties": { "mode": { "const": "cartesian" }, "x": { "type": "number" }, "y": { "type": "number" }, "z": { "type": "number" } }, "required": ["mode", "x", "y", "z"] }, { "properties": { "mode": { "const": "joint" }, "joints": { "type": "array", "items": { "type": "number" } } }, "required": ["mode", "joints"] } ] }

oneOf表示只能命中其中一个分支,anyOf表示至少命中一个,allOf表示同时满足所有。老实说,这类复杂约束在实际MCP工具定义里用得不多——不是不好,而是很多开源模型对复杂JSON Schema的遵循能力有限,出错的概率会变大。我的建议是:能用简单结构解决的,不要上条件约束;确实有复杂场景,优先拆成多个独立工具,而不是塞进一个工具里。

3. 完整工具定义示例:从通用场景到具身智能

3.1 一个通用示例:模拟查询设备状态

先看一个贴近日常开发的示例。假设我们要做一个智能运维Agent,需要查询机房设备的温度、风扇转速等状态:

{ "name": "get_device_status", "description": "查询指定设备的实时运行状态,包括CPU温度、风扇转速、电源功率等。当用户询问设备是否过热、风扇是否异常、功耗情况时使用。", "inputSchema": { "type": "object", "properties": { "device_id": { "type": "string", "description": "设备唯一标识ID,格式如rack-01-node-03。" }, "metrics": { "type": "array", "description": "要查询的指标列表,可选值:cpu_temp、fan_speed、power、memory_usage。不传则返回所有指标。", "items": { "type": "string", "enum": ["cpu_temp", "fan_speed", "power", "memory_usage"] } } }, "required": ["device_id"] } }

这个定义有两个值得学习的点:一是description里明确写了“当用户询问……时使用”,这是在引导大模型的调用时机;二是metrics参数利用enum+array的组合,既给了模型灵活性,又限制了取值边界。这种“自由但有界”的设计思路,比单纯的必填约束效果更好。

3.2 具身智能核心示例一:机械臂力控抓取

接下来是具身智能项目里最常见的一类工具:控制机械臂执行力控抓取。这个场景既要控制位置,又要限制力度,参数设计比纯位置控制复杂很多。

{ "name": "grasp_object_force_control", "description": "控制机械臂以指定的夹持力抓取目标物体。适用于抓取易碎品、形状不规则物体或需要恒力夹持的场景。抓取前通常需要先调用move_arm_to_pose将机械臂移动到物体附近。", "inputSchema": { "type": "object", "properties": { "target_position": { "type": "object", "description": "目标抓取位置的笛卡尔坐标,单位毫米。", "properties": { "x": { "type": "number", "description": "X坐标,相对机械臂基座。" }, "y": { "type": "number", "description": "Y坐标,相对机械臂基座。" }, "z": { "type": "number", "description": "Z坐标,相对机械臂基座。" } }, "required": ["x", "y", "z"] }, "force": { "type": "number", "description": "目标夹持力,单位牛顿,范围5到30。默认15。", "minimum": 5, "maximum": 30, "default": 15 }, "grasp_strategy": { "type": "string", "description": "抓取策略:平行夹爪、吸附、自适应抓取。", "enum": ["parallel", "suction", "adaptive"], "default": "parallel" }, "timeout": { "type": "number", "description": "抓取超时时间,单位秒。", "default": 10 } }, "required": ["target_position"] } }

这个示例里我特意用了嵌套对象target_position来聚合三个坐标值。相比把xyz平铺在顶层,这种方式在语义上更内聚:模型一眼就能看出这三个值是一组的。同时,forcegrasp_strategy都给了默认值,模型只需关心最关键的位置参数,调用成功率明显提升。

3.3 具身智能核心示例二:读取传感器数据

具身智能系统普遍依赖传感器反馈,例如六维力/力矩传感器、激光雷达、相机深度数据。MCP工具定义同样适用于这些数据获取场景:

{ "name": "read_ft_sensor", "description": "读取机械臂末端六维力/力矩传感器的当前数值,包括三轴力和三轴力矩。当需要判断机械臂是否接触物体、检测碰撞或评估夹持力时使用。", "inputSchema": { "type": "object", "properties": { "filter": { "type": "string", "description": "滤波方式:raw原始数据、kalman卡尔曼滤波、moving_average滑动平均。", "enum": ["raw", "kalman", "moving_average"], "default": "kalman" }, "axes": { "type": "array", "description": "需要读取的通道列表,可选Fx、Fy、Fz、Mx、My、Mz,不传则返回全部。", "items": { "type": "string", "enum": ["Fx", "Fy", "Fz", "Mx", "My", "Mz"] } } } } }

这类工具定义的重点是告诉模型“在什么判断场景下使用”。很多具身智能Agent在任务执行中需要根据传感器反馈做决策,如果模型不知道有这个工具,它就只会按开环逻辑运行,碰到意外碰撞就抓瞎。描述写得越场景化,模型越知道何时该查传感器。

4. 工具定义实操要点与策略

4.1 接口描述的“提示词工程”属性

我在多个项目里反复验证过一件事:工具定义里的description字段,本质上是给大模型看的提示词。模型通过description来理解工具语义、调用时机、参数含义。所以写description的时候,不要只写技术参数,还要写使用场景。

一句话标准:描述里应该包含“这个工具是干什么的、什么时候该用它、什么时候不该用它、参数的语义/单位/范围”。能做到这四点,大模型的工具调用准确率会有立竿见影的提升。我见过不少团队花大量时间调系统提示词,却没意识到工具定义里那几十行description才是真正决定工具调用质量的核心。

4.2 参数数量与必填项的取舍策略

工具参数的个数对模型调用准确率影响很大。经验法则:参数尽量控制在5个以内,超过5个时考虑拆分工具或合并参数为嵌套对象。原因很简单——模型生成参数时,每多一个字段就多一次出错机会,参数越多,联合出错的概率越大。

必填项同样要克制。有些开发者习惯把所有参数都设为必填,理由是“调用者就应该把所有信息都给全”。但在大模型场景里,这种做法反而增加失败率。模型拿不到某个参数值时,可能会编造一个,而不是主动向你确认。给关键参数设置安全的默认值,把必填项压到最少,这才是符合大模型行为模式的策略。

我通常在项目里遵循一个原则:只把“没有值就没法执行”的参数设为必填,其余全部设置默认值或标记为可选。

4.3 工具粒度的划分:一个工具只做一件事

工具粒度设计是另一个高频踩坑点。一种常见错误是把所有操作都塞进一个工具里,用一个大参数对象控制,表面上看简洁,实际运行却麻烦不断。

反例:

{ "name": "robot_control", "description": "控制机械臂。", "inputSchema": { "type": "object", "properties": { "action": { "type": "string", "enum": ["move", "grasp", "release", "stop"] }, "x": { "type": "number", "description": "目标X坐标" }, "y": { "type": "number", "description": "目标Y坐标" }, "z": { "type": "number", "description": "目标Z坐标" }, "force": { "type": "number" }, "speed": { "type": "number" } }, "required": ["action"] } }

这种设计的问题在于:action不同时,需要的参数完全不同,但模型面对的是全部参数的组合空间。move动作不需要force,可模型可能就会莫名其妙地传一个force进来,造成混乱。

正确做法是拆成多个工具:move_arm_to_posegrasp_object_force_controlrelease_objectstop_arm。每个工具的参数只覆盖自己的场景,模型决策时目标更清晰,参数空间更小,准确率自然更高。一个工具只做一件事,这是工具定义的黄金法则。

4.4 参数命名、顺序与版本的隐性影响

参数命名对模型的理解也有影响。虽然理论上JSON对象的键是无序的,但在模型眼里,命名本身携带着语义信息。xyz这种简写没问题,因为坐标系在具身智能里是常识;但业务含义较强的参数,命名尽量用完整的单词组合,比如grasp_strategytarget_position,避免用gstp这类只有开发者才懂的缩写。

关于参数顺序,JSON格式本身不要求字段有序,但实际测试中,把最重要的参数放在properties定义的前面,模型倾向于优先关注这些参数,减少遗漏。这可能是训练数据分布带来的行为特征,不一定每个模型都一致,但没有坏处。

版本管理方面,工具定义一旦发布给外部客户端使用,修改时要考虑兼容性。新增可选字段是安全的,删除或重命名字段会破坏已有调用,调整required要格外谨慎。我在项目里会为工具接口打版本号,较大的不兼容变更直接定义一个V2版本,而不是改原来的定义。

5. 具身智能场景下的特殊考量与扩展

5.1 物理世界约束必须写进定义

具身智能与纯软件工具的最大区别在于,它操作的是真实物理设备,存在机械极限、安全风险、实时性要求。这些约束必须显式写在工具定义里,否则模型是“看不见”这些限制的。

例如机械臂的关节角限制、最大速度、最大力矩,都要在description或约束字段里明确。不要指望模型“凭常识”知道某台机械臂的Z轴行程范围——不同型号的机械臂参数差异极大,模型没有上帝视角。

更重要的是安全参数。力控抓取时最大夹持力、运动时允许的最大速度,这些涉及人身安全和设备安全的参数,不仅要在JSON里约束,服务器端还要做硬性校验。JSON Schema是做第一层防御的,真正的安全底线必须在代码层兜住。

5.2 工具之间的协作与编排

具身智能任务通常需要多个工具协同。一个典型的手眼协调场景:先用相机获取物体位置(get_object_pose),再规划路径(plan_trajectory),然后移动机械臂(move_arm_to_pose),最后执行抓取(grasp_object_force_control)。

MCP协议本身不支持在一个工具定义里直接调用另一个工具,工具间的协作由大模型在推理过程中自主编排。但工具定义的description可以暗示这种上下游关系,比如在grasp_object_force_control的description里写上“抓取前通常需要先调用move_arm_to_pose将机械臂移动到物体附近”。这相当于给模型提供了任务规划的路线图,能显著提升多工具协作的流畅度。

5.3 MCP工具与Agent Skill的区别

这个话题最近讨论很多。我的理解是:MCP工具更接近“原子能力”的标准化接口——输入输出明确、可校验、可以被多种上层逻辑复用;Agent Skill则更接近“高层策略或流程模板”,类似一个封装好的动作序列或者决策逻辑。

举具身智能的例子:MCP工具是move_arm_to_posegrasp_object_force_controlread_ft_sensor;Agent Skill则是更上层的“拿桌上的杯子”这种完整行为模板,内部会调用多个MCP工具,并且包含条件判断和失败恢复逻辑。两者的关系不是替代而是互补:Skill负责“怎么决策”,MCP负责“怎么执行”。在实际工程里,我倾向于把底层的硬件控制全部封装成MCP工具,上层再通过Skill或Agent框架做编排。

5.4 大模型对工具定义真的是按JSON解析的吗

这个问题要区分“训练时”和“推理时”。推理时,MCP客户端把工具定义以JSON文本的形式放入上下文窗口,大模型通过注意力机制理解这段文本,再通过类似函数调用的机制输出JSON格式的参数。所以模型的解析本质是语义理解,不是严格的程序化解析。

这就解释了两个现象:一是为什么description写得越好,调用越准——因为模型的“理解”主要来自语义;二是为什么某些模型对复杂的JSON Schema(比如oneOf、嵌套多层的if-then)遵循能力较差——它不一定“理解”这些约束的精确逻辑含义。实操中我的建议是:为保证兼容性,工具定义尽量用JSON Schema的基础能力(type、properties、required、enum、minimum/maximum、default),高级约束只在服务器端代码里做校验,不要过度依赖模型来遵守。

6. 常见问题与排查技巧实录

6.1 高频问题速查表

下面整理了我实际项目中遇到的典型问题,直接对照排查:

症状可能原因解决方案
模型调用工具但参数校验失败参数类型不匹配,比如数字传成了字符串在description里明确类型和格式;服务器端做宽松类型转换
模型传了不存在的参数工具定义缺少additionalProperties: false在inputSchema顶层加上"additionalProperties": false
模型不知道什么时候该调用工具description缺少使用场景提示重写description,加入“当……时使用”的引导语句
单位或坐标系错误description里没写单位/坐标系在参数description中补全单位、坐标系、取值范围
模型选了错误的工具工具定义太相似或命名模糊补充差异化描述,必要时调整工具名称
嵌套参数模型总是生成不完整嵌套层级过深简化结构,减少嵌套深度;或将复杂结构拆成单独工具
同一工具被反复调用导致资源浪费缺少状态检查工具增加状态查询工具,并在主工具description里提示先查询状态
模型输出超长或格式错误返回结果过大在工具内部做结果截断或摘要,控制返回内容大小

6.2 一个真实排查案例:力控参数被模型传成字符串

有一次我在跑抓取场景时,发现模型调用了grasp_object_force_control,但force参数被传成了"force": "15N"。JSON Schema里明明定义的是"type": "number",照理说校验应该直接拦下来,但实际是因为客户端框架的校验不够严格,字符串值被直接透传到了服务器端。

排查过程:先在服务器日志里看到force是字符串类型,Python代码里做力控计算时直接抛异常。定位到问题后,我没有只改服务器代码,而是做了三件事:第一,在参数description里明确加上“仅传数字,不要带单位,单位固定为牛顿”;第二,在服务器端入口加了严格的类型校验和转换逻辑;第三,在工具定义里加了"examples": [15]作为参考值(虽然有部分模型对examples字段的利用不稳定,但对Claude和部分国产模型有效)。改完之后,同一场景连续测试50次,没有再出现字符串力控值。

6.3 排查工具定义问题的调试方法

当你发现Agent的工具调用不符合预期时,按这个顺序排查效率最高:

第一步,用单向测。直接绕过Agent,用MCP客户端或测试脚本调用工具,传入预期参数,确认工具本身的逻辑是否正确。很多“工具调用失败”其实是工具内部代码报错,跟工具定义无关,先把硬件和逻辑层问题排除。

第二步,审查JSON Schema。用JSON Schema官方校验工具(比如Python的jsonschema库)验证定义是否合法。我遇到过有人把items写在了array字段的同级而不是items里,导致定义本身就是非法的。

第三步,看模型实际“看到”的文本。很多MCP框架会把工具定义做转换或截断,模型实际看到的描述可能跟你写的不一样。把发给模型的完整消息打印出来,逐字检查工具定义的描述是否完整、有没有被截断、格式是否正确。

第四步,小步修改,单变量验证。不要一次改多个字段,否则你无法确定是哪个改动生效了。每次只调整一个描述或约束,跑一批测试样本,对比准确率变化。我习惯准备一组固定的测试问题集,用来做工具定义修改前后的回归对比。

6.4 两个容易忽略的“隐藏炸弹”

第一个是工具定义的总长度。MCP会把所有工具定义都塞进上下文,如果你的工具列表很长、每个描述又写得特别啰嗦,会占用大量上下文窗口,既挤占了对话历史的空间,又可能让模型在长上下文中忽略某些工具。建议每个工具的description控制在100到150个汉字以内,参数description控制在30到50个汉字以内,总工具数量尽量控制在20个以内,超过的话考虑按业务域拆分多个MCP Server。

第二个是数字精度问题。JSON的number类型在多数语言里对应双精度浮点数,但具身智能里有些参数需要高精度,比如毫米级坐标。如果参数值超过53位二进制精度,可能会导致精度丢失。实际项目中这个问题很少见,但如果你在传递用于闭环控制的精密参数时发现值被微妙地改变了,可以留意一下这个方向。

7. 结尾:一点个人体会

做了小半年具身智能Agent的工程落地,我对MCP工具定义最大的感受是:它看起来像一份简单的接口文档,实际上是大模型与物理世界之间最薄也最关键的一层翻译层。写工具定义的过程,本质上是在用一种“模型能理解的方式”重新描述真实世界的规则。你写得越清晰、越结构化,模型的行为就越可靠。反过来说,如果你只把它当成普通的JSON配置随便写写,后面一定会在各种意想不到的地方被坑到。

最后再分享一个小技巧:每次写完一个新的工具定义,我都习惯找一个大模型,用“你会怎么调用这个工具”来问一遍,看看它的理解是否与我的意图一致。这种“面试”式的测试成本极低,却能提前发现绝大多数描述不清的问题。MCP生态还在快速演进,工具定义的标准也在不断完善,但底层的原则不会变——让机器理解你的意图,先从写一份清楚直白的JSON说明书开始。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 2:38:27

Vue.js实战:搭建影视云视听平台的前端架构与性能优化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 2:37:30

达梦数据库定时备份与清理任务实战:从图形化配置到自动化运维

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 2:35:05

n8n-mcp Docker 部署与连接 n8n 实例故障排查完全指南

n8n-mcp Docker 部署与连接 n8n 实例故障排查完全指南 【免费下载链接】n8n-mcp A MCP for Claude Desktop / Claude Code / Windsurf / Cursor to build n8n workflows for you 项目地址: https://gitcode.com/GitHub_Trending/n8/n8n-mcp 导读 本指南面向使用 Docke…

作者头像 李华