传统方案由工作流预先抓取全部行塞入 prompt,量大了既贵又超上下文;MCP 方案让 AI Agent 在执行过程中按需调工具抓取指定行,实现按需查询而非全量灌入。
我的 n8n 工作流用于回答关于 Google Sheet 的问题,一度运行良好,直到用户提问不再是我预先规划的那些。这个 Sheet 是一个产品目录。我的工作流用内置的 Google Sheets 节点读取整个表格,把每一行都塞进 prompt,让模型自己处理。五十行时这没问题。到了两千行,速度变慢、成本变高,最终还会超出上下文窗口,而模型仍然把大部分注意力花在过滤它根本不会用到的行上。
解决方案不是更大的 prompt,而是让 agent 自己获取需要的行,而不是我替它获取。这就是 Google Sheets 节点和 Google Sheets MCP 服务器的区别,也是使用后者的全部原因。
MCP(Model Context Protocol)是 AI agent 与外部数据源通信的标准方式。MCP 服务器公开一组固定的工具,agent 可以在运行时调用其中任何一个来获取所需信息。n8n 提供了一个 MCP Client Tool 节点,可以附加到 AI Agent 节点上,让工作流中的 agent 能够在推理时调用这些工具。我开发了 PasteSheet,它将 Google Sheet 发布为只读的 MCP 服务器,所以接下来的内容都是基于实际设置而非假设。
这是我最初理解错的地方,所以我要直说。n8n 的原生 Google Sheets 节点在你明确知道需要哪些行时是合适的工具。它具有确定性,你可以配置精确的范围或过滤器,甚至能够回写数据。这些能力都不会改变。在你能够掌控的步骤中继续使用它。
MCP 服务器用于 agent 处于控制地位的步骤。与其在设计时预先决定查询逻辑,不如让 agent 在运行时根据用户实际提出的问题来做出决定。它读取表格的 schema,选择筛选条件,然后仅提取匹配的行。你不再需要硬编码"获取状态为 active 的 C 列",而是将这项工作交给 agent 来处理。
所以准确的表述不是"节点 vs MCP",而是"确定性写入和已知读取用节点,开放式推理用 MCP"。真实的工作流通常会同时使用两者。
n8n 内部的设置很简洁。你需要在工作流中已经有一个接入了聊天模型的 AI Agent 节点。
添加一个 MCP Client Tool 节点。
将其附加到 AI Agent 节点的工具输入槽位——和接入其他 agent 工具时使用的同一个插槽。
将服务器 URL 设置为你的端点的 MCP URL。在 PasteSheet 中,这个地址在端点的 Connect via MCP 面板里。
如果端点是私密的,在节点上添加 Authorization: Bearer YOUR_KEY 请求头。
正常地为 agent 写 prompt 即可。
最后这一步看起来似乎太简单了。你不需要告诉 agent 有哪些工具可用或如何调用它们。它从服务器读取工具列表,看到 get_schema 和 query_rows,在问题需要表格数据时自行调用它们。像"20 美元以下缺货的产品有哪些"这样的 prompt,会转化为一次 schema 读取加一次带过滤条件的查询,整个过程中你无需编写任何查询逻辑。
以下是从 agent 视角看到的一次运行大致过程:
User: which products are out of stock under $20?
Agent -> get_schema()
<- { columns: ["Name", "Price", "Stock", "Category"] }
Agent -> query_rows({ filters: { "Stock": "0" }, limit: 50 })
<- { data: [...], total: 14, limit: 50, offset: 0 }
Agent: 3 products are out of stock under $20: ...
Agent 因为先读取了 schema 才选对了列名。那次 schema 调用开销很小,但它正是阻止模型为一个列名是 Stock 的表格凭空发明一个叫 Quantity 的列、然后报告一个运行前就错了的查询没有结果的关键。
你可以接入 n8n 的 Google Sheets 节点,或者直接用 HTTP 节点调用 Sheets API,让 agent 代替调用。这样做在达到某个临界点之前都没问题,而失败的原因是配额。
Agent 的调用频率与定时自动化完全不同。一个用户问题会转化为一次 schema 读取加三到四次探索性查询,如果你的工作流服务于多个用户,这个数字还会翻倍。Google 允许每个项目每分钟 300 次读取、每个用户每分钟 60 次,超过则返回 429(公开限额)。60 次/用户/分钟这个上限才是真正坑人的,因为一个繁忙的 agent 就能触发它,而你的项目用量看起来仍然很低。
有了缓存端点就不一样了。表格在一个刷新窗口内只从 Google 读取一次,之后 agent 的所有工具调用都从缓存中获取。一分钟内一百次查询对 Google 只产生一次读取,不是一百次。任何 Google Sheets MCP 服务器暴露的都是同样的三个读取工具:list_tabs、get_schema 和 query_rows,所以缓存才是真正发挥作用的部分。
只读设计是诚实的边界,而且这是刻意的,不是缺失的功能。你的 n8n agent 无法通过 PasteSheet 回写表格。服务器上没有 update 工具,所以无论是一个困惑的 agent,还是一个被 prompt 注入的 agent,都没有路径能够覆盖你的数据源。这正是设计的目的。
但这确实意味着一个需要修改表格的工作流必须分割任务。用原生 Google Sheets 节点处理写操作,因为那是它擅长的;用 MCP 处理读取和围绕数据的推理。如果你原本希望把整个流程交给一个既读又写的 agent,这里就是你感受到裂痕的地方,你应该从一开始就意识到这一点,而不是在构建过程中才发现。
不过,对于真正只需要读取和推理的自动化场景——这占了大多数 agent 工作流——这种分割实际上没有代价。Agent 获取实时数据,你有缓存保护不让 Google 配额被打爆,表格的安全性和你把模型指向它之前完全一样。如果你来自定时同步的思维方式,值得对比一下 Zapier 和 Make 等老派方案——它们按时间表移动数据,而这个方案则是按问题来移动。
我开发了 PasteSheet:粘贴一个 Google Sheet URL,就能得到一个缓存的 JSON API 外加一个你的 AI agent 可以查询的只读 MCP 服务器。有免费层级,无需信用卡,也不需要 Google Cloud 项目。如果你在 n8n agent 中接入了 MCP 服务器,我想知道你最终采用了哪种节点组合方式,因为我怀疑节点加 MCP 的分割比文档里显示的要普遍得多。