MCP
MCP 服务端
把真实系统通过受控协议边界暴露给 AI 客户端的那一层。
服务端职责
MCP 服务端把真实系统变成 AI 客户端可以发现和调用的能力。它负责集成细节、校验输入、执行动作,并返回结构化结果。
如何设计一个好能力
1
命名
使用动词 + 名词,比如 search_docs、create_ticket、validate_invoice。
2
描述
说明什么时候该调用它,以及它会返回什么结果。
3
输入 schema
把必填字段写清楚,能结构化就别让模型塞自由文本。
4
结果 schema
返回稳定、可预测的数据,避免让模型自己解析散文。
可直接复制的工具定义
这个定义故意不绑定框架。真实 MCP SDK 也可以通过协议 API 暴露同样的契约。
export const searchDocsTool = {
name: "search_docs",
description: "搜索文档页面,返回和新手问题相关的结果。",
inputSchema: {
type: "object",
required: ["query"],
properties: {
query: {
type: "string",
minLength: 1,
description: "用户问题里的搜索短语。"
},
limit: {
type: "number",
minimum: 1,
maximum: 10,
default: 3
}
}
}
}写处理器
处理器就是服务端自己负责的部分。验证要靠近执行,返回值结构要稳定。
export function handleSearchDocs(input, pages) {
const query = input?.query
const limit = input?.limit ?? 3
if (!query || typeof query !== "string") {
return capabilityError("INVALID_QUERY", "query 必须是非空字符串", false)
}
if (!Number.isInteger(limit) || limit < 1 || limit > 10) {
return capabilityError("INVALID_LIMIT", "limit 必须是 1 到 10 之间的整数", false)
}
const q = query.toLowerCase()
return {
results: pages
.filter((page) => `${page.title} ${page.body}`.toLowerCase().includes(q))
.slice(0, limit)
.map(({ title, url, body }) => ({ title, url, snippet: body }))
}
}
function capabilityError(code, message, retryable) {
return { error: { code, message, retryable } }
}错误行为
错误本身也是 API 的一部分。好的服务端会告诉你哪里坏了,以及客户端应该重试、补输入、问用户还是直接停下。
{
"error": {
"code": "MISSING_REQUIRED_FIELD",
"message": "customer_id 字段是必需的。",
"retryable": false,
"user_action": "请用户提供 customer id。"
}
}新手应该测试的三个错误
handleSearchDocs({}, pages)
// INVALID_QUERY:客户端应该先问用户要搜索短语。
handleSearchDocs({ query: "MCP", limit: 99 }, pages)
// INVALID_LIMIT:客户端应该用合法 limit 重试。
handleSearchDocs({ query: "billing" }, pages)
// 这不是错误。返回 { "results": [] },让 agent 继续说“没找到”。运营清单
权限把只读动作和写入/破坏性动作分开。
限流保护后端 API,并清楚说明重试限制。
可观测性记录工具调用、耗时、失败和结果大小。
版本管理输入或输出结构变化时,不要轻易破坏客户端。