浏览 MCP与Skills教程与资源
PostgreSQL MCP 只读接入:从专用角色到同一条查询的权限验证
用独立教学库 analytics_lab、角色 mcp_reader 和一张汇总表演示可执行授权;同时说明 Server restricted 模式、数据库 GRANT 和查询成本各自解决什么问题。
本例使用 Postgres MCP Pro,不泛指所有数据库 MCP
Server 选用 crystaldba/postgres-mcp(Postgres MCP Pro),这是第三方开源项目,并非 PostgreSQL 核心项目。需要本机已准备好的 PostgreSQL、psql、uv/uvx 和 Codex;本文只演示同机 127.0.0.1:5432 的专用教学库。管理员准备环境后,MCP 全程使用 mcp_reader,不能使用 postgres 管理员连接串。
restricted 模式把工具 SQL 放进只读事务;数据库 GRANT 决定这个角色本来能读哪些表;statement_timeout 限制单条语句等待和执行的总时间。这三层可以互补,任何一层都不能保证查询没有 CPU、磁盘或连接开销。下面是可复现的教学工件与预期,尚未在本站连接真实数据库执行。
在全新 analytics_lab 中创建两行教学数据
把下面内容保存为 setup.sql,由获准管理员用 psql -U postgres -d postgres -v ON_ERROR_STOP=1 -f setup.sql 执行;使用其他管理员身份时替换 -U 值。analytics_lab 或 mcp_reader 已存在就停止,换名称并统一替换全文,不要套到现有生产库。CREATE DATABASE 不在事务块内执行。密码通过 psql 的交互式命令设置,不写进 SQL 文件。
建立教学库、汇总表与最小角色
\set ON_ERROR_STOP on
DO $mcp_prereq$
BEGIN
IF EXISTS (SELECT 1 FROM pg_database WHERE datname = 'analytics_lab')
OR EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'mcp_reader') THEN
RAISE EXCEPTION 'analytics_lab 或 mcp_reader 已存在;停止,勿覆盖现有对象';
END IF;
END;
$mcp_prereq$;
CREATE DATABASE analytics_lab;
\connect analytics_lab
CREATE SCHEMA reporting;
CREATE TABLE reporting.monthly_orders (
month date PRIMARY KEY,
order_count integer NOT NULL CHECK (order_count >= 0)
);
INSERT INTO reporting.monthly_orders VALUES
('2026-08-01', 12), ('2026-09-01', 18);
CREATE ROLE mcp_reader LOGIN NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION;
\password mcp_reader
REVOKE ALL ON DATABASE analytics_lab FROM PUBLIC;
GRANT CONNECT ON DATABASE analytics_lab TO mcp_reader;
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
GRANT USAGE ON SCHEMA reporting TO mcp_reader;
GRANT SELECT ON reporting.monthly_orders TO mcp_reader;
ALTER ROLE mcp_reader IN DATABASE analytics_lab SET default_transaction_read_only = on;
ALTER ROLE mcp_reader IN DATABASE analytics_lab SET statement_timeout = '3s';开头先检查数据库和角色名,发现冲突即停止;CREATE DATABASE 仍单独执行。建库不能包进这段事务,因此后续若因密码输入或其他错误中止,可能留下部分对象,应由管理员检查后处理,不能直接重跑或自动删库。本例 GRANT SELECT 只针对单张教学表,未授予未来所有新表;default_transaction_read_only 可以被会话改变,不能代替表权限。
以 mcp_reader 登录,核对身份、结果和真实权限
先使用 psql 的密码提示连接,再执行以下 SQL。如果直连就失败,应先处理数据库监听、pg_hba.conf 或账号权限;MCP 无法修复数据库自身的拒绝。
通过交互提示输入密码
psql -h 127.0.0.1 -p 5432 -U mcp_reader -d analytics_lab -W
核对相同身份与业务结果
SELECT current_database(), current_user;
SHOW default_transaction_read_only;
SHOW statement_timeout;
SELECT month, order_count
FROM reporting.monthly_orders
ORDER BY month DESC LIMIT 10;
SELECT has_table_privilege(current_user, 'reporting.monthly_orders', 'SELECT') AS can_read,
has_table_privilege(current_user, 'reporting.monthly_orders', 'INSERT') AS can_insert,
has_table_privilege(current_user, 'reporting.monthly_orders', 'UPDATE') AS can_update;预期身份是 analytics_lab / mcp_reader;业务查询返回 2026-09-01→18、2026-08-01→12;权限检查为 true、false、false。这里说明预期值,没有虚构查询日志。系统目录仍可能可见,不能据此声称该角色‘看不见任何其他 schema’。
连接串与 Codex 配置都保持 mcp_reader
通过本机凭证管理方式提供 DATABASE_URI,形式为 postgresql://mcp_reader:密码@127.0.0.1:5432/analytics_lab;密码中的 URL 特殊字符需正确编码。不要把实际连接串写入仓库。以拥有该环境变量的进程启动 Codex,并合并下面配置。uvx 首次会获取第三方包,先核对项目来源;本文不替读者执行安装。
restricted + 单一查询工具
[mcp_servers.postgres_lab] command = "uvx" args = ["postgres-mcp", "--access-mode=restricted"] env_vars = ["DATABASE_URI"] enabled_tools = ["execute_sql"]
只重复基线 SQL
仅使用 postgres_lab 的 execute_sql。 先运行 SELECT current_database(), current_user; 只有返回 analytics_lab 和 mcp_reader 时才继续。 随后运行: SELECT month, order_count FROM reporting.monthly_orders ORDER BY month DESC LIMIT 10; 逐项报告两行日期与数量,不添加其他 schema 查询或性能分析任务。 结果与我在 psql 的同一查询不一致时,先停止并保留实际 SQL。
表只有两行,所以 LIMIT 10 返回两行是正确结果。若 restricted 模式或 Server 改写了事务超时,核对 MCP 连接内的实际 SHOW 值,不把 psql 会话的参数截图当作另一个连接的证据。
只读事务拒绝与角色权限拒绝是两种证据
仅在本页新建的教学库中,以 mcp_reader 的 psql 会话执行这个零行更新。它不修改数据,但会检查 UPDATE 权限;显式 READ WRITE 是为了排除‘只读事务提前拦住’的影响,观察角色本身是否有写权限。
零行更新后回滚
BEGIN READ WRITE; UPDATE reporting.monthly_orders SET order_count = order_count WHERE false; ROLLBACK;
预期在 UPDATE 处得到表权限拒绝,再用 ROLLBACK 退出失败事务。如果更新没有被拒绝,说明角色获得了额外权限或身份不对;虽然 WHERE false 避免改行,也不能把权限配置标为通过。restricted MCP 中的拒写另由只读事务拦截,二者要分开记录。
只读不等于便宜,LIMIT 也不保证少扫描
LIMIT 限制返回行数,排序、聚合或缺少索引的筛选仍可能扫描大量数据。真实业务应使用脱敏视图或副本,并由数据库负责人评估查询计划、连接数和超时。EXPLAIN 可以查看计划;EXPLAIN ANALYZE 会实际执行查询,不能在未知成本的生产查询前随手加上。
如果 SQL 能运行但 MCP 失败,保留原 SQL、角色、数据库名、SQLSTATE 和耗时,检查 Server 事务模式与工具错误。不要换成管理员账号尝试‘解决’。本例没有授予性能扩展权限,因此不能据此要求所有健康检查、索引建议工具都可用。
本页的一手资料
核对 uvx、DATABASE_URI、restricted 模式和 execute_sql;不是 PostgreSQL 官方 Server。
一手来源PostgreSQL GRANT核对数据库连接、schema USAGE 和表 SELECT 权限。
一手来源PostgreSQL DO核对建库前匿名代码块的写法;CREATE DATABASE 在该块结束后单独执行。
一手来源PostgreSQL ALTER ROLE核对角色级/数据库级会话默认设置。
一手来源PostgreSQL SET TRANSACTION说明只读事务的含义与范围,不能替代角色权限。
