用 LangGraph + MCP Server 打造 SpreadJS 智能助手:让 AI 真正懂你的表格需求 用 LangGraph MCP Server 打造 SpreadJS 智能助手让 AI 真正懂你的表格需求在这篇教程中我们将从零搭建一个智能助手它能够理解你对 SpreadJS 表格的自然语言需求并自动执行操作。我们使用 LangGraph 来编排多步推理流程并通过 MCP Server 将 AI 与 SpreadJS 的 API 桥接最终实现一个“会思考的表格管家”。## 1. 为什么需要 LangGraph MCP ServerSpreadJS 是一个功能强大的 JavaScript 电子表格组件但用户需要通过代码或复杂配置来操作它。传统 AI 助手只能生成代码片段无法直接与表格交互。LangGraph 提供了一个循环推理的框架让 AI 能像人类一样“思考-执行-验证”而 MCP Server 则充当了 AI 与 SpreadJS 之间的桥梁让 AI 能直接调用 SpreadJS 的 API。### 基础概念-LangGraph基于图的工作流引擎支持条件跳转、循环和状态管理。-MCP Server模型上下文协议服务器将 AI 的意图映射为具体的函数调用。-SpreadJS纯前端表格控件支持数据绑定、公式计算和 UI 操作。## 2. 环境搭建与核心依赖首先安装必要的 Python 包bashpip install langgraph langchain-openai mcp同时你需要一个 SpreadJS 的 Node.js 后端这里用简易 Express 服务模拟javascript// server.js - 模拟 SpreadJS 操作的后端const express require(express);const app express();app.use(express.json());let sheetData [[姓名, 年龄, 成绩], [张三, 25, 90], [李四, 28, 85]];app.post(/api/set-cell, (req, res) { const { row, col, value } req.body; if (sheetData[row] sheetData[row][col] ! undefined) { sheetData[row][col] value; res.json({ success: true, data: sheetData }); } else { res.status(400).json({ error: 无效的行列索引 }); }});app.get(/api/get-data, (req, res) { res.json(sheetData);});app.listen(3001, () console.log(SpreadJS 模拟服务运行中));## 3. 第一步构建 MCP Server 工具MCP Server 的核心是定义一组工具函数让 AI 能够调用。下面我们创建一个工具用于修改表格单元格的值。python# mcp_tools.py - 定义供 AI 调用的 SpreadJS 工具from mcp.server import Server, stdio_serverfrom mcp.types import Tool, TextContentimport requests# 定义工具函数修改单元格def set_cell_value(row: int, col: int, value: str) - str: 修改 SpreadJS 表格中指定单元格的值 url http://localhost:3001/api/set-cell payload {row: row, col: col, value: value} try: response requests.post(url, jsonpayload) if response.status_code 200: return f成功设置单元格 ({row},{col}) 为 {value} else: return f设置失败{response.json().get(error, 未知错误)} except Exception as e: return f网络错误{str(e)}# 注册为 MCP 工具server Server(spreadsheet-assistant)server.list_tools()async def list_tools(): return [ Tool( nameset_cell, description修改 SpreadJS 表格中一个单元格的值, inputSchema{ type: object, properties: { row: {type: integer, description: 行索引从0开始}, col: {type: integer, description: 列索引从0开始}, value: {type: string, description: 要设置的文本值} }, required: [row, col, value] } ) ]server.call_tool()async def call_tool(name: str, arguments: dict): if name set_cell: result set_cell_value(**arguments) return [TextContent(typetext, textresult)] else: raise ValueError(f未知工具: {name})if __name__ __main__: stdio_server.run(server)## 4. 第二步用 LangGraph 编排 AI 推理流程LangGraph 的核心是节点Node和边Edge我们构建三个节点think理解用户需求、execute调用 MCP 工具、verify验证结果。python# langgraph_agent.py - 构建智能助手工作流from langgraph.graph import StateGraph, ENDfrom langchain_openai import ChatOpenAIfrom langchain_core.messages import HumanMessage, AIMessagefrom mcp import ClientSession, StdioServerParametersfrom typing import TypedDict, Optional# 定义状态类型class AgentState(TypedDict): messages: list # 对话历史 user_query: str # 用户原始请求 plan: Optional[str] # AI 的执行计划 tool_result: Optional[str] # 工具执行结果 verified: bool # 是否验证通过# 初始化 LLMllm ChatOpenAI(modelgpt-4, temperature0)# 节点1: 理解并生成计划def think_node(state: AgentState): 分析用户需求生成操作计划 user_query state[user_query] prompt f 用户说{user_query} 请分析需要修改 SpreadJS 表格的哪个单元格。格式 计划: [行索引, 列索引, 新值] 如果无法理解回复计划: 未知 response llm.invoke([HumanMessage(contentprompt)]) plan response.content.strip() return {plan: plan, messages: state[messages] [AIMessage(contentplan)]}# 节点2: 执行工具调用def execute_node(state: AgentState): 根据计划调用 MCP 工具 plan state[plan] if 计划: not in plan: return {tool_result: 计划解析失败, verified: False} # 解析计划内容例如 计划: [0, 2, 85] import re match re.search(r\[(\d),\s*(\d),\s*\?(.*?)\?\], plan) if match: row, col, value int(match.group(1)), int(match.group(2)), match.group(3) # 这里模拟调用 MCP 工具实际应通过 ClientSession result f调用 set_cell(row{row}, col{col}, value{value}) 成功 return {tool_result: result, verified: True} else: return {tool_result: 无法解析计划, verified: False}# 节点3: 验证结果def verify_node(state: AgentState): 检查执行结果是否满足用户需求 if state[verified]: return {messages: state[messages] [AIMessage(contentf操作完成{state[tool_result]})]} else: return {messages: state[messages] [AIMessage(contentf操作失败{state[tool_result]}请重新描述需求)]}# 构建 LangGraphworkflow StateGraph(AgentState)workflow.add_node(think, think_node)workflow.add_node(execute, execute_node)workflow.add_node(verify, verify_node)workflow.set_entry_point(think)workflow.add_edge(think, execute)workflow.add_edge(execute, verify)workflow.add_conditional_edges( verify, lambda state: end if state[verified] else think, {end: END, think: think})app workflow.compile()# 运行助手def run_assistant(user_query: str): initial_state { messages: [], user_query: user_query, plan: None, tool_result: None, verified: False } result app.invoke(initial_state) return result[messages][-1].contentif __name__ __main__: # 测试示例 print(run_assistant(请将张三的成绩改为95))## 5. 高级用法多步操作与上下文记忆真实场景中用户可能要求“将第一行的标题加粗再把李四的年龄改为30”。我们需要让 AI 记住之前的操作并支持连续指令。python# advanced_graph.py - 支持多步骤和上下文记忆from langgraph.checkpoint import MemorySaver# 添加记忆功能memory MemorySaver()# 修改 think_node 以利用历史消息def think_node_advanced(state: AgentState): 利用对话历史理解连续指令 messages state[messages] user_query state[user_query] # 构建包含上下文的提示 context \n.join([f{用户 if isinstance(m, HumanMessage) else 助手}: {m.content} for m in messages[-4:]]) prompt f 历史上下文 {context} 新指令{user_query} 请分析需要修改哪个单元格并给出格式化的计划。 如果是格式化操作如加粗计划格式为格式化: [行, 列, 类型] response llm.invoke([HumanMessage(contentprompt)]) return {plan: response.content, messages: state[messages] [AIMessage(contentresponse.content)]}# 重建工作流带记忆workflow_advanced StateGraph(AgentState)workflow_advanced.add_node(think, think_node_advanced)workflow_advanced.add_node(execute, execute_node)workflow_advanced.add_node(verify, verify_node)workflow_advanced.set_entry_point(think)workflow_advanced.add_edge(think, execute)workflow_advanced.add_edge(execute, verify)workflow_advanced.add_conditional_edges( verify, lambda state: end if state[verified] else think, {end: END, think: think})# 使用记忆app_advanced workflow_advanced.compile(checkpointermemory)# 连续对话示例config {configurable: {thread_id: user_001}}for query in [请将张三的成绩改为95, 现在把李四的年龄改为30]: state app_advanced.invoke({ messages: [], user_query: query, plan: None, tool_result: None, verified: False }, config) print(f用户: {query}\n助手: {state[messages][-1].content}\n)## 6. 总结通过 LangGraph 和 MCP Server 的结合我们打造了一个真正“懂”表格的智能助手。LangGraph 提供了灵活的推理循环让 AI 能够根据反馈不断调整计划MCP Server 则安全地暴露了 SpreadJS 的底层操作接口。从简单的单元格修改到复杂的多步操作这个架构都能胜任。未来你可以扩展更多 MCP 工具如插入行、设置公式、导入数据甚至加入图像识别——让 AI 看懂用户的截图后自动调整表格。现在你已经掌握了核心技术快去打造属于你自己的“会思考的表格管家”吧