当 PostgreSQL 成为 AI 的双手——Bruce Momjian 的 MCP Server 实战
原文Building an MCP Server Using PostgresBruce MomjianPGDay Armenia 2026CC BY 4.0。本文AI率80%Bruce MomjianPG core team写了 20 多年发行注记的那位最近在 PGDay Armenia 2026 做了一个演讲Building an MCP Server Using Postgres。70 页幻灯片信息密度极高。有理论有实践是一个不错的借鉴。直接读是比较费劲的哪怕是直接让AI解读一下估计也不知道说的是什么我也是看了一会问了几个问题后才算看明白了。这 70 页可以清晰地切成两层——前半部分是理论教学后半部分是实战 demo。两层之间关系不大。理论层用 Transformer 解释 RAG → MCP 的演进Slide 1-33理论层占了近一半篇幅从 LLM 基本原理讲到 MCP 的工作方式。Outline 很清楚RAG vs MCP一句话说清RAG 的流程大家都熟了程序员决定查什么数据 → 检索结果拼到 system prompt → LLM 读完后生成回答。预编排——LLM 能看到什么在用户提问之前就定好了。MCP 不一样。工具描述注册给 LLMLLM 在生成过程中自己判断要不要调工具、调哪个。动态决策——程序员只负责暴露工具LLM 负责编排。Bruce 用一句话总结RAG 只能做程序员预设的事。MCP 可以根据输出质量动态调整可以迭代调用多个工具还可以触发外部任务。“是词还是 MCP”——那套向量嵌入图解Slide 18-33 是理论层最核心的部分。Bruce 画了一套详细的 Transformer 内部流程图他的逻辑是把每个 MCP tool 的描述文本比如 “Return the radiation level (CPM) at 13 Roberts Road…”用文本嵌入模型向量化塞进 attention 层的向量空间里。然后在每一步推理时output vector 去匹配最近似的向量——“The closest vector might be a word or an MCP.”这个模型对吗这是我最疑惑的地方以下是我的浅见。Bruce 这 15 页 slides 画得很好看但如果当工程实现去理解是有问题的① MCP tool 不需要嵌入。实际工程中tool 定义是作为文本直接写在 system prompt 里的。LLM 读到 “你有这些工具geiger()、get_pretzel_inventory()…”靠语义理解决定什么时候调。不需要把 tool 描述算成向量不需要和词向量做余弦距离比较。Bruce 这套教学模型的本质是把LLM 决策解释成向量最近似匹配这更像 retrieval 的范式而不是 generation 的范式。② Attention 不产出查最近似的操作。output Σ(softmax(Q·K) × V)产出的是一个加权混合后的上下文向量。没有在词向量表和 tool 向量表里二选一这一步。LLM 选工具的实际机制是 attention 产出 hidden state → LM head → softmax over 词表 → 输出 tool call JSON。从来没有在词和 tool 之间二选一只有在整个词表上做 softmax。③ system prompt 和 user prompt 在 attention 里没有边界。Token 序列就是 token 序列attention block 对所有 token 一视同仁做 Q·K 点积。不存在system 区和user 区。所以这 33 页理论层可以看作 Bruce 给非 AI 背景的 DBA 做的一个教学简化模型——好看、好懂但别当架构图用。MCP 真正革命性的地方在协议标准化统一的 tool 注册/发现/调用规范不在向量化的 trick。实践层两个能跑的 demoSlide 34-69从 Slide 34 开始风格突变——全是代码、终端输出、硬件照片。理论层那套 Transformer 向量模型完全消失了取而代之的是curl、psql、Perl 脚本。两层之间的唯一联系是它们都在讲 MCP但理论层画的向量匹配机制和实战中的实现方式几乎是两套逻辑。 这可能正是 Bruce 演讲的张力所在——理论层让你理解 MCP 为什么比 RAG 强实践层告诉你现在怎么落地。Demo 1让 ChatGPT 读取真实世界的盖革计数器Bruce 在自家院子里架了一台 GQ GMC-800 盖革计数器测辐射的USB 接树莓派每 15 分钟测一次环境辐射。先看 ChatGPT 用 MCP 调用真实数据的效果MCP 可以调用外部工具获取实时数据——这是 RAG 做不到的。接上硬件用fastmcp写了 Python wrapperfromfastmcpimportFastMCP mcpFastMCP(Geiger counter MCP server)mcp.tooldefgeiger()-int:Return the radiation level (CPM) at 13 Roberts Road, Newtown Square, PA, USAreturnsubprocess.check_output(/var/lib/postgresql/tmp/geiger,shellTrue,textTrue)底层是一个 Perl 脚本往串口发GETCPM指令读回 4 字节 CPM 值。Apache 做 443 端口反代OpenAI 只跟 443 通信注册到 ChatGPT 后User: 13 Roberts Road 的辐射水平是多少 GPT: 我没有这个位置的公开数据…… User: 用我的 custom app GPT: [调用 geiger tool] → 14 CPM。正常环境背景辐射5-25 CPM。 User: 测五次给我平均值 GPT: [调用 ×5] 15 16 13 15 15 → 平均 14.8 CPM两个关键行为LLM 可以迭代调工具做计算——RAG 是一次性塞数据MCP 是调 → 拿结果 → 判断 → 再调 → 算用户必须显式授权——第一次问的时候 ChatGPT 没说我有你的盖革计数器数据直到说 “use my custom app” 才触发 tool call。安全模型很保守Demo 2用 PG 做椒盐卷饼店的库存系统从硬件回到软件。建一个椒盐卷饼pretzel库存库CREATETABLEpretzel(quantityINTEGERCHECK(quantity0));INSERTINTOpretzelVALUES(0);-- 初始库存 0MCP tool 直接用psql操作 PGmcp.tooldefget_pretzel_inventory()-int:Return the number of unsold pretzelsreturnsubprocess.check_output(psql --tuples-only -c SELECT quantity FROM pretzel; -d mcp,shellTrue,textTrue)mcp.tooldefsold_one_pretzel()-str:Call this when a pretzel is sold; reduces inventory by onereturnsubprocess.check_output(psql --tuples-only -c UPDATE pretzel SET quantity quantity - 1; -d mcp,shellTrue,textTrue)mcp.tooldefbaked_6_pretzels()-str:Call this when a tray of 6 pretzels is baked; increases inventoryreturnsubprocess.check_output(psql --tuples-only -c UPDATE pretzel SET quantity quantity 6; -d mcp,shellTrue,textTrue)交互流程User: How many pretzels available? GPT: 0 pretzels. User: I just baked a tray → 6 pretzels User: I sold two → 4 remaining User: I sold four → 0 remaining User: I sold one pretzel → ERROR! CHECK constraint 阻止了 quantity 变负数LLM 不直接写 SQL而是调你预先定义的受控接口。PG 的 CHECK 约束天然构成了一个安全兜底——即使 LLM 被诱导调了不该调的函数数据库层的约束还能挡一道。但也暴露了问题LLM 忠实执行了sold_one_pretzel但不会预判库存已经是 0 了调了会报错。MCP 是执行层不是推理层。生产还差多远Bruce 在最后一页坦承了当前实现的局限没有认证——谁都可以调你的 MCP Server没有参数化——三个 tool 都是无参函数现实中的 tool 需要传参数动态 SQL 没做安全限制——工具描述声明了语义但 LLM 可能被注入恶意内容连接池、事务管理、频率限制——一概没考虑两篇值得读的实践经验pgedge.com: Lessons Learned Writing an MCP Server for PostgreSQLCardinalOps: MCP Defaults — Hidden Dangers of Remote Deployment两层之间回头看这 70 页幻灯片最有趣的不是任何一个 demo而是MCP的理论思路和动手说明MCP能做什么理论层用 Transformer 向量空间解释LLM 如何在词和工具之间做选择——这是教学模型实践层用psql、curl、Perl 脚本去落地——这是工程实现而真正的 MCP 机制——tool 定义当文本塞 system prompt、LLM 靠语义理解决定调哪个、输出 tool call JSON——应该是不需要理论层那套向量嵌入模型。两层之间Bruce 没有画出来连接线。这可能不是 bug是 feature。