1. 为什么要在本地跑 Postgres MCP
Postgres MCP 简单说就是把 PostgreSQL 数据库包装成一个 MCP Server,让支持 MCP 协议的客户端(比如 Claude Code、Cursor、各类 Agent 框架)能直接通过自然语言去查表、建表、看 schema,而不用你手写 SQL 再复制粘贴。它适合两类人:一类是本地开发时想让 AI 帮忙读数据库结构的后端同学,另一类是搭 Agent 工具链、需要把数据库能力挂上去的工程师。
我这次的目标很明确:用 Docker 起一个 Postgres 16,再起一个 postgres-mcp 服务,然后让客户端通过统一 Key 走 TaoToken 的 API 通道去调用模型,把「数据库 + MCP + 模型」这条链路一次跑通。整个过程里最容易卡住的不是 Docker,而是 MCP 客户端的配置位置和 Key 的填法,所以下面会把 config.toml 和 settings.json 的骨架都给出来,你照着改参数就行。
先明确几个概念,避免后面看配置时懵:
Postgres 是数据库本体,跑在 5432 端口;postgres-mcp 是一个独立进程,它连上 Postgres 后对外暴露 MCP 协议接口,默认走 SSE 传输,跑在 8000 端口;MCP 客户端(你的编辑器或 Agent)再去连这个 8000 端口。模型调用则走 TaoToken 的统一 API 通道,Key 只需要配一份,多个工具共用。
2. TaoToken 前置准备:统一 Key 与 API 通道
在动手配 MCP 之前,先把模型侧的通道准备好,否则后面客户端连上了 MCP 也没法让模型去理解你的自然语言指令。
TaoToken 在这里的角色是统一入口:你不需要为每个工具单独申请不同厂商的 Key,一份 Key 就能覆盖对话、编码、Agent 等场景。官网入口是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 基址是 https://taotoken.net/api (这个地址不加 UTM 参数,配置里直接写它)。
具体操作分三步:
第一步,进控制台创建 Key。打开 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,在 API Keys 页面点新建,复制出来的字符串就是你的统一 Key,形如 sk-xxxx。这个 Key 只显示一次,先存到本地环境变量里,别直接写进会提交到 git 的文件。
第二步,确认你要用的模型。如果你只是想让 MCP 客户端能对话、能读数据库,用模型对话页面的默认模型就够;如果你要长期跑编码类 Agent,建议看 Coding Plan 页面选合适的套餐,避免按量计费跑飞。模型对话入口:https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite ;Coding Plan 入口:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。
第三步,把 Key 写进环境变量。Linux/macOS 用 export,Windows PowerShell 用 $env:,这样 MCP 客户端和后续命令行测试都能读到同一个值:
# Linux / macOS export TAOTOKEN_API_KEY="sk-你的统一Key" export TAOTOKEN_BASE_URL="https://taotoken.net/api" # Windows PowerShell $env:TAOTOKEN_API_KEY="sk-你的统一Key" $env:TAOTOKEN_BASE_URL="https://taotoken.net/api"注意:API 基址写 https://taotoken.net/api 即可,不要在后面手动拼 /v1 之类的路径,客户端 SDK 会自己补全。填错路径最常见的表现是 404,而不是 401,排查时先看状态码。
Key 准备好后,接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,遇到参数不确定时对着文档核对字段名,比在群里问快。
3. 可复制配置:起 Postgres、起 MCP、配客户端
这一节是全文的核心,所有命令和配置都能直接复制,只需要替换用户名、密码、库名。
3.1 用 Docker 起 Postgres 16
先拉镜像并后台运行容器。下面这条命令把容器命名为 postgres-mcp-db,映射 5432 端口,设置好账号密码和默认库:
docker run -d \ --name postgres-mcp-db \ -e POSTGRES_USER=mcp_user \ -e POSTGRES_PASSWORD=mcp123! \ -e POSTGRES_DB=mcp_db \ -p 5432:5432 \ postgres:16参数逐个说清楚:-d 是后台运行;--name 指定容器名方便后续 docker logs 和 docker stop;三个 -e 分别设用户名、密码、默认库名,这里我用 mcp_user / mcp123! / mcp_db,你换成自己的强密码;-p 5432:5432 把容器端口映射到主机,Postgres 默认就是 5432;最后 postgres:16 指定版本,想用 15 就改成 postgres:15。
启动后验证容器状态:
docker ps | grep postgres-mcp-db输出里能看到 postgres:16 且 STATUS 是 Up 就说明数据库起来了。如果没看到,用 docker logs postgres-mcp-db 看报错,常见的是端口被占用,把主机侧 5432 换成 5433 再映射即可。
3.2 起 postgres-mcp 服务
数据库就绪后,起 MCP 服务。它需要知道怎么连数据库,所以要把 DATABASE_URI 传进去,格式是 postgresql://用户名:密码@主机:端口/库名:
docker run -p 8000:8000 \ -e DATABASE_URI=postgresql://mcp_user:mcp123!@host.docker.internal:5432/mcp_db \ crystaldba/postgres-mcp \ --access-mode=unrestricted \ --transport=sse这里有个坑要提前说:如果你在容器里连宿主机的 Postgres,主机名不能写 localhost,因为容器里的 localhost 指向容器自己。Linux 上用 host.docker.internal 需要额外加 --add-host=host.docker.internal:host-gateway,macOS 和 Windows 的 Docker Desktop 默认支持。更省事的做法是把两个容器放到同一个自定义网络里,用容器名互连:
docker network create mcp-net docker network connect mcp-net postgres-mcp-db docker run -p 8000:8000 --network mcp-net \ -e DATABASE_URI=postgresql://mcp_user:mcp123!@postgres-mcp-db:5432/mcp_db \ crystaldba/postgres-mcp \ --access-mode=unrestricted \ --transport=sse--access-mode=unrestricted 表示放开读写权限,本地开发方便,但如果你连的是有真实数据的库,建议改成受限模式,只读或只允许特定操作。--transport=sse 指定用 SSE 传输,客户端配置里的 Type 要跟它对应。
首次运行会拉 crystaldba/postgres-mcp 镜像,等它拉完启动,看到监听 8000 的日志就成功了。
3.3 客户端配置骨架:config.toml 与 settings.json
不同客户端的配置文件格式不一样,这里给两个最常见的骨架。Claude Code 这类用 config.toml,Cursor 这类用 settings.json,字段名基本一致,只是语法不同。
config.toml 骨架:
[mcp_servers.postgres] type = "sse" url = "http://localhost:8000/sse" [model] provider = "openai-compatible" api_key = "${TAOTOKEN_API_KEY}" base_url = "https://taotoken.net/api" model = "你的模型名"settings.json 骨架:
{ "mcpServers": { "postgres": { "type": "sse", "url": "http://localhost:8000/sse" } }, "model": { "provider": "openai-compatible", "apiKey": "${TAOTOKEN_API_KEY}", "baseUrl": "https://taotoken.net/api", "model": "你的模型名" } }两个骨架里,mcpServers 段负责连数据库工具,model 段负责连模型通道。Key 用 ${TAOTOKEN_API_KEY} 引用环境变量,这样配置文件可以安全地提交到仓库。baseUrl 统一写 https://taotoken.net/api ,model 字段填你在模型对话页面选定的模型名。
注意:url 里的 /sse 路径不能省,它对应服务端的 --transport=sse。如果你改成 streamable-http 传输,路径和 type 都要同步改,否则客户端会一直连不上。
4. 验证请求:确认 MCP 连接与查询生效
配置写完,重启客户端,然后按下面几步验证,每一步都有明确的成功标志。
第一步,看 MCP 服务是否被客户端识别。在客户端的 MCP 面板里,postgres 这一项应该显示已连接或绿色状态。如果显示失败,先手动 curl 一下 SSE 端点:
curl -N http://localhost:8000/sse正常会持续输出 event: 开头的数据流,按 Ctrl+C 退出。如果连 curl 都连不上,说明 MCP 容器没起好,回去看 docker logs。
第二步,让模型执行一次真实查询。在对话里输入「列出当前数据库里所有的表」,模型会通过 MCP 调用 Postgres。首次可能需要在客户端里授权工具调用,点允许即可。成功的话你会看到它返回一个空列表,因为 mcp_db 是新建的,还没有表。
第三步,建表再查,验证读写都通。直接对模型说「创建一张 users 表,包含 id 自增主键和 name 文本字段」,它会生成并执行建表语句。然后再问「现在数据库有多少张表」,应该返回 1。接着问「postgres 有多少种模式」,它会去查 pg_namespace,返回包括 public、information_schema 等在内的模式列表。
如果你想绕过模型直接验证数据库,用 psql 进容器查:
docker exec -it postgres-mcp-db psql -U mcp_user -d mcp_db -c "\dt"这条命令列出所有表,跟模型查出来的结果应该一致。两边对得上,说明 MCP 链路和数据库本身都没问题。
第四步,验证模型通道确实走的是 TaoToken。在客户端里发一句普通对话,比如「你好」,能正常回复就说明 Key 和 base_url 生效。如果对话报 401,检查环境变量有没有被客户端进程读到;报 404,检查 base_url 是不是多写了路径。
5. 本篇常见错排查
跑这条链路时,报错基本集中在四个地方,我按出现频率排一下。
连接被拒绝(Connection refused)。九成是 MCP 容器没起来或端口没映射对。先 docker ps 看容器在不在,再确认 -p 8000:8000 有没有写。如果客户端和服务不在同一台机器,localhost 要换成实际 IP。
DATABASE_URI 认证失败。报错通常是 password authentication failed。检查三处:URI 里的用户名密码跟起 Postgres 时的 -e 参数是否一致;密码里如果有特殊字符(比如 @、:、/),要做 URL 编码,否则会被解析成分隔符;库名是否拼错。
MCP 连上了但工具调用超时。多半是 access-mode 或网络问题。unrestricted 模式下如果数据库响应慢,客户端会等超时。先用 psql 直连确认数据库本身不慢,再排查容器网络。跨容器连接时确认两个容器在同一个 network 里。
模型侧报 Key 无效或额度问题。先确认环境变量在当前 shell 里 export 过,且客户端是从这个 shell 启动的。Windows 上如果用了系统环境变量,要重启客户端才生效。额度相关的问题去控制台看用量,Coding Plan 用户注意套餐覆盖范围。
还有一个隐蔽的坑:config.toml 和 settings.json 同时存在时,有的客户端只读其中一个。改完配置不确定生效没,最稳的办法是重启客户端后看 MCP 面板的连接状态,而不是猜。
6. 把这条链路用起来
跑通之后,你可以把 postgres 这个 MCP Server 当成一个常驻工具。日常开发时让模型帮你查表结构、生成迁移 SQL、排查慢查询,比来回切终端快很多。如果后面要接更多数据库或工具,MCP 的配置是并列的,再加一个 server 段就行,Key 还是共用同一份。
需要长期跑编码类 Agent 的话,建议把模型侧切到 Coding Plan,按套餐走比按量计费更可控,入口在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。只是想临时验证模型能不能正常对话,用模型对话页面就够:https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 。Key 管理和新建在控制台:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,接入细节对着文档核对:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。
最后留一个实用习惯:把 DATABASE_URI 和 TAOTOKEN_API_KEY 都放进 .env 文件,用 docker run --env-file 加载,配置文件里只留变量引用。这样换库、换 Key 都不用改配置,也不会把敏感信息误提交。