MCPSkill
Mcp和Skill市场MCP 与 Skill
示例

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 能直接拿到可用字段。
错误设计错误要告诉客户端重试是否有意义。