示例
MCP 服务端示例
一个可以复制的新手例子,用来设计、实现和测试一个 MCP 风格能力。
目标
做一个叫 search_docs 的小文档搜索能力。它接受查询词,并返回包含标题、URL 和摘要的匹配页面。
能力清单
先写契约。真正的 MCP 服务端会通过协议暴露这些信息;这里用一个简化例子让它更容易看懂。
{
"name": "search_docs",
"description": "搜索文档页面并返回相关结果。",
"inputSchema": {
"type": "object",
"required": ["query"],
"properties": {
"query": { "type": "string", "description": "搜索词。" },
"limit": { "type": "number", "description": "最大结果数。" }
}
},
"outputSchema": {
"type": "object",
"properties": {
"results": {
"type": "array",
"items": {
"type": "object",
"properties": {
"title": { "type": "string" },
"url": { "type": "string" },
"snippet": { "type": "string" }
}
}
}
}
}
}能力处理器
这段故意写成纯 JavaScript,让新手可以先复制理解行为,再接入任何服务端框架。
// search-docs.js
const pages = [
{
title: "MCP 架构",
url: "/mcp/architecture",
body: "客户端发现服务端。服务端暴露工具、资源和提示词。"
},
{
title: "MCP 服务端",
url: "/mcp/server",
body: "服务端负责校验输入、执行能力,并返回结构化结果。"
},
{
title: "Skill 结构",
url: "/skill/structure",
body: "Skill 包含 SKILL.md,以及可选的 references、scripts 和 assets。"
}
]
export function searchDocs(input) {
const query = input?.query
const limit = input?.limit ?? 5
if (!query || typeof query !== "string") {
return {
error: {
code: "INVALID_INPUT",
message: "query 必须存在且必须是字符串",
retryable: false
}
}
}
const normalized = query.toLowerCase()
const results = pages
.filter((page) => `${page.title} ${page.body}`.toLowerCase().includes(normalized))
.slice(0, limit)
.map((page) => ({
title: page.title,
url: page.url,
snippet: page.body
}))
return { results }
}测试处理器
// test-search-docs.js
import { searchDocs } from "./search-docs.js"
console.log("成功场景")
console.log(JSON.stringify(searchDocs({ query: "server", limit: 2 }), null, 2))
console.log("错误场景")
console.log(JSON.stringify(searchDocs({ query: "" }), null, 2))这个例子教什么
发现客户端要先有名称、描述和 schema,模型才知道该不该选它。
校验服务端会在碰真实系统前先拒绝坏输入。
结构化结果agent 能直接拿到可用字段。
错误设计错误要告诉客户端重试是否有意义。