Dbboard

io.github.meta-taro由 GitHub 帳號 meta-taro 發布v0.22.2更新於 Nov 6, 2026

Hands AI agents the databases dbboard connects to: reads by default, and never a secret.

已驗證STDIO僅桌面資料庫安全與監控

概覽

AI 產生的概覽

dbboard 桌面資料庫用戶端的配套 MCP 伺服器,讓 AI 代理以唯讀方式讀取你已連線的資料庫,且拿不到密碼。

可以做什麼
  • 把 dbboard 桌面應用程式裡儲存的連線開放給代理,讓它能查詢同一批 Postgres、MySQL、Turso/libSQL、D1、Firestore、MongoDB 與 Redis 相容儲存。
  • 在資料庫本身的唯讀模式下執行讀取,寫入會在伺服器端失敗,而不是靠關鍵字過濾攔截。
  • 密碼不會交給代理,憑證保存在作業系統鑰匙圈中。
  • 只有在針對單一連線開啟時才允許寫入,即使如此也會拒絕 DROP、TRUNCATE 與權限變更。
適用情境
適合資料庫分散在多個服務商、希望助理在同一處檢視或查詢這些資料庫的情境,尤其是需要讓代理讀取正式環境但絕不能修改時。
執行需求
需要 Windows 或 macOS 上的 dbboard 桌面應用程式,並已在應用程式中加入資料庫連線;MCP 伺服器透過 stdio 在本機執行並共用這些連線。從原始碼建置另需 Rust 1.98.0、cargo 與 C/C++ 工具鏈。
安裝前請注意
唯讀由資料庫引擎強制執行,但可依連線開啟寫入,指向正式環境前請確認該設定。連線字串與服務帳戶金鑰屬於機密,保存在作業系統鑰匙圈中,不要納入版本控制。應用程式的選用 AI 面板會把提示詞與回覆原樣寫入本機歷史檔案,貼上的機密會落到磁碟。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Dbboard,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

[dbboard logo]

dbboard

⬇️ Download dbboard — Windows .exe / macOS .dmg

[Download] [Latest release]

One window for every database you look after — and a safe way to let an AI agent read them.

[dbboard with a Postgres server open: databases, schemas and tables in the sidebar, and a JOIN that ran in the shop database with 180 rows in the grid]

dbboard is a desktop database client for Windows and macOS. It speaks Postgres (and Neon, Supabase, CockroachDB, Aurora DSQL), MySQL / MariaDB, Turso / libSQL, Cloudflare D1, Cloud Firestore, MongoDB and Redis-compatible stores (Redis, Valkey, Amazon MemoryDB, Amazon ElastiCache, Upstash), keeps every password in the operating system's keychain, and ships a separate MCP server so that Claude and other agents can read the same databases without being able to change them.

When it helps

Your databases live on four different services. Production is on Neon, the side project on Supabase, the old system on a MySQL server behind a bastion, and the experiments in a Turso file. Instead of four web consoles and a terminal, they sit in one sidebar. An SSH tunnel reaches the one behind the bastion, and a colour and a tag on each connection make it obvious which one you are about to run a statement against.

You want an AI agent to read production, and it must never write. dbboard-mcp hands your existing connections to Claude Code or Claude Desktop. Reads run inside the database's own read-only mode (a READ ONLY transaction, PRAGMA query_only), not behind a keyword filter, so an UPDATE fails at the server. Writing stays off until you switch it on for one connection, and even then DROP, TRUNCATE and privilege changes are refused. Passwords never reach the agent. → MCP server

One login can see a dozen databases. Leave the database name blank when you add a Postgres or MySQL connection, and the sidebar lists every database that account can open, with its schemas and tables beneath. Click a table and the editor runs in that database; the label next to Run says which.

Someone needs one value fixed, without writing an UPDATE. Open the table, double-click the cell, type, and Save changes. The edit is keyed on the primary key, so a table without one stays read-only instead of guessing.

Try it

  1. Download the installer for your machine from the download page (Windows x64 / ARM64 .exe, macOS .dmg).
  2. Open it. The builds are not code-signed, so Windows SmartScreen and macOS Gatekeeper ask you to confirm the first time; compare the file with SHA256SUMS.txt from the release first if you want to be sure.
  3. Click Manage → Add connection, pick the database type and fill in the server. dbboard requires TLS unless you turn it off for that connection.

There are no Linux builds yet; on Linux, build from source (see Run).

A tour

Add a connection. Host, port, user and password, or paste a connection URL instead. The password goes to the OS keychain, never to a file. Leave Database blank to browse all of them.

[The add-connection form for a Postgres server on 127.0.0.1, with the database field left blank]

Find the table. Databases, then schemas, then tables. Selecting a table opens its structure: columns, types, defaults, the primary key, and the foreign keys in both directions. Notes you add stay on your machine.

[The structure view of public.orders, with its columns and three relationships]

Query it. Write SQL and press ⌘/Ctrl + Enter. Results come back in a grid you can copy as TSV or CSV or save to a file, and recent queries are kept in that connection's history.

Change a row. Select top 100 from the table's menu opens an editable grid. Edits stay pending, highlighted, until you save or discard them.

[A products table with one edited stock value waiting to be saved]

Light or dark, in your language. The theme follows the system or stays where you put it, and the interface is available in eleven languages.

[The same query in the dark theme]

Every screenshot here is taken in a separate profile against fictional data (scripts/demo-profile), never against a real connection (ADR-0098).

Status

Pre-1.0. Phases 1, 3, 6, and the Phase 4 AI assistant are closed, and dbboard now doubles as an MCP server (dbboard-mcp) for external AI agents (ADR-0046) — read-only unless you opt a connection in, and never for privilege changes, TRUNCATE or DROP (ADR-0087). The Turso, Cloudflare D1, CockroachDB, Neon, Supabase, AWS Aurora DSQL, MySQL / MariaDB, Cloud Firestore, MongoDB and Redis-compatible adapters all ship over the local HTTP backend. See CHANGELOG.md for what landed and docs/roadmap.md for the next phase.

The client is Tauri 2 + SvelteKit over the shared Rust core crates. The egui client it replaced shipped through v0.4.0 and was retired in ADR-0089; releases up to v0.4.0 still carry its binaries.

This is the desktop implementation. The web counterpart lives at meta-taro/dbboard-web (Nuxt + NestJS). The two share concepts and feature parity goals but are independent codebases.

Download

A prebuilt Windows installer (.exe) and macOS disk image (.dmg) for the latest release are on the download page (GitHub Pages), or directly on the Releases page. Every release ships a SHA256SUMS.txt; verify your download before running it. The binaries are not code-signed, and will not be — a certificate is a recurring purchase this project does not make (ADR-0106). Windows SmartScreen / macOS Gatekeeper therefore warn on first launch, on every release. The checksum is what you verify instead.

Goals

  • Performance first — Rust core; the UI is a WebView shell over it, not a bundled browser runtime.
  • Local first — no required external services to run.
  • Modular — database and AI layers are decoupled.
  • Extensible — new databases and AI providers can be added behind traits.

Supported Databases (initial scope)

  • Turso / libSQL (SQLite-based distributed DB)
  • Cloudflare D1 (SQLite-based, REST API)
  • CockroachDB (distributed SQL, PostgreSQL-wire)
  • Neon (managed PostgreSQL)
  • Supabase (managed PostgreSQL)
  • AWS Aurora DSQL (managed PostgreSQL-wire)
  • MySQL / MariaDB (mysql://…, its own SQL dialect)
  • Cloud Firestore (document store, REST API — read-only)
  • MongoDB (document store, official driver — read-only)
  • Redis-compatible stores: Redis, Valkey, Amazon MemoryDB, Amazon ElastiCache, Upstash (key-value, RESP — read-only)

All ten adapters ship today. The four pg-wire flavors share the generic dbboard-postgres adapter (sqlx + tls-rustls-ring), differing only in the runtime label exposed by DatabaseAdapter::id() ("postgres", "neon", "supabase", "aurora-dsql") so the connection picker and history records can label each connection precisely. See ADR-0018 (Neon), ADR-0019 (Supabase), and ADR-0021 (Aurora DSQL).

MySQL / MariaDB is the first engine on a genuinely different SQL dialect (back-tick identifiers, back-slash string escapes, X'…' blobs, no NaN/±Inf in DOUBLE): it has its own dbboard-mysql adapter over sqlx's MySQL driver and a distinct SqlDialect::MySql. See ADR-0068.

Cloud Firestore is the first adapter that is not SQL at all. A query is a Firestore StructuredQuery written as JSON — the same object Google's docs show, with no translation layer and no invented query language — and nested documents come back in Value::Json cells. It is read-only by construction: the REST API splits reads from writes at the endpoint, and the crate contains no code able to build a write URL. It connects with a service-account key (stored in the OS keychain, never in connections.toml) or, with no credential at all, to the local emulator. See ADR-0091, ADR-0093, and ADR-0094.

MongoDB is the second, and it needed a different guarantee. A query is a command document written as JSON — {"find": "orders", "limit": 100}, the same object the mongosh docs show. Every MongoDB command travels one runCommand path, so read-only cannot be structural the way Firestore's is: it is an allowlist of commands and, per command, of their options, which is why {"find": …, "insert": …} is refused for having an option find does not take rather than for a remembered verb. $out and $merge are walked for at any depth, and server-side JavaScript is refused outright. The whole connection URI is the secret and lives in the OS keychain. MongoDB connections cannot be tunnelled over SSH — one URI may name several hosts and mongodb+srv:// discovers a replica set from DNS, so forwarding a single host leaves the driver failing over to members the tunnel never covered. See ADR-0095 and ADR-0096.

Redis-compatible stores are the third, and the first with no tables at all. Redis, Valkey, Amazon MemoryDB, Amazon ElastiCache and Upstash all speak RESP, so they share one adapter and differ only in the label and the form's defaults. A query is one command line, as redis-cli takes it — HGETALL user:1 — and read-only is again an allowlist of commands and of their arguments. Writes, scripts, blocking and pub/sub commands are refused before anything is sent, and so is KEYS, which blocks the server: SCAN gives the same answer a page at a time, and dbboard follows its cursor until it has the keys asked for, across every node of a cluster. A command that returns a whole hash, set, list or sorted set checks its size first. The sidebar lists key prefixes (user:*). MemoryDB always runs in cluster mode and over TLS. A store inside a private network is reached through an SSH bastion: every node the cluster names is forwarded on its own, and the URL keeps the host its TLS certificate names. See ADR-0166 and ADR-0167.

Aurora DSQL also has a second connection kind, aurora-dsql-iam (ADR-0036): instead of a manually supplied URL whose token expires in ~15 minutes, dbboard mints the SigV4 IAM token itself from stored AWS credentials, for connections that need to stay up 24/7. A background task re-mints the token and swaps in a freshly authenticated pool before it expires (ADR-0037, 段階B), so an unattended connection survives Aurora DSQL's idle recycle without a manual reconnect.

The Supabase REST/auth layer is deliberately deferred to a future ADR — at this stage all pg-wire flavors use the same postgres://… URL contract (the aurora-dsql-iam kind excepted, which stores AWS credentials rather than a URL).

The authoritative per-version support matrix (Tier 1 / Tier 2 / best effort) lives in docs/compatibility.md; versioning and DB-support policy are defined in ADR-0011.

Architecture

Three main layers, organised as a cargo workspace:

  • UI layer — a Tauri 2 shell (apps/desktop) with a SvelteKit frontend, calling the core crates over Tauri IPC.
  • Database adapter layer — abstracts database-specific logic behind a single trait so multiple providers plug in.
  • AI integration layer (optional) — pluggable providers (Claude, OpenAI, local LLMs). Isolated from core DB operations.

See docs/architecture.md for the full crate map and dependency rules.

Requirements

  • Rust 1.98.0. The version is pinned in rust-toolchain.toml, so rustup installs it for you inside this checkout; a machine set up by hand needs the same one. It is bumped deliberately rather than tracking stable, because clippy -D warnings makes the lint set part of the build (ADR-0139).
  • cargo (bundled with Rust)
  • A C/C++ toolchain for libsql native deps:
    • Windows: MSVC Build Tools
    • macOS: Xcode Command Line Tools
    • Linux: build-essential

Setup

sh
git clone https://github.com/meta-taro/dbboard.gitcd dbboardsh scripts/cargo-test-serialised.sh

Then install the git hooks (pre-commit, commit-msg, pre-push):

sh
sh scripts/install-hooks.sh

They are a local convenience — CI runs the same checks on every push and pull request either way. Re-run the installer after editing a hook.

Run

sh
cd apps/desktoppnpm install        # first time onlypnpm tauri dev

The frontend never touches a database: it calls Tauri commands that wrap the same McpService the MCP server exposes, so the engine-enforced read-only path has one implementation. Nothing listens on a network interface. (The loopback HTTP backend in crates/dbboard-server is the executable statement of the contract the web sibling implements — see docs/api-contract.md — and is no longer booted by the client.)

By default the app opens an in-memory Turso/libSQL database, so it runs with no configuration. The backend is chosen by, in priority order:

  1. The environment variables documented below (DBBOARD_AURORA_DSQL_URL > DBBOARD_NEON_URL > DBBOARD_SUPABASE_URL > DBBOARD_PG_URL > DBBOARD_MYSQL_URL > DBBOARD_D1_* > DBBOARD_FIRESTORE_PROJECT_ID > DBBOARD_MONGODB_URI > DBBOARD_TURSO_PATH). Among the four pg-wire flavors the order is alphabetical — setting two flavored vars at once is unusual but the precedence is fully defined.
  2. DBBOARD_CONNECTION=<id> resolved against connections.toml — the local connection store backed by your OS keychain (ADR-0013).
  3. If connections.toml has exactly one entry, that one is auto-selected.
  4. Otherwise an in-memory Turso/libSQL database.

See docs/connections.md for the connection-store schema and where the file lives per OS.

Once registered, the Connections window (top bar) lets you add / edit / delete entries and swap the active connection on the running process — the per-row Connect button swaps the backend in-place, no app restart needed (in-flight requests intentionally finish on the old backend; new ones pick up the new one). See ADR-0020 for the swap semantics.

The same window can Export all connections to a passphrase-encrypted .dbbx bundle (age scrypt + ChaCha20-Poly1305) that carries the connection metadata and its secrets, and Import one on another machine — the one-file way to move a whole setup without hand-seeding the keychain. Import is skip-and-report on id/reference conflicts. See ADR-0038 and docs/connections.md.

A connection to a database that only listens on a bastion's localhost can reach it through an SSH tunnel: the desktop connection form has an SSH tunnel section (for the Postgres family, MySQL and the Redis-compatible stores) to set the bastion host/port/user, key- or password-based auth, and a mandatory server host-key pin (fingerprint or known_hosts). dbboard opens a pure-Rust local port forward (russh) and rewrites the connection URL to the tunnel before dialing; the key passphrase / SSH password live only in the keychain. See ADR-0069 and docs/connections.md.

The top bar carries a Language / 言語 menu listing the 11 shipped locales by their native names. Picking one swaps the UI language in place; the DBBOARD_LANG env var still drives the startup default and is unchanged by the runtime switcher. See ADR-0022.

The Help menu shows the running version and, when a newer release has been published, an Update available notice with the release notes. This is the one network call dbboard makes on its own behalf: a single best-effort check at startup against the signed latest.json published with each release, compared to the running version. You choose whether to install it; the download is verified against the release signing key before anything is replaced (ADR-0067). The check is silent when offline or on any error, and you can turn it off completely by setting DBBOARD_NO_UPDATE_CHECK to any non-empty value. See ADR-0040.

A Backup… button on the query toolbar dumps the active connection to a single self-contained .sql file — schema plus data, in the source engine's own dialect (verbatim DDL for the Turso/D1 SQLite family, reconstructed DDL for the Postgres family including Neon, Supabase, and Aurora DSQL). The dump streams INSERT batches straight to disk with keyset pagination, so a large database never buffers in memory. Before starting, a preflight row count warns if the database is bigger than a threshold (500k rows by default, adjustable under the Backup menu and remembered across restarts) so a giant dump isn't kicked off blindly; while running, a window shows table/row progress and a percentage bar and can Cancel at any time (the file keeps the partial dump). See ADR-0049 and ADR-0050 (the configurable threshold).

A Restore… button on the same toolbar plays a .sql file back into the active connection — the read side of the backup above, and it also accepts foreign scripts (pg_dump, sqlite3 .dump). It runs whole-script against an engine of the matching family (SQLite for Turso/D1, Postgres for Neon, Supabase, and Aurora DSQL) and applies statements inside a transaction where the engine supports one (Aurora DSQL falls back to per-statement). To stay safe, restore targets empty databases: loading into a connection that already holds tables raises a confirmation rather than merging or diffing. A window shows per-statement progress and can Cancel mid-run; the summary reports how many schema and data statements applied and which failed. See ADR-0051.

The examples below set an env var for one run; they assume the working directory is apps/desktop (that is where pnpm tauri dev lives). Anything you would rather keep is better placed in connections.toml — see docs/connections.md.

Local Turso/libSQL (default)

VariablePurposeDefault
DBBOARD_TURSO_PATHlibSQL file path, or :memory::memory:

Cloudflare D1

Set all three of the following to connect to D1 instead of Turso:

VariablePurpose
DBBOARD_D1_ACCOUNT_IDCloudflare account ID
DBBOARD_D1_DATABASE_IDD1 database ID (wrangler d1 info <name>)
DBBOARD_D1_TOKENAPI token with the D1 Edit permission
DBBOARD_D1_BASE_URL(optional) API root override; defaults to https://api.cloudflare.com/client/v4

The account and database IDs are shown in the Cloudflare dashboard (Workers & Pages → D1) or via wrangler d1 info <database-name>. Create the API token under My Profile → API Tokens with a D1 read/write permission. If any of the three required variables is missing, the app falls back to the local Turso default.

sh
DBBOARD_D1_ACCOUNT_ID=... DBBOARD_D1_DATABASE_ID=... DBBOARD_D1_TOKEN=... \  pnpm tauri dev

Cloud Firestore

The project id alone is enough to select Firestore. Everything else is optional, which makes the emulator the zero-configuration case:

VariablePurpose
DBBOARD_FIRESTORE_PROJECT_IDGoogle Cloud project id. Selects the Firestore backend.
DBBOARD_FIRESTORE_SERVICE_ACCOUNT(optional) The service-account key, as the JSON file's whole contents. Omit it to talk to the local emulator, which authenticates every request as owner.
DBBOARD_FIRESTORE_DATABASE_ID(optional) Named database; defaults to the project's (default).
DBBOARD_FIRESTORE_BASE_URL(optional) API root override; defaults to https://firestore.googleapis.com. This is where the emulator's address goes.

A service-account key is never sent over plain HTTP: an http:// base URL is refused outright when one is configured, and the client is built https_only so a redirect cannot route around it. The emulator is exempt because it issues no credential to leak.

sh
# The local emulator — no credential at all.DBBOARD_FIRESTORE_PROJECT_ID=demo-project \DBBOARD_FIRESTORE_BASE_URL=http://127.0.0.1:8080 \  pnpm tauri dev
# A real project. The key is a secret: keep it out of version control.DBBOARD_FIRESTORE_PROJECT_ID=my-project \DBBOARD_FIRESTORE_SERVICE_ACCOUNT="$(cat key.json)" \  pnpm tauri dev

Queries are Firestore StructuredQuery objects in JSON, not SQL — the sidebar's Select top 100 generates one for you:

json
{  "from": [{ "collectionId": "users" }],  "limit": 100}

MongoDB

VariablePurpose
DBBOARD_MONGODB_URIThe whole connection URI, mongodb://… or mongodb+srv://…. Selects the MongoDB backend. The password rides in the URI's authority, so treat the variable itself as the secret.
DBBOARD_MONGODB_DATABASE(optional) Database name. Omit it when the URI's path already names one.
sh
# A local server started with:#   docker run -d --rm -p 27017:27017 mongo:8DBBOARD_MONGODB_URI=mongodb://127.0.0.1:27017 DBBOARD_MONGODB_DATABASE=test   pnpm tauri dev

DBBOARD_SSH_* is refused on a MongoDB backend rather than ignored: a URI may list several hosts and mongodb+srv:// discovers a replica set from DNS, so a single-host forward would appear to work and then fail over to a member the tunnel does not front.

Queries are command documents in JSON, not SQL — the sidebar's Select top 100 generates one for you:

json
{ "find": "users", "limit": 100 }

Reads are the allowlist aggregate, count, distinct, find, listCollections and listIndexes; anything else, including a read carrying $out, $merge, $where, $function or $accumulator, is refused before it reaches the server.

CockroachDB / PostgreSQL

Set a single connection string to connect to CockroachDB or any generic PostgreSQL-wire database (vanilla Postgres, self-hosted) via the dbboard-postgres adapter:

VariablePurpose
DBBOARD_PG_URLFull connection string, e.g. postgresql://user:pass@host:26257/db?sslmode=verify-full

For CockroachDB Cloud, copy the connection string from the cluster's Connect dialog in the CockroachDB Cloud Console (Basic free tier works). For a self-hosted node started with cockroach start-single-node, use its postgresql://… string; the default SQL port is 26257. CockroachDB requires TLS, so keep sslmode=verify-full (or the mode your deployment expects).

sh
DBBOARD_PG_URL='postgresql://user:pass@host:26257/db?sslmode=verify-full' \  pnpm tauri dev

For Neon, Supabase, and AWS Aurora DSQL the same adapter is used but the connection is labelled distinctly at runtime ("neon", "supabase", "aurora-dsql" vs "postgres") so the picker and history records can tell them apart. Each flavor has its own env var, all of which outrank DBBOARD_PG_URL:

VariablePurpose
DBBOARD_NEON_URLNeon connection string. TLS required — sslmode=require (or stronger). See ADR-0018.
DBBOARD_SUPABASE_URLSupabase connection string. TLS required. Both the direct :5432 endpoint and the transaction-pooler :6543 endpoint work — the URL itself picks. See ADR-0019.
DBBOARD_AURORA_DSQL_URLAurora DSQL connection string. TLS required. The password segment must be a fresh short-lived IAM authentication token (~15 min TTL); an expired token surfaces as a connection error at startup. See ADR-0021.

All four pg-wire vars contain credentials — keep them out of version control (use .env, which is gitignored). The app never logs them.

sh
DBBOARD_NEON_URL='postgres://user:pass@ep-…neon.tech/db?sslmode=require' \  pnpm tauri dev
DBBOARD_SUPABASE_URL='postgres://user:pass@db.<ref>.supabase.co:5432/postgres?sslmode=require' \  pnpm tauri dev
# Aurora DSQL: the password segment is a short-lived IAM token.DBBOARD_AURORA_DSQL_URL='postgres://admin:<IAM-token>@<cluster>.dsql.<region>.on.aws:5432/postgres?sslmode=require' \  pnpm tauri dev

Because the Aurora DSQL IAM token expires in ~15 minutes, the env-var form above suits short sessions. For a long-lived / 24/7 connection use the aurora-dsql-iam connection kind instead, which stores AWS credentials in connections.toml + the OS keychain and lets dbboard mint the token itself. It is configured in the connection store, not via an env var — see docs/connections.md and ADR-0036.

AI integration (optional)

dbboard ships an optional AI panel that can explain SQL and suggest queries against the active connection's schema. The panel and the menu entry that toggles it are both hidden when no provider is configured — graceful degradation = absence (see ADR-0023 Decision 11).

When wired, the AI Assistant menu entry (top bar, between Connections and Language) opens a two-mode window: Explain SQL (paste SQL, get a natural-language walkthrough) and Suggest SQL (describe a question, get a SQL draft using the active connection's table list as context). Responses render inline; errors are surfaced with translated prefixes so a 429 or network failure does not look identical to a successful empty response. AI calls do not travel the dbboard-web HTTP contract — they go directly from the desktop binary's worker thread to the provider over reqwest.

Responses stream incrementally for providers that advertise the capability (both wired providers do — the Anthropic provider per ADR-0026, the OpenAI provider per ADR-0052). Text appears chunk by chunk as the model generates it, and a running Tokens: N in / M out meter updates from the cumulative usage chunks. While a request is in flight the Send button is replaced with Cancel: clicking it drops the in-flight stream (closing the HTTP connection so the server stops generating) while preserving any partial text already shown, and a quiet Cancelled. line marks the outcome. The same cancel button works on the atomic path used by providers without streaming support.

In Suggest mode, an Include column details checkbox appears when the active database adapter can describe tables (all three bundled adapters can — ADR-0028). Ticking it makes Send first fetch each table's columns and primary key from the live connection, then embed that schema in the prompt, which largely eliminates hallucinated column names in the drafts. The trade-off is prompt size: the full schema counts against the provider's context window and your token bill — watch the token meter, and leave the box off (its default, reset each session) for large schemas or metered keys. If some tables fail to describe, a warning shows the count and the suggestion proceeds with the rest.

Two providers are wired today — the Anthropic Messages API and the OpenAI Chat Completions API (ADR-0052, default model gpt-4o). Both are configured via either of two paths, evaluated in the order below; the first to resolve wins.

1. ai-providers.toml + OS keychain (recommended)

Add one or more entries to a per-user ai-providers.toml next to connections.toml (path: same OS config dir as the connection store) and the API key is held in the OS keychain — Windows Credential Manager, macOS Keychain, or Linux Secret Service — under dbboard.ai.<id>.api_key. The TOML file itself records the keyring reference, never the literal key.

The runtime store is the same one the Settings UI mutates (open it from the AI Providers menu, ADR-0025 slice b): adding an entry seeds the keychain, "Use" rebuilds the in-process provider and updates active_id atomically, and "Delete" tears down the entry and its secret together. A hand-edited TOML works too — useful for seeding a new machine without opening the window — provided the keyring_api_key_ref it names has a matching keychain entry:

The kind discriminator sits inline on each [[providers]] entry ("anthropic" or "openai"); model is optional and falls back to the provider's default when omitted:

toml
# ai-providers.tomlversion = 1active_id = "primary"
[[providers]]id = "primary"name = "Anthropic"kind = "anthropic"model = "claude-sonnet-5"             # optional; omitted = defaultkeyring_api_key_ref = "dbboard.ai.primary.api_key"
[[providers]]id = "gpt"name = "ChatGPT"kind = "openai"model = "gpt-4o"                      # optional; omitted = gpt-4okeyring_api_key_ref = "dbboard.ai.gpt.api_key"

The env-variable path below stays Anthropic-only; configure OpenAI through ai-providers.toml (or the AI Providers Settings window).

2. Environment variables (back-compat / CI)
VariablePurposeDefault
DBBOARD_ANTHROPIC_API_KEYAPI key from the Anthropic console. Sets the panel up without touching ai-providers.toml.(unset = fall through to TOML)
DBBOARD_ANTHROPIC_MODELModel identifier override.claude-sonnet-5

When DBBOARD_ANTHROPIC_API_KEY is set, it always wins over ai-providers.toml. This preserves the original Stage 1 wiring for headless / CI use and avoids surprising a user who already exports the env var. Unset it to let the TOML path take over:

sh
DBBOARD_ANTHROPIC_API_KEY='sk-ant-…' pnpm tauri dev

If neither path resolves a provider (or any branch fails — missing keyring entry, construction error), the binary logs to stderr and continues without AI; the panel and menu entry are hidden. The key never appears in Debug output or in history.jsonl; it is held only in memory for the process lifetime.

Every completed AI call (streamed or atomic, ok / error / cancelled) is recorded to history.jsonl as a kind: "ai" record alongside SQL history (schema v:2 per ADR-0027). The prompt and response are written verbatim — same stance as the SQL text in v:1 query records. The at-rest protection is the same too: 0o600 on Unix / user-only DACL on Windows, per ADR-0024. On a shared machine, be aware that anything typed into the AI panel — including schema-context in follow-ups and any secrets pasted into an Explain request — lands unredacted on disk under your user account.

Remaining deferred Stage 2 capability (full-DDL schema snapshots + function-calling — Group D) is tracked in ADR-0023 §9. Groups A / B / C are closed (ADR-0025 / ADR-0026 / ADR-0027).

MCP server

Besides being an AI client, dbboard also ships as a headless MCP server — dbboard-mcp — that hands the databases dbboard is already configured with to an external AI agent (Claude Desktop, Claude Code) as a small tool surface over stdio. It reuses the exact same connections.toml + OS keychain machinery as the GUI, so it adds no new place to keep credentials. See ADR-0046 and the crate README, crates/dbboard-mcp/README.md, for the full spec.

Twenty-two fixed tools. Seven read a database — list_connections, list_tables, describe_table, search_schema (ADR-0053), list_relationships (ADR-0054), run_read_query, and get_annotations (dbboard's local notes, ADR-0045) — plus run_write and dump_database (ADR-0087). Seven reach no database at all, and work the window instead: get_ui_locale / set_ui_locale change the app's display language (ADR-0107), capture_window returns a PNG of the running window (ADR-0108), and set_editor_sql / run_query / open_ai_panel / open_ai_settings drive it (ADR-0109) — so a claim about what the interface renders can be set up, performed and checked instead of asserted. Those seven act on a screen someone is sitting in front of; all but the two getters fail outright when dbboard is not running. Two reach nothing whatever. get_server_info names the build that is answering (ADR-0116), because this binary is installed by hand and a stale one is otherwise indistinguishable from a broken one; about describes the product itself — what it is for, which engines it speaks, and what each released version changed, with the changelog compiled into the build so the answer describes the binary that is replying (ADR-0154).

The last four work on the connection list itself, and none of them opens a database. add_connection registers a connection in connections.toml so a database an agent has just set up is usable without asking a person to retype its path — and only for the kinds that store nothing in the keychain, a local SQLite/libSQL file and the Firestore emulator (ADR-0134). Everything that needs a password, a token or a key is refused in the tool's own description, before the credential is sent rather than after. set_connection_mark and move_connection colour and reorder the list (ADR-0136), which is the wrong shape of work for a person doing it twenty times and the right shape for an agent doing it once. export_connections seals connections into an encrypted bundle for another machine, mints the passphrase itself and files it in this machine's keychain rather than returning it, and is refused entirely until a human has named a directory for the files in connections.toml (ADR-0140). The security posture is the reason it is safe to point an agent at:

  • Secrets never cross the wire. The only connection metadata serialized is { id, name, kind } — no URLs, tokens, or keyring references, and no error message embeds one.
  • Reading is engine-enforced read-only, not string-matched. Postgres-wire runs each statement inside BEGIN TRANSACTION READ ONLY, libSQL/Turso under PRAGMA query_only, and D1 classifies the AST — so UPDATE, DDL, multi-statement batches, and SELECT … FOR UPDATE all fail at the source.
  • Writing is off until a human turns it on, per connection (mcp_write in connections.toml, or Connections → Edit → AI agent access). Even then run_write only accepts an allowlisted statement (INSERT / UPDATE / DELETE / MERGE, CREATE TABLE / VIEW / INDEX / SCHEMA, ALTER TABLE) — classified on the AST, failing closed — and GRANT / REVOKE / DENY, user and role DDL, SET PASSWORD, TRUNCATE, and DROP of anything at all are refused whatever the flag says (ADR-0087).
  • Exporting is off until a human names a directory for it ([mcp_export] in connections.toml), and the passphrase for what it seals is generated by dbboard, filed in this machine's keychain, and never returned — a tool result is plaintext in an agent's transcript, so the bundle and its key must not travel together (ADR-0140).
  • Result sets are bounded. run_read_query clamps max_rows to a hard cap of 1000 (default 200) with a truncated flag.
  • stdout is sacred. JSON-RPC frames own stdout; all logging goes to stderr (RUST_LOG, default info).

Get it from the latest release — dbboard-mcp-windows-x86_64.exe, dbboard-mcp-windows-aarch64.exe (Windows on ARM) or dbboard-mcp-macos-universal. It is a single executable with no runtime dependencies.

On Windows, from v0.22.2 the desktop installer brings it along and puts it at %LOCALAPPDATA%\dbboard\dbboard-mcp.exe, so if dbboard is installed you can skip straight to registering it, and every upgrade replaces the server with the app (ADR-0169). Without the app, or on macOS, download it and put it somewhere stable, because the path goes into the agent's config:

powershell
# Windows (PowerShell)mkdir -Force "$env:LOCALAPPDATA\dbboard"Move-Item -Force ~\Downloads\dbboard-mcp-windows-x86_64.exe "$env:LOCALAPPDATA\dbboard\dbboard-mcp.exe"
sh
# macOSmkdir -p ~/.local/binmv ~/Downloads/dbboard-mcp-macos-universal ~/.local/bin/dbboard-mcpchmod +x ~/.local/bin/dbboard-mcpxattr -d com.apple.quarantine ~/.local/bin/dbboard-mcp   # Gatekeeper, unsigned build

Register it with Claude Code in one command — --scope user makes it available in every project on the machine:

sh
# macOS / Linuxclaude mcp add dbboard --scope user -- "$HOME/.local/bin/dbboard-mcp"
powershell
# Windows (PowerShell)claude mcp add dbboard --scope user -- "$env:LOCALAPPDATA/dbboard/dbboard-mcp.exe"

To build it yourself instead:

sh
cargo build --release -p dbboard-mcp# binary at target/release/dbboard-mcp(.exe)

Or with Claude Desktop, by adding the absolute path to the built binary in claude_desktop_config.json (%APPDATA%\Claude\claude_desktop_config.json on Windows, ~/Library/Application Support/Claude/claude_desktop_config.json on macOS):

jsonc
{  "mcpServers": {    "dbboard": {      "command": "C:\\path\\to\\dbboard-mcp.exe"    }  }}

Either way, restart the agent afterwards. Each client spawns its own dbboard-mcp process and holds it for the session, so an already-running agent keeps talking to the old one — and restarting the dbboard desktop app does nothing to it, because they are separate processes.

With no arguments it reads the same per-user connections.toml the GUI uses; pass --config (or set DBBOARD_CONFIG) to point at a curated, least-privilege subset instead. That is the only thing the environment decides: a tool call names a connection_id, and the server resolves it against the store file and the keychain, so a connection the store does not describe cannot be reached. Full configuration — the per-OS config paths, running several agents at once, TLS behind a corporate proxy, and the literal error strings a failed connection produces — is documented in crates/dbboard-mcp/README.md.

To point an agent working in a different repository at dbboard, copy the block in docs/agent-onboarding.md into that repository's CLAUDE.md / AGENTS.md. An agent does not go looking for tools it has not been told about — one that searched the web for dbboard concluded it was "not a publicly available tool".

A walkthrough in Japanese, from downloading the binary to the first refused DROP, is on Zenn: Claude Code に自分の DB を触らせる.

Development

Before committing, the pre-commit hook runs:

sh
cargo fmt --all -- --checkcargo clippy --all-targets --all-features -- -D warningscargo check --all-targets --all-featurescargo test --all-features

Before pushing, the pre-push hook also runs:

sh
cargo build --releasecargo test --all-features --release

Pure deletion pushes (git push --delete <branch>) skip the build/test cycle — there is no working tree to validate.

You can run these manually at any time.

Security checks

dbboard creates connections.toml and history.jsonl under your per-user config dir (DBBOARD_CONFIG_DIR=<path> replaces it — every file dbboard owns moves together, which is how you start it with an empty profile for a demo or a screenshot; see docs/connections.md). On Unix both land as mode 0o600; on Windows they inherit the user-only DACL of %APPDATA%\Roaming\<user>\. If the resolved config dir lives under a cloud-sync vendor folder (OneDrive Known Folder Move, iCloud Drive, Dropbox, Google Drive), the binary emits one stderr warning at startup naming the vendor. The single most effective hardening on a lost laptop is full-disk encryption — enable BitLocker / FileVault / dm-crypt. See docs/connections.md § File permissions and ADR-0024 for the full posture.

cargo-deny gates the dependency graph on advisories, licenses, duplicate versions, and unknown sources. Configuration lives in deny.toml.

sh
cargo install --locked cargo-deny    # one-time, ~5 min buildcargo deny check                     # advisories + licenses + bans + sources

CI does not run this yet; run it locally when adding or upgrading a dependency. New license expressions surfaced by the check go into deny.toml's licenses.allow list with a one-line rationale.

Packaging & distribution

Windows and macOS bundles are produced by the Tauri CLI from apps/desktop. Linux is not built today.

Note on trust. The artifacts are not code-signed, and that is a decision, not a gap waiting to be filled (ADR-0106): Windows SmartScreen and macOS Gatekeeper will warn about an unknown publisher on every release. Verify a download against the published SHA256SUMS.txt (see Release builds & checksums) — that, not the OS warning, is what tells you the file is the one this repo built. This is separate from the updater signing key, which is already in use and is what proves an auto-update came from this project (ADR-0067).

Building a bundle locally

sh
cd apps/desktoppnpm install          # first time onlypnpm tauri build

The bundles land under target/release/bundle/ — the workspace shares one target directory, so they are at the repository root and not beside the crate that produced them. They are named after productName, which is dbboard; the cargo package is still dbboard-desktop, and releases v0.5.0 through v0.14.0 carry that spelling in their filenames:

PlatformArtifactBuilt on
Windows x64nsis/dbboard_<version>_x64-setup.exeWindows x64
Windows ARM64nsis/dbboard_<version>_arm64-setup.exeWindows ARM64 (built natively, not cross-compiled; ADR-0164)
macOSdmg/dbboard_<version>_universal.dmgmacOS (a .dmg cannot be produced from Windows)

App identity — bundle identifier, icons, window defaults, updater endpoint — lives in apps/desktop/src-tauri/tauri.conf.json; the icons are generated from assets/ (see DESIGN.md).

Because the frontend is a static SPA, pnpm tauri build runs the Vite build first; a stale apps/desktop/build/ is never what ships.

Release builds & checksums

Pushing a v*.*.* tag runs .github/workflows/release.yml, which builds the Windows and macOS bundles on their native runners and attaches them to the matching GitHub Release together with a combined SHA256SUMS.txt and the signed latest.json the in-app updater reads. A manual workflow_dispatch run builds the same artifacts as a smoke test without publishing. The download page then serves whatever the newest release holds — it reads the Releases API at load, so it needs no separate deploy. Verify a download:

sh
sha256sum -c SHA256SUMS.txt        # Linux/macOS# or on Windows PowerShell:#   (Get-FileHash .\dbboard_<version>_x64-setup.exe -Algorithm SHA256).Hash

Handing a build to someone

Three role-specific guides cover the actual handoff:

Connections and their secrets move between machines as a single passphrase-encrypted .dbbx bundle (Export / Import in the connection window, ADR-0038); the passphrase always travels on a separate channel.

Contributing

This project follows the rules in CLAUDE.md. In short:

  1. Write a failing test before changing behaviour.
  2. Keep changes small and focused.
  3. Use conventional-style commit messages in English.
  4. Record non-trivial decisions in docs/decisions.md.

License

See LICENSE.

來源:README.md,提交 b501e62

工具

0
SourceWeft 尚未在沙箱中啟動過該軟體包,因此其工具未知。

版本歷史

3
  1. v0.22.2最新Nov 6, 2026
  2. v0.22.1Nov 5, 2026
  3. v0.22.0Nov 4, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分