本文是知识卡。想知道
In/Out两个泛型参数到底换来了什么,看这张表。
签名长什么样
func(_ context.Context, request *CallToolRequest, input In) (result *CallToolResult, output Out, _ error)
In 和 Out 是泛型参数。写工具时可以只关心 input → output / error 这条线,request 和 result 直接传 nil。
In / Out 不是摆设
框架在背后做了这些事:
| 行为 | 触发条件 | 说明 |
|---|---|---|
| 生成默认 input schema | 总是 | 用 In 的类型推断;想自定义,在 mcp.Tool.InputSchema 里显式传一个覆盖 |
| 自动反序列化入参 | 总是 | 把客户端传来的 arguments 填进 input,不用自己 json.Unmarshal |
| 调用前校验参数 | 总是 | 不合法直接在协议层拒掉(InvalidParams),不用在业务代码里写校验 |
| 生成默认 output schema | Out 不是 any 时 |
成功路径下,结构化输出写进结果的 StructuredOutput |
| 自动补内容 | 没设置 result.Content 时 |
用输出 JSON 填上,方便「只关心返回一个 JSON 对象」的用法 |
| 把 error 当业务错误 | 返回非 nil error 时 | SDK 把描述塞进 content 并把 IsError 置为 true,符合 MCP 对工具调用失败的建模 |
什么时候才需要碰 request 和 result
只有这三种情况:
- 要读原始请求元数据(比如客户端的
_meta字段) - 要自定义返回的 content(比如返回图片、多段内容)
- 要精细控制结果的各个字段
其余时候让 SDK 补全就行。错误类型的选择见错误返回与重试。
参数是怎么从 In 推出来的
| 结构体里写的 | 变成 schema 的 |
|---|---|
字段名 + json 标签 |
属性名 |
| Go 字段类型 | 属性类型(string / array / integer …) |
jsonschema 标签 |
属性的 description,模型能读到 |
没有 omitempty |
进 required 列表 |
有 omitempty |
可选 |
枚举、默认值、最小值这些推断不出来的约束,靠 mcp.Tool.InputSchema 覆盖。完整做法见工具的参数。
mcp.Tool 的字段
| 字段 | 用途 |
|---|---|
Name |
工具名称,客户端靠它发起调用 |
Description |
给人看,也给模型看——模型靠它决定什么时候调用 |
InputSchema |
JSON Schema;不填时由 In 类型推断 |
OutputSchema |
输出结构;Out 不是 any 时自动推断 |
Title / Icons / Annotations |
展示与补充信息,进阶场景 |
完整定义见 pkg.go.dev。