dolt-mcp-vcs
Intent Solutions is a Claude Partner Network Select Services Partner.
One plugin for every make and model of Dolt. Point it at any workspace and it answers the
first question that matters — what kind of Dolt database am I working with? — then does the
work: version-control verbs (branch / merge / diff / log / AS OF / data-PR awareness) over
the dolthub/dolt-mcp server, with a verb-class
mutation gate that keeps destructive operations recommend-only.
Formerly
beads-dolt— same plugin, renamed to its Dolt-first identity. The rename is non-breaking: the GitHub repo URL redirects, thebeads-doltmarketplace install slug still resolves (a deprecated catalog alias), and/beads-doltis still an accepted trigger. The beads (bd) task tracker ships as use-case adapter #1.
Why this exists
The Dolt ecosystem is no longer one product. There is classic Dolt (MySQL wire, GA),
Doltgres (Postgres wire), DoltLite (an embeddable SQLite fork with a prolly-tree
engine, alpha), and DumboDB (a Mongo-wire experiment on Dolt's storage engine) — and a
single machine routinely hosts several modes of the same flavor at once: classic .dolt/
repos, live dolt sql-server processes (which bind ephemeral ports that differ from
config.yaml), and embedded single-writer stores owned by another tool. Every existing
integration assumes you already know which of these you have and hand-writes the connection
config to match.
This plugin removes that assumption. Detection is Step 0: a stdlib-only detector
(scripts/dolt-detect.py) probes the directory layout, the process table (reading the
actual bound port from /proc, never a config file), file headers, and the wire — and
returns ranked findings, each one a ready-to-use connection descriptor. What it cannot
confirm it reports as unconfirmed; what it does not find it names as "not a Dolt database"
with the list of what was checked. Nothing is guessed.
The detection contract
Mixed layouts (a workspace with both .beads/dolt/ and .beads/embeddeddolt/ — migrated
state) return both findings, ranked live-server > repo > embedded > file. A plain-SQLite
runtime file paired with a dolt/ system-of-record sidecar (the DoltLite-shaped pattern) is
recorded as evidence on the repo finding.
Detection output is a connection descriptor (flavor/mode/endpoint/database/
creds-ref/maturity), so it composes with everything downstream with zero hand-written
config:
python3 scripts/dolt-detect.py # what am I looking at? (read-only)
python3 scripts/dolt-detect.py --json # machine-readable findings + evidence
python3 scripts/dolt-detect.py --emit-descriptor # write connection.descriptor.json
python3 scripts/dolt-mcp-client.py \
--descriptor connection.descriptor.json list_databases # connect — flavor honored
What's in the plugin
- A skill (
/dolt-mcp-vcs, also/beads-dolt) — Step 0 detection, then routed work: DoltHub visibility diagnosis (the near-universal cause is no remote configured), thebd dolt remote add+ push fix, the JSONL throttle/export model, and dispatch to the agents below. - Expert agents — grounded in a live-fetched (never frozen) reference of Dolt internals
(
references/dolt-internals.md):dolt-sync-advisor— DoltHub remotes,bd dolt push/pull, backup vs push, federation, drift.bead-epic-auditor— subtree/epic-closure audits (which epics have all children closed).bead-dependency-mapper— dependency graphs, cycles, critical path (SQL via the Dolt MCP).bead-recovery-specialist— rapid-write-race recovery, embedded↔server mode migration, dolt-server incidents.beads-guru— general bd/Dolt expertise and the three-layer mirror discipline.
- A wired Dolt MCP server (
.mcp.json) — the officialdolthub/dolt-mcpserver (a ~40-tool version-control surface — fetch the exact list live, never freeze it), least-privilege wired. - The safety layer —
scripts/dolt-mcp-guard.py, the plugin's MCP entrypoint: a stdio proxy that wrapsdolt-mcp-serverand enforces the mutation posture ON the wire. Destructive tools (push / pull / both merges /reset --hard/ branch-delete /DROP DATABASE) are refused before they reach the server and filtered out oftools/list; everyquery/execpasses the verb-class statement classifier (scripts/sql_classifier.py); safe-write SQL throughexecadditionally requiresDOLT_MCP_ALLOW_MUTATION=1. (Until 2026-08-19 this posture was enforced only on thedolt-mcp-client.pypath — a baredolt-mcp-serverregistration exposed the destructive verbs ungated. Register through the guard; see § Wire the MCP server.)
Declared mutation posture
- Reads execute freely.
- Safe writes (INSERT/UPDATE/DELETE …) require an explicit
--allow-mutation, a non-mainagent branch, and a GA/beta flavor maturity. - History-affecting statements (push / merge /
reset --hard/ branch-delete /DROP DATABASE/ unknownCALL) are always refused — recommend-only. Enforced at BOTH boundaries: the client path (dolt-mcp-client.py) and the MCP wire itself (dolt-mcp-guard.py); proven bytests/test_dolt_mcp_guard.py, which drives the guard over real JSON-RPC. - Pre-GA flavors (
doltlitealpha,dumboexperimental) are held read-only by the maturity gate and have no wired connection (fail-closed descriptor stubs, decision 6). - Embedded stores are never written — the single-writer lock belongs to the embedding tool.
- The detector itself is read-only: it never starts, stops, or writes to any database.
Indirect SQL execution
The stateless SQL gate refuses PREPARE, EXECUTE, and EXPLAIN with an
ANALYZE/ANALYSE option, through both the client and native MCP registration.
Mutation opt-in does not enable these forms: a prepared name can hide a write
or history operation, and an executing plan runs its subject. Use direct SQL
subject to the existing mutation gate, or plain EXPLAIN for a non-executing
plan. Executing-plan option lists are conservatively refused even when they
say ANALYZE FALSE; the gate does not interpret dialect-specific option values.
Executable SQL comments (/*! ... */ and /*M! ... */) outside quoted data
are also refused, rather than being stripped into an apparently empty read.
Ordinary comments and comment-like text inside quoted values remain supported.
Statement splitting honors backslash and doubled-quote escapes. Double-dash
comments follow MySQL's whitespace/control requirement so arithmetic such as
1--2 cannot hide the next statement.
This is a bounded statement-classification rule, not a general SQL parser or a
replacement for database permissions. It does not certify all SQL effects.
The semantics are documented by Dolt's supported statements,
MySQL prepared statements,
and PostgreSQL EXPLAIN.
See also MySQL executable-comment semantics.
tests/test_sql_classifier.py checks the refusal matrix;
tests/test_mcp_registration.py proves refused calls never reach its inert peer.
Install
Any consumer, no estate-specific assumptions:
- The plugin — install
dolt-mcp-vcsfrom the marketplace (thebeads-doltslug still resolves), or clone this repo into your plugins directory. - The MCP server binary (needed for wire work only — detection and CLI-verb work run
without it), pinned — never
@latest:
Pinned modulego install github.com/dolthub/dolt-mcp/mcp/cmd/[email protected] # native (Go) # or docker pull dolthub/dolt-mcp:v0.3.6 # container # or grab the v0.3.6 release binary from https://github.com/dolthub/dolt-mcp/releasesgithub.com/dolthub/dolt-mcp v0.3.6verifies against the Go checksum database ash1:uwjh1zf0er51VBT6uY3tI7JLj5pYxWyk9uB6CYQOhfU=. A version bump is proposed by thedolt-watchroutine and reviewed — never auto-trusted. - Wire the MCP server THROUGH THE GUARD — never register the bare binary (that
exposes drop_database/reset-hard/push as ungated live tools):
"dolt-mcp-vcs": { "command": "python3", "args": ["<plugin>/scripts/dolt-mcp-guard.py", "--", "dolt-mcp-server", "--stdio", "--dolt", "--host", "127.0.0.1", "--port", "3308", "--user", "root", "--database", "beads"] } - Detect —
python3 scripts/dolt-detect.py(stdlib-only; no other dependency). - For the beads adapter:
bd≥ 1.0.4 with a Dolt-backed workspace.
Configuration
Zero config is the default path: dolt-detect.py --emit-descriptor writes
connection.descriptor.json and every downstream tool honors it. Environment overrides
remain available:
Authentication
DoltHub pushes authenticate with a dolt creds keypair (dolt login), or
DOLT_REMOTE_USER/DOLT_REMOTE_PASSWORD. The MCP connection uses DOLT_USER/DOLT_PASSWORD
(bd's local server is unauthenticated by default — user root, empty password).
Built on
- Dolt / DoltHub — the
version-controlled SQL database family: Doltgres,
DoltLite, DumboDB. The MCP server is
dolthub/dolt-mcp. - beads — the
bdtask tracker (use-case adapter #1).
How it was evaluated
This plugin was run end-to-end through the Intent Eval Platform — deterministic gates → behavioral eval (real model) → kernel-validated Evidence Bundle → ship/no-ship decision. The full evidence and the ship/no-ship decision are recorded in DOGFOOD.md; the methodology write-up is the platform's case study. (The eval even surfaced — and we fixed — a bug in the platform's own evidence emitter.)
License
Apache-2.0. See LICENSE.
Idle reaper safety
Version 0.2.1 checks user databases named dolt and refuses failed or malformed
MCP responses. Encoded schema discovery prevents embedded newlines from hiding
databases behind apparently clean rows. Positive bd ownership is required before
queries; unrelated/Freshie processes remain untouched. The reaper verifies the candidate PID owns the loopback listener,
queries main explicitly, and rechecks process identity and activity before
SIGTERM. Deploy scripts/reaper_endpoint.py beside scripts/dolt-idle-reaper.sh;
a missing helper keeps the server alive. The pinned MCP dependency is unchanged.
Use automatic reaping only for bd-managed servers whose work lives on main,
whose account sees all databases. Encoded identifiers outside the supported
single-line ASCII set conservatively retain the server. Other branches, hidden
databases, and a concurrent write after the final check are outside this
observation protocol. This is not an atomic shutdown guarantee.
The complete safety contract and hermetic validation procedure
record the formatter provenance and refusal cases. Roll back by disabling the
reaper schedule first, then restoring a reviewed prior revision; keep scheduling
disabled while that revision contains the skip-dolt defect. No cron or live
process is changed by installing this patch.