每天跟Excel打交道的朋友应该都有这种体会:处理报表本身不是最费时间的,费时间的是那些重复性的操作——打开表格、定位列、写公式、复制粘贴、再生成新表。尤其是当数据源有变动、格式不统一的时候,整个人都会烦躁起来。
我最近用MCP(Model Context Protocol)写了一个Excel处理服务,把这块工作彻底交给了AI。MCP可以理解为一个“AI工具插线板”:它定义了一套标准协议,让Claude、GPT这类大模型能够直接调用外部工具、读取外部文件、操作外部系统。换句话说,AI不再只是一个聊天框,它可以真正“伸手”帮你干活。
这篇会从零开始,讲清楚MCP的核心概念、SDK选型、工具注册方法,以及一个完整的Excel自动化案例。适合正在做数据处理的开发者、对AI Agent感兴趣的工程师,以及想给日常工作装上“AI外挂”的内容创作者。
1. 为什么要自己写一个MCP服务
1.1 传统Excel处理方式的痛点
在MCP出现之前,让AI处理Excel通常有三条路,但每条路都走得不太舒服。
第一条路:把Excel导出成CSV,然后复制粘贴给AI。这条路只适合一次性小数据,数据一多就白搭,而且每次粘贴都得校验格式、处理编码,非常折磨。我见过不少人用这个办法让AI写个求和公式,表面看是“AI处理Excel”,实际上只是把AI当成了搜索引擎。
第二条路:用Python加openpyxl、pandas写一次性脚本。每次数据结构变一点,脚本就要跟着改,长期维护成本很高。更重要的是,脚本本身是“死”的——它不会根据自然语言指令动态调整处理逻辑,遇到意料之外的表格结构,只能报错收场。
第三条路:用RPA工具录制鼠标键盘操作。录制简单,但表格结构一变化就崩,灵活性和可维护性都很差。RPA适合稳定的表单录入,不适合需要“看懂数据”的分析任务。
这三条路的共同问题是:AI和工具之间没有真正打通。要么人工搬运数据,要么AI只能纸上谈兵。MCP的思路完全不同——它把能力封装成工具(Tool),让模型自己决定要不要调用、怎么调用,数据和执行结果都直接走协议返回给模型。这样一来,AI既有了“眼睛”能读取数据,又有了“手”能执行操作和写回结果。
1.2 MCP协议到底做了什么
MCP全称Model Context Protocol,它于2024年11月被Anthropic开源,是一个开放协议。它的定位非常明确:让AI应用(宿主)能够以标准方式发现并调用外部能力提供者(MCP服务器)暴露的工具、资源和提示词。
用个直白的生活类比:MCP就像USB-C接口。以前每个设备都得配自己的充电线,现在统一成一个标准接口,什么设备都能插。MCP就是AI领域的“USB-C”,任何AI客户端(Claude Desktop、Cursor、VS Code里的Copilot,甚至自己写的Agent框架)连接上任何MCP服务器,都能立刻用上它所暴露的能力。
协议层面,MCP基于JSON-RPC 2.0。每个客户端和服务器之间通过一条消息通道进行请求/响应通信,通道可以是stdio(标准输入输出),也可以是流式HTTP(SSE)。核心交互有这么几类:
- initialize:握手,确认协议版本与能力。
- tools/list:客户端获取服务器支持的工具有哪些。
- tools/call:客户端请求调用某个工具。
- resources / prompts:暴露资源和提示词能力。
MCP并没有规定工具内部必须用什么技术实现。你用Python、TypeScript、Go都能写,只要能正确处理JSON-RPC消息就行。社区里已经有官方SDK,比如Python的fastmcp、mcp库,TypeScript的@modelcontextprotocol/sdk。
1.3 为什么选择MCP做Excel工作流,而不是直接写脚本
问一个很实际的问题:既然最终都得写代码,那直接写Python脚本不就行了,为什么要套一层MCP?
第一,MCP把“写死的脚本”变成了“可被模型动态编排的能力”。传统脚本是一个固定流程:输入、处理、输出。MCP工具是原子能力,比如“读取工作表某区域”“把指定列做去重后求和”“生成透视表”。AI能根据对话上下文动态决定调用顺序,遇到异常还能自己换路径重试。实话说,这种灵活性在传统脚本里很难实现。
第二,MCP服务器是一次开发、多处复用。你在Claude Desktop里调试好的Excel工具集,拿到Cursor、n8n、自己写的Agent里都能直接用,只要实现的是同一个协议。n8n这类工作流平台现在也原生支持MCP节点,意味着你的工具可以无缝嵌入到自动化流程中。这种“一次封装,到处调用”的体验,普通脚本给不了。
第三,MCP服务器的边界和权限是可控制的。服务器暴露哪些工具、允许操作哪些路径,都由你在代码里决定。相比给AI一个通用终端让它随便跑,MCP的权限粒度要细得多,也安全得多。比如你可以只让工具读写data目录下的文件,其他路径一律拒绝。
说白了,MCP的定位是“AI的能力外设”。Excel只是其中一个典型场景,还有人用MCP连接数据库、浏览器、设计软件甚至游戏引擎。浏览器自动化有Playwright MCP,接口安全测试有BurpSuite MCP,3D建模有Blender MCP。理解了这层,你就不会再把它当成一个普通的API封装工具。
2. 动手前的核心概念梳理
2.1 传输方式:stdio和SSE怎么选
MCP服务器和客户端之间通信,官方支持两种主要传输方式,一定要先弄清楚区别。
stdio模式:客户端以子进程方式启动服务器,通过标准输入(stdin)发送JSON-RPC消息,服务器通过标准输出(stdout)返回结果。这种模式最简单,是本地开发调试的主力。Claude Desktop里配置的"type": "stdio"就是这种。
SSE模式(Server-Sent Events):服务器跑在一个HTTP端点上,客户端通过HTTP POST发送请求,服务器通过SSE流推送事件。这种模式适合远程服务器、多客户端共享场景,也是把MCP能力部署到云上的基础。
我建议开发第一个MCP的时候先用stdio。原因很简单:可以用命令行直接验证服务器是否正确响应,断点调试方便,不用处理CORS、跨域、鉴权这些网络问题。等跑通了再升级到SSE也不迟。
顺带提醒一句:网上有些公开示例会直接让你填一个远程MCP服务器的SSE地址,有的地址还带着token参数。我不建议把别人的云端服务地址直接写进自己的配置里,一是你控制不了那个服务的行为,二是数据会经过第三方。自己部署一个本地服务器,才能完全掌控数据和行为。
2.2 MCP是软件协议,不是硬件驱动协议
有个高频疑问:“MCP是软件协议还是硬件协议?为什么网上说的都是抽象概念?”
答案很明确:MCP是应用层软件协议,和HTTP、WebSocket是同一类概念。它跟USB HID这类硬件驱动协议没有任何关系。MCP解决的问题是:AI应用和外部工具之间如何描述能力、如何发起调用、如何返回结构化结果。它不关心具体干活的代码用什么语言写。
理解了这一点,再看代码就会清爽很多。MCP封装的每个工具,本质上就是一个有名字、有描述、有参数Schema、有返回值的函数。你用任何语言实现这个函数都行,SDK只是帮你处理了协议层的序列化、反序列化和握手细节。
2.3 三大能力原语:Tool、Resource、Prompt
MCP服务器可以暴露三类能力,理解它们的区别很重要。
Tool(工具):主动动作。比如“读取Excel工作表”“合并CSV文件”“写入单元格”。模型根据用户意图决定调用哪个工具。这是Excel场景里用得最多的一类。
Resource(资源):被动数据。比如某个固定路径的Excel文件、某个报表模板,客户端可以读取这些内容作为上下文补充。适合暴露有固定结构的模板文件。
Prompt(提示词模板):预设的交互模式。比如“帮我汇总这个目录下所有Excel的销售数据”,定义好模板后,模型会按模板补全变量执行。适合封装常见分析套路。
在Excel处理场景中,90%的需求集中在Tool上。Resource用于暴露模板,Prompt用于定义分析套路。新手第一版只实现Tool就够用,后面再按需补充。
2.4 安全边界:为什么不能把整张表都丢给模型
刚开始做的时候很容易踩一个坑:图方便,把整个Excel文件读成文本全部塞给AI。数据量大时,这个方案在Token消耗和上下文长度上都不现实。更重要的是,AI对超大文本的理解精度会显著下降,尤其是数字、日期这类容易混淆的格式。
正确做法是:让MCP工具只返回“窗口化数据”。比如读取一个表,默认只读取前N行、指定列,或者先返回工作表名和列名的元信息,让模型决定下一步。这样既省Token,又不会因为数据量过大导致模型回答失真。
我自己实测下来,一份5000行左右的销售明细表,用分页读取的方式每次取1000行,最终只让模型看2000行做汇总,Token开销大约在2000到3000。相比直接把5000行全部塞进上下文(大概1.5万Token),成本降低了一半以上,模型对数字的识别准确率也更高。所以“窗口化读取 + 分步决策”不仅仅是为了省钱,本身就是提升准确性的有效手段。
3. 开发环境与SDK选型
3.1 技术栈:为什么我用Python加fastmcp
MCP官方有Python和TypeScript两套SDK。我推荐新手用Python加fastmcp这个社区库,理由有三点。
第一,Excel处理生态成熟。openpyxl、pandas、xlsxwriter全都在Python生态里,处理xlsx、xls、csv都是顺手的事。MCP服务的核心业务代码,80%是在跟Excel文件打交道,Python能把精力集中在业务逻辑上,而不是折腾DLL引用和COM对象。
第二,fastmcp把协议细节封装得很干净。你只需要写一个装饰器函数,SDK自动帮你生成JSON Schema和工具描述,几乎不需要手写JSON-RPC。这比直接用官方mcp库写原始协议要友好一个量级。
第三,调试方便。Python的logging可以直接输出到stderr,用Claude Desktop或者mcp-inspector连接时,可以实时看到日志。对比TypeScript在子进程模式下需要额外处理流,Python的调试体验更直接。
当然,如果你本身是前端或Node开发者,用@modelcontextprotocol/sdk写TypeScript版也完全可行。原则只有一个:选你熟悉的技术栈,别把精力浪费在学习语言上。
3.2 环境准备与依赖安装
先建一个干净的环境,避免污染系统Python。我用venv处理:
python -m venv .venv source .venv/bin/activate # Windows下用: .venv\Scripts\activate pip install mcp openpyxl pandas fastmcp这里有个细节:fastmcp内部依赖官方的mcp包来做底层协议传输,所以两个都要装。装完可以用下面这条命令验证版本:
python -c "import fastmcp; print(fastmcp.__version__)"如果输出正常,环境就准备好了。
3.3 项目结构规划
一个最小的MCP项目,结构大概是这样:
mcp-excel/ ├── server.py # MCP服务器主文件 ├── tools/ │ ├── read.py # 读取Sheet │ ├── write.py # 写入/追加数据 │ └── summary.py # 聚合统计分析 ├── requirements.txt └── data/ # 示例Excel文件我的建议是:别一上来就把模块拆得太散。先在一个server.py里堆工具,跑通了再拆。MCP工具的复用点是“能力”而不是“业务场景”,所以按能力聚合文件会更好维护。等你积累了五六个工具后,再拆分成模块也不迟。
4. 实现一个Excel MCP服务器
4.1 服务器骨架与初始化
用fastmcp写服务器非常直接,核心就三行:
from fastmcp import FastMCP mcp = FastMCP("excel-helper") if __name__ == "__main__": mcp.run()FastMCP("excel-helper")创建了一个名为excel-helper的MCP服务器,mcp.run()默认以stdio模式运行,读取stdin上的JSON-RPC。
启动后程序会等待stdin输入,看起来像“卡住了”,这是正常的。可以用mcp-inspector发消息验证,也可以在命令行里手动输入一个JSON-RPC消息试试。
4.2 第一个工具:读取Excel表格
读取工具是整个服务器的基础。设计参数时要想清楚:模型需要什么信息、什么格式最省Token。
import json import pandas as pd from fastmcp import FastMCP mcp = FastMCP("excel-helper") @mcp.tool() def read_sheet( path: str, sheet_name: str = None, max_rows: int = 20, include_columns: list[str] = None, ) -> str: """ 读取Excel文件中指定Sheet的数据,返回JSON字符串。 - path: Excel文件路径 - sheet_name: Sheet名,缺省时打开第一个Sheet - max_rows: 最多返回行数,避免数据过大 - include_columns: 只返回指定列名列表 """ xl = pd.ExcelFile(path) if sheet_name is None: sheet_name = xl.sheet_names[0] df = pd.read_excel(path, sheet_name=sheet_name) if include_columns: df = df[include_columns] preview = df.head(max_rows).fillna("").astype(str) result = { "sheet_names": xl.sheet_names, "used_sheet": sheet_name, "total_rows": len(df), "columns": list(df.columns), "preview_rows": json.loads(preview.to_json(orient="records")), } return json.dumps(result, ensure_ascii=False, indent=2)这里有几个关键细节。include_columns用了None作为默认值,没有用可变默认值,这是Python函数定义的基本修养。返回前对数据做了fillna("")和astype(str),防止NaN被序列化成null、防止int64类型无法json.dumps。
更重要的是返回值结构:模型拿到total_rows和columns之后,才能决定是否要继续读取更多数据。这就是“窗口化读取”的实现基础。另外,docstring不要写“读取Excel”这么简单,要把每个参数的含义写清楚,特别是max_rows要说明建议范围,模型会根据你的描述调整行为。
4.3 第二个工具:写入与追加数据
Excel写入要区分场景:新建文件写入和已有文件追加。我写了两个工具:write_sheet用于新建或覆盖,append_rows用于在现有Sheet末尾追加。
from openpyxl import load_workbook import os @mcp.tool() def write_sheet( path: str, data: list[list], sheet_name: str = "Sheet1", ) -> str: """ 新建或覆盖写入Excel文件。 - path: 目标文件路径 - data: 二维数组,第一行为表头 - sheet_name: Sheet名 """ df = pd.DataFrame(data[1:], columns=data[0]) if data else pd.DataFrame() df.to_excel(path, sheet_name=sheet_name, index=False) return json.dumps({ "status": "ok", "rows": len(df), "path": path, "sheet": sheet_name }, ensure_ascii=False)覆盖写入要非常小心。我建议在工具参数里加一个overwrite开关,默认False,必须显式传True才允许覆盖已有文件。这个保护看着简单,实际能挡掉不少误操作。
附加追加工具:
@mcp.tool() def append_rows( path: str, data: list[list], sheet_name: str = None, ) -> str: """ 在已有Excel文件的Sheet末尾追加数据。 - path: 目标文件路径 - data: 需要追加的二维数组 - sheet_name: Sheet名,缺省使用第一个Sheet """ if not os.path.exists(path): return json.dumps({"error": "file not found"}, ensure_ascii=False) wb = load_workbook(path) if sheet_name is None: sheet_name = wb.sheetnames[0] ws = wb[sheet_name] start_row = ws.max_row + 1 for i, row in enumerate(data): for j, value in enumerate(row): ws.cell(row=start_row + i, column=j + 1, value=value) wb.save(path) return json.dumps({ "status": "ok", "appended": len(data), "start_row": start_row }, ensure_ascii=False)这里有个细节:append_rows没有用pandas的to_excel,而是直接用openpyxl逐格写入。原因是pandas的to_excel每次都会重建整个文件,追加时必须用openpyxl操作工作簿对象,否则之前的内容会丢。这个坑我踩过,第一次写追加功能时想着“反正都是写Excel,用pandas多方便”,结果文件被整个覆盖了,还好当时只是测试数据。
4.4 第三个工具:数据清洗与聚合
Excel工作流中最常见的需求就是去重统计、按条件汇总。这个工具能帮AI省掉大量“理解pandas语法”的成本。
@mcp.tool() def summarize( path: str, sheet_name: str = None, group_by: str = None, agg_column: str = None, agg_func: str = "sum", ) -> str: """ 对Excel数据做分组聚合,返回统计结果。 - path: Excel文件路径 - sheet_name: Sheet名,缺省使用第一个Sheet - group_by: 分组列名 - agg_column: 聚合列名 - agg_func: 聚合方式,支持sum/mean/count/min/max """ df = pd.read_excel(path, sheet_name=sheet_name or 0) if not group_by or not agg_column: return json.dumps({"error": "需要group_by和agg_column参数"}, ensure_ascii=False) result = df.groupby(group_by)[agg_column].agg(agg_func).reset_index() records = json.loads(result.to_json(orient="records")) return json.dumps(records, ensure_ascii=False, indent=2)举例说明:给AI一张销售明细表,模型调用summarize,group_by设为“产品”,agg_column设为“销售额”,就能得到各产品总销售额。这个工具的价值在于:AI不需要理解pandas语法,只要知道“有个工具能帮我按某列聚合计算某列”就够了。用户用自然语言说“按产品汇总销售额”,模型自动就能把参数映射好。
4.5 关键设计决策:工具描述是给模型看的说明书
MCP工具的描述文字会被模型当作“使用说明书”读取。描述越具体,模型越能准确决定什么时候调用、传什么参数。
我踩过一个真实案例:read_sheet没有约束返回行数时,模型经常傻乎乎地请求读一万行。后来在docstring里写了“为避免Token过载,max_rows建议在100以内,如需更多数据请多次调用”,模型的调用行为立刻变得合理了。
所以,工具描述不是给人类看的注释,它是提示词的一部分。写的时候要站在“模型视角”去写:什么情况下用、参数取值范围、错误时的备选方案,都写清楚。这个认知是我开发MCP过程中最值钱的经验之一。
5. 接入客户端:从Claude Desktop到自定义Agent
5.1 在Claude Desktop中配置MCP
服务写好了,接下来把它接到客户端里。以Claude Desktop为例,打开设置,在Developer里的Edit Config,编辑claude_desktop_config.json:
{ "mcpServers": { "excel-helper": { "command": "python", "args": ["/绝对路径/server.py"], "env": {} } } }有两个路径坑一定要注意。command最好写python的绝对路径,特别是用虚拟环境时,要写.venv里的python路径,否则客户端找不到依赖包。args里的server.py也要写绝对路径,别用相对路径。Windows下command写成python.exe的完整路径更稳妥。
配置好后重启Claude Desktop,在对话里直接说“帮我看一下data目录下的销售汇总表”或“把data/orders.xlsx按地区汇总一下销售额”。第一次调用时,你能在对话界面上看到AI请求工具、拿到结果、继续操作的完整过程,那种体验还是很奇妙的。
5.2 用mcp-inspector调试每个工具
接入客户端之前,强烈建议先用mcp-inspector把所有工具调试一遍。它是一个网页调试面板,能以可视化的方式连接你的MCP服务器。
npx @modelcontextprotocol/inspector python server.py启动后,它会显示initialize握手结果、工具列表,以及每次调用的入参和返回结果。我建议在接入正式客户端之前,先把所有工具都跑一遍,确认IO和异常处理。尤其要测一下非法路径、空表格、列名不存在这些边界情况,别直接上生产环境。
5.3 在自定义Agent中调用MCP
如果你不想用现成客户端,而是在自己的Python Agent里调用这个MCP服务,可以用mcp SDK的ClientSession。这段代码展示了MCP协议的最小闭环:初始化、列出工具、调用工具。
import asyncio from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client async def main(): server_params = StdioServerParameters( command="python", args=["server.py"] ) async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() tools = await session.list_tools() print("available tools:", [t.name for t in tools]) result = await session.call_tool( "read_sheet", {"path": "data/orders.xlsx", "max_rows": 5} ) print(result.content) asyncio.run(main())理解了这个流程,你就掌握了MCP的精华。剩下的所有配置和封装,都是在完善这个“发现工具、调用工具”的循环。
6. 完整案例:用MCP重构日报汇总工作流
6.1 手工工作流的痛点拆解
假设你每天要做一份销售日报,数据分散在5个区域团队的Excel表格中,每个表结构并不完全一致。
传统手工流程是这样的:打开5个Excel,手动复制每个表的“销售额”列,打开汇总模板粘贴,写公式求和,生成图表,另存为日报。每天20分钟,一周就是近2小时。更难受的是,每次某个表格多了一个Sheet、列名改了一个字,公式和引用就会错乱。
这种工作流的本质是“人肉数据搬运”。所有环节中,机器能做的事和AI能做的事都被浪费了,最耗时的复制粘贴恰恰是价值最低的操作。
6.2 MCP化改造后的执行链路
改造后的工作流就简单了:把5个文件放进data/input目录,打开Claude Desktop,对AI说“请汇总data/input目录下5个Excel的销售数据,按地区分组合并,输出一张汇总表到data/output/日报.xlsx”。
AI接到指令后,内部会做这些事:
- 先列出目录文件,确认有哪些Excel。
- 对每个文件调用read_sheet读取前几行,了解表结构。
- 必要时继续读取更多数据或指定列。
- 识别“地区”“销售额”等字段映射关系。
- 调用write_sheet把结果写入新文件。
整个过程,AI不需要手动复制粘贴,也不依赖固定表结构。遇到列名不一致的情况,模型会主动问“某个文件里没有销售额列,是否使用实收金额代替”。这种动态协商能力,是传统脚本永远做不到的。
6.3 为什么这个方案更抗变化
看到这里你可能会问:这不就是把Python脚本改成了AI调用吗?表结构变化时AI怎么知道怎么处理?
答案是:AI拥有自然语言理解能力,它可以即席理解新表结构。比如某天区域团队新增了一列“退款金额”,AI会在汇总时合理排除或单独标注。而传统脚本遇到多一列,通常直接报错或悄悄算错。
MCP工具返回的是结构化数据,AI能根据列名和内容进行推理。它不需要理解每个单元格的公式逻辑,只需要知道“数据长什么样”和“用户想要什么结果”。这种“用工具拿数据、用语言做决策”的组合,就是AI工作流的核心模式。
6.4 实测表现与Token成本
我实测下来,一份5000行左右的销售明细表,用read_sheet分页读取,每次1000行、最终读取2000行做汇总,对主流大模型来说Token开销大约在2000到3000。如果直接全量读取,Token开销轻松破万,而且数字识别准确率明显下降。
这里有个实用技巧:如果数据量确实很大,可以让MCP工具先返回列名和一个抽样行的值,让模型先“看懂”表结构,再决定是否全量读取。很多情况下,模型只需要看到结构就能完成推理,不需要看每一行。
7. 常见问题与排查技巧
7.1 工具报错“Tool not found”
典型原因是服务器更新后客户端没有刷新工具列表。重启客户端或重新initialize即可。还有一种情况是配置文件里写的命令指向了另一个server.py,改一下路径就好。
7.2 中文路径乱码问题
Windows下读取含中文的Excel路径,pandas一般能处理,但openpyxl在保存时有概率遇到编码问题。建议统一使用绝对路径,并在工具内部用os.path.abspath规范化,避免相对路径歧义。
7.3 数据序列化报错
工具返回必须是JSON可序列化的。pandas的Timestamp、numpy的int64和float64都不能直接json.dumps。我统一用astype(str)或tolist()处理,并加上fillna("")防止NaN被序列化成null。如果你自建了返回结构,最好在return前加一个json.dumps测试,提前发现问题。
7.4 stdout和stderr混淆
stdio模式下,日志必须打印到stderr,工具结果打印到stdout。如果在工具函数里误用了print()把调试信息写到stdout,会导致客户端解析JSON-RPC消息失败。调试时统一用logging模块,或者写print(..., file=sys.stderr)。这个问题很隐蔽,因为本地运行时看起来一切正常,但接上客户端就莫名其妙断开。
7.5 安全建议:给路径加白名单
MCP服务器赋予了AI读写本地文件的能力,默认配置应该只允许访问指定目录,不要把一个“什么都能读”的Excel工具连接到任意客户端。我习惯在工具函数里检查传入的path是否在合法目录白名单内,不在就返回错误信息而不是执行操作。
ALLOWED_DIR = os.path.abspath("./data") def _safe_path(path: str) -> str: p = os.path.abspath(path) if not p.startswith(ALLOWED_DIR): raise ValueError("路径不在允许范围内") return p加了这层保护后,即使AI被恶意提示词诱导去读其他目录的文件,也会被工具自己拦住。虽然MCP工具本身有权限边界,但多一层防御总没坏处。
我个人开发这个MCP服务后体会最深的是:MCP最大的价值不在于“让AI能操作Excel”这个具体功能,而在于它提供了一个真正标准化的AI工具接口。以前我们给AI写工具,每个项目都需要自己定义调用方式、参数格式、错误处理,现在有了MCP,所有客户端和服务器之间只要遵循同一套协议,就能自由组合。
最后分享一个小技巧:开发MCP服务时,不要追求“大而全”。把一个工具写好——描述准确、参数精简、返回稳定——远胜于堆十个半吊子工具。先跑通一个read_sheet,把它接到Claude Desktop上试用一周,再逐步加入写入、聚合、导出功能。这种增量式的开发节奏,踩坑最少,体验也最好。
如果你也在跟Excel死磕,试着用这个思路做一次重构,我相信你会回来感谢自己。