ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

从零实现Agent搜索MCP Server:接入Claude、Dify与Cursor

从零实现Agent搜索MCP Server:接入Claude、Dify与Cursor 先分享一个最近的实践体会和朋友讨论 Agent 生态时发现很多团队都在做自己的 Agent 市场或者 Agent 目录但用户真正想用的时候往往要在网页里搜到 Agent 说明再去对应客户端里手动配置。整个流程非常割裂。MCPModel Context Protocol出现后这个体验可以做成闭环把“搜索 AI Agent”的能力封装成一个 MCP Server任何支持 MCP 的客户端都能直接调用不用重复开发集成层。这篇文章就来拆解这个思路。我们会从 MCP 的核心概念讲起然后从零实现一个“Agent 搜索类 MCP Server”最后分别接入 Claude Desktop、Dify、Cursor 这类常见客户端并整理实际开发中容易踩的坑。如果你正在做 Agent 平台、AI 工具聚合、或者想给自己的业务加一个“AI 能直接调用的搜索能力”这篇文章会比较适合你。学完后你能理解 MCP Server 的完整开发流程也能照着代码跑通一个本地服务。1. 弄清楚 MCP 是什么以及为什么要用它1.1 MCP 解决的核心问题MCP 的全称是 Model Context Protocol中文一般叫“模型上下文协议”。它由 Anthropic 提出并开源目标是统一 AI 应用与外部数据源、工具之间的连接方式。在 MCP 出现之前每接入一个 AI 工具开发团队差不多都要写一套专用集成给 Claude 写一套工具调用给 ChatGPT 写一套 Plugin给 Dify 写一套自定义工具给 Cursor 再写一套扩展。这种“点对点”集成的维护成本很高而且 AI Agent 每换一个客户端能力就无法复用了。MCP 把连接方式标准化以后“三方关系”变得很清晰MCP Host承载 AI 能力的进程比如 Claude Desktop、Dify、Cursor、自研 Agent。MCP ClientHost 内部与 Server 建立连接的组件负责协议通信。MCP Server对外提供工具、资源、提示词等能力的服务通过 MCP 协议暴露给 Client。也就是说你的 AI Agent 搜索能力只需要实现一次做成一个 MCP Server就能被不同客户端复用。1.2 为什么是“Search AI Agents from Any MCP Client”现在很多 AI Agent 平台会提供 Agent 市场用户可以按分类、标签、评分搜索 Agent。但搜索入口通常停留在 Web 页面。如果让 AI 助手能直接调用这个搜索能力用户就可以在聊天中完成搜索某个领域 Agent、查看其能力描述、获取调用建议甚至一键拉起对话。要做到这一点最合适的方式不是再去开发一款新的 App而是把 Agent 搜索封装成 MCP Server。只要对方客户端支持 MCP就能通过自然语言触发搜索工具。这也是“Buy My Agent MCP Server”这类产品能成立的原因它在卖的不是传统 API而是“AI 可以直接使用的服务能力”。1.3 MCP Server 与普通 API Server 的区别很多开发者会问既然我有 REST API为什么还要转成 MCPREST API 解决的是“程序调用程序”的问题AI 要使用它还需要额外知道接口地址、鉴权方式、参数格式、返回结构这些都需要人工写代码对接。MCP Server 在协议层就解决了这个问题。它把接口描述、参数结构、调用权限这些信息以标准化的元数据暴露给 Client。AI Agent 通过 MCP 协议自动发现工具能力按标准格式传参再拿到结构化返回结果。从“教 AI 怎么用你的接口”变成了“AI 通过协议自然学会用你的工具”。2. 环境准备与版本说明2.1 运行环境本文的实操案例使用 Node.js TypeScript因为官方 SDK 支持较完整生态也比较成熟。如果你更熟悉 Python也可以参考类似的思路使用mcpPython SDK。项目说明操作系统Windows / macOS / Linux 均可运行时Node.js 18 或更高版本含 npm语言TypeScript编译后运行核心依赖modelcontextprotocol/sdk、zod测试客户端Claude Desktop、Dify、Cursor 或任意 MCP Client版本需要根据你的项目实际情况调整。MCP 协议本身迭代速度不慢本文示例以常见环境为例重点演示配置思路具体 API 以你安装的 SDK 版本为准。2.2 初始化项目先创建一个新目录并初始化 npm 项目mkdir agent-search-mcp-server cd agent-search-mcp-server npm init -y然后安装核心依赖npm install modelcontextprotocol/sdk zod npm install -D typescript types/node tsx创建tsconfig.json{ compilerOptions: { target: ES2022, module: NodeNext, moduleResolution: NodeNext, outDir: ./dist, rootDir: ./src, strict: true, esModuleInterop: true, skipLibCheck: true, resolveJsonModule: true }, include: [src/**/*], exclude: [node_modules] }这里的关键配置是module和moduleResolution。Node.js 目前对 ESM 支持成熟使用 NodeNext 可以避免 CommonJS 和 ESM 之间的兼容问题。3. MCP Server 核心概念拆解在写代码之前需要先理解 MCP Server 暴露能力的三种主要载体。它们是之后写所有工具的基础。3.1 Tools让模型执行动作Tools 是 MCP Server 最常用的一种能力载体。它对应 AI Agent 的“动作”能力例如搜索 Agent、获取 Agent 详情、提交评价等。一个 Tool 由三部分组成名称机器可读的唯一标识。描述告诉模型这个工具能做什么模型会依据描述决定是否调用。输入 Schema定义参数的结构和约束通常用 JSON Schema 描述。server.registerTool( search_agents, { title: 搜索 AI Agent, description: 根据关键词和分类搜索可用的 AI Agent 列表, inputSchema: { type: object, properties: { keyword: { type: string, description: 搜索关键词 }, category: { type: string, description: 分类筛选可空 }, limit: { type: number, minimum: 1, maximum: 20, default: 5 } }, required: [keyword] } }, async (args) { // 业务逻辑 return { content: [{ type: text, text: 搜索结果 }] }; } );这里需要注意的是模型的工具调用并不保证参数一定合理。开发者要在执行阶段做好参数校验和兜底。zod的作用就是帮助我们完成这部分校验。3.2 Resources让模型读取上下文Resources 对应“读取”能力用于向模型暴露结构化上下文例如项目文档、Agent 的使用说明、配置文件片段。server.registerResource({ name: agent-usage-guide, mimeType: text/markdown, uri: guide://usage }, async (uri) ({ contents: [{ uri: guide://usage, mimeType: text/markdown, text: # Agent 使用指南\n\n通过搜索工具可以查找可用 Agent。 }] }));Resource 一般不需要模型“思考要不要调用”它更像上下文注入。对于 Agent 搜索服务来说我们可以把热门搜索词、分类白名单做成 Resource减少模型乱猜分类的概率。3.3 Prompts为模型提供可复用的提示词Prompts 允许 Server 向 Client 暴露预设提示词模板。它适合定义“搜索某种 Agent 的标准表达方式”。server.registerPrompt( search-agent-template, { title: Agent 搜索提示词模板, description: 将用户输入转化为结构化的 Agent 搜索需求, arguments: [ { name: userInput, description: 用户的原始需求, required: true } ] }, async (args) ({ messages: [{ role: user, content: { type: text, text: 请从用户需求中提取关键词和分类然后调用搜索工具。用户需求${args.userInput} } }] }) );3.4 通信机制stdio 与 SSEMCP Server 与 Client 之间的通信主要分两种。stdioServer 作为子进程启动Client 通过标准输入输出传输 JSON-RPC 消息。适合本地开发、桌面客户端接入。SSEServer-Sent EventsServer 作为独立 HTTP 服务Client 通过 HTTP 连接。适合远程部署、多客户端共享。开发初期推荐先用 stdio 模式调试起来直观也便于定位问题。需要给远端团队共享时再切换到 SSE。4. 完整实战构建 Agent 搜索 MCP Server下面进入重点章节。我们实现一个本地可运行的 Agent 搜索 MCP Server。它内部维护一份 Agent 列表通过搜索工具暴露给任何 MCP Client。4.1 项目结构agent-search-mcp-server/ ├── package.json ├── tsconfig.json ├── .env.example └── src/ ├── index.ts // 入口加载配置并启动服务 ├── server.ts // MCP Server 实例与工具注册 ├── types.ts // 类型定义 └── agent-service.ts // Agent 搜索业务逻辑4.2 定义类型与搜索逻辑先建立 Agent 数据模型和搜索逻辑。src/types.ts:export interface AIAgent { id: string; name: string; description: string; category: string; tags: string[]; author: string; rating: number; endpoint?: string; } export interface SearchResult { total: number; items: AIAgent[]; }src/agent-service.ts:import { AIAgent, SearchResult } from ./types.js; // 模拟的 Agent 数据库生产环境可替换为 API 或数据库查询 const MOCK_AGENTS: AIAgent[] [ { id: agent-code-review-01, name: CodeReviewGPT, description: 自动审查代码质量发现潜在 Bug 和安全风险, category: 开发, tags: [code, review, security], author: example-team, rating: 4.8 }, { id: agent-data-analysis-01, name: DataPilot, description: 连接数据库通过自然语言生成 SQL 并分析数据, category: 数据分析, tags: [sql, database, analysis], author: example-team, rating: 4.6 }, { id: agent-doc-writer-01, name: DocWriter, description: 根据对话内容自动生成项目文档和接口文档, category: 效率, tags: [document, writing], author: example-team, rating: 4.5 } ]; export class AgentService { private agents: AIAgent[]; constructor() { this.agents MOCK_AGENTS; } async search(keyword: string, category?: string, limit 5): PromiseSearchResult { const kw keyword.trim().toLowerCase(); let filtered this.agents.filter((agent) { const matchedKeyword agent.name.toLowerCase().includes(kw) || agent.description.toLowerCase().includes(kw) || agent.tags.some((tag) tag.toLowerCase().includes(kw)); const matchedCategory category ? agent.category category : true; return matchedKeyword matchedCategory; }); // 按评分降序再截取数量 filtered.sort((a, b) b.rating - a.rating); const items filtered.slice(0, limit); return { total: items.length, items }; } }搜索结果按评分排序是关键逻辑之一。用户通过自然语言搜索时往往期望排在前面的是更可靠的 Agent。4.3 注册 Tool 到 MCP Serversrc/server.ts是核心文件负责创建 MCP Server 实例并注册工具。import { McpServer } from modelcontextprotocol/sdk/server/mcp.js; import { z } from zod; import { AgentService } from ./agent-service.js; export function createAgentSearchServer() { const server new McpServer({ name: agent-search-server, version: 1.0.0 }); const agentService new AgentService(); server.registerTool( search_agents, { title: 搜索 AI Agent, description: 根据关键词、分类和数量限制搜索可用的 AI Agent 列表。当用户需要查找 Agent、推荐 AI 工具或解决某个场景问题时可以调用此工具。, inputSchema: { type: object, properties: { keyword: { type: string, description: 搜索关键词例如代码审查、数据分析 }, category: { type: string, description: 分类名称可选例如开发、数据分析、效率 }, limit: { type: number, description: 最大返回条数范围 1-10默认 5 } }, required: [keyword] } }, async (args) { const keyword args.keyword; const category args.category || undefined; const limit args.limit || 5; const result await agentService.search(keyword, category, limit); return { content: [ { type: text, text: JSON.stringify(result, null, 2) } ] }; } ); server.registerTool( get_agent_detail, { title: 获取 Agent 详情, description: 根据 Agent ID 获取某个 AI Agent 的详细信息, inputSchema: { type: object, properties: { agentId: { type: string, description: Agent 的唯一标识 } }, required: [agentId] } }, async (args) { const agents await agentService.listAll(); const agent agents.find((item) item.id args.agentId); if (!agent) { return { content: [{ type: text, text: 未找到该 Agent }], isError: true }; } return { content: [{ type: text, text: JSON.stringify(agent, null, 2) }] }; } ); return server; }如果你发现inputSchema的写法在你的 SDK 版本中不生效可以改用registerTool的 zod 形式server.registerTool( search_agents, { title: 搜索 AI Agent, description: 根据关键词搜索可用的 AI Agent 列表 }, { keyword: z.string().describe(搜索关键词), category: z.string().optional().describe(分类名称), limit: z.number().min(1).max(10).default(5).describe(最大返回条数) }, async ({ keyword, category, limit }) { // 业务逻辑 } );这种写法在类型推导上更友好建议优先使用。具体重载形式参照你安装的 SDK 类型声明即可。4.4 创建服务入口src/index.ts负责接入 stdio 传输层把标准输入输出作为 MCP 通信通道。import { StdioServerTransport } from modelcontextprotocol/sdk/server/stdio.js; import { createAgentSearchServer } from ./server.js; async function main() { const server createAgentSearchServer(); const transport new StdioServerTransport(); await server.connect(transport); console.error(Agent Search MCP Server running on stdio); } main().catch((error) { console.error(Fatal error in main():, error); process.exit(1); });注意这里不能用console.log输出调试信息。因为 stdio 模式下标准输出是 MCP 协议通信通道所有日志必须走标准错误输出也就是console.error否则会破坏 JSON-RPC 消息格式。4.5 配置 npm scripts 并编译运行修改package.json中的 scripts{ scripts: { dev: tsx src/index.ts, build: tsc, start: node dist/index.js } }启动服务npm run dev服务启动后不会有明显输出因为它正在等待 MCP Client 通过 stdio 发起连接。此时不要急着 CtrlC我们下一步会把它接入客户端测试。5. 从任意 MCP Client 连接与测试5.1 在 Claude Desktop 中添加本地 MCP ServerClaude Desktop 是 MCP 官方支持度最高的客户端之一。配置方式通常是编辑客户端的配置文件。macOS 路径~/Library/Application Support/Claude/claude_desktop_config.jsonWindows 路径%APPDATA%\Claude\claude_desktop_config.json添加内容{ mcpServers: { agent-search: { command: node, args: [/absolute/path/to/agent-search-mcp-server/dist/index.js] } } }修改后重启 Claude Desktop在会话中提问“搜索代码审查相关的 AI Agent”。正常情况下Claude 会调用search_agents工具并返回搜索结果。如果项目使用tsx直接启动也可以把 command 改为项目本地的 tsx 执行入口但生产环境建议先编译为 JS。5.2 在 Dify 中添加本地 MCP 服务Dify 支持 MCP 服务的接入。进入工作台后在“工具”或“插件”页面找到 MCP 配置入口选择“添加 MCP 服务”类型选择 stdio命令node参数/absolute/path/to/agent-search-mcp-server/dist/index.js环境变量按需设置配置完成后Agent 应用即可通过“工具”节点调用搜索能力。Dify 中需要注意的是不同版本对 MCP 的配置入口差异较大如果找不到入口优先查看对应版本文档而不是直接复制社区里的老配置。5.3 通过 .mcp 文件接入支持 MCP 的 IDE近期的开发工具例如 Trae、Cursor 等开始支持.mcp文件作为项目级 MCP 配置。你可以在项目根目录创建.mcp文件{ mcpServers: { agent-search: { command: node, args: [/absolute/path/to/agent-search-mcp-server/dist/index.js] } } }.mcp文件的作用是把 MCP Server 配置随项目共享团队其他成员拉取代码后自动获得工具能力。这个配置方式对开发类 Agent 场景尤其合适。5.4 使用 MCP Inspector 调试官方提供的modelcontextprotocol/inspector可以在没有完整客户端的情况下测试 MCP Server。npx modelcontextprotocol/inspector node dist/index.js启动后浏览器打开 Inspector 页面可以看到 Server 暴露的 Tools、Resources、Prompts 列表也可以直接填入参数调用工具并查看返回结果。这个工具能帮你快速定位参数 Schema 写错、返回结构不标准等问题。6. 常见问题与排查思路MCP Server 开发过程中不同类型的客户端会有各自奇怪的报错。这里整理几个最常遇到的问题。问题现象常见原因解决思路启动后没有任何输出stdio 模式下标准输出被占用检查代码里不要使用 console.log日志全部改用 console.error客户端提示failed to start login server或 token exchange failed客户端连接远程 MCP Server 时鉴权失败本地开发优先切到 stdio 模式远程部署检查访问令牌和网络策略Windows 下客户端启动失败路径分隔符或命令格式问题使用绝对路径JSON 配置中反斜杠需转义为\\\\或使用正斜杠工具调用报参数解析失败inputSchema 与业务代码参数不匹配用 Inspector 检查实际发送的参数结构和 Schema 一一比对修改代码后客户端仍使用旧逻辑客户端缓存了旧的 stdio 子进程重启客户端或先结束残留的 node 子进程远程服务部署后客户端连接超时防火墙或 SSE 路径配置问题确认端口开放SSE 模式需要让 Server 支持跨域访问路径需与 SDK 端点一致在多个客户端间切换时最容易忽略的是“同一个 MCP Server 是否支持同时被多个客户端连接”。stdio 模式下每个客户端会启动一个独立子进程因此不存在并发问题。SSE 模式下需要额外处理并发和会话隔离。7. 最佳实践与工程建议7.1 工具描述要写“模型能看懂的话”MCP 的工具描述不是给人类看的 API 文档而是给大模型做工具选择的依据。描述越具体模型越可能在正确的场景下调用工具。错误写法搜索 Agent正确写法根据用户需求搜索可用的 AI Agent 列表。当用户需要查找 Agent、推荐 AI 工具、寻找某个场景解决方案时调用此工具。支持通过关键词和分类筛选。如果搜索结果为空请提示用户更换关键词。7.2 参数类型必须完整约束使用 zod 或 JSON Schema 时尽量把类型约束写全字符串长度、数字范围、枚举值、是否必填。这既能减少非法请求也能让模型在调用前自主判断参数是否符合要求。7.3 不要把敏感信息写进代码Agent 搜索服务可能会接入付费 API 或内部数据库这时候密钥管理非常重要。建议通过环境变量注入并在.env.example中只保留占位说明不提交真实密钥。AGENT_API_ENDPOINThttps://api.example.com/agents AGENT_API_KEYyour-key-here7.4 返回结构要稳定MCP 工具最终返回给模型的是一段文本。建议一律使用 JSON 字符串并且保持字段稳定。模型对固定结构的理解能力远强于自由文本字段不稳定会直接影响后续多轮对话中的引用效果。7.5 注意超时与重试机制模型调用工具时用户耐心有限。远程 API 调用建议设置超时时间超时后返回友好错误信息同时通过isError: true标记失败方便模型向用户解释。const controller new AbortController(); const timeout setTimeout(() controller.abort(), 5000); try { const response await fetch(endpoint, { signal: controller.signal }); // ... } catch (error) { return { content: [{ type: text, text: 搜索服务超时请稍后重试 }], isError: true }; } finally { clearTimeout(timeout); }7.6 权限与安全边界MCP Server 暴露给 AI Agent 的能力本质上是可被自动化调用的接口。在权限设计上要遵循最小原则只暴露必要工具不暴露与业务无关的内部方法。远程部署必须做鉴权不裸奔。对用户输入做校验防止注入恶意参数。涉及数据库、文件、支付等敏感操作必须在工具描述中明确提示并在代码层增加二次确认机制。7.7 版本管理与发布MCP Server 与普通 npm 包一样建议使用语义化版本管理。升级工具 Schema 时要注意向后兼容因为不同的客户端可能缓存了旧的工具定义。如果你的目标是让外部团队也能使用这个 MCP Server可以考虑发布到 npm 并维护一个精简的 README说明启动命令、环境变量、工具能力列表和配置案例。8. 下一步可以做什么到这里一个可复用的 Agent 搜索 MCP Server 已经跑通了从 MCP 基础概念到 TypeScript 开发再到 Claude Desktop、Dify、IDE 客户端接入最后还覆盖了常见报错排查和生产环境建议。你可以沿着几个方向继续深入把本地 Mock 数据替换为真实 Agent 目录 API增加缓存层和限流。将 stdio 传输切换为 SSE 模式部署到服务器让团队多人共享一个服务。增加 Resources 能力例如定期同步热门 Agent 分类让模型在搜索前先了解分类体系。尝试用 Python SDK 重写一遍对比不同语言生态下的开发体验。为你的 MCP Server 制作一个.mcp文件分发包方便团队一键接入。MCP 生态还处在快速演进期工具注册方式、传输层协议、客户端支持范围都可能有变化。但只要抓住“Server 暴露能力、Client 消费能力、协议标准化连接”这个核心后续不管 SDK 怎么升级你都能很快跟过来。建议现在就动手跑一个最小示例。不用一次做完整功能先让搜索工具能在 Claude Desktop 里被调用再逐步加细节。这个正反馈循环会让后续学习顺畅很多。
返回列表