news 2026/11/2 17:29:19

从零开发ExcelMCP:用Python让AI自动处理Excel数据

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从零开发ExcelMCP:用Python让AI自动处理Excel数据

1. 为什么我要自己动手写一个 MCP

1.1 从一次崩溃的 Excel 处理经历说起

上个月帮朋友处理一份销售数据,三千多行,需要按区域拆分、按品类汇总、再生成一份带图表的周报。我当时的做法很原始:打开 Excel,写几个公式,手动筛选,复制粘贴到新表,再插入图表。整个过程花了将近两个小时,中间还因为一次误操作把公式引用搞乱了,不得不从头再来。

那天晚上我就在想,这种重复性极高、逻辑又相对固定的 Excel 处理任务,能不能交给 AI 来做?不是那种“帮我写个公式”的浅层辅助,而是让 AI 真正理解我的意图,自动完成读取、清洗、计算、输出这一整套流程。

后来我接触到了 MCP 这个概念。MCP 全称是 Model Context Protocol,翻译过来叫“模型上下文协议”。你可以把它理解成一座桥——桥的一头是 AI 大模型,另一头是你的本地工具、数据源或者任何可执行的服务。有了这座桥,AI 就不再只是一个“聊天机器人”,而是能真正动手帮你干活的助手。

市面上已经有不少现成的 MCP 工具,比如 Playwright MCP 可以让 AI 操控浏览器,Chrome DevTools MCP 能让 AI 调试网页,还有各种数据库 MCP、文件系统 MCP。但 Excel 处理这个场景比较特殊——它既涉及文件读写,又涉及数据计算,还涉及格式控制,现成的工具要么功能太泛,要么不够灵活。于是我决定:自己写一个。

这篇文章就是记录我从零开始开发第一个 MCP 的完整过程。如果你也经常和 Excel 打交道,或者想了解 MCP 到底怎么落地,这篇内容应该能帮到你。

1.2 这个 MCP 能做什么,适合谁看

先把这个 MCP 的能力边界说清楚。我给它取名叫ExcelMCP,核心功能包括:

  • 读取 Excel 文件,自动识别表头和数据类型
  • 按指定列进行分组汇总、条件筛选、去重
  • 在同一列中统计包含特定关键词的数据并求和
  • 将处理结果写入新的 Excel 文件,保留基本格式
  • 支持多表操作,比如从多个 sheet 中提取数据合并

适合阅读这篇文章的人:

  • 有 Python 基础,但没写过 MCP 的开发者
  • 经常处理 Excel 数据,想用 AI 提效的职场人
  • 对 AI Agent 和工作流自动化感兴趣的技术爱好者
  • 想了解 MCP 协议实际怎么用的人

如果你完全没写过 Python,也不用慌。我会把每一步都拆开讲,代码给全,命令给全,你跟着抄作业就行。

2. MCP 的核心概念与整体设计思路

2.1 MCP 到底是什么,用生活化类比讲清楚

很多人第一次听到 MCP 会懵——它是软件协议还是硬件协议?其实都不是。MCP 是一个应用层协议,专门用来规范 AI 模型和外部工具之间的通信方式。

打个比方。你家里有一个很聪明的管家(AI 模型),他知道很多事情,但你让他去开灯,他做不到,因为他没有手。MCP 就是给管家装的那双手——通过一套标准化的接口,管家可以调用各种工具:开灯、关窗、煮咖啡。

技术一点说,MCP 定义了一套 JSON-RPC 格式的通信规范。AI 模型作为客户端,向 MCP Server 发送请求;MCP Server 执行具体操作,把结果返回给模型。整个过程对用户是透明的,你只需要用自然语言说“帮我把这份 Excel 按区域汇总”,AI 就会自动调用对应的 MCP 工具完成任务。

MCP 的几个核心概念:

概念含义类比
MCP Host运行 AI 模型的环境管家的脑子
MCP Client发起请求的一方管家本人
MCP Server提供工具服务的一方管家的手和工具
Tool具体可执行的操作开灯、煮咖啡
Resource可读取的数据源冰箱里的食材
Prompt预定义的提示模板菜谱

我这次要写的 ExcelMCP,就是一个 MCP Server。它对外暴露几个 Tool,比如read_excel、filter_data、group_sum、write_excel,AI 模型根据需要自动调用。

2.2 为什么选 Python 而不是其他语言

MCP Server 可以用任何语言写,官方提供了 Python、TypeScript、Java 等多种 SDK。我选 Python 的原因很实际:

第一,Excel 处理生态成熟。openpyxl、pandas、xlrd、xlsxwriter这些库覆盖了几乎所有 Excel 操作场景,社区活跃,遇到问题容易找到答案。

第二,Python 的 MCP SDK 封装得好。官方mcp包提供了FastMCP类,几行代码就能定义一个 Tool,省去了大量样板代码。

第三,调试方便。Python 可以边写边跑,配合print和日志,排查问题比编译型语言快得多。

第四,和 AI 生态衔接顺畅。很多 AI 工具链、数据处理管道都是 Python 写的,后续扩展成本低。

当然,如果你更熟悉 TypeScript,用 Node.js 写也完全没问题。核心逻辑是一样的,只是语法不同。

2.3 整体架构设计:三层结构

我的 ExcelMCP 采用三层结构:

第一层:协议层。基于mcp包实现 MCP Server,负责和 AI 客户端通信。这一层不需要我写太多代码,SDK 已经处理好了 JSON-RPC 的序列化和反序列化。

第二层:业务逻辑层。这是核心,包含所有 Excel 处理函数。每个函数对应一个 Tool,输入是参数,输出是处理结果。这一层完全独立于 MCP,即使不用 AI,也可以直接调用。

第三层:数据层。负责实际的文件读写,用pandas做数据处理,用openpyxl做格式控制。

这样分层的好处是:业务逻辑和协议解耦,方便单元测试;数据层可以替换,比如以后想支持 CSV 或数据库,只需要改这一层。

3. 环境准备与项目初始化

3.1 Python 安装与环境配置

如果你电脑上还没有 Python,先去官网下载安装包。建议选 3.10 或以上版本,因为 MCP SDK 要求 Python 3.10+。

安装时有一个关键选项:勾选“Add Python to PATH”。这个选项如果不勾,后面在命令行里敲python会提示找不到命令。我见过太多人卡在这一步。

安装完成后,打开终端验证:

python --version pip --version

如果都能正常输出版本号,说明安装成功。

接下来配置虚拟环境。虚拟环境的作用是隔离项目依赖,避免不同项目之间的包版本冲突。操作如下:

mkdir excel-mcp cd excel-mcp python -m venv venv

激活虚拟环境:

  • Windows:venv\Scripts\activate
  • macOS/Linux:source venv/bin/activate

激活后,命令行前面会出现(venv)标识。

3.2 安装核心依赖包

在虚拟环境中安装以下包:

pip install mcp pandas openpyxl

三个包的作用:

  • mcp:MCP 协议 SDK,提供 Server 和 Tool 的基础设施
  • pandas:数据处理核心库,负责读取、筛选、分组、汇总
  • openpyxl:Excel 文件读写引擎,pandas 底层调用它来操作.xlsx文件

如果你还需要处理.xls老格式,额外装一个xlrd:

pip install xlrd

注意:xlrd从 2.0 版本开始不再支持.xlsx,只支持.xls。所以.xlsx文件还是靠openpyxl。

3.3 项目目录结构

我习惯把项目结构搭得清晰一点,方便后续扩展:

excel-mcp/ ├── venv/ ├── server.py # MCP Server 入口 ├── excel_tools.py # Excel 处理业务逻辑 ├── requirements.txt # 依赖清单 └── test_data/ └── sample.xlsx # 测试数据

server.py负责注册 Tool 和启动服务,excel_tools.py放具体的处理函数。这样分开写,代码可读性高,也方便单独测试业务逻辑。

生成requirements.txt:

pip freeze > requirements.txt

4. 核心功能实现:从读取到写入的完整链路

4.1 读取 Excel 并自动识别表头

第一个 Tool 是read_excel。它的任务是读取指定 Excel 文件,返回数据概览,包括列名、行数、前几行数据。

import pandas as pd def read_excel(file_path: str, sheet_name: str = None) -> dict: """ 读取 Excel 文件,返回基本信息 """ try: df = pd.read_excel(file_path, sheet_name=sheet_name) result = { "columns": df.columns.tolist(), "row_count": len(df), "dtypes": {col: str(dtype) for col, dtype in df.dtypes.items()}, "preview": df.head(5).to_dict(orient="records") } return {"status": "success", "data": result} except Exception as e: return {"status": "error", "message": str(e)}

这段代码有几个细节值得说:

sheet_name=None时,pandas 默认读取第一个 sheet。如果你想读取所有 sheet,可以传sheet_name=None,但那样返回的是一个字典,需要额外处理。

df.head(5)只取前五行做预览,避免返回数据量过大。MCP 的返回结果会传给 AI 模型,如果一次返回几千行,会消耗大量 token,既慢又贵。

dtypes返回每一列的数据类型。这个信息很重要,因为 AI 需要知道哪些列是数字、哪些是文本,才能正确选择汇总方式。

4.2 条件筛选与关键词统计求和

这是最实用的功能之一。热词里有人搜“excel同一列中统计含关键词对应数据求和”,这个需求在销售分析、日志统计里非常常见。

def filter_and_sum(file_path: str, keyword: str, text_column: str, value_column: str) -> dict: """ 在 text_column 中查找包含 keyword 的行, 对 value_column 求和 """ df = pd.read_excel(file_path) mask = df[text_column].astype(str).str.contains(keyword, na=False) filtered = df[mask] total = filtered[value_column].sum() return { "status": "success", "matched_rows": len(filtered), "total_sum": float(total), "details": filtered[[text_column, value_column]].head(10).to_dict(orient="records") }

关键点解释:

astype(str)是为了防止列里有非字符串类型导致报错。比如某列混了数字和文本,直接调.str.contains()会出问题。

na=False表示遇到空值时当作不匹配处理,而不是报错。这个参数在实际数据里非常必要,因为真实 Excel 几乎不可能没有空单元格。

float(total)是类型转换。pandas 的sum()返回的是numpy类型,直接塞进 JSON 会序列化失败。转成 Python 原生float就没问题了。

4.3 分组汇总与多表合并

分组汇总是 Excel 里最常用的操作之一。比如按区域汇总销售额、按月份统计订单量。

def group_sum(file_path: str, group_column: str, value_column: str, agg_func: str = "sum") -> dict: """ 按 group_column 分组,对 value_column 做聚合 agg_func 支持 sum/mean/count/max/min """ df = pd.read_excel(file_path) agg_map = { "sum": "sum", "mean": "mean", "count": "count", "max": "max", "min": "min" } if agg_func not in agg_map: return {"status": "error", "message": f"不支持的聚合方式: {agg_func}"} grouped = df.groupby(group_column)[value_column].agg(agg_map[agg_func]) result = grouped.reset_index() result.columns = [group_column, f"{value_column}_{agg_func}"] return { "status": "success", "group_count": len(result), "data": result.to_dict(orient="records") }

多表合并的场景也很常见。比如一个文件里有“一月”“二月”“三月”三个 sheet,需要合并成一张总表:

def merge_sheets(file_path: str, sheet_names: list) -> dict: """ 合并多个 sheet 的数据 """ dfs = [] for name in sheet_names: df = pd.read_excel(file_path, sheet_name=name) df["来源表"] = name dfs.append(df) merged = pd.concat(dfs, ignore_index=True) return { "status": "success", "total_rows": len(merged), "columns": merged.columns.tolist() }

ignore_index=True的作用是重置索引,避免合并后索引重复。df["来源表"] = name是加一列标记数据来源,方便后续追溯。

4.4 写入 Excel 并保留格式

处理完数据,最后一步是写回 Excel。这里我用openpyxl做引擎,因为它支持格式控制。

def write_excel(data: list, output_path: str, sheet_name: str = "Result") -> dict: """ 将数据写入 Excel 文件 """ try: df = pd.DataFrame(data) with pd.ExcelWriter(output_path, engine="openpyxl") as writer: df.to_excel(writer, sheet_name=sheet_name, index=False) worksheet = writer.sheets[sheet_name] # 自动调整列宽 for column in worksheet.columns: max_length = 0 column_letter = column[0].column_letter for cell in column: if cell.value: max_length = max(max_length, len(str(cell.value))) worksheet.column_dimensions[column_letter].width = min(max_length + 2, 50) return {"status": "success", "output_path": output_path} except Exception as e: return {"status": "error", "message": str(e)}

自动调整列宽这段代码很实用。默认情况下,Excel 列宽是固定的,长文本会显示不全。这段逻辑遍历每一列,找出最长的内容,把列宽设为“最长内容长度 + 2”,同时限制最大宽度为 50,避免某一列特别长导致表格难看。

5. 把业务逻辑包装成 MCP Server

5.1 用 FastMCP 注册 Tool

业务逻辑写好了,接下来要把它暴露成 MCP Tool。官方 SDK 提供了FastMCP类,用起来很简洁:

from mcp.server.fastmcp import FastMCP from excel_tools import read_excel, filter_and_sum, group_sum, write_excel mcp = FastMCP("ExcelMCP") @mcp.tool() def tool_read_excel(file_path: str, sheet_name: str = None) -> dict: """读取 Excel 文件,返回列名、行数和前五行数据""" return read_excel(file_path, sheet_name) @mcp.tool() def tool_filter_and_sum(file_path: str, keyword: str, text_column: str, value_column: str) -> dict: """在指定列中查找包含关键词的行,并对目标列求和""" return filter_and_sum(file_path, keyword, text_column, value_column) @mcp.tool() def tool_group_sum(file_path: str, group_column: str, value_column: str, agg_func: str = "sum") -> dict: """按指定列分组,对目标列做聚合计算""" return group_sum(file_path, group_column, value_column, agg_func) @mcp.tool() def tool_write_excel(data: list, output_path: str, sheet_name: str = "Result") -> dict: """将数据写入 Excel 文件,自动调整列宽""" return write_excel(data, output_path, sheet_name) if __name__ == "__main__": mcp.run()

@mcp.tool()装饰器是关键。它把普通 Python 函数注册成 MCP Tool,SDK 会自动读取函数的类型注解和文档字符串,生成对应的 JSON Schema。AI 模型就是根据这个 Schema 来理解每个 Tool 需要什么参数、能做什么事。

文档字符串("""...""")非常重要,它是 AI 选择 Tool 的主要依据。写的时候要简洁准确,把功能、输入、输出说清楚。

5.2 启动服务与连接测试

启动 MCP Server:

python server.py

默认情况下,FastMCP 使用 stdio 传输方式,也就是通过标准输入输出和客户端通信。这种方式适合本地集成,比如在 IDE 或桌面 AI 助手里使用。

如果你想用 HTTP 方式,可以改成:

mcp.run(transport="streamable-http", host="127.0.0.1", port=8000)

测试连接是否正常,可以用 MCP 官方提供的 Inspector 工具:

npx @modelcontextprotocol/inspector python server.py

Inspector 会启动一个网页界面,你可以在里面看到所有注册的 Tool,手动传参数调用,验证功能是否正常。这个工具在开发阶段非常有用,强烈建议用起来。

5.3 在 AI 客户端中配置使用

以常见的桌面 AI 工具为例,配置文件通常是一个 JSON 文件,在里面加上:

{ "mcpServers": { "excel-mcp": { "command": "python", "args": ["/path/to/excel-mcp/server.py"] } } }

配置完成后重启客户端,AI 就能识别到 ExcelMCP 提供的 Tool。之后你直接说“帮我读取 test_data/sample.xlsx,按区域汇总销售额”,AI 就会自动调用tool_read_excel和tool_group_sum完成任务。

6. 实操中踩过的坑与排查技巧

6.1 常见报错与解决方案速查表

报错信息原因解决方法
ModuleNotFoundError: No module named 'mcp'没装 mcp 包或虚拟环境没激活激活 venv 后pip install mcp
FileNotFoundError文件路径不对用绝对路径,或确认工作目录
JSON serialization error返回了 numpy 类型用float()、int()转换
KeyError: 'xxx'列名不存在先用read_excel确认列名
openpyxl does not support .xls文件格式不匹配.xls用 xlrd,.xlsx用 openpyxl
中文乱码编码问题确保文件是 UTF-8,或指定 encoding

6.2 三个我实际踩过的坑

第一个坑:列名里有空格。有一次读取一个客户给的 Excel,列名是“销售额 ”(末尾有个空格),我代码里写的是“销售额”,结果一直报 KeyError。排查了半小时才发现。后来我养成了一个习惯:读取后先print(df.columns.tolist()),确认列名再写后续逻辑。

第二个坑:数字列被识别成文本。有些 Excel 里数字是文本格式存储的,sum()会变成字符串拼接。解决方法是读取时加dtype参数强制指定类型,或者用pd.to_numeric(df[col], errors='coerce')转换。

第三个坑:大文件内存溢出。有一次处理一个 50 万行的 Excel,直接pd.read_excel把内存吃满了。后来改成read_excel(..., chunksize=10000)分块读取,或者先用openpyxl的只读模式过滤再加载。

6.3 性能优化与安全建议

性能方面,几个实用建议:

  • 读取大文件时指定usecols参数,只加载需要的列
  • 用dtype参数预设类型,避免 pandas 自动推断的开销
  • 写入时用xlsxwriter引擎比openpyxl快,但不支持读取
  • 频繁操作同一文件时,考虑先加载到内存,处理完再统一写回

安全方面,MCP Server 能读写本地文件,所以要特别注意:

  • 限制可访问的目录范围,不要让 AI 随意读取系统文件
  • 对输出路径做校验,防止覆盖重要文件
  • 如果暴露成 HTTP 服务,加上认证机制,不要裸奔在公网

提示:开发阶段可以用print打日志,但生产环境建议用logging模块,把日志写到文件,方便排查问题。

7. 这个 MCP 还能怎么扩展

7.1 接入更多数据源

目前只支持 Excel,但架构上数据层是独立的。你可以很容易地加上 CSV 支持:

def read_csv(file_path: str) -> dict: df = pd.read_csv(file_path, encoding="utf-8") return {"columns": df.columns.tolist(), "row_count": len(df)}

或者接入数据库,用sqlalchemy做查询。核心思路是一样的:读数据、处理、返回结果。

7.2 结合工作流做自动化

MCP 最大的价值在于和 AI 工作流结合。比如你可以搭一个这样的流程:

  1. AI 收到一封带附件的邮件
  2. 自动调用 ExcelMCP 读取附件
  3. 按预设规则清洗和汇总
  4. 生成报告并写回新文件
  5. 把结果发给指定的人

整个过程不需要人工干预。我试过用这种方式处理每周的销售周报,原来要花一小时,现在几分钟就搞定了。

7.3 加入图表生成能力

Excel 的图表功能很强,但 pandas 本身不支持直接生成图表。可以结合xlsxwriter的图表功能:

import xlsxwriter workbook = xlsxwriter.Workbook("output.xlsx") worksheet = workbook.add_worksheet() chart = workbook.add_chart({"type": "column"}) chart.add_series({ "categories": ["Sheet1", 1, 0, 5, 0], "values": ["Sheet1", 1, 1, 5, 1] }) worksheet.insert_chart("D2", chart) workbook.close()

这样 AI 就能根据数据自动生成柱状图、折线图、饼图,直接输出一份完整的分析报告。

7.4 错误处理与日志记录

生产环境里,错误处理和日志是必须的。我现在的做法是:

import logging logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s", handlers=[ logging.FileHandler("excel_mcp.log"), logging.StreamHandler() ] ) logger = logging.getLogger(__name__)

每个 Tool 调用前后都打日志,记录输入参数和返回结果。出问题时翻日志,比在代码里到处加print高效得多。

8. 一些个人体会

写这个 MCP 的过程中,我最大的感受是:MCP 真正降低了 AI 落地的门槛。以前想让 AI 操作本地文件,得自己写 API、处理认证、设计接口,现在有了 MCP 协议,只需要专注业务逻辑,通信层 SDK 全包了。

另一个体会是:文档字符串比代码本身还重要。AI 是根据文档字符串来选择 Tool 的,写得不清楚,AI 就会选错工具或者传错参数。我一开始没重视这个,结果 AI 经常把filter_and_sum和group_sum搞混。后来把文档写详细了,准确率立刻上来了。

最后分享一个小技巧:开发 MCP 时,先用 Inspector 把每个 Tool 单独测通,再接入 AI 客户端。这样出问题时能快速定位是 Tool 本身的问题,还是 AI 调用的问题。我一开始跳过这一步,直接在客户端里测,结果排查了半天才发现是参数类型不对。

这个 ExcelMCP 目前还在持续迭代,后面打算加上数据透视表、条件格式、多文件批量处理这些功能。如果你也在做类似的事情,欢迎交流。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/2 17:26:05

实测三款AI大模型:用Three.js生成3D游戏谁更强?

1. 为什么选 3D 游戏当考题1.1 三位参赛选手是谁先把主角们拉出来亮个相。这次实测的三个模型分别是 Step 5 Preview、DeepSeek V4 Pro 和 GLM5.3,都是近期在推理能力、代码生成和长上下文这几个方向上讨论度很高的名字。Step 5 Preview 是 Step 系列里一个很新的预…

作者头像 李华
网站建设 2026/11/2 17:25:56

C-NCAP2024 AEB VRU测试详解与优化策略

1. C-NCAP2024 AEB VRU测试概述2024版C-NCAP规程中最引人注目的更新之一,就是针对弱势道路使用者(VRU)保护的AEB测试体系全面升级。作为车辆主动安全的核心项目,这套测试直接决定了车型在行人、自行车骑行者等事故高发场景中的安全…

作者头像 李华
网站建设 2026/11/2 17:25:25

十大自动化工具实测:从安装到跑通十分钟内搞定

1. 为什么"可试用"才是自动化工具的真正分水岭大多数自动化工具清单的问题在于,它们只告诉你"有这个工具",却不告诉你"怎么在十分钟内跑起来"。我翻过太多所谓的开源工具合集,洋洋洒洒列了五十个项目&#xff…

作者头像 李华
网站建设 2026/11/2 17:24:28

AI营销三力闭环:生成力、推理力、互动力如何重构营销决策

简介:这份研究报告面向市场营销从业者、企业决策者及AI技术研究者,系统梳理中国AI营销从1956年技术萌芽到2025年的发展脉络,帮助读者理解AI如何从效率工具升级为战略资产。报告围绕四大板块展开:AI营销发展阶段与服务商市场格局、…

作者头像 李华
网站建设 2026/11/2 17:23:17

ZooKeeper在Hadoop生态中的角色:主备切换、状态存储与排障

凌晨两点半被电话叫起来,说某套集群的 NameNode 主备在十几分钟里来回切了三次,上层写入大面积超时。爬起来先翻 NameNode 自己的日志,干干净净,没有任何异常堆栈;再去看 ZKFC 的日志,满屏的ConnectionLoss…

作者头像 李华
网站建设 2026/11/2 17:19:47

ISSA-CNN-LSTM-Attention模型在时序预测中的应用

1. 项目概述 今天想和大家分享一个我在时间序列预测项目中实际应用过的创新模型架构——ISSA-CNN-LSTM-Attention。这个组合模型在多个工业预测场景中表现优异,特别是在处理具有复杂时空特征的数据时,相比传统单一模型有显著提升。 这个模型的创新点主要…

作者头像 李华