MCP 基础
Model Context Protocol(MCP)是一套让 AI 应用以统一方式发现和调用外部工具、资源与提示模板的开放协议。它解决的是接入边界,不替你解决权限、安全和业务正确性。
如果你正在区分相邻概念,先记住:Tool Calling 是模型提出结构化调用意图的方式,MCP 是 Host 与能力提供方之间的连接协议,Agent 是多轮任务运行系统,Harness 则负责上下文、权限、执行、审批、验证和恢复。完整分层由 Tool Calling、MCP 与 Agent 的关系统一说明,本页只展开 MCP 接入。
本页属于 AI Harness 工程化专题。
角色与原语
- Host 管理用户会话、模型和整体权限。
- Client 负责与一个 Server 建立协议连接。
- Server 暴露工具、资源和提示模板。
- Tool 执行动作,Resource 提供可读取数据,Prompt 提供可复用模板。
调用链
MCP 调用流程必须和协议版本一起理解。旧版 SDK 常见 initialize 与会话协商;2026-07-28 版本的 Streamable HTTP 传输改为无握手、无会话契约,不应继续发送旧 initialize。下面展示本站当前采用的 2026-07-28 思路:
带 Mcp-Method / Mcp-Name 的无状态请求
-> tools/list 或 resources/list
-> tools/call
-> 返回结构化结果
-> Host 将结果交给模型如果维护旧 Client/Server,先确认双方协议版本,再按对应版本实现;不能把旧握手与新请求头混在一条调用链里。
工具描述应包含名称、用途、输入 schema、错误语义和副作用说明。工具返回值也应区分文本、结构化数据和用户可见资源。
最小 Go Server 思路
下面是协议实现的结构示意,实际项目应使用对应版本的官方 SDK 或经过验证的实现:
type SearchInput struct {
Query string `json:"query"`
}
func Search(ctx context.Context, input SearchInput) (any, error) {
if strings.TrimSpace(input.Query) == "" {
return nil, errors.New("query is required")
}
return index.Search(ctx, input.Query)
}不要把任意 Shell 暴露成一个名为 run 的万能工具。拆成 go_test、read_file、search_symbol 等边界清楚的工具,并对每个输入做校验。
接入真实仓库:从只读能力开始
第一次把 MCP 接入代码仓库时,优先实现 repo_info、read_file、search_symbol 这类只读能力,而不是直接开放 write_file 或 Shell。
一个仓库 Tool 至少应把以下信息作为显式输入或由 Host 注入:
{
"workspace_id": "repo-42",
"path": "internal/order/service.go",
"revision": "6ab292c",
"request_id": "req-1001"
}workspace_id映射到服务端已授权的仓库根目录,不能接受客户端传入任意绝对路径;path规范化后必须仍位于该根目录内;revision让读取与后续修改基于同一仓库快照,避免上下文过期;request_id贯穿 Host、Client、Server 和下游仓库服务,便于审计。
Server 仍需按调用者身份校验仓库、分支、路径和动作。Host 只向模型暴露某个 Tool 是上下文裁剪,不是授权;MCP 连接建立成功也不代表当前用户自动拥有 Server 后面的代码库权限。
当只读链路稳定后,再将写入拆成“生成补丁—预览 diff—人工确认—应用补丁—运行验证”几个动作。这样审批针对可见变更,而不是针对一句模糊的“允许 Agent 修改代码”。
stdio 适用场景
stdio 适合本机单用户工具:
- Server 与 Host 在同一台机器;
- 进程由 Host 启动和回收;
- 不需要远程共享;
- 权限可以继承本地工作区边界。
日志不要写入协议标准输出,否则会破坏 JSON-RPC 消息;把诊断日志写到 stderr 或独立文件。
JSON-RPC 错误
把错误分为:
- 参数校验失败:调用者可以修正输入;
- 权限失败:需要审批或换身份;
- 业务失败:外部系统拒绝或状态不满足;
- 临时失败:可以在预算内重试;
- 内部错误:需要记录 trace id 并人工排查。
练习
- 设计一个只读
search_symbolTool 的输入和输出 schema。 - 解释为什么 MCP Server 的日志不能随意写 stdout。
- 为一个会修改代码的 Tool 写出三条权限和审计要求。