使用说明
PostgreSQL MCP服务器
也有俄语版本: README-ru.md
备注这个项目是为我的个人需求而设计的。我不打算用我不使用或无法验证的功能来扩展它的功能。您可以自由提交建议和拉取请求,但我不保证所有内容都会被接受。
MCP服务器,用于全面集成PostgreSQL,具有以下功能:
- 数据库操作 -连接到PostgreSQL实例,列出数据库和模式
- 餐桌管理 -列出表、视图、函数并获取详细信息
- 查询工具 -使用完整的PostgreSQL语法执行SELECT、INSERT、UPDATE、DELETE查询
- 连接管理 -使用只读模式支持管理PostgreSQL连接
- 流文件导出 -流式保存到大型数据集的文件
- 只读模式 -安全的只读操作,防止意外的数据修改
- 监控 -数据库统计、性能指标
- 架构操作 -创建、修改和删除表、视图、函数和索引
目录
需求
- Node.js≥22
- 环境变量:
POSTGRES_MCP_CONNECTION_STRING--PostgreSQL连接字符串(PostgreSQL://格式)POSTGRES_MCP_TIMEZONE--日期操作的可选时区(默认:Europe/Moscow),必须是有效的IANA时区标识符(例如。,Europe/London,America/New_York,Asia/Tokyo)POSTGRES_MCP_OUTPUT_DIRS--可选:-目录的独立白名单,其中execute-sql允许写入filePath导出(默认:仅操作系统临时目录)。当LLM客户端需要将转储放在项目旁边时使用它,例如。POSTGRES_MCP_OUTPUT_DIRS=/var/data/exports:/srv/dumps. 安全警告: 白名单是操作员的责任——一旦列出了目录,MCP进程可以写入的任何内容都会放在那里。不包括系统或共享路径,例如/,/etc,/usr,/var,/var/log,/root,/home,你的$HOME,或项目源根;将其限制在专用导出目录中。
- CLI标志(通过MCP客户端传递
args):--read-only/--no-read-only--以只读或读写模式启动。违约:--read-only。要启用写入,请传递--no-read-only在MCP客户端配置中。--pool-size <n>--连接池大小(默认值:1)。--idle-timeout <ms>--池连接的空闲超时(默认值:30000)。--connection-timeout <ms>--初始连接超时(默认值:10000)。--auto-connect--启动时使用连接POSTGRES_MCP_CONNECTION_STRING默认设置:关闭。
VS代码库配置
使用此MCP服务器 克莱恩 VS代码中的扩展名:
- 打开安装了Cline扩展的VS代码
- 单击Cline顶部导航中的MCP服务器图标
- 选择“配置”选项卡,然后单击“配置MCP服务器”
- 将以下配置添加到
cline_mcp_settings.json:
{
"mcpServers": {
"postgres-mcp": {
"command": "npx",
"args": ["-y", "@vitalyostanin/postgres-mcp@latest"],
"env": {
"POSTGRES_MCP_CONNECTION_STRING": "postgresql://localhost:5432/postgres"
}
}
}
}
注: 此配置使用npx运行已发布的包。对于当地发展,使用 "command": "node" 随着 "args": ["/absolute/path/to/postgres-mcp/dist/index.js"]The POSTGRES_MCP_TIMEZONE 环境变量是可选的。池大小由CLI标志控制 --pool-size (默认值 1);它不能通过环境变量进行更改。
发展
本节面向从签出运行服务器的贡献者和操作员。AI代理直播的详细风格和评论说明 代理商.md.
git clone https://github.com/VitalyOstanin/postgres-mcp.git
cd postgres-mcp
npm install
Node.js 24是推荐的开发版本(参见 .nvmrc).这 engines.node 地板是 >=22 因此,该包仍然为Node 22 LTS发布,CI在22.x和24.x上运行矩阵。
项目结构
index.ts--CLI入口点(bin: postgres-mcp);解析参数,连接stdio传输,注册信号处理程序。src/server.ts—PostgreSQLServer班级;拥有池生命周期并注册所有MCP工具。src/postgres-client.ts--薄薄的异步包装pg.Pool(生命周期,executeQuery,streamQuery,withTransaction).src/tools/--每个MCP工具一个文件(connect,disconnect,service-info,list-schemas,list-objects,show-object,execute-sql,index-operation).src/utils/--共享助手:连接保护、编校、标识符引用、分页、SQL参数验证、文件路径安全、流式传输、查询分析。src/defaults.ts--默认池大小、超时、时区、分页边界的单一真实来源。test/--vitest单元套房(模拟游泳池);test-integration/--vitest集成套件,与真正的PostgreSQL容器对话。coverage/--生成于npm run test:coverage;HTML覆盖率报告(gitignored)。temp/--测试使用的本地暂存目录(gitignored)。docs/--仅限当地的项目文件;docs/reviews/持有由以下人员撰写的审查报告project-check技能(整体docs/这棵树被忽视了,这里什么都没有发表)。
构建
| 命令 | 它的作用 |
|---|---|
npm run build |
使用编译TypeScript tsconfig.build.json 进入 dist/。设置 +x 位和副本 package.json 到 dist/ 通过 postbuild. |
npm run dev |
TypeScript手表(tsc --watch).MCP stdio服务器本身不是热重载的——重建后重新启动MCP客户端。 |
npm start |
运行内置服务器(node dist/index.js).使用后 npm run build. |
npm run typecheck |
tsc -p tsconfig.json --noEmit (封面 src/, test/, test-integration/,顶级文件)。 |
测试
| 命令 | 它的作用 |
|---|---|
npm test |
运行单元套件(vitest run 反对 test/). |
npm run test:watch |
在监视模式下运行单元测试。 |
npm run test:coverage |
在覆盖范围内运行单元测试;HTML报告在 coverage/index.html. |
npm run test:integration |
对本地PostgreSQL容器运行集成套件。 |
npm run test:integration:up |
podman-compose -f compose.yaml up -d --启动容器。 |
npm run test:integration:down |
podman-compose -f compose.yaml down --停下并取出容器。 |
单元套房使用游泳池模型(test/__mocks__/postgres-client.mock.ts);集成套件需要一个在上公开的正在运行的PostgreSQL容器 127.0.0.1:55432 --从以下内容开始 npm run test:integration:up 之前 npm run test:integration.
装订和格式化
格式化由ESLint风格规则强制执行(没有单独的Prettier配置)。运行:
| 命令 | 它的作用 |
|---|---|
npm run lint |
Lint .ts / .mts 通过中的平面配置文件 eslint.config.mjs. |
npm run lint:fix |
与 lint,但会自动修复违反安全规则的行为。 |
npm run format |
别名 lint:fix.用你喜欢的名字。 |
使用本地PostgreSQL容器
compose.yaml 声明绑定到的PostgreSQL 18服务 127.0.0.1:55432 使用一次性凭证 test:test。这些凭据是针对本地容器和匹配的CI服务的,它们也从中引用 test/setup.ts 和 test-integration/setup.ts。不要将绑定更改为 0.0.0.0 不要复制 compose.yaml 进入生产环境。
npm run test:integration:up # start container in background
npm run test:integration # run integration tests against it
npm run test:integration:down # tear it down when finished
MCP工具
只读模式工具
service-info
获取PostgreSQL服务信息和当前连接状态。没有参数。
connect
使用建立连接 POSTGRES_MCP_CONNECTION_STRING.
readonlyMode(布尔值,默认值true).poolSize(数字,默认值1).idleTimeoutMillis(数字,默认值30000).connectionTimeoutMillis(数字,默认值10000).
disconnect
关闭池并清除连接状态。没有参数。
list-schemas
列出用户模式(不包括 information_schema, pg_catalog, pg_toast).
limit(数字,1-1000,默认值100).offset(数字,默认值0).
list-objects
列出架构中的表、视图或函数。
schema(字符串,默认值'public').type('table' | 'view' | 'function' | 'all',默认值'all').limit(数字,1-1000,默认值100).offset(数字,默认值0).
show-object
显示单个表、视图或函数的详细信息。
schema(字符串,默认值'public').name(string,必填)--对象名称。type('table' | 'view' | 'function',必填)。
execute-sql
运行SELECT/WITH/VALUES查询(只读模式拒绝数据修改语句,PostgreSQL错误25006)。
query(字符串,必填)--SQL$1/$2占位符。params(数组,可选)--值。允许:标量,null,Date,Buffer、数组、纯对象(以JSON/JSONB格式发送)。saveToFile(布尔值,默认值false)--将结果流式传输到文件。filePath(string,可选)--必须在操作系统临时目录或以下目录之一中POSTGRES_MCP_OUTPUT_DIRS.format('jsonl' | 'json',默认值'jsonl').forceSaveToFile(布尔值,默认值false)--对于非游标查询,先在内存中缓冲,然后再写入。
index-operation (仅限 operation: 'list' 在只读模式下)
operation('create' | 'drop' | 'list',必填)。schema(字符串,默认值'public').table(string)--必填项create/drop;可选list(按表格筛选)。name(string)——索引名称;必需create/drop.columns(string[])--必需create.unique(布尔值,默认值false).ifNotExists/ifExists(布尔值,默认值false).tableName(字符串,已弃用的别名table为了list).limit(数字,1-1000,默认值100);offset(数字,默认值0).
非只读模式工具
在读写模式下(--no-read-only)以上所有工具都可用,另外 execute-sql 接受插入/更新/删除/DDL和 index-operation 允许 create/drop。参数形状不变。
注: 默认情况下,服务器以只读模式运行,以防止意外的数据修改。在会话级别应用只读强制:当 connect 打开游泳池 readonlyMode=true,每个池连接都以以下方式启动 default_transaction_read_only=on,因此任何数据修改语句都会在服务器端失败,出现PostgreSQL错误25006(read_only_sql_transaction).
在只读模式下,以下内容被阻止:
INSERT,UPDATE,DELETE,MERGE,TRUNCATE- DDL:
CREATE,ALTER,DROP,COMMENT,GRANT,REVOKE create和drop操作在index-operation工具
只读模式的局限性
只读模式是一个护栏,而不是一个完整的沙盒。以下操作仍然是可能的,因为它们不是PostgreSQL意义上的写事务:
- 读取敏感系统目录(
pg_authid,pg_shadow等等),如果连接角色具有特权。 - 召唤
SECURITY DEFINER内部写入数据的函数——内部角色的写入绕过了外部会话标志。 - 服务器端文件访问功能,如
pg_read_server_files,lo_export,COPY ... TO PROGRAM(后者需要超级用户)。 - 在运行时切换只读模式需要重新连接;呼叫
connect再次使用不同的工具readonlyModevalue使用新设置重建池。
为了加强隔离,请使用缺少以下功能的PostgreSQL角色 INSERT/UPDATE/DELETE/USAGE 关于相关对象。
特权边界(生产建议): 身份验证和授权完全委托给嵌入式PostgreSQL角色 POSTGRES_MCP_CONNECTION_STRING --MCP服务器没有自己的用户概念。对于生产部署,请使用仅具有工作负载所需最低权限的角色进行连接:避免超级用户,不要授予 pg_read_server_files,并审计任何 SECURITY DEFINER 在通过以下方式公开搜索路径上的函数之前 execute-sql.使用默认值运行 --read-only 而没有 --auto-connect 只要可能,就从秘密管理器获取连接字符串,而不是将其提交到配置文件。
连接池行为
- 池默认为单个连接(
--pool-size 1).这是一个深思熟虑的权衡:大小为1,两个平行tools/call请求是序列化的,但一个多步骤的事务会作为几个部分发出execute-sql电话(BEGIN,…,COMMIT)可靠地落在同一后端会话上。随着--pool-size > 1连续的execute-sql呼叫可能会打到不同的池客户端,这些客户端会悄无声息地中断BEGIN/COMMIT跨调用拆分流——在单个调用中执行多语句事务execute-sql(例如,通过CTE,INSERT … ON CONFLICT,或aBEGIN; …; COMMIT;一个查询中的块)。增加--pool-size如果你需要并行读/写,并且不依赖于多调用事务。 - 延迟提示:如果您的MCP主机并行发出多个工具调用(例如。
list-schemas+service-info+execute-sql立即),如果您希望它们在数据库端重叠,请提高--pool-size2-4。记住上面的多调用事务警告——任何拆分的东西BEGIN/COMMIT跨线通话必须保持在1号池中。 - 池级错误(网络掉线、服务器重启等)将服务器设置为断开连接状态,但确实如此 不 自动重新连接。下一个调用返回录制的
connectionError;呼叫connect再次恢复。 disconnect通过以下方式关闭所有空闲插槽pool.end()MCP服务器本身继续运行,并将接受新的connect立即。