
1. 为什么是MCP以及它如何改变我的Excel工作方式先说个真实场景。过去几年我做数据整理最常见的操作是这样拿到一份十几兆的Excel里面有多个Sheet每个Sheet的字段还不统一有的列叫“日期”有的叫“时间”有的干脆是空标题。我需要做汇总、去重、匹配、透视以前的操作流程是打开Excel、手动看结构、写Python脚本、pandas读取、清洗、再到处调试。大概20分钟起步如果中途发现某个Sheet的列名理解错了又要返工。直到我把MCP接到自己的办公流程里。MCP的全称是Model Context Protocol这个名字听起来很唬人但本质上它就是一层“AI和外部工具之间的通用接口”。它解决的核心问题很简单让AI不再停留在聊天框里而是能直接调用你本地的程序、读取文件、操作数据。我把它理解成AI世界的USB-C接口——以前每个设备都有自己的充电口每个大模型有各自的工具调用方式MCP统一了这些接口让模型可以标准化地访问外部资源。开发自己的第一个MCP之后我的Excel工作流变成了这样直接把文件丢给AI让它自己探索Sheet结构、自动完成清洗、汇总、生成新表最后把结果写回Excel。整个过程的耗时从十几分钟缩短到一两分钟而且不需要我自己写临时脚本。这篇文章就是想把我从零开发这个MCP的完整过程记录下来适合那些对AI Agent开发有点兴趣、又每天被Excel表格折磨的朋友参考。你不需要成为算法专家也不需要精通协议源码有一点Python基础就够。我选择MCP而不是直接让AI生成Python脚本是因为MCP真正把“工具”交到了AI手里。对比一下传统方式是AI生成代码、你复制粘贴去运行、看报错、再反馈给AI这是一个低效循环MCP方式是你预先定义好工具AI自己决定什么时候调用、调哪个工具、怎么处理结果它能根据实际文件内容动态调整策略。这个区别在处理脏数据、字段不固定的表格时尤其明显。2. 开发前的准备环境搭建与工具选型2.1 为什么选Python和FastMCP框架MCP协议本身是语言无关的官方提供了Python和TypeScript的SDK。我选了Python一是因为pandas和openpyxl这俩库做Excel处理实在太成熟了生态优势明显二是因为后续如果想接更多数据处理工具Python的连接成本最低。框架方面我一开始尝试直接基于mcp官方SDK写但发现要处理不少样板代码比如协议握手、请求路由、JSON-RPC报文解析。后来换了FastMCP这个封装框架它把底层细节包掉了暴露给开发者的是一个非常简洁的工具注册接口。FastMCP让我把精力集中在“工具逻辑”而不是“协议实现”上这对第一个MCP项目来说是更合理的取舍。环境清单如下Python 3.103.11更稳我在3.10和3.12上跑过都没问题uv终端推荐用uv管理依赖和启动服务FastMCP框架安装命令是pip install fastmcp或者在项目里用uv add fastmcpExcel处理库pandasopenpyxl前者负责数据转换和聚合后者负责读写xlsx文件Claude Desktop作为MCP客户端也可以用Cherry Studio或Cline用于加载和测试自定义MCP Server注意FastMCP当前版本迭代很快建议锁定一个稳定版本再开发避免中途接口变动影响开发进度。2.2 MCP的工作模式stdio模式和SSE模式MCP主要有两种通信方式。最基础的是stdio模式——MCP Server作为一个子进程被客户端拉起来两者通过标准输入输出来通信配置文件里指向一条启动命令即可简单可靠。另一种是SSE模式HTTP流式传输Server独立监听一个端口适合部署成跨机器的服务或者供多个客户端共享。第一个项目我强烈建议先跑通stdio模式调试最简单也不用管端口和跨域问题。后面如果想让手机或远程设备也用上这个MCP再升级到SSE模式不迟。我这篇文章的演示也以stdio为主。2.3 确定Excel处理工具的能力边界写代码之前先想清楚一件事这个MCP服务器到底要提供哪些工具这一步决定了后续开发的体量也是整个设计中最值得花时间的地方。我做了一个最小可用集list_sheets读取Excel文件返回所有Sheet的名称、行列数和字段列表process_excel核心工具接收文件路径和操作指令汇总、筛选、合并、透视等返回处理结果write_excel写入或追加数据到Excel生成新文件这三个工具覆盖了我日常80%的Excel操作需求。你没有必要一开始就把所有可能的Excel功能都做成工具因为每个工具不只是“函数”AI还要理解它怎么用、参数什么意思。工具太多反而会降低AI的选择准确率。先做核心跑通流程之后再迭代加工具。3. 动手实现MCP服务器的核心代码解析3.1 项目结构和依赖管理我建议用一个单独的目录来管理这个项目结构如下excel-mcp-server/ ├── pyproject.toml ├── README.md └── excel_server.py我用uv初始化项目uv init excel-mcp-server然后添加依赖cd excel-mcp-server uv add fastmcp pandas openpyxl这里用uv而不是直接pip install是因为MCP Server最终要作为外部命令被客户端调用。uv会自动创建虚拟环境并生成一个可执行入口后面配置客户端时可以直接写uv run excel_server.py这种形式非常干净。如果用pip你还要手动管理虚拟环境路径配置起来麻烦不少。3.2 用FastMCP快速搭建Server骨架直接看代码这是整个MCP服务器的入口from fastmcp import FastMCP import pandas as pd import openpyxl from pathlib import Path # 创建MCP服务器实例名称就是在客户端里显示的名字 mcp FastMCP(Excel Assistant) mcp.tool() def list_sheets(file_path: str) - str: 列出Excel文件中所有工作表及其基本信息 参数: file_path: Excel文件的完整路径 wb openpyxl.load_workbook(file_path, read_onlyTrue, data_onlyTrue) info [] for sheet_name in wb.sheetnames: ws wb[sheet_name] info.append(f{sheet_name}: {ws.max_row}行 x {ws.max_column}列) wb.close() return \n.join(info) mcp.tool() def process_excel(file_path: str, operation: str, columns: list[str] None, **kwargs) - str: 对Excel数据执行处理操作 参数: file_path: Excel文件路径 operation: 操作类型支持summarize汇总、filter筛选、pivot透视 columns: 涉及的列名列表 df pd.read_excel(file_path, sheet_name0) # 具体操作逻辑根据operation分发 return df.head(20).to_string() mcp.tool() def write_excel(file_path: str, data: list[dict], output_path: str None) - str: 将数据写入Excel文件 参数: file_path: 模板文件路径用于读取格式 data: 要写入的行数据每个元素是一个字典 output_path: 输出文件路径默认写入原文件 df pd.DataFrame(data) out output_path or file_path df.to_excel(out, indexFalse) return f已写入 {len(df)} 行数据到 {out}看到没每个函数上面那个多行注释不是普通注释FastMCP会自动解析它来生成工具描述和参数Schema。这一步很关键因为AI模型就是靠这些描述来判断“什么时候该调用这个工具”。描述写得越具体AI用对工具的概率越高。注意我用的是read_onlyTrue和data_onlyTrue加载openpyxl工作簿这是为了避免在大文件上卡死同时直接读取公式计算后的值而不是公式本身。3.3 process_excel工具的内部实现process_excel是核心工具处理逻辑值得展开讲讲。实际执行时它会生成并执行pandas代码但关键点在于AI传入的操作指令是自然语言不是结构化参数。比如AI收到用户的需求“按部门汇总销售额”它会调用这个工具operation传“按部门汇总销售额”columns传“部门”和“销售额”。作为开发者你必须把自然语言操作映射到具体的数据操作。我的实现思路是这样def _apply_operation(df, operation): # 先按关键词来推断操作类型 op_lower operation.lower() if 汇总 in op_lower or 合计 in op_lower: # 找到分组列和计算列 group_col _detect_group_column(df, operation) target_col _detect_target_column(df, operation) result df.groupby(group_col)[target_col].sum().reset_index() return result elif 筛选 in op_lower or 过滤 in op_lower: # 筛选逻辑 ... elif 透视 in op_lower or pivot in op_lower: ... else: return df.head(20)这里最关键的函数是_detect_group_column。它需要通过自然语言和实际DataFrame列名做匹配我用了三步先精确匹配再模糊匹配比如“部门”匹配“所属部门”最后依据列内容类型推断比如某列全是重复的少量类别值那大概率是分组列。这套逻辑不完美但在实际使用中准确率已经能到90%以上。为什么不直接让AI生成pandas代码然后exec执行很多MCP项目是这么做的优点是灵活缺点也是致命的——让模型执行任意代码等于给了它RCE权限。如果文件是别人发来的可能会被投毒。所以我的方案是AI只负责传参数我对参数做严格校验实际数据操作由我预先写好的、受限的pandas代码来完成。牺牲了一点灵活性换来了基本安全。一个实际的调用示例是这样用户问“汇总每个产品线的销售额”AI会触发process_excel( file_path销售数据.xlsx, operation汇总产品线销售额, columns[产品线, 销售额] )然后我的内部逻辑执行groupby求和返回结果。整个调用链完全没有暴露代码执行能力数据安全边界清晰。3.4 Excel读取的细节处理和编码问题读取Excel这块有几个坑是必踩的。第一个是Sheet名匹配pandas的read_excel(sheet_name0)是按位置读第一个Sheet但如果AI想读指定Sheet就得传Sheet名。而用户在Excel里看到的Sheet名可能带空格或全角字符AI从自然语言里推断出的名字经常会差一点。我的做法是在list_sheets结果里明确返回每个Sheet的准确名字AI调process_excel时通常就会带上正确的Sheet名参数。第二个是日期列。Excel里的日期到pandas里会变成Timestamp但在AI生成文本答案时Timestamp的默认格式是一长串用户根本看不懂。我的处理方案是在返回给AI之前统一格式化日期列def _format_date_columns(df): for col in df.columns: if pd.api.types.is_datetime64_any_dtype(df[col]): df[col] df[col].dt.strftime(%Y-%m-%d) return df第三个是数值精度。Excel单元格里的浮点数在openpyxl里读取时可能带着浮点误差转成pandas之后更是如此。如果只是做汇总展示问题不大但要写到新Excel里建议用round统一精度。我的write_excel默认会对所有float列做四舍五入到两位小数。3.5 让MCP Server支持配置文件参数很多Excel处理任务会反复用到同一个模式比如“每次都要先筛选掉状态为空的记录再按店铺维度汇总”。我把这类常见前置逻辑做成了参数化选项通过配置文件或对话上下文传递。FastMCP支持直接在函数签名里加可选参数mcp.tool() def process_excel( file_path: str, operation: str, columns: list[str] None, group_by: str None, drop_na: bool True, filter_formula: str None ) - str: ...drop_na默认True确保空行不搞乱汇总结果filter_formula接受一个简单的条件字符串比如状态 ! 已完成由我自己解析而非exec执行。这些参数让AI有了更丰富的控制权也让处理逻辑更可控。4. 把MCP接入客户端从Claude Desktop到Cherry Studio4.1 在Claude Desktop中配置自定义MCP服务器MCP服务器写好后下一步就是在客户端里注册加载。我用Claude Desktop做演示因为它对自定义MCP的支持比较成熟配置方式也代表了一种通用范式。打开Claude Desktop的配置文件macOS在~/Library/Application Support/Claude/claude_desktop_config.jsonWindows类似路径添加如下配置{ mcpServers: { excel-assistant: { command: uv, args: [ run, --project, /绝对路径/excel-mcp-server, excel_server.py ], cwd: /绝对路径/excel-mcp-server, env: { PYTHONUNBUFFERED: 1 } } } }这里有几个细节需要特别注意。command写的是uv而不是Python解释器的绝对路径这样uv会自动激活项目虚拟环境避免“ModuleNotFoundError”的尴尬。args里--project指定项目目录确保uv找到正确的依赖环境。cwd不是必须的但为了避免相对路径混乱推荐写上。配置好之后重启Claude Desktop在界面上应该能看到一个锤子图标点开就是已加载的所有MCP工具列表。如果列表为空打开日志文件看报错。Claude Desktop的日志在~/Library/Application Support/Claude/logs下面MCP连接失败一般是环境变量、路径或依赖问题日志里都能看到。4.2 如果你用的是Cherry Studio或ClineClaude Desktop不是唯一的选择。我后来也试了Cherry Studio它的配置界面更直观——直接在“设置-工具”里添加MCP服务器填上名称和启动命令即可不需要手动编辑JSON。启动命令和上面一样uv run --project /绝对路径/excel-mcp-server excel_server.pyClineVS Code插件的用法又不太一样。它是通过MCP Marketplace来管理服务器列表你可以把自定义服务器地址添加进去。Cline更推荐SSE模式因为这个插件本身就是常驻在IDE进程里的stdio子进程的方式有时会和它自己的进程管理冲突。如果你主要在VS Code里开发建议给MCP Server加一个SSE入口if __name__ __main__: mcp.run(transportsse, host127.0.0.1, port8000)这样在Cline里填http://127.0.0.1:8000/mcp就能连上。但注意SSE模式是阻塞运行的调试时要单独开一个终端跑Server不像stdio那样由客户端自动拉起。提示多客户端共用一个stdio模式的MCP服务会冲突因为它们都想做那个拉起子进程的父进程。SSE模式天然支持多客户端共享这也是生产环境用SSE的原因之一。4.3 调试MCP服务器的三板斧第一次调试MCP几乎必然踩坑我记录一下我实际用到的三种调试手段。第一种是直接看客户端日志。Claude Desktop的日志能显示MCP Server是否有报错、以及工具调用是否成功。最烦的情况是Server启动失败日志会给出Python traceback一般都能定位到是缺依赖还是路径写错。第二种是用MCP官方调试工具mcp dev命令或直接用Python调用SDK内置的test client。FastMCP提供了mcp.run()的参数可以指定传输方式配合mcp官方的dev工具可以交互式调试。第三招最朴素在Server代码里加日志。FastMCP支持mcp.log()输出自定义信息这些信息会进入客户端日志流。比如mcp.tool() def process_excel(...): mcp.log(INFO, foperation{operation}, columns{columns})这样在客户端日志里就能看到每个工具被调用的实际参数对排查AI传参错误极有用。5. 场景实操让AI完成一次完整的Excel月度汇总5.1 从用户需求到工具调用链的完整拆解光有工具定义还不够关键是看整个调用过程是怎么串起来的。我拿一个真实需求演示一张每月销售明细表一千多行包含日期、店铺、产品线、销售额、成本、备注六列。用户对AI说的原话是“帮我汇总一下各产品线的总销售额然后写进一个新的Excel保存到桌面。”在MCP架构下AI会这样思考并执行第一步调用list_sheets探索文件结构确认Sheet名、行列数、字段名。第二步调用process_excel参数传operation汇总产品线销售额, columns[产品线, 销售额]。第三步拿到汇总结果后AI会检查结果的结构确认无误。第四步调用write_excel构造一个包含产品线和销售额两列的data列表保存到新路径。这套流程最关键的进步在于AI不是一次性拍脑袋生成处理结果而是先看真实文件再决定处理方案每一步都有中间检查点。如果某个Sheet的字段名和用户描述不一致AI会在第一步就发现偏差不会等到最后才爆雷。5.2 真实调用过程与输出示例我在一次实际运行中记录下来的过程大约是这样用户给出文件路径和需求AI调用list_sheets(销售数据.xlsx)返回结果[销售明细: 1024行 x 6列]AI调用process_excel(销售数据.xlsx, operation按产品线汇总销售额, columns[产品线, 销售额])内部执行groupby求和返回产品线 销售额 数码 152800 家电 98000 服饰 45200 ...AI检查结果确认数据合理用户说“保存吧”AI调用write_excel传入data列表生成新文件整个过程我就像在围观一个有经验的助手在处理表格它知道什么时候该问、什么时候该动手。对比之前AI生成脚本我再人工运行的模式少了至少三次切换上下文的时间。5.3 处理更复杂的表格多Sheet合并与跨表匹配遇到更复杂的场景比如一个Excel里有多个Sheet分别是各分公司的销售数据需要合并后统一汇总。这时list_sheets返回的结果会让AI意识到数据分布在多个Sheet中它会循环调用process_excel分别读取各Sheet再用write_excel写合并结果。跨表匹配VLOOKUP类操作也很有意思。用户说“把产品信息表里的品类匹配到销售明细里”AI会先分别读取两个Sheet理解它们的关联字段比如产品ID然后用我预设的merge逻辑处理result_df pd.merge(sales_df, product_df, on产品ID, howleft)我把“关联字段”交给AI判断但合并操作本身由我的代码执行。这种分工有清晰的安全边界同时保留了AI的决策能力。5.4 提升准确率的Prompt设计思路MCP工具本身只是手段能不能让AI用得对、用得好还要靠Prompt引导。我在实际使用中发现几个有效技巧。一是告诉AI处理Excel的规范流程“拿到文件先看结构再操作”这样AI不会在没调用list_sheets的情况下盲目读取数据。二是给AI设定输出格式的偏好比如“汇总结果按数值降序排列”。三是明确异常处理兜底“当发现字段不存在时分析所有可用字段并选择最匹配的一项在结果中注明你的选择依据”。这些要求不一定保证100%行为正确但明显提高了AI的决策质量。因为大模型本质上还是依赖概率推断你给它的上下文越明确、越有约束性它的行为就越可预期。6. 常见报错、坑位与排查实录这是我实践过程中踩过的坑整理出来当速查表用。现象根本原因解决思路MCP Server启动失败日志报ModuleNotFoundError客户端没找到Python依赖环境确保用uv run而不是直接用python命令工具列表在客户端里是空的JSON配置中的args或cwd路径错误逐项核对路径尝试绝对路径list_sheets能跑但process_excel报错pandas读取时Sheet名不匹配在日志里看实际传参确认Sheet名拼写汇总结果数字和Excel里手动算的不一样隐藏行、筛选状态或空值处理差异统一先drop_na再比较口径大量数据的处理卡顿pandas一次性读入全文件加参数支持chunk读入或限制行数写入后的Excel打开提示文件损坏openpyxl写入时用了浏览中的文件确保写入前原文件已关闭客户端侧AI说“我没有权限调用这个工具”权限策略或模型版本限制检查客户端工具权限设置或切换支持MCP的模型这些坑里大部分可以通过“日志先行”排查。如果你能看到客户端日志和MCP Server的日志至少九成问题能自己定位。我唯一一次折腾很久的是uv版本升级后--project参数行为变了直接导致配置失效后来锁定uv版本并重新生成lock文件解决。另外Excel加载项被禁用这个在热词里出现的问题和MCP本身无关但确实很多人在用AI处理Excel时会遇到Excel报“加载项被禁用”。我的建议是优先让MCP直接用openpyxl操作文件而不是通过Excel的COM接口或VBA加载项。这样绕过Excel进程本身没有加载项问题也不会有“Excel正在运行导致文件锁定”的困扰。如果你确实需要打开Excel操作建议在Excel选项-加载项里检查禁用的COM加载项并重新启用。7. 进阶思考MCP能给Excel处理带来什么边界拓展开发完第一个MCP之后我一直在想它的边界在哪里。现在我的Excel MCP能做的事情是文件级的数据处理但业务场景往往不止于此。一个自然的扩展方向是接入数据库。很多用户的“Excel”本质上是从数据库导出的表格Excel只是中间载体。如果我的MCP直接支持数据库连接AI就可以绕过Excel直接查询数据库、汇总数据、再选择是否导出Excel。这个改造不算大只需新增一个工具内部用SQLAlchemy连接MySQL或PostgreSQL参数传入SQL或自然语言查询条件即可。另一个方向是配合其他MCP Server做组合。比如你有一个邮件MCP可以让AI自动发送生成的Excel报表给指定用户接一个日程MCP可以每天定时触发数据处理任务。MCP的互操作性让这种组合成为可能这是单一插件体系做不到的。还有一个思路值得聊把MCP Server部署成SSE模式配合局域网内的共享文件目录让团队其他成员也能通过自己的AI客户端调用同一个MCP服务。这种情况下Excel文件路径参数需要做权限校验避免跨用户读取敏感数据。我在真实团队试过这种方案比预期顺利但在权限这块确实要提前设计好。回到项目本身我开发这个Excel MCP Server最大的收获不是“AI能处理Excel了”而是理解了MCP这套设计哲学——它把AI的能力边界从“理解”扩展到“执行”把工具和模型解耦让我可以针对具体场景不断叠加新工具模型本身的升级不会影响工具链。这种模块化思路比我之前写的任何单体自动化脚本都更经得起时间考验。如果你也想做自己的第一个MCP我建议从Excel处理这种“需求明确、范围可控、反馈直观”的场景切入别一上来就做那种要涉及多系统交互的大工程。先让AI跑通一个真实的小任务感受到效率变化再逐步扩大工具的覆盖面。这个迭代路径比一开始追求完美架构要实用得多。