基于Go的GaussDB只读MCP服务:为Claude Code构建安全数据查询通道

发布时间:2026/9/29 3:14:12

基于Go的GaussDB只读MCP服务:为Claude Code构建安全数据查询通道 1. 为什么我要给 Claude Code 配一个只读的 GaussDB 通道先说结论我写了一个用 Go 实现的 MCP 服务把 GaussDB 的查询能力以只读方式暴露给 Claude Code。它解决的核心问题是——我想让 AI 帮我查数据、写 SQL、分析表结构但绝对不能让它在生产库上执行任何写操作。这个服务适合所有正在用 Claude Code 做数据相关开发、又对生产库安全有硬性要求的后端和 DBA 同学参考。事情的起因很朴素。我日常要维护一套跑在 GaussDB 上的业务系统经常需要确认某张表的结构、某个字段的分布、某条 SQL 的执行计划。以前的做法是打开客户端、连上库、手敲 SQL来回切换窗口效率很低。后来用上 Claude Code发现它写 SQL 的能力相当靠谱我就想能不能让它直接连到库里查但紧接着一个念头把我按住了——生产库万一它哪次理解偏了给我来个 UPDATE 或者 DELETE那可不是闹着玩的。MCP 协议正好是干这个的。MCP 全称 Model Context Protocol本质上是给 AI 客户端比如 Claude Code和外部工具之间定的一套通信规范。你可以把它理解成AI 世界的 USB 接口只要你的服务按这个协议说话Claude Code 就能把它当成一个可调用的工具。我需要的不是让 AI 拥有数据库的全部权限而是给它开一扇只能看、不能改的窗。这就是只读 MCP 服务的由来。为什么用 Go 写几个现实原因。第一Go 编译出来是单个静态二进制扔到服务器上就能跑不用装运行时部署成本极低。第二Go 的并发模型处理数据库连接池很顺手多个查询请求进来不会互相阻塞。第三GaussDB 官方提供了 Go 的驱动兼容性有保障。第四我自己 Go 写得比 Python 熟出问题好排查。这几点加起来Go 就是最省心的选择。这篇文章我会把整个服务的思路、关键代码、踩过的坑、以及怎么和 Claude Code 对接全部摊开讲。不管你是刚接触 MCP 的新手还是已经在用 Claude Code 的老手都能照着复现一套属于自己的只读数据通道。2. 整体设计只读这件事必须从架构层面锁死2.1 只读不能靠约定要靠机制很多人第一反应是我在提示词里告诉 AI只准查不准改不就行了我劝你千万别这么想。提示词是软的AI 的理解是概率性的你没法保证它 100% 遵守。真正靠谱的只读必须在服务端用机制强制实现让写操作在物理上就没有执行的可能。我的设计里只读是通过三层来保证的。第一层是数据库账号权限给这个服务单独建一个数据库用户只授予 SELECT 权限从根上堵死写操作。第二层是 SQL 语句校验服务在把 SQL 发给数据库之前先做一次解析只放行 SELECT 和 EXPLAIN 这类只读语句其他一律拒绝。第三层是连接参数在连接串里显式设置只读模式让数据库驱动层面也帮忙兜底。三层叠加任何一层被绕过还有另外两层挡着。提示数据库账号权限是最硬的一道墙。哪怕你的代码有 bug只要账号没有写权限数据库自己就会拒绝。所以这一步绝对不能省也不能图省事直接用业务账号。2.2 为什么选 MCP 而不是直接写个 HTTP 接口有人会问我直接写个 REST API 给 Claude Code 调不行吗行但麻烦。Claude Code 原生支持 MCP你按 MCP 协议实现它就能自动发现你的工具、自动读取工具描述、自动把参数传进来。你不用去教 AI这个接口怎么调、参数叫什么MCP 的 schema 会把这些信息结构化地告诉它。这就像你给 AI 递了一本说明书而不是让它猜。MCP 服务支持两种传输方式stdio 和 SSE。stdio 是通过标准输入输出通信适合本地进程SSE 是通过 HTTP 长连接适合远程服务。我选的是 stdio因为我的场景是本地开发机连生产库通过跳板或专线服务就跑在本地Claude Code 直接拉起进程简单直接不用管端口和网络。2.3 工具粒度怎么切MCP 服务对外暴露的是一个个工具tool。工具切得太粗AI 不好用切得太细AI 要调很多次。我最后定了四个工具list_tables列出当前库或指定 schema 下的所有表describe_table查看某张表的字段、类型、注释、索引run_query执行一条只读 SQL 并返回结果explain_query对一条 SQL 生成执行计划这四个覆盖了我 90% 的日常需求。list_tables和describe_table让 AI 先了解数据结构run_query用来取数explain_query用来分析性能。工具描述我写得比较详细把每个参数的用途、格式、限制都写清楚了这样 AI 调用时不容易传错参数。3. 核心实现从连接池到 SQL 校验的完整拆解3.1 环境准备与依赖选型先说环境。我用的 Go 版本是 1.21GaussDB 驱动用的是官方提供的gaussdb驱动基于 PostgreSQL 协议因为 GaussDB 兼容 PG 协议。MCP 的 Go SDK 我用的是社区维护的mcp-go库它把协议细节封装好了我只需要关注工具的实现。依赖清单如下go mod init gaussdb-mcp go get github.com/mark3labs/mcp-go go get github.com/HuaweiCloudDeveloper/gaussdb-go这里有个坑要提前说GaussDB 的驱动和 PostgreSQL 的lib/pq在连接串格式上略有差异尤其是 SSL 相关的参数。我一开始直接套用 PG 的连接串结果一直连不上后来查了官方文档才发现 GaussDB 对sslmode的取值有额外要求。这个后面在排查章节会细讲。3.2 数据库连接池的配置连接池这块我用的是database/sql标准库配合驱动。关键参数有三个最大连接数、最大空闲连接数、连接最大存活时间。生产库的连接资源是有限的不能让你一个 MCP 服务把连接占满。db, err : sql.Open(gaussdb, connStr) if err ! nil { log.Fatalf(open db failed: %v, err) } db.SetMaxOpenConns(5) db.SetMaxIdleConns(2) db.SetConnMaxLifetime(30 * time.Minute)为什么最大连接数设 5因为 MCP 服务的查询请求是串行偏多的AI 一次通常只发一两个查询5 个连接足够应对突发。设太大反而会挤占业务连接。最大空闲连接设 2保证有请求时不用现建连接又不会长期占着资源。存活时间设 30 分钟是为了避免连接被数据库端或中间网络设备悄悄断开后客户端还在用一个死连接。注意连接池参数没有万能值要根据你的库的max_connections和业务并发来调。我的经验是MCP 服务占用的连接数不要超过总连接数的 5%。3.3 只读账号的创建与权限收敛这一步在数据库侧做。我建了一个叫mcp_reader的用户只给 SELECT 权限CREATE USER mcp_reader WITH PASSWORD your_strong_password; GRANT CONNECT ON DATABASE your_db TO mcp_reader; GRANT USAGE ON SCHEMA public TO mcp_reader; GRANT SELECT ON ALL TABLES IN SCHEMA public TO mcp_reader; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO mcp_reader;最后那句ALTER DEFAULT PRIVILEGES很关键。它保证以后新建的表mcp_reader也自动有 SELECT 权限不用每次建表后手动授权。我一开始漏了这句结果新加的表 AI 查不到排查了半天才发现是权限问题。密码这块我强烈建议不要硬编码在代码里用环境变量传。我在服务启动时从GAUSSDB_MCP_PASSWORD环境变量读取代码里只留一个占位。3.4 SQL 只读校验的实现这是整个服务最核心的一段逻辑。我的做法是拿到 SQL 后先做词法层面的检查提取出语句的第一个关键字只允许SELECT、EXPLAIN、SHOW、WITH这几种。为什么把WITH也放进来因为 CTE公共表表达式在很多分析场景里很有用而WITH ... SELECT本身是只读的。但要注意WITH后面如果跟的是INSERT或UPDATE那就危险了所以还得进一步检查。func isReadOnly(sqlStr string) bool { normalized : strings.TrimSpace(strings.ToUpper(sqlStr)) // 去掉开头的注释 normalized stripLeadingComments(normalized) allowedPrefixes : []string{SELECT, EXPLAIN, SHOW, WITH} for _, p : range allowedPrefixes { if strings.HasPrefix(normalized, p) { // 对 WITH 做额外检查防止 CTE 里藏写操作 if p WITH { return !containsWriteKeyword(normalized) } return true } } return false }containsWriteKeyword会扫描整条语句如果发现INSERT、UPDATE、DELETE、DROP、TRUNCATE、ALTER、CREATE这些词就直接拒绝。这里有个细节不能简单地用字符串包含来判断因为字段名或字符串常量里可能恰好含有这些词。我的做法是配合简单的词法分析把这些关键字从字符串常量和注释里排除掉再判断。提示SQL 校验永远做不到 100% 完美因为 SQL 语法太灵活了。所以它只是第二道防线真正的底线是数据库账号权限。两者配合安全性才有保障。3.5 MCP 工具的注册与描述MCP 服务的核心是注册工具。每个工具需要提供名称、描述、参数 schema 和处理函数。描述写得越清楚AI 用得越准。我以run_query为例tool : mcp.NewTool(run_query, mcp.WithDescription(执行一条只读 SQL 查询并返回结果。仅支持 SELECT/EXPLAIN/SHOW/WITH 语句。返回结果最多 1000 行。), mcp.WithString(sql, mcp.Required(), mcp.Description(要执行的只读 SQL 语句)), mcp.WithNumber(limit, mcp.Description(返回行数上限默认 100最大 1000)), )注意我在描述里明确写了仅支持只读语句和最多 1000 行。这两个约束很重要前者让 AI 知道边界后者防止一条SELECT *把几十万行数据灌进上下文既慢又浪费 token。处理函数里我会强制加上LIMIT即使 AI 没传 limit 参数。4. 实操过程从零跑通一个查询4.1 编译与本地测试代码写完后先编译go build -o gaussdb-mcp .得到一个二进制文件。测试时我建议先不接 Claude Code直接用命令行手动喂 JSON-RPC 消息确认服务能正常响应。MCP 的 stdio 模式就是一行一个 JSON 消息你可以用 echo 管道测试echo {jsonrpc:2.0,id:1,method:tools/list} | ./gaussdb-mcp如果返回了工具列表说明服务基本正常。这一步能帮你把协议层的问题和数据库层的问题分开排查起来快很多。4.2 配置 Claude Code 接入Claude Code 的 MCP 配置在一个 JSON 文件里。我把它配成这样{ mcpServers: { gaussdb-readonly: { command: /path/to/gaussdb-mcp, env: { GAUSSDB_MCP_HOST: your-db-host, GAUSSDB_MCP_PORT: 8000, GAUSSDB_MCP_USER: mcp_reader, GAUSSDB_MCP_PASSWORD: your_password, GAUSSDB_MCP_DBNAME: your_db } } } }配好后重启 Claude Code它启动时会自动拉起这个进程。你可以在对话里问它现在有哪些数据库工具可用它会列出我注册的四个工具。然后就可以让它查表了比如帮我看看 orders 表的结构它会自动调describe_table。4.3 一次完整的查询实录我实际用的时候会这样跟 Claude Code 对话我帮我查一下最近 7 天每天的订单量按日期排序。Claude Code 会先调describe_table看 orders 表有哪些字段确认时间字段叫created_at然后生成 SQL 调run_querySELECT DATE(created_at) AS day, COUNT(*) AS cnt FROM orders WHERE created_at NOW() - INTERVAL 7 days GROUP BY DATE(created_at) ORDER BY day;服务收到后先过只读校验通过再补上LIMIT 1000发给 GaussDB拿到结果返回。整个过程我只需要说一句话剩下的它自己搞定。这就是 MCP 的价值——把查数据这件事的交互成本降到了最低。4.4 结果集大小的控制这里单独说一下结果集控制因为它直接影响使用体验。我踩过的坑是有一次让 AI 查一张日志表它生成了SELECT * FROM logs结果表里有上百万行。虽然我加了LIMIT 1000但返回的 1000 行数据里有很多长文本字段塞进上下文后直接把对话撑爆了响应变得极慢。后来我做了两个改进。第一在run_query的返回里如果某一行某个字段超过 500 字符就截断并标注...[truncated]。第二在工具描述里明确告诉 AI查询大表时请先用 COUNT 确认行数再取样本数据。这两招之后再没出现过上下文被撑爆的情况。5. 常见问题与排查技巧实录5.1 连接不上数据库的几种典型情况连接问题是最常见的。我整理了一个排查表现象可能原因排查方法报 SSL 相关错误sslmode 参数不匹配尝试 disable/require/verify-full 逐个测试连接超时网络不通或端口错telnet 测试端口连通性认证失败用户名密码错或权限不足用同账号在客户端手动连一次连接被拒数据库 max_connections 满查 pg_stat_activity 看连接数我遇到最多的是 SSL 问题。GaussDB 对sslmode的处理和标准 PG 有差异有些版本只认disable和require你写prefer它会报错。解决办法就是明确指定别用默认值。5.2 SQL 校验误杀怎么办只读校验有时候会误杀合法查询。比如字段名里带update这个词或者字符串常量里有delete。我的处理方式是先看被拒绝的 SQL 是不是真的只读如果是就调整校验逻辑把字符串常量和注释排除掉再判断。但我的原则是宁可误杀不可放过——如果一条 SQL 的只读性有疑问我宁愿让 AI 换个写法也不冒险放行。提示如果你发现某类合法查询频繁被误杀可以在校验函数里加白名单但一定要谨慎白名单越少越好。5.3 AI 生成的 SQL 性能问题AI 写的 SQL 语法通常没问题但性能不一定好。我遇到过它生成的查询没走索引全表扫描把库拖慢的情况。解决办法是在工具描述里加一句生成查询前请先查看表的索引信息并且提供explain_query工具让 AI 可以自己检查执行计划。另外我在数据库侧给mcp_reader账号设了statement_timeout超过 30 秒的查询自动终止防止慢查询拖垮库。ALTER USER mcp_reader SET statement_timeout 30s;这一句非常有用相当于给 AI 的查询加了个保险丝。5.4 中文乱码与字符集问题GaussDB 的字符集如果和客户端不一致返回的中文可能乱码。我在连接串里显式指定了client_encodingUTF8并且在 Go 侧确认返回的字符串按 UTF-8 处理。如果还是乱码检查数据库的server_encoding是不是 UTF8。这个坑不常遇到但一旦遇到很影响体验。5.5 服务进程被意外拉起多次Claude Code 在某些情况下可能会重复拉起 MCP 进程导致多个实例同时连库。我的做法是在服务启动时检查一个锁文件如果已有实例在跑就直接退出。这样能避免连接数被无谓占用。6. 几个让服务更好用的进阶技巧6.1 给工具加上下文提示MCP 工具的描述里可以塞一些使用建议。比如我在run_query的描述里加了查询前建议先用 describe_table 了解表结构。这看起来是小事但能显著减少 AI 的无效调用。AI 看到这句话会先了解结构再查生成的 SQL 准确率高很多。6.2 返回结果的结构化run_query返回的不只是数据我还把列名、列类型、行数一起返回。这样 AI 拿到结果后能更准确地理解数据含义。比如它看到某列类型是timestamp就知道可以做时间运算。这个细节让后续对话的连贯性好了不少。6.3 日志与审计虽然是只读服务但审计还是要有。我把每次查询的 SQL、执行时间、返回行数都记到日志里。一方面方便排查问题另一方面也能看到 AI 到底在查什么心里有数。日志我按天切分保留 7 天避免占满磁盘。6.4 敏感字段的脱敏生产库里难免有手机号、身份证这类敏感字段。我在服务里加了一个可配置的脱敏规则如果查询结果里出现配置的敏感列名就自动打码。比如手机号只显示前三位和后四位。这个功能不是必须的但如果你的库里有敏感数据强烈建议加上。7. 我踩过的坑和最后的几句实在话回过头看这个项目最大的价值不是代码本身而是它让我重新思考了AI 和数据的边界。以前我总觉得要么全给权限、要么完全不给现在发现中间地带是存在的——通过 MCP 这样的协议通过只读账号和 SQL 校验这样的机制我可以精确地控制 AI 能做什么、不能做什么。踩过的坑里最值得说的是权限那一次。我一开始图省事直接用了一个有写权限的账号想着反正有 SQL 校验兜着。结果有一次校验逻辑有个边界没覆盖到AI 生成的一条语句差点就执行了写操作幸好数据库账号权限拦住了。从那以后我就明白了安全设计里永远不要依赖单一防线每一层都要能独立兜底。还有一个体会是关于工具描述的。我一开始描述写得很简略结果 AI 经常传错参数或者用错工具。后来我把每个参数的格式、取值范围、默认值都写清楚调用准确率立刻上来了。这让我意识到MCP 服务的用户体验很大程度上取决于你给 AI 的说明书写得好不好。最后分享一个小技巧如果你也想做类似的服务建议先从最小的工具集开始比如只做一个run_query跑通了再逐步加工具。我一开始想一口气做七八个工具结果每个都半成品反而不好用。聚焦核心需求把一两个工具做扎实比铺一堆半吊子工具强得多。这个服务现在每天帮我省下大量切窗口、敲 SQL 的时间而且用得安心——因为我知道它只能看不能改。
延伸阅读

更多相关文章

2026/9/29 3:14:12

复杂系统数字孪生:从可视化大屏到智能仿真引擎的跃迁

简介:一份关于复杂系统数字孪生的Word文档,面向工业互联网、智能制造领域的研究者与工程师,系统梳理了数字孪生从单元级到系统级的演进路径,并围绕GE智能电厂IGCC场景解析典型应用。内容覆盖产品生命周期各阶段孪生模型的融合、P-…

2026/9/29 3:14:12

智能硬件四维协同:板卡、固件、云端、App的契约化开发实践

1. 为什么智能硬件项目总在“最后一公里”集体失速?“板卡还没回厂,固件还在debug,云端API刚跑通,App提测被拒三次”——这几乎是我过去八年带过的23个智能硬件项目里,90%以上团队在Q3末期脱口而出的原话。不是没人加班…

2026/9/29 3:09:11

GLSL语法规范深度拆解:从BNF到Shader编译错误排查

说一下我对这个标题的直觉。很多OpenGL开发者,写了几年shader,GLSL代码能跑能出画面,但很少人真正翻开过规范最后那几十页——OpenGL Shading Language Specification里的Shading Language Grammar,也就是GLSL的语法规范英文原版。…

2026/9/28 3:03:23

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/9/28 6:05:15

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/28 6:07:41

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/29 0:04:04

AI Evals实战指南:从零搭建LLM应用评估体系与CI/CD集成

1. 为什么AI Evals值得你花时间搞明白做LLM应用的人,迟早会撞上同一堵墙:模型输出飘忽不定,今天答得好好的,明天换个问法就胡说八道。你改了一版提示词,感觉好像好了点,但到底好了多少?说不清。…

2026/9/29 0:04:04

Java采购管理系统实战:从数据库设计到事务一致性

简介:这是一套面向Java Web初学者与课程设计者的采购管理系统完整源码,采用JSP技术搭建,配合MySQL数据库,用于解决企业采购信息的管理问题,适合作为毕业设计、课程大作业或进销存类项目的参考模板。系统实现了用户登录…

2026/9/29 3:53:39

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/26 19:58:38

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/28 1:59:25

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑