
最近两周我一直在折腾一件事给自己常用的 AI 助手装上一双能直接操作 Excel 的“手”。起因特别简单——每周我都要整理销售明细、汇总多张报表、按客户维度做数据透视这些活虽然不复杂但极其耗时。传统的做法是写 VBA、用 Python 脚本或者手动复制粘贴每次需求一变化代码就得跟着改效率很低。后来我接触到MCPModel Context Protocol突然意识到与其让 AI 只做一个“聊天框”不如把它变成一个真正能干活的工作流引擎而 Excel 就是最好的切入点。这篇博文我就完整记录一下“开发自己的第一个 MCP——用 AI 重构 Excel 处理工作流”的全过程。从协议的概念拆解、开发环境准备到 Server 端代码实现再到接入 AI 客户端实测最后附上我踩过的坑和排查实录。如果你也天天跟 Excel 打交道又想用 AI 把这些重复劳动自动化这篇文章应该能帮你少走不少弯路。不管你是开发出身还是数据分析岗只要愿意折腾照着下面的步骤走就能拥有一套属于你自己的 AIExcel 自动化工作流。1. 为什么我要用 MCP 重构 Excel 处理工作流1.1 传统 Excel 自动化的三个痛点在动手之前先聊聊旧方案为什么让我越来越不舒服。以前处理 Excel我基本就靠三样东西Excel 自带的函数和透视表、VBA 宏、以及临时抱佛脚的 Python 脚本。函数和透视表的问题在于它们只能处理“规则明确”的数据。比如“统计某列含关键词的对应数值总和”这种需求用 SUMIF 系列函数可以做但一旦关键词变成动态的、或者说需求变成“帮我看看这个表格里有哪些异常”函数就无能为力了。VBA 宏则更尴尬——录制宏只能解决重复操作遇到数据结构变化就得改代码而且 VBA 的语法对现代开发者来说太古老了调试起来非常痛苦。我见过太多同事的宏换个 Sheet 名字就崩那真的是在维护“祖宗代码”。Python 脚本比如用 pandas 或 openpyxl在数据处理能力上确实强但它有一个致命问题脚本只能干你预先写好的事。你说“帮我统计 A 列的异常值”脚本得先定义什么是“异常”你说“帮我按区域汇总”脚本得先知道你有哪些区域。这其实是在用另一种方式写规则根本没用到 AI 的“理解力”。1.2 MCP 到底解决了什么问题MCP 的全称是 Model Context Protocol名字里“上下文”三个字很关键。它本质上是一个标准化协议让 AI 模型能够以统一的方式调用外部工具、读取外部数据源。你可以把它理解成一个 USB 接口——以前 AI 只是显示器只能看不能摸MCP 就是那个 USB 口插上打印机、扫描仪、移动硬盘AI 就变成了全能办公台。具体到我的 Excel 场景MCP 带来的核心改变是AI 有了“手”它不仅能理解“帮我统计每个区域的平均销售额”还能真正打开 Excel 文件、读取数据、做计算、甚至把结果写回新文件。工作流变成对话以前处理一份报表要写一个脚本现在我可以直接跟 AI 说“先看一下这个表的结构然后按客户类型分组把异常值标出来”它会自主规划、调用工具、返回结果。可复用性强同一套 MCP Server接 Claude、接国内大模型、接自己写的 Agent 都能用。工具写在 Server 端客户端随时换不用重新开发。1.3 为什么选 Excel 作为第一个 MCP 项目说实话第一个 MCP 项目选择 Excel除了它确实是我的刚需场景还有一个原因Excel 数据结构的“确定性”非常适合作为协议入门的练兵场。MCP 涉及服务端、客户端、工具协议、参数定义这么多概念如果你一上来就调外部 API、搞实时数据流光是调试环境就能劝退一半人。但 Excel 的文件读写、单元格操作、数据筛选这些功能逻辑上非常直白——读文件、解析 Sheet、执行操作、返回结果。这种清晰的功能边界让我能把注意力集中在理解 MCP 协议本身而不是被复杂业务逻辑带偏。而且 Excel 处理是典型的“AI 能听懂、但自己干不了”的任务。AI 非常擅长理解“帮我统计这三张表的合同金额汇总”但它天然没有文件系统访问能力也没有表格计算能力。MCP 正好把这两者接起来。2. 开发环境准备与 MCP 协议基础2.1 开发环境与工具选型先交代一下我最终的开发环境都是目前社区里最主流、文档最全的搭配组件选择说明编程语言Python 3.10MCP 官方 SDK 支持最好生态链完善MCP SDKmcpPython 包官方提供的协议实现已支持 typescript但 Python 更直观Excel 操作库openpyxlpandas分别负责 xlsx 读写和数据处理客户端Claude Desktop或支持 MCP 的客户端用于验证 Server 能否被 AI 调用辅助工具uvPython 包管理器用 uv 管理虚拟环境比 pip 更清爽这里说一个小小的选择理由为什么不用 xlwings 或 win32com因为这两个库强依赖 Windows 上的 Excel COM 接口一旦服务器上没有安装 Microsoft Excel 就直接歇菜。而openpyxl是纯 Python 实现跨平台无痛处理普通的 xlsx 文件完全够用。如果只是做数据分析和报表处理openpyxl 加 pandas 的组合已经能覆盖九成需求。安装命令也很简单用 uv 初始化项目并添加依赖uv init excel-mcp-server cd excel-mcp-server uv add mcp openpyxl pandas如果你还没有安装 uv直接用 pip 也是可以的只是虚拟环境管理上稍微繁琐一点。这一套下来整个项目就是一个标准的 Python 包结构后面写工具逻辑会很顺手。2.2 MCP 架构拆解三大角色是干什么的在写代码之前花五分钟搞清楚 MCP 的架构模型非常重要。很多教程一上来就贴代码结果读者连 Server、Client、Tool 之间的关系都没弄明白遇到报错就抓瞎。MCP 架构里就三个核心角色MCP Host宿主就是 AI 聊天客户端本身比如 Claude Desktop、各种支持 MCP 的 IDE。它向用户显示对话并在后台管理多个 MCP Server 的会话。MCP Server服务端轻量级服务暴露出特定功能。在我这个项目里它暴露的就是 Excel 的读写、统计、sheet 操作等能力。每个 Server 可以声明多个 Tool。MCP Client客户端在 Host 进程内部负责与 Server 建立一对一的连接。它是协议的实际发起方。这里最容易混淆的就是 Host 和 Client 的关系。用一句大白话解释Host 是你的微信Client 是你微信里打开的各个小程序Server 是提供数据和服务的外部商家。你在微信里跟朋友聊天顺手点开一个小程序订咖啡——聊天是 Host 的功能小程序运行依赖 Client而真正给你做咖啡的是商家Server的机器。在这个 Excel 项目中我要做的就是那个“商家”——实现一个 Server里面提供诸如read_excel、write_excel、get_sheet_names这样的工具。AI 客户端Host收到用户指令“帮我把这些 Excel 合并了”后会通过 Client 调用我的 Server 暴露出来的工具再把工具返回的结果组织成自然语言回复给用户。2.3 MCP Server 的两种传输方式MCP 协议支持两种传输方式虽然现在很多入门教程会跳过但你后续部署到远程服务器、或者接到 Web 应用里时大概率会碰到提前知道很有用stdio标准输入输出Server 作为 Host 的一个子进程运行通过 stdin/stdout 进行 JSON-RPC 通信。这是本地开发最常用、最省事的方式。Claude Desktop 连接本地 MCP Server 用的就是这种。HTTP SSEServer-Sent EventsServer 作为独立服务运行Host 通过 URL 连接。适合部署在服务器上、多人共用、或者需要跨进程通信的场景。我的开发阶段只用了 stdio 方式零网络配置、零端口冲突日志直接在终端里看最适合学习调试。等你理解透整个协议再去玩远程部署就不迟。3. 从零实现一个 Excel 处理 MCP Server3.1 项目结构设计一个标准 MCP Server 的结构非常清晰其实就是“Python 类 装饰器 生命周期管理”。我先把我最终的项目结构放出来excel-mcp-server/ ├── pyproject.toml ├── README.md └── src/ └── excel_server/ ├── __init__.py ├── server.py # MCP Server 主入口 ├── excel_ops.py # Excel 实际操作逻辑 └── models.py # 数据模型定义这种分层设计有一个明显的好处server.py里只负责协议相关内容工具注册、参数校验、返回 JSONexcel_ops.py里放真正的 Excel 业务逻辑。如果将来你想加一个“读取 CSV 文件”或者“操作 PDF”的 MCP不需要动协议层只需要新增一个 ops 文件再注册工具就行。3.2 核心代码如何定义和注册一个 MCP ToolMCP 的 Python SDK 提供了非常优雅的装饰器模式。我们直接在server.py里创建 FastMCP 实例然后用mcp.tool()注册工具。先看最简单的工具定义——读取 Excel 文件的 sheet 列表from mcp.server.fastmcp import FastMCP import openpyxl from typing import Any # 创建 MCP Server 实例名字会展示给 AI 客户端 mcp FastMCP(excel-server) mcp.tool() def get_sheet_names(file_path: str) - list[str]: 获取 Excel 文件中所有 sheet 的名称列表。 Args: file_path: Excel 文件的完整路径支持 .xlsx 格式 wb openpyxl.load_workbook(file_path, read_onlyTrue) return wb.sheetnames代码看着很简单但有几个关键点一定要说透。首先是工具的描述和参数文档。在 MCP 协议中工具函数名、docstring、参数名和类型标注都会被序列化后发给 AI 模型模型靠这些信息来决定“什么时候调用哪个工具”。所以你写的 docstring 越清晰、参数说明越准确AI 的调用成功率就越高。我实测下来的经验是每个参数都要说清楚格式是 .xlsx 还是 .csv、单位是万元还是元、允许的范围这能显著减少 AI 乱传参的概率。其次每个工具只干一件事。我第一次设计时犯过一个错误做了一个“全能处理函数”把读文件、筛选、统计全塞进去参数多达八个。结果 AI 模型经常漏传参数或者传错类型调试得脑壳疼。后来拆分成read_excel、filter_rows、sum_column这种小粒度工具虽然工具多了几个但每个调用都非常稳定可靠。这也符合 MCP 官方推荐的“最小工具原则”。3.3 扩展工具集筛选、统计、写入、透视光有一个get_sheet_names显然不够我接着注册了几个最实用、最能体现“重构 Excel 工作流”价值的工具。读取数据并转换为 JSON——AI 理解的中间格式import pandas as pd from typing import Optional mcp.tool() def read_excel_to_json(file_path: str, sheet_name: Optional[str] None, max_rows: Optional[int] 0) - list[dict[str, Any]]: 读取 Excel 数据并转换为 JSON 列表。 Args: file_path: Excel 文件路径 sheet_name: 要读取的 sheet 名默认为 None取第一个非空 sheet max_rows: 最多读取多少行默认 0 代表全部读取 df pd.read_excel(file_path, sheet_namesheet_name) if max_rows: df df.head(max_rows) return df.to_dict(orientrecords)按条件筛选并统计求和——这直接对应热搜词里那个经典需求“统计同一列中含关键词的数据求和”mcp.tool() def filter_and_sum(file_path: str, column: str, keyword: str, sum_column: str) - float: 筛选指定列包含关键词的行并对另一列求和。 Args: file_path: Excel 文件路径 column: 用于筛选的列名 keyword: 筛选关键词支持模糊匹配 sum_column: 需要求和的数值列名 df pd.read_excel(file_path) filtered df[df[column].astype(str).str.contains(keyword, naFalse)] return float(filtered[sum_column].sum())把结果写入新的 Excel 文件mcp.tool() def write_dataframe_to_excel(data: list[dict[str, Any]], output_path: str, sheet_name: str Sheet1) - str: 将 JSON 格式的数据写入 Excel 文件。 Args: data: 要写入的数据必须是字典列表 output_path: 输出文件路径 sheet_name: sheet 名称 df pd.DataFrame(data) with pd.ExcelWriter(output_path, engineopenpyxl) as writer: df.to_excel(writer, sheet_namesheet_name, indexFalse) return f文件已写入{output_path}到这步你可能会发现一个趋势有了这几个工具AI 就像一个熟练的表哥表姐能读、能筛、能算、能写。MCP 的价值在于你不需要预先定义“处理步骤”只需要定义“能力边界”。具体怎么做AI 会根据你说的话自己组合工具去完成。3.4 Server 启动入口如何与客户端建立连接工具定义好了以后需要一个入口把这些都启动起来。在server.py末尾加上标准的启动逻辑if __name__ __main__: mcp.run()sdk的run()方法在本地默认监听 stdio也就是说我们现在只要运行python src/excel_server/server.py这个 MCP Server 就会在标准输入输出上等待调用请求。我自己的习惯是顺手加一个if __name__ __main__的测试分支在启动前模拟一下调用确保工具代码本身没有语法错误或路径问题。这比直接连客户端再排查要快得多if __name__ __main__: # 本地冒烟测试做一次真实调用 test_result get_sheet_names(./测试数据.xlsx) assert isinstance(test_result, list), 测试失败 print(自检通过sheet 列表, test_result) mcp.run()3.5 运行时的参数校验与安全边界在这版里我特意做了几件“防呆”的事也算是最想分享的经验。第一所有涉及文件路径的工具统一做存在性检查。如果文件不存在立刻抛一个异常而不是让 pandas 或 openpyxl 去报一堆混乱的底层错误。MCP 协议会把这个异常字符串原样返回给 AI我的经验是越明确的错误提示AI 越能自己纠正后续操作。第二默认不要在全量数据上做聚合操作。我的read_excel_to_json里加了max_rows参数默认读前 100 行。目的是防止 AI 在一个几万行的表上不知轻重地全量加载把上下文塞爆。等它确认结构之后再通过专用工具做全量统计这样上下文占用能控制到比较安全的范围。第三写入类的工具不直接覆盖原文件。我的write_dataframe_to_excel要求传入一个新的output_path而不是覆盖输入文件。原因很原始但也很重要AI 生成的结果可能有偏差我不能让它把源数据改错了。输出到新文件出了问题大不了重来原始数据文件永远是安全的。这一点是 AI 自动化和传统程序之间最大的差异——AI 是概率模型必须给它预设犯错的空间。4. 接入 AI 客户端让模型开始“动手”操作 Excel4.1 本地客户端配置以 Claude Desktop 为例Server 写完了下一步就是接入一个支持 MCP 的 AI 客户端。目前市面上支持 MCP 的客户端越来越多Claude Desktop、Cline、Cherry Studio、还有各种 IDE 插件都支持。配置方式大同小异核心都是编辑客户端的 MCP 配置文件告诉它“去哪个地址启动 Server”。以 Claude Desktop 为例配置文件在claude_desktop_config.json操作原理是把 Server 的启动命令写进去{ mcpServers: { excel-server: { command: python, args: [D:/projects/excel-mcp-server/src/excel_server/server.py], cwd: D:/projects/excel-mcp-server/src/excel_server } } }这里有一个特别容易踩的坑绝对路径里的任何反斜杠都必须写成正斜杠或双反斜杠。Windows 用户在配置 JSON 里写路径时经常在这里翻车。我自己的建议是直接在项目里用pathlib解决跨平台路径但配置文件的路径字符串只能手动处理好。配置好后重启客户端MCP Server 会在客户端启动时作为子进程自动拉起。你可以在对话界面上看到一个带锤子图标的工具列表被加载说明 Server 注册成功了。4.2 实测场景让 AI 完成一整套报表汇总为了验证重构效果我准备了一个真实的测试场景。文件夹里放着三家分公司的月度销售表格式略有差异需求是合并这三张表按产品类别汇总销售额并输出一个新的汇总表。我在对话里直接输入“请查看 D:/sales 下的三家分公司销售表分别获取它们的 sheet 结构和前几行数据然后合并它们按类别汇总销售额把结果输出到 D:/sales/汇总表.xlsx。”然后观察 AI 的表现。它很自然地先调用了get_sheet_names和一个read_excel_to_json的工具来理解三张表的结构发现三张表的列名不完全一致比如“金额”和“销售额”实际上是同一字段然后它会主动询问我是不是要统一映射或者直接基于常识做标准化处理。最后它会多次调用write_dataframe_to_excel写出结果。整个过程肉眼可见地顺畅这就是 MCP 带来的质变AI 不是一次性把数据处理完而是把一个长任务拆解成多个工具调用每次调用后都会检查中间结果。这跟人类处理复杂 Excel 任务的思路完全一致。4.3 让 AI 识别“不规则需求”从死规则到活理解前面提到函数和宏解决不了“模糊需求”MCP 最大的优势就在这。我故意测试了一个不规则的指令“看看这个销售表里有哪些异常数据帮我清理一下然后在原文件旁边生成一个清洗后的版本。”这个需求里“异常数据”没有明确定义。AI 会先读数据然后根据字段名比如数值列出现负数、日期列格式错误、关键列有空值判断哪些属于“异常”并告诉它自己的判断依据然后调用过滤和写入工具生成新版文件。这在传统 VBA 脚本里几乎没法做——你怎么给 VBA 定义“异常”但在 MCP 世界AI 的理解能力就是规则引擎工具只是它的双手。这也是我为什么推荐所有人都尝试一下“AI Excel”组合的根本原因——它不是在替代你做重复劳动是在替代你思考“怎么定义问题”。5. 常见问题与排查技巧实录5.1 典型报错与解决方案速查表我在开发过程中踩坑不少这里整理一个速查表基本都是社区里高频出现的问题报错现象根本原因解决方案“Connection closed” 客户端连不上Server 启动失败多半是依赖没装或路径错误手动运行python server.py先看控制台有没有报错工具调用后返回空列表工具执行有异常但被吞了或者读取的 sheet 里确实没数据在 Server 里先做assert冒烟测试排除业务问题参数校验失败 / 类型不匹配工具函数参数未写类型标注AI 无法推断所有参数必须标注类型docstring 里写清格式“Tool not found”工具没有正确注册或者客户端加载的是旧配置检查mcp.tool()是否装饰了函数重启客户端中文字段读取乱码openpyxl 默认编码问题或读取时用了错误的路径统一用 pandas 读取它对中文支持更好FileNotFoundError 反复出现AI 传的路径带中文或空格没有转义在 Server 内部做路径规范化处理用os.path.abspath5.2 排查工具链的实战心得排查 MCP 问题时最重要的一件事是学会分开看两段日志。一段是客户端侧的Host 是否发起了调用、传了什么参数一段是 Server 侧的工具是否真的执行成功、返回值是什么。开发阶段我最常用的排查操作是在不启动客户端的情况下手动用命令行喂给 Server 一条模拟请求观察输出是否符合预期。比如echo {jsonrpc:2.0,id:1,method:tools/call} | python server.py这样可以快速定位是协议层的问题还是工具逻辑的问题不用反复重启客户端。另外强烈建议在 Server 代码里加logging.basicConfig(levellogging.INFO)把每次工具调用的参数和结果长度打印出来。这不仅对调试有用还能反过来看到 AI 是怎么思考的——它每一步选择了什么工具、传了什么参数。我经常通过日志纠正自己写给 AI 的工具描述而这也正是不断优化 MCP 工作流的关键。5.3 我对安全边界的一些实践思考最后聊聊安全这个话题。MCP 给了 AI 真正的文件系统读取和写入能力这确实带来了一些风险。在我自己的实践中有几点相对保守的做法值得参考Server 默认只读取“指定目录”下的文件不开放全盘访问。可以在 Server 初始化时传入一个base_dir白名单所有文件路径必须在这个目录下才允许读取。写入操作强制走新文件输出这在我前面的代码里已经体现了。AI 可以创建新文件但不能覆盖源文件。配合定期备份习惯安全性就能兜底。敏感数据比如身份证号、手机号可以在工具层做脱敏处理再返回给 AI避免隐私信息进入模型上下文。当初我决定拿 Excel 作为第一个 MCP 项目回头看这个选择非常正确。MCP 的协议细节比想象中简单真正的门槛在于如何把业务需求拆解成清晰、单一职责的工具。我现在已经把这套 Server 拓展到了 CSV 清洗、Excel 批量转 PDF、多表合并等好几个场景但整个架构还是最初这三个核心工具的模式——读数据、处理数据、写数据。如果你也想上手玩我的建议很简单别追求一步到位先把最简单的“读取 Excel 文件名列表”跑通然后再逐步添砖加瓦。当你第一次看到 AI 自动调用你自己的工具把一张乱糟糟的表整理成干净文件时那种成就感会告诉你这一趟折腾值了。