MCP 协议从零搭建实战:手写一个文件搜索工具 Server

发布时间:2026/7/24 12:04:05
MCP 协议从零搭建实战:手写一个文件搜索工具 Server 前言说实话MCP 协议从去年底爆火到现在已经成了 AI 开发圈绕不开的话题。但你真要动手写一个 Server很多教程要么讲得太浅要么跳过了关键细节。今天就手把手带大家写一个文件搜索工具 MCP Server功能很简单让 AI 能通过 MCP 协议搜索本地文件。但麻雀虽小五脏俱全整个过程你能完整理解 MCP 的工作原理。MCP 是什么一句话说清楚MCP (Model Context Protocol) 是 Anthropic 去年推出的一种开源协议专门解决 AI 模型和外部工具之间的通信问题。通俗点说MCP 就是 AI 世界的 USB 接口。以前你给 AI 加功能每个 AI 有自己的一套插件系统像不同品牌的充电器不通用。MCP 统一了接口标准写一次工具任何支持 MCP 的 AI 客户端都能用。环境准备首先确保你的环境满足以下条件# Python 3.10python--version# 安装 MCP 开发包pipinstallmcp我们用 Python 实现因为生态最成熟。如果你不会 Python用 TypeScript 也行官方支持两种语言。第一步定义工具MCP Server 的核心是暴露工具Tool给 AI 调用。每个工具需要定义名称— AI 调用时用的标识符参数描述— 告诉 AI 需要什么参数实现逻辑— 实际干活的代码frommcp.serverimportServerfrommcp.typesimportTool,TextContentfromtypingimportAnyimportosimportfnmatch# 创建 Server 实例serverServer(file-search-server)# 注册工具server.list_tools()asyncdeflist_tools()-list[Tool]:return[Tool(namesearch_files,description搜索本地文件支持通配符模式,inputSchema{type:object,properties:{pattern:{type:string,description:文件搜索模式例如 *.py 或 data/*.csv},root_dir:{type:string,description:搜索根目录默认为当前目录},max_results:{type:integer,description:最大返回结果数默认 20,default:20}},required:[pattern]})]第二步实现工具逻辑工具定义好了接下来实现 AI 发起调用时实际执行的代码server.call_tool()asyncdefcall_tool(name:str,arguments:dict)-list[TextContent]:ifnamesearch_files:patternarguments[pattern]root_dirarguments.get(root_dir,.)max_resultsarguments.get(max_results,20)results[]forroot,dirs,filesinos.walk(root_dir):# 跳过隐藏目录dirs[:][dfordindirsifnotd.startswith(.)]# 跳过 node_modules 等大目录dirs[:][dfordindirsifdnotin(node_modules,__pycache__,.git,venv)]forfilenameinfiles:iffnmatch.fnmatch(filename,pattern):filepathos.path.join(root,filename)try:sizeos.path.getsize(filepath)results.append({path:filepath,size:size,size_str:format_size(size)})exceptOSError:continue# 按大小排序最大的在前results.sort(keylambdax:x[size],reverseTrue)resultsresults[:max_results]return[TextContent(typetext,textformat_results(results,pattern))]else:raiseValueError(fUnknown tool:{name})第三步传输层配置MCP 支持两种传输方式标准输入输出stdio和 SSEServer-Sent Events。本地开发用 stdio 最简单defformat_size(size:int)-str:格式化文件大小forunitin[B,KB,MB,GB]:ifsize1024:returnf{size:.1f}{unit}size/1024returnf{size:.1f}TBdefformat_results(results:list[dict],pattern:str)-str:格式化搜索结果ifnotresults:returnf没有找到匹配 {pattern} 的文件lines[f找到{len(results)}个匹配 {pattern} 的文件\n]forrinresults:lines.append(f-{r[path]}({r[size_str]}))return\n.join(lines)if__name____main__:frommcp.server.stdioimportstdio_serverimportasyncioprint(启动 MCP File Search Server...)asyncio.run(stdio_server(server))第四步配置客户端Server 写好了怎么让 AI 用起来以 Claude Desktop 为例{mcpServers:{file-search:{command:python,args:[path/to/search_server.py]}}}配置完成后重启 Claude DesktopAI 就能自动发现并使用你的文件搜索工具了。踩坑指南写 MCP Server 最常遇到的几个坑1. 参数描述不够详细AI 模型依赖参数描述来理解怎么用。如果描述太模糊AI 可能传错参数。建议每个参数都写清楚「这个参数干什么用的」「什么格式」。2. 超时处理MCP 默认有超时时间如果你的工具执行时间太长比如扫描几百万个文件AI 会超时。建议加入超时限制和进度反馈。3. 工具返回值太长AI 模型的上下文窗口有限一次性返回太多结果会被截断。建议加 max_results 限制或者分页返回。# 加入超时控制的改进版本importasyncioimportsignalasyncdefsearch_with_timeout(pattern,root_dir,max_results,timeout30):try:resultawaitasyncio.wait_for(search_files_async(pattern,root_dir,max_results),timeouttimeout)returnresultexceptasyncio.TimeoutError:return[{error:搜索超时请缩小搜索范围}]进阶玩法写完了基础版你还可以扩展更多功能文件内容搜索结合 grep 模式搜索文件内容实时文件监控用 watchfiles 监听文件变化多 Agent 协作让多个 MCP Server 协同工作总结MCP 协议的价值不在于技术有多复杂而在于它定义了一个通用的接口标准。以前的 AI 工具链像一个个孤岛MCP 就是连接这些孤岛的桥梁。写完这个 demo 你会发现MCP 本身并不难真正的难点在于设计好的工具接口。好的工具接口 清晰的参数描述 合理的错误处理 可预期的行为。下一步推荐你试试把搜索工具改成异步实现asyncio加上文件内容预览功能试试用 SSE 模式部署成远程服务有什么问题欢迎在评论区讨论