关于 dbprint
dbprint 将数据库结构、值分布、关联关系及人工注释保存为仓库中的文本快照,供编码 Agent 离线读取。它通过 MCP 服务、命令行或技能提供上下文,无需让 Agent 连接数据库。
主要功能
- 01生成结构与列统计快照
- 02记录声明或推断的关联
- 03支持人工注释且不覆盖
- 04离线提供表级上下文
- 05检查快照并用于 CI
适用场景
- 01让编码 Agent 在离线环境理解表和字段
- 02为生成 SQL 提供值域与关联信息
- 03审查数据库快照的结构或数据变化
- 04在 CI 中检查快照新鲜度与断言
MCP 相关
dbprint 提供只读 MCP 服务,读取仓库中已提交的快照而不连接数据库;MCP 客户端无需数据库凭据。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
dbprint
只需在代码旁记录一次数据库的含义,每个 Agent 会话都会读取。
你的编码 Agent 会读取迁移文件和模型,因此能正确了解数据库的结构。但它无法从结构中得知其他信息:revenue_cents 是总额,而每份报表都使用净额列;status 有两种拼写;orders 与 shipments 的一对多联结比任何人预想的都常见;legacy_uid 自迁移后就已废弃。同事只需 30 秒就能告诉它这些信息。没有数据库连接,Agent 无从得知;有了连接,它每个会话都得实时重新发现相同事实——这些查询耗费数据仓库的时间和预算,也消耗 Agent 的令牌——而且它仍可能理解错:计数不会告诉它某个代码已废弃,也不会说明某一列是总额。
dbprint 将这些知识转化为提交到代码库中的纯文本:
- 只需测量一次数据库。 每个表的 DDL、其联结关系——包括已声明的关系,以及在架构未声明关系时推断出的关系——以及每列的统计信息:空值占比、包含所有拼写形式的完整值列表、范围、分布、值形态等。支持八种数据库引擎。
- 由 Agent 记录数字的含义。
dbprint annotate会将一个表的测量结果及其留下的待解问题交给 Agent——某个代码代表什么、某个哨兵日期意味着什么、报表会排除哪些行——Agent 再根据代码和只读查询回答这些问题,并写入 dbprint 永远不会覆盖的文件。dbprint annotate --check会标记与数据相矛盾的说明。 - 之后的每个会话都可离线读取。 可通过 MCP 服务、打包的技能或
dbprint context使用,无需数据库连接,也无需向 Agent 提供凭据。由于内容以文本形式存放在 git 中,架构或数据变更会在审查中显现,dbprint check还能在 CI 中对其进行把关。
使用 dbprint,Agent 能以更低成本答对更多问题。 在我们针对多个代码库进行的测试中,读取带注释数据打印件的编码 Agent,答错的答案比不读取时少 80%,每个正确答案的成本低 17%;对于只有数据打印件明确说明才能识别的问题,答错的答案更是少 90%。
Agent 会读取的内容
以下摘录自本仓库中参考数据打印件的某个表上的 dbprint context --purpose query,展示了 Agent 编写 SQL 前会收到的内容:
# Table: arboretum.seedbank.germination_trial (900 rows, 8 columns)
## Joins
- accession_id -> arboretum.seedbank.accession.accession_id (declared)
- collector_id -> arboretum.seedbank.collector.collector_id (inferred)
## Data dictionary
One row per germination attempt run against a batch drawn from an accession.
## Column values
| Column | Values (count) | Coverage | Nulls |
|---|---|---|---|
| medium | 'moist filter paper' (176), 'sterile grit' (176), 'vermiculite mix' (176), 'agar medium' (175), 'sand tray' (176) {'sand tray' (151), 'Sand Tray' (25)}, 'control' (21) = 'No growth medium: a no-treatment control group, its germinated_count compared against ambient conditions rather than a physical medium.' | 100% - the list is the whole domain | |
这里有三件事是任何迁移文件都不会说明的:medium 仅包含这些值,不含其他值;sand tray 有两种拼写形式,因此按其中一种筛选会漏掉 25 行;control 根本不是一种 medium。前两点由 dbprint 测量得出;第三点由人或 Agent 记录一次,之后每个会话都会读取。
你可以亲自运行,无需数据库,也无需任何配置,只需安装 uv:
uvx dbprint context arboretum.seedbank.germination_trial --purpose query \
--project https://github.com/jakubro/dbprint/blob/main/docs/format/v1/examples/production/.dbprint.yaml
快速开始
需要 Python 3.13+。请为你的数据库安装对应驱动的额外依赖:
uv tool install 'dbprint[postgres]' # or [mysql], [snowflake], [duckdb], [clickhouse], [redshift], [databricks], [bigquery]
在同一次安装中添加 [mcp]、[docs] 或 [dbt] 额外依赖——例如 uv tool install 'dbprint[postgres,mcp]'——因为后续安装会替换先前安装的依赖,而不是在其基础上添加。
Postgres 适配器会调用 pg_dump 获取 DDL,因此 PostgreSQL 客户端二进制文件必须位于你的 PATH 中。
在仓库根目录中创建项目骨架:
dbprint init
此操作会写入 .dbprint.yaml(请将其提交到版本库)、创建 prints/,并将凭据模板写入 ~/.dbprint/connections.yaml——该文件位于仓库之外,因此机密信息不会与配置文件放在一起。
在凭据文件中填写连接详情:
# ~/.dbprint/connections.yaml
primary:
host: localhost
port: 5432
database: my_db
user: dbprint_ro
password: change_me
并在 .dbprint.yaml 中指定要使用的适配器以及要读取的表:
# .dbprint.yaml
connections:
primary:
adapter: postgres
auto: true
tables:
include:
- "*.public.*"
凭据的解析顺序为:先从 DBPRINT_<CONNECTION>_<KEY> 环境变量读取,其次读取 ~/.dbprint/connections.yaml,最后读取项目根目录下的 .env。这两个文件中的所有键都列在 docs/CONFIG.md 中。
生成数据档案:
dbprint generate
将结果与代码一同提交。之后即使无法连接数据库,也可以检查它:
dbprint list
然后让 Agent 为表添加注释——任务说明包含注释技能中的步骤,因此任何 Agent CLI 都可以照此执行:
dbprint annotate my_db.public.orders | claude -p
并连接你的 Agent来使用结果。
它会对你的数据库做什么
- 只读。 只需一个可以对你要生成档案的表执行
SELECT的角色即可;每种引擎的适配器页面都从你的首份数据档案链接到,并列出了确切的授权要求。唯一的写入操作,是临时复制一个抽样表中抽取的行;会话结束时即删除(在 BigQuery 上则会在过期时间到达时删除),且仅在进行抽样时发生——read.tables.materialize可以将其关闭。 - 会发布真实值。 值列表、范围和百分位数都是单元格值,会被写入你的仓库。默认情况下不会隐藏任何内容:脱敏会根据列名、检测到的敏感类型(
personal_name、national_id……)或数据形态,对这些值进行遮蔽、删除或哈希处理,同时保留所有计数。 - 只需运行一次数据分析,之后按需重新运行。 当表的数据档案超过新鲜度阈值或其设置发生变化时,才会重新读取该表;在数据仓库上,可以通过抽样、行筛选器和仅读取目录信息来控制成本——参见选择要分析的内容。
数据档案示例
Agent 读取的上下文由普通 YAML 文件组成。以下是同一份参考数据档案中某个表的 statistics.yaml 摘录,部分字段已省略:
row_count: 2500
columns:
catalogue_url:
sql_type: character varying(200)
nullable: false
null_rate: 0.0
classification: text
cardinality: 2500
cardinality_ratio: 1.0
inferred:
looks_like: url
sampled: 1000
matched: 1000
candidate_key: true
values:
- value: https://specimens.example.org/accession/1
count: 1
- value: https://specimens.example.org/accession/10
count: 1
# ... 28 more
values_coverage: 0.012 # top 30 of 2500 - a value list, not a claim of completeness
distribution: long_tail
provenance_country:
sql_type: character(2)
classification: categorical
cardinality: 10
inferred:
looks_like: country_code
sampled: 10
matched: 10
values:
- value: AU
count: 250
- value: CA
count: 250
- value: DE
count: 250
- value: FR
count: 250
- value: GB
count: 250
# ... 5 more
values_coverage: 1.0 # the list is the whole domain, not a sample
distribution: uniform
received_at:
sql_type: timestamp(0) with time zone
classification: temporal
range:
min: '2018-01-08T00:00:00Z'
max: '2024-11-28T00:00:00Z'
span_days: 2516
percentiles:
p01: '2018-02-09T00:00:00Z'
p25: '2019-10-02T00:00:00Z'
p50: '2021-06-19T00:00:00Z'
p75: '2023-03-05T00:00:00Z'
p99: '2024-10-25T00:00:00Z'
values_coverage: 1.0 是关键字段:这十个值就是该列的完整取值范围,而不只是前十个值。无需查询数据库,就能排除第十一个值。(如果表是基于样本而非全量数据生成档案,覆盖率则根据实际读取的行计算——见下文限定范围的数据分析。)
inferred 是 dbprint 推断出的内容,而不是读取到的内容:looks_like: country_code 是判断结果,sampled/matched 是它的依据,因此,基于十个值确认的形态不会看起来像是基于一万个值确认的。
与之并列的 relationships.yaml 保存了关联关系图:
refers_to:
- column:
- collector_id
target_table: arboretum.seedbank.collector
target_column:
- collector_id
on_delete: RESTRICT
detection: declared # or `inferred`, when dbprint guessed the edge from naming
observed:
fanout_avg: 6.25
target_coverage: 1.0
这部分是测量所得。另一部分由你编写,放在同一目录中,并在同一次提交中提交——列级注释写在 statistics.annotations.yaml 中:
columns:
collector_id:
note: >-
FK to collector.collector_id. Field collectors are affiliated with a
partner institution; collector.institution names it.
表级说明则写在 description.md 中,用于记录统计数据无法表达的内容。
dbprint 从不写入这两个文件;它们都会与统计信息一同读取——但对于统计信息能够回答的问题,以统计信息为准;说明文档只对数字无法表达的内容具有权威性。
写入仓库的内容
prints/<connection>/
manifest.yaml # inventory, freshness, per-table thresholds
reading.md # generated guide - how to read the rest of the print
diff.yaml # machine-readable drift from the last run
manifest.annotations.yaml # optional, connection-level notes you write
<schema>/<table>/
ddl.sql # native DDL, normalized for stable diffs
statistics.yaml # column distributions
relationships.yaml # declared + inferred foreign keys
description.md # optional, you write it
statistics.annotations.yaml # optional, per-column notes you write
relationships.annotations.yaml # optional, per-edge notes you write
每次运行都会重新写入 reading.md:它会告诉使用者哪些字段适用于哪些用途,让从未见过这种格式的 Agent 也能看懂打印结果。
这四个 .md / .annotations.yaml 文件由你管理——dbprint 从不覆盖它们,并且 Agent 阅读的内容中会包含这四个文件。
命令
| 命令 | 作用 |
|---|---|
dbprint init | 创建 .dbprint.yaml、prints/ 和凭据模板 |
dbprint config explain | 打印某张表解析得到的配置文件,并为每个值注明其默认值、来源连接或设置它的规则 |
dbprint generate | 为数据库生成概要;写入打印结果和 diff.yaml |
dbprint list | 离线汇总已提交的打印结果 |
dbprint diff | 将实时数据库与已提交的打印结果进行比较 |
dbprint check | CI 门禁:检查结构、时效性和统计断言;--online 会额外检查偏差和 SQL 断言 |
dbprint context | 输出一个或多个表的适用于提示词的 Markdown 视图 |
dbprint annotate | 输出单个表的注释编写指南,或使用 --check 检查注释 |
dbprint docs | 以 HTML 网站形式浏览打印结果——可实时 serve,也可静态 build(需安装 [docs] 扩展) |
dbprint serve | 在已提交的打印结果上运行只读 MCP 服务(需安装 [mcp] 扩展) |
完整参考:docs/CLI.md。
连接 Agent
MCP 客户端会自行启动服务,因此由客户端(而不是你)选择工作目录。请明确指定项目:
{
"mcpServers": {
"dbprint": {
"command": "uvx",
"args": ["--from", "dbprint[mcp]", "dbprint", "serve", "--project", "/srv/analytics"]
}
}
}
服务会读取已提交的打印结果,且从不连接数据库,因此客户端不需要凭据。
读取远程项目
--project 也接受 Git 地址,因此无需先手动克隆,就能读取提交在他人仓库中的打印结果:
dbprint list --project https://github.com/jakubro/dbprint/blob/main/docs/format/v1/examples/production/.dbprint.yaml
dbprint context arboretum.seedbank.accession --project https://github.com/jakubro/dbprint#main:docs/format/v1/examples/production
dbprint 会为你克隆仓库,且不需要任何自身凭据——访问私有仓库时,你已有的 SSH Agent 或凭据助手即可处理认证。它是只读的:会写入或连接实时数据库的命令(generate、diff、check --online)会拒绝远程定位符;其他所有命令都能像在本地一样对其运行。
超越基础功能
- 语义推断。 每列都会获得 8 种分类之一。文本、类别和外键列会获得 38 种形态模式之一(
uuid、email、phone、ip、country_code……),并公布判定所依据的样本量和匹配数。对于数据不得离开数据库的列,会标注sensitivity维度(personal_name、postal_address、national_id、credential……)。唯一性实际上很高(基数比率 >= 0.9999)的列会标记为candidate_key;只要此阈值纳入的是测得或估算的重复值,而非真正唯一的值,就会同时标记candidate_key_exception。对于你的架构中未声明的外键,会根据命名进行推断,并标注detection: inferred。 - 脱敏。 使用
mask、drop或hash(加盐)隐藏单元格值,可按 glob、推断出的敏感度或形态来指定列——因此,明年新增的personal_name列也会受到今天编写的规则保护。计数、基数和分布都会保留;只有字面值会被隐藏。盐值与凭据一同保存,绝不会写入已提交的配置。 - 断言。 使用 YAML 针对任意统计数据编写数据质量检查,也可以直接编写 SQL。统计断言会通过普通的
dbprint check,针对已提交的打印结果进行评估,无需连接数据库;SQL 断言则需要dbprint check --online。参见docs/ASSERTIONS.md。 - CI 退出码。
0表示正常,1表示打印结果格式错误或配置不可用,2表示过时,3表示存在差异,4表示连接失败,5表示运行不完整,6表示断言失败,7表示完全失败。diff、check和context都支持--format json|yaml。 - 范围化分析。 每表规则可以进行采样(在引擎支持设置种子的情况下,使用表名作为种子)、应用行筛选器,或更改测量内容——并依据表大小设置条件,因此一条规则就能覆盖所有尚未命名的事实表。以这种方式读取的表会包含一个
scope区块和每列的rows_scanned;文件中的所有计数都以实际读取的行数为基数,绝不会悄悄按整张表计算。 - MCP 服务。
dbprint serve提供 7 个工具——get_table_context、list_tables、search_columns、resolve_value、get_manifest、get_diff、get_reference——并将每个产物作为资源提供。它只读取已提交的打印结果,不会打开数据库连接。参见docs/MCP.md。 - Markdown 技能文件。 对于可接收 Markdown 规则或自定义指令的客户端,直接可用的技能文件会告诉 Agent 已提交的打印结果能回答什么问题、应该使用哪个工具回答,以及每个数字涵盖的范围——无需运行任何进程。另一个技能文件则让 Agent 根据写入每张表的代码和只读查询编写注释文件,并使用
dbprint annotate --check检查。两者都位于docs/examples/skill/,你可以先阅读,再安装任何内容。 - dbt 血缘。 将连接的
dbt_manifest指向已编译的 dbtmanifest.json,generate就会将每个模型列的源列记录为derived_from,因此,在源列上编写一次的说明就会传递到由该列构建的所有模型([dbt]extra)。参见docs/CONFIG.md。 - 令牌预算上下文。
dbprint context arboretum.seedbank.accession --budget 4000会将 Markdown 视图控制在令牌预算内,并优先移除优先级最低的部分。
最接近的工具
| 项目 | 功能 | dbprint 的不同之处 |
|---|---|---|
| dryrun | 离线 Postgres 架构快照 + MCP 服务 + lint | 最接近本项目的工具。它的快照是压缩的二进制包,需要在 .gitattributes 中将其标记为 binary;dbprint 的产物则是可逐行比较的 YAML,具有公开规范,支持八种数据库 |
| dbt-profiler | 将列配置文件提交为 dbt YAML / Markdown | 仅支持 dbt 项目。没有 DDL、关系图、语义推断或脱敏功能 |
| 实时连接的 MCP 服务(dbhub、postgres-mcp、Supabase、Neon) | 在 Agent 运行时查询和内省数据库 | 需要 Agent 在每个会话中提供凭据。dbprint 只需生成一次配置文件并提交结果,之后即可在无法连接数据库的情况下提供服务 |
| tbls、SchemaSpy | 为人类生成架构文档和 ER 图 | 仅包含结构,不含数据分布。dbprint docs serve 会基于 print 中经过测量的列,呈现相同的可浏览页面和 FK 图 |
dbprint 不是什么
- 不是迁移工具。 它不会编写、应用或管理 DDL 变更的版本。请使用 Alembic、Flyway、Liquibase、sqldef、Atlas。
- 不是架构管理或 ORM 层。 print 是从你的数据库生成的;它绝不是你据以构建数据库的事实来源。
- 不是实时查询接口。 print 中的任何内容都不会为你的 Agent 执行 SQL。
- 不是数据质量平台。 断言 DSL 是针对 print 的 CI 门禁,不提供监控、告警或血缘功能。请使用 Soda、Great Expectations、Elementary。
- 不是数据目录。 没有托管服务、共享搜索索引或业务术语表。
dbprint docs会提供已提交 print 的本地只读视图,并绑定到环回地址,无需管理任何内容。
格式
print 是数据库结构及列级数据分布的可移植快照,可提交到 Git,供人类、AI 编码 Agent 和 CI 离线使用。 磁盘上的格式,而非 CLI,才是这里的持久产物:它有明确规范,独立于工具进行版本管理,并且旨在供其他生成工具使用。
格式规范见 docs/format/v1/SPEC.md。
安装包中包含七个 JSON Schemas,位于 src/dbprint/spec/v1/——四个用于生成的产物,三个用于你编写的注释文件;一致性验证器是公开 API,无需数据库、配置或 CLI 即可使用:
from dbprint.conformance import validate_print
issues = validate_print("prints/production") # conforms iff no error-severity issues
docs/format/v1/examples/ 中的参考 print 是真实的 dbprint 输出,并非手写示例——你在那里看到的就是实际得到的内容。
配置
.dbprint.yaml 保存项目配置(提交到版本库);~/.dbprint/connections.yaml 保存凭据(绝不提交)。两个文件的所有键、类型、默认值和解析顺序,均见 docs/CONFIG.md。内部实现文档见 docs/ARCHITECTURE.md。
许可证
Copyright 2026 Jakub Roman。根据 Apache License 2.0 分发。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。