1. 为什么要在本地跑 MCP Toolbox for Databases
MCP Toolbox for Databases 是 Google 开源的一个数据库工具服务端,它把 Postgres、MySQL、MongoDB、BigQuery 这些数据源统一抽象成「工具」,再通过 MCP 协议暴露给 AI 智能体。你可以把它理解成一个「数据库能力网关」:智能体不直接连库,而是向 Toolbox 请求工具列表、调用工具,Toolbox 负责连接池、鉴权、SQL 执行和埋点。对做 AI 智能体开发的人来说,它解决的是「让模型安全地读数据库」这件事,适合后端工程师、Agent 开发者、以及想把自然语言查询接进业务系统的人。
我这次的目标很具体:在本地 Python 环境里把 Toolbox 跑起来,用 TaoToken 统一 Key 和 API 通道完成鉴权联调,最后让智能体用不到 10 行 Python 代码查一次数据库。整个链路是「Python 客户端 → Toolbox Server → 数据库」,而模型侧的调用统一走 TaoToken 的 endpoint,这样 Key 只需要维护一份,换模型、换智能体框架都不用改配置。
先说清楚 Toolbox 的定位。它不是 ORM,也不是数据库驱动,而是一个独立的 Server 进程。你在tools.yaml里声明数据源和工具,Server 启动后监听一个 HTTP 端口,客户端 SDK 通过这个端口加载 toolset。MCP 协议在这里的作用是标准化「工具发现 + 工具调用」的接口,所以 LangChain、LlamaIndex、自研框架都能用同一套工具定义,不用为每个框架重写一遍数据库访问逻辑。
本地跑的好处是调试快。数据库可以先用 Docker 起一个 Postgres,Toolbox 用二进制或容器启动,Python 侧装toolbox-core就能连。等本地验证通过,再把 endpoint 换成 TaoToken 的地址做鉴权联调,最后上生产。下面按这个顺序展开,每一步都给可复制的命令和配置。
2. TaoToken 前置:统一 Key 与 API 通道怎么准备
在动 Toolbox 之前,先把 TaoToken 这边的 Key 和 endpoint 准备好,因为后面 Python 客户端调模型、以及 Toolbox 联调时的鉴权都会用到。TaoToken 的官网是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 基址是 https://taotoken.net/api ,注意 API 地址不带 UTM 参数,配置里直接写这个。
第一步是拿 Key。进控制台的 API Keys 页面创建一个新 Key,建议按项目命名,比如toolbox-local-dev,方便后面排查是哪个环境在用。创建后立刻复制保存,页面刷新后就看不到完整 Key 了。这个 Key 就是后面环境变量里的TAOTOKEN_API_KEY。
第二步是确认模型 ID。TaoToken 的模型对话页面能看到当前可用的模型列表,选一个你常用的,比如 Claude 系列或 GPT 系列,把模型 ID 记下来。这个 ID 会写进 Python 客户端的配置里,作为model参数。如果你后面要用 Coding Plan 做长期编码或 Agent 任务,可以在 Coding Plan 页面看套餐说明,它更适合高频调用场景。
第三步是理解鉴权方式。TaoToken 走的是标准 Bearer Token,请求头里带Authorization: Bearer <你的Key>。Toolbox 本身不直接管模型的鉴权,它管的是数据库连接;模型侧的鉴权由 Python 客户端在调用时带上。所以「统一 Key」的意思是:模型调用、Agent 框架、以及后续可能接的 coding 工具,都用同一个 TaoToken Key,而不是每个服务各配一套。
这里有个容易踩的坑:不要把 Key 硬编码进tools.yaml。tools.yaml是数据库凭据的存放处,模型 Key 应该放在环境变量或.env文件里,由 Python 进程读取。两者职责分开,后面换 Key 或换数据库都不会互相影响。环境变量建议这样写:
export TAOTOKEN_API_KEY="sk-你的Key" export TAOTOKEN_BASE_URL="https://taotoken.net/api" export TOOLBOX_URL="http://127.0.0.1:5000"TOOLBOX_URL是本地 Toolbox Server 的地址,默认端口 5000。等本地验证通过,如果你要把模型 endpoint 也指向 TaoToken 做联调,就把TAOTOKEN_BASE_URL传给客户端。这样一套环境变量同时覆盖了「连 Toolbox」和「连模型」两个方向。
3. 可复制配置:tools.yaml 与 Python 客户端
这一节给完整的可复制片段。先建一个工作目录,比如~/toolbox-demo,在里面放tools.yaml和agent.py。
tools.yaml分三块:sources 定义数据源,tools 定义具体工具,toolsets 把工具分组。下面是一个 Postgres 的完整示例,数据库用 Docker 起:
docker run -d --name toolbox-pg \ -e POSTGRES_USER=toolbox_user \ -e POSTGRES_PASSWORD=my-password \ -e POSTGRES_DB=toolbox_db \ -p 5432:5432 postgres:16然后写tools.yaml:
sources: my-pg-source: kind: postgres host: 127.0.0.1 port: 5432 database: toolbox_db user: toolbox_user password: my-password tools: search-hotels-by-name: kind: postgres-sql source: my-pg-source description: 按名称模糊查询酒店 parameters: - name: name type: string description: 酒店名称关键词 statement: SELECT * FROM hotels WHERE name ILIKE '%' || $1 || '%'; toolsets: booking_agent: - search-hotels-by-name注意statement里用的是$1占位符,Toolbox 会做参数绑定,不要自己拼字符串,否则会有注入风险。toolsets是给智能体加载用的分组,一个工具可以出现在多个 toolset 里。
接着写 Python 客户端。先装依赖:
pip install toolbox-core openaiagent.py的核心逻辑是:连 Toolbox 加载工具,再用 TaoToken 的 endpoint 调模型。下面这段不到 10 行就能完成一次数据库查询:
import asyncio, os from toolbox_core import ToolboxClient from openai import OpenAI async def main(): async with ToolboxClient(os.environ["TOOLBOX_URL"]) as client: tools = await client.load_toolset("booking_agent") result = await tools[0].invoke({"name": "希尔顿"}) print(result) asyncio.run(main())如果你要把模型也接进来做自然语言查询,就在同一个文件里加 TaoToken 客户端:
client = OpenAI( api_key=os.environ["TAOTOKEN_API_KEY"], base_url=os.environ["TAOTOKEN_BASE_URL"], ) resp = client.chat.completions.create( model="claude-3-5-sonnet", messages=[{"role": "user", "content": "帮我查一下名字带希尔顿的酒店"}], )这里base_url指向 TaoToken 的 API 地址,api_key用环境变量里的 Key。模型 ID 按你在模型对话页面看到的实际值填。这样模型负责理解意图,Toolbox 负责执行 SQL,两边通过工具调用串起来。
4. 验证请求:从启动 Server 到拿到查询结果
配置写完,按顺序验证。第一步启动 Toolbox Server。用二进制方式:
export VERSION=0.8.0 curl -O https://storage.googleapis.com/genai-toolbox/v$VERSION/linux/amd64/toolbox chmod +x toolbox ./toolbox --tools-file tools.yaml看到监听 5000 端口的日志就说明起来了。如果端口被占用,加--port 5001换端口,同时把TOOLBOX_URL改掉。
第二步准备测试数据。进 Postgres 建表插几条:
docker exec -it toolbox-pg psql -U toolbox_user -d toolbox_db -c " CREATE TABLE hotels (id serial primary key, name text, rooms int); INSERT INTO hotels (name, rooms) VALUES ('希尔顿酒店', 120), ('万豪酒店', 80); "第三步跑agent.py。预期输出是包含「希尔顿酒店」的记录。如果打印出[{'id': 1, 'name': '希尔顿酒店', 'rooms': 120}]这类结构,说明 Toolbox 到数据库这条链路通了。
第四步验证模型侧。把agent.py改成先调模型解析意图,再调工具。你可以先用一句自然语言问「有哪些酒店」,看模型返回的工具调用参数是否正确。这一步的 endpoint 就是 TaoToken 的 API 地址,Key 从环境变量读。如果模型返回了tool_calls,并且参数里的name是「希尔顿」,说明模型和 Toolbox 的对接没问题。
第五步做一次端到端联调:模型解析 → 工具调用 → 结果回传 → 模型总结。整个过程你只需要维护一个 TaoToken Key,Toolbox 的数据库凭据在tools.yaml里,两边不混。实测下来,本地这套跑通大概十分钟,主要时间花在等 Docker 拉镜像和确认模型 ID 上。
5. 本篇常见错排查:401、local proxy failed 与 reading choices
第一个高频错误是 401。表现是 Python 客户端调模型时抛AuthenticationError,或者 Toolbox 日志里出现unauthorized。原因通常是TAOTOKEN_API_KEY没导出,或者导出的是旧 Key。排查方法:在 Python 里打印os.environ.get("TAOTOKEN_API_KEY")的前几位,确认非空且和 TaoToken 控制台里的一致。注意不要在日志里打印完整 Key。
第二个是local proxy failed。这个报错一般出现在客户端连 Toolbox 时,说明TOOLBOX_URL指向的地址连不上。先确认 Server 进程还在跑,再确认端口没被防火墙拦。本地开发最常见的是 Server 崩了但终端没注意,重新./toolbox --tools-file tools.yaml即可。如果用了 Docker 跑 Toolbox,注意容器内的127.0.0.1和宿主机的127.0.0.1不是一回事,要么用host.docker.internal,要么把数据库和 Toolbox 放同一个 network。
第三个是reading choices相关报错,通常长这样:Error reading choices from response。这多半是模型返回体不符合 OpenAI 兼容格式,或者base_url写错了。检查TAOTOKEN_BASE_URL是不是https://taotoken.net/api,注意结尾不要多加/v1或斜杠。另外确认model参数填的是 TaoToken 模型列表里真实存在的 ID,填错模型名有时也会导致返回体异常。
第四个是 OAuth 相关报错。如果你在 Toolbox 里配了需要 OAuth 的数据源(比如 BigQuery),本地没配凭据就会报oauth token not found。本地调试建议先用 Postgres 这种用户名密码方式,把链路跑通再换数据源。真要调 OAuth,按 Toolbox 文档配好服务账号 JSON,并把路径写进tools.yaml的对应字段。
第五个是工具加载为空。load_toolset("booking_agent")返回空列表,说明tools.yaml里 toolset 名字拼错,或者工具没被正确引用。检查toolsets下的名字和load_toolset的参数是否完全一致,YAML 缩进是否用了空格而不是 Tab。
6. 把 endpoint 改到 TaoToken 完成鉴权联调
本地验证通过后,最后一步是把模型 endpoint 正式切到 TaoToken,做一次完整的鉴权联调。这一步的核心是确认三件套齐全:Base URL、Key、Model ID。Base URL 用https://taotoken.net/api,Key 用控制台创建的,Model ID 用模型对话页面确认的。
联调时建议加一个最小重试逻辑,避免网络抖动误判:
from openai import OpenAI import os, time client = OpenAI( api_key=os.environ["TAOTOKEN_API_KEY"], base_url=os.environ["TAOTOKEN_BASE_URL"], ) for i in range(3): try: resp = client.chat.completions.create( model="claude-3-5-sonnet", messages=[{"role": "user", "content": "ping"}], ) print(resp.choices[0].message.content) break except Exception as e: print(f"attempt {i+1} failed: {e}") time.sleep(2)跑通后,把agent.py里的模型调用和 Toolbox 工具调用串起来,就完成了「TaoToken 鉴权 + Toolbox 数据库访问」的完整链路。后续如果你要接 Claude Code 或 Cline 这类编码工具,Base URL 和 Key 的填法是一样的,Model ID 按工具要求填。需要看更多接入细节可以去接入文档,验证模型效果可以去模型对话页面直接试,长期跑 Agent 任务的话 Coding Plan 更合适。
最后留一个实用技巧:把tools.yaml和.env都加进.gitignore,数据库密码和 API Key 不要进版本库。本地调试时用direnv或source .env自动加载环境变量,省得每次开终端都手动 export。这套配置我用了两周,换过一次数据库和一次模型,都只改了对应的一处配置,没有动业务代码。