从零构建一个 MCP Server:让 Claude 和 ChatGPT 接入你自己的工具 MCPModel Context Protocol是 Anthropic 提出的开放协议让 AI 模型通过标准化接口调用外部工具和数据源。本文带你从零构建一个实用的 MCP Server——一个能查询天气、管理本地文件、执行 Shell 命令的工具集合并接入 Claude Desktop 实际使用。1. 背景为什么需要 MCP2024 年底Anthropic 开源了 Model Context ProtocolMCP一个用于连接 AI 模型与外部工具和数据的开放标准。在此之前每个 AI 平台都有自己的 Function Calling / Tool Use API——OpenAI 有 function callingAnthropic 有 tool useGoogle 有 function declarations。虽然功能相似但接口各不相同。MCP 的目标是成为AI 世界的 USB-C 接口一个统一的协议让你写一次工具实现就能接入任何支持 MCP 的 AI 客户端Claude Desktop、Cursor、Continue 等。MCP 的架构很简洁只有三个角色MCP HostAI 应用本身如 Claude Desktop负责与用户交互MCP ClientHost 内部的协议客户端负责与 Server 通信MCP Server你编写的工具服务暴露具体的工具能力通信方式有两种stdio标准输入输出适合本地工具和 HTTPSSE适合远程服务。本文聚焦 stdio 方式因为它最简单、延迟最低。2. 上手用 Python SDK 搭建第一个 MCP Server2.1 环境准备pipinstallmcp --break-system-packagesMCP Python SDK 提供了装饰器风格的 API写起来和 FastAPI 很像。2.2 最小可运行示例# server.pyimportasynciofrommcp.serverimportServerfrommcp.server.stdioimportstdio_serverfrommcp.typesimportTool,TextContent# 创建 Server 实例serverServer(my-first-mcp-server)server.list_tools()asyncdeflist_tools()-list[Tool]:告诉客户端这个 Server 提供哪些工具return[Tool(nameecho,description将输入原样返回,inputSchema{type:object,properties:{message:{type:string,description:要回显的消息}},required:[message]}),Tool(nameadd,description计算两个数的和,inputSchema{type:object,properties:{a:{type:number,description:第一个数},b:{type:number,description:第二个数}},required:[a,b]})]server.call_tool()asyncdefcall_tool(name:str,arguments:dict)-list[TextContent]:处理工具调用请求ifnameecho:messagearguments[message]return[TextContent(typetext,textfEcho:{message})]ifnameadd:resultarguments[a]arguments[b]return[TextContent(typetext,textf结果:{result})]raiseValueError(f未知工具:{name})asyncdefmain():asyncwithstdio_server()as(read_stream,write_stream):awaitserver.run(read_stream,write_stream,server.create_initialization_options())if__name____main__:asyncio.run(main())这个仅 50 行的 server 提供了两个工具echo和add。把它保存为server.py然后用python server.py运行但先别急——单独运行它不会做任何事因为它在等待 stdio 上的 MCP 协议消息。2.3 接入 Claude Desktop在 Claude Desktop 的配置文件中注册这个 Server。macOS 上的配置文件路径是~/Library/Application Support/Claude/claude_desktop_config.json添加以下内容{mcpServers:{my-first-server:{command:python,args:[/path/to/server.py]}}}重启 Claude Desktop你应该能在工具列表中看到echo和add两个工具。试试对 Claude 说“用 echo 工具把 ‘Hello MCP’ 回显出来”或者用 add 工具算一下 3.14 加 2.86。3. 进阶构建一个实用的多功能 Server上面的示例只是玩具。下面我们构建一个实用的 Server包含三个实用工具天气查询、本地文件读取、Shell 命令执行。# practical_server.pyimportasyncioimportsubprocessimportjsonfrompathlibimportPathfrommcp.serverimportServerfrommcp.server.stdioimportstdio_serverfrommcp.typesimportTool,TextContent serverServer(practical-tools)# 模拟天气数据实际项目中替换为真实 API 调用WEATHER_DATA{北京:{temp:22,condition:晴,humidity:45%},上海:{temp:26,condition:多云,humidity:65%},深圳:{temp:30,condition:阵雨,humidity:80%},}server.list_tools()asyncdeflist_tools()-list[Tool]:return[Tool(nameget_weather,description查询指定城市的天气信息,inputSchema{type:object,properties:{city:{type:string,description:城市名称如北京、上海、深圳}},required:[city]}),Tool(nameread_local_file,description读取本地文件内容。请提供绝对路径,inputSchema{type:object,properties:{file_path:{type:string,description:文件的绝对路径}},required:[file_path]}),Tool(namerun_shell_command,description执行一个 Shell 命令并返回输出。⚠️ 仅用于只读操作如 ls, cat, wc 等不要执行破坏性命令,inputSchema{type:object,properties:{command:{type:string,description:要执行的 Shell 命令}},required:[command]})]server.call_tool()asyncdefcall_tool(name:str,arguments:dict)-list[TextContent]:ifnameget_weather:cityarguments.get(city,)weatherWEATHER_DATA.get(city)ifweather:textf{city}天气{weather[temp]}°C{weather[condition]}湿度{weather[humidity]}else:textf未找到城市「{city}」的天气数据。当前支持{, .join(WEATHER_DATA.keys())}return[TextContent(typetext,texttext)]ifnameread_local_file:file_patharguments.get(file_path,)pathPath(file_path)ifnotpath.exists():return[TextContent(typetext,textf错误文件不存在 -{file_path})]ifnotpath.is_file():return[TextContent(typetext,textf错误路径不是文件 -{file_path})]ifpath.stat().st_size1024*1024:# 1MB 限制return[TextContent(typetext,textf错误文件过大超过 1MB拒绝读取)]try:contentpath.read_text(encodingutf-8)# 截断过长的内容iflen(content)5000:contentcontent[:5000]\n\n... (内容已截断原文件共 {} 字符).format(len(content))return[TextContent(typetext,textcontent)]exceptUnicodeDecodeError:return[TextContent(typetext,textf错误无法以 UTF-8 解码该文件可能是二进制文件)]ifnamerun_shell_command:commandarguments.get(command,)# 安全检查拒绝明显危险的命令dangerous_patterns[rm ,sudo ,mkfs,dd , /dev/,format ]ifany(patternincommandforpatternindangerous_patterns):return[TextContent(typetext,textf安全拦截命令「{command}」包含潜在危险操作拒绝执行。)]try:resultsubprocess.run(command,shellTrue,capture_outputTrue,textTrue,timeout10)outputresult.stdoutifresult.stderr:output\n[stderr]\nresult.stderrifresult.returncode!0:outputf\n[退出码:{result.returncode}]iflen(output)5000:outputoutput[:5000]\n\n... (输出已截断)return[TextContent(typetext,textoutput)]exceptsubprocess.TimeoutExpired:return[TextContent(typetext,text错误命令执行超时10 秒)]exceptExceptionase:return[TextContent(typetext,textf错误命令执行失败 -{str(e)})]raiseValueError(f未知工具:{name})asyncdefmain():asyncwithstdio_server()as(read_stream,write_stream):awaitserver.run(read_stream,write_stream,server.create_initialization_options())if__name____main__:asyncio.run(main())4. 避坑清单与最佳实践经过实际使用这里有几个关键的经验教训工具描述description至关重要。模型是根据工具的名称和描述来决定是否调用、何时调用的。描述要写清楚三件事这个工具做什么、输入参数的含义、什么时候该用它。模糊的描述会导致模型调用不准确或完全不调用。inputSchema 是模型理解参数的唯一依据。如果参数是file_pathdescription 里最好写文件的绝对路径而不是简单写路径。模型会逐字读取 schema 中的 description 来推断参数应该填什么。错误处理要友好。工具调用失败时返回一个包含错误信息的 TextContent而不是抛出异常。这样模型可以根据错误信息调整策略比如换个文件名再试而不是直接崩溃。安全边界由你定义。MCP Server 运行在用户的机器上拥有和用户同等的权限。在暴露 Shell 命令执行、文件系统访问等能力时一定要加上安全限制路径白名单、命令黑名单、文件大小限制等。永远不要让模型有能力执行rm -rf /。stdio vs HTTP 的选择。stdio 适合个人使用和本地工具——零配置、低延迟、自动生命周期管理。HTTPSSE 适合团队共享的服务——多个客户端可以同时连接Server 可以独立部署和更新。资源Resources和提示Prompts是可选的加分项。MCP 协议除了 Tools 之外还定义了 Resources暴露数据如文件内容、数据库记录和 Prompts预定义的提示模板。对于大多数实用场景先从 Tools 开始就足够了。5. 总结MCP 实现了AI 使用工具的标准化。本文从一个 50 行的 echo server 出发逐步构建了一个包含天气查询、文件读取、Shell 执行的实用工具集。实际的 MCP Server 可以接入任何 API 或数据源——数据库查询、Slack 消息、Jira 工单、Git 操作——只要你能用 Python或 TypeScript写出来就能变成 AI 的工具。MCP 生态正在快速增长。截至 2026 年 5 月社区已经有上千个开源的 MCP Server覆盖了从 Notion 到 PostgreSQL 的几乎所有常见工具。如果你的团队还在为每个 AI 平台单独写 tool-use 适配层MCP 值得认真考虑。6. 参考资料Model Context Protocol 官方文档MCP 架构说明MCP Python SDK (GitHub)MCP TypeScript SDK (GitHub)Awesome MCP Servers (社区整理)