Quarry
Allows querying and managing MariaDB databases with support for read-only mode, safety rails, and structured results.
Allows querying and managing MySQL databases with support for read-only mode, safety rails, and structured results.
Allows querying and managing AWS Neptune graph databases with support for read-only mode, safety rails, and structured results.
Allows querying and managing PostgreSQL databases with support for read-only mode, safety rails, and structured results.
Allows querying and managing Redis databases with support for read-only mode, safety rails, and structured results.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Quarrylist my connections"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Quarry
The database workbench built for the AI era — one kernel, many faces (CLI / GUI / MCP / agent skill).
Every database tool you know — DBeaver, TablePlus, pgAdmin — assumes a human at the keyboard. But increasingly, the entity running your queries is an AI agent, and agents need different guarantees:
Results a machine can parse, not a screen a human can read
Safety rails that live in the kernel, so no client can forget them
Deterministic error contracts (stable exit codes), not stack traces to scrape
Configuration as files, not clicks — so it can be versioned, diffed, and shared with agents
Quarry inverts the traditional design: it is a query kernel with an agent-safe contract first, and the human faces (CLI, GUI) are thin shells grown from the same kernel. Whether a query comes from a person in the browser, a script in CI, or Claude running a skill, it passes through the exact same safety rails and returns the exact same structured result.
Philosophy
One core, many faces. Connection management, query execution, schema introspection, and safety rails live in an importable kernel (
quarry.core). The CLI (qy), the GUI, the MCP server, and agent skills are thin shells. Fix a bug once, every face gets it.Read-only by default; escalation is explicit and graduated. Writes and DDL are blocked (exit code
8) unless you pass--write. Production connections require an additional confirmation on top of--write. Every query gets an automaticLIMIT 500unless you opt out. Because the rails are in the kernel, an agent cannot bypass them by picking a different entry point.A contract machines can trust. Every query returns
{columns, rows, rowCount, truncated, elapsedMs, engine, sql}. Exit codes are stable API:0ok,2connection error,3SQL error,8safety block. An agent can branch on outcomes without parsing prose.Workspace as code. A workspace is just a directory:
connections.toml+queries/**/*.sql(named queries with-- @metaheaders). It lives in your repo, versioned by git, shared between teammates and agents alike. The kernel itself carries zero business logic and zero secrets.Nearly zero dependencies. Pure stdlib. PostgreSQL goes through your system
psql, Redis throughredis-cli, SSH tunnels through systemssh. MySQL is one optionalpymysql. No Electron, no daemon, no cloud.
Related MCP server: sqlite-mcp
Install
pipx install quarry-db # or: pip install quarry-db
qy --helpPostgreSQL uses the system psql binary; MySQL needs pip install "quarry-db[mysql]".
Quickstart
mkdir my-workspace && cd my-workspace
cat > connections.toml <<'EOF'
[shop]
url = "postgresql://user:pass@localhost:5432/shop"
engine = "postgres"
env = "dev"
EOF
qy connections # list connections
qy exec shop --sql "select * from customers"
qy schema shop customers # table structure (\d+)
qy gui # browser data gridWorkspace
A workspace directory is the source of connections + queries:
my-workspace/
├── connections.toml # [key] url / engine / env / group / notes
└── queries/<db>/*.sql # named queries (with -- @meta headers)Resolution order: --workspace PATH → ~/.config/quarry/config.toml → current directory.
CLI reference
Command | Purpose |
| Manage connections |
| Reachability probe (ok/fail + latency; exit 1 if any fail) |
| Run ad-hoc SQL |
| Benchmark the current PostgreSQL/MySQL tunnel path |
| Live table structure |
| Run a saved named query |
| Save a named query |
| Manage named queries |
| Manage aggregated workspaces |
| Workspace tunnel keep-alive keeper |
| Local dev containers (see below) |
| Launch the local GUI |
| Serve the MCP face over stdio (for AI agents) |
MCP (the agent-native face)
qy mcp speaks the Model Context Protocol over stdio — pure stdlib, no SDK dependency. Agents get six tools (list_connections, list_tables, describe_table, exec_sql, list_saved_queries, run_saved_query) with the exact same kernel rails: read-only unless the server was started with --write and the call passes write: true; a prod env additionally requires confirm_prod: true.
# Claude Code
claude mcp add quarry -- qy mcp --workspace ~/my-workspace// or any MCP client (.mcp.json)
{ "mcpServers": { "quarry": { "command": "qy", "args": ["mcp", "--workspace", "/path/to/workspace"] } } }Published in the MCP Registry as mcp-name: io.github.Wangggym/quarry.
Safety rails (the AI-native moat)
Read-only by default: writes/DDL blocked with exit code
8;--writeto allowAutomatic row cap:
run_query()injectsLIMIT 500; raise with--max-rows NGraduated prod protection: all envs default read-only → dev needs
--write→ prod needs--writeplus an interactive confirmation (--yesfor automation)Stable exit-code contract:
0ok /2connection /3SQL /8safety block
Timeouts
Query execution and connection establishment (including SSH tunnel setup) are capped independently, so an unreachable host fails fast instead of eating the whole query budget:
Connect timeout: 15s, fixed — bounds tunnel/dial only.
Execute timeout: 300s default for the CLI/GUI, 120s for MCP (agents should converge faster).
The effective execute timeout is resolved in priority order:
--timeout N(CLI, onqy exec/qy run)QUARRY_TIMEOUTenv varthe connection's
timeoutfield inconnections.toml(set viaqy connections add/set --timeout N)the default above
[shop_prod]
url = "postgresql://…prod…/shop"
timeout = 600 # this connection alone gets 10 minutesOn PostgreSQL, qy also sets a server-side statement_timeout (~90% of the execute timeout) before running the query; on MySQL/MariaDB it sets the equivalent session variable (MAX_EXECUTION_TIME / max_statement_time, whichever the server supports) best-effort. Either way, the database itself cancels a runaway query and reports the real reason — instead of the client giving up and leaving the query running server-side. A timeout error always tells you how to raise it (--timeout, QUARRY_TIMEOUT, or the connection's timeout setting). --timeout and the timeout field must be a positive number of seconds.
As a library (what the GUI and agents use)
from quarry import configure_workspace, get_connection, run_query
configure_workspace("~/my-workspace")
res = run_query(get_connection("shop"), "select * from customers")
print(res.to_dict()) # {columns, rows, rowCount, truncated, elapsedMs, engine, sql}SSH tunnels
For databases only reachable via a bastion, add ssh_* fields and qy opens the tunnel automatically (system ssh, zero dependencies):
[internal_db]
url = "postgresql://user:pass@127.0.0.1:5432/appdb"
engine = "postgres"
ssh_host = "bastion.example.com"
ssh_user = "ubuntu"
ssh_key = "~/.ssh/id_ed25519"Neptune participates in the same tunnel path now: if a Neptune connection has
ssh_host (plus optional ssh_user/ssh_key/ssh_port), it joins tunnel
pooling/keep-alive the same way as Postgres/MySQL/Redis.
Workspace keep-alive (qy up/down/status)
If you query the same SSH-backed connections repeatedly (CLI + GUI + MCP), run the workspace keeper once and reuse warm forwards across processes:
qy up # start keeper for current workspace (also turns keep-alive on)
qy status # text status: keeper + per-connection tunnel state
qy status --format json # machine-readable state (up/reconnecting/down)
qy down # stop keeperkeep_alive=true + reconnect=true are persisted per workspace in
~/.config/quarry/config.toml. When reconnect is enabled, dropped tunnels are
re-opened with exponential backoff and reported as reconnecting in both qy status and the GUI header badge. If keep-alive is enabled but the keeper is
down, cold qy exec/qy run still work (legacy behavior) and print a one-line
hint to stderr suggesting qy up.
Proxy (for throttled tunnels)
If an SSH tunnel's throughput is throttled (a cross-border bastion, for example — the handshake connects fine but data crawls), route it through your machine's HTTP(S) proxy instead:
qy proxy # show the discovered proxy + each workspace's toggle state
qy proxy on # enable for the current workspace
qy proxy off # disable it again
qy exec mydb --no-proxy --sql "..." # skip the proxy for one call, even if enabledThe proxy is auto-discovered — macOS system proxy settings first (scutil --proxy), falling back to ALL_PROXY/HTTPS_PROXY — and the toggle is persisted per workspace in config.toml (never connections.toml). It only affects connections with ssh_host (tunneled via ProxyCommand) and Neptune's direct HTTPS requests; a direct (non-tunneled) DB connection is unaffected, and qy connections add/set warns if you enable the proxy for a connection with no ssh_host. If the proxy is enabled but nothing is listening on its port, qy falls back to a direct connection instead of erroring; targets covered by the system proxy's exceptions list (loopback, private CIDR ranges) are never proxied.
Confirming the proxy is actually in effect
Because the fallback-to-direct behavior above is silent by design (a query still has to run), it's worth knowing how to check whether a given call actually went through the proxy:
qyoutput: if a workspace has the proxy enabled but a call still ran direct,qy exec/qy runprint a one-line reason to stderr — no proxy discovered, discovered but nothing listening on its port, or the target is covered by the proxy's exceptions list.--no-proxysuppresses this (you asked for direct, so there's nothing to report).qy proxy: besides the discovered proxy and each workspace's toggle, it lists every pooled SSH tunnel — ssh target, local port, whether it's actually routed through the proxy (and which address), and whether the underlyingsshprocess is still alive. Add--format jsonfor atunnelsarray with the same fields, handy for scripting.GUI: an env pill in the sidebar shows a small badge when that connection's tunnel is routed through the proxy; the workspace manager shows each workspace's proxy toggle alongside the currently discovered proxy address. Both are computed server-side from the same logic
qyuses, not guessed in the browser.
Redis
engine = "redis" (uses system redis-cli). Queries are redis commands:
qy exec cache --sql "SCAN 0 COUNT 100"
qy exec cache --sql "HGETALL user:42"Read-only rail applies here too: GET/SCAN/TYPE/TTL/HGETALL pass; SET/DEL/FLUSHALL are blocked without --write. In the GUI, redis keys are clickable with TYPE-aware value display.
Groups & env-sets
Connections can be organized into project folders (group) and env-sets (same db, different env, shared schema):
[shop_dev]
url = "postgresql://…dev…/shop"; group = "shop"; db = "shop"; env = "dev"
[shop_prod]
url = "postgresql://…prod…/shop"; group = "shop"; db = "shop"; env = "prod"Connections with the same
dbfold into one env-set — one saved query runs against any environment:qy exec shop --env prodUnspecified env defaults to
dev(the safest)The GUI shows an environment switcher (prod turns red)
Multiple workspaces
qy aggregates all workspaces listed in ~/.config/quarry/config.toml — one GUI/CLI over all your projects:
qy workspace add ~/projects/acme/db-workspace
qy workspace add ~/projects/side-project/db
qy connections # both projects, grouped
qy gui # sidebar shows both groups side by side--workspace a:b (os.pathsep-separated) works as a temporary override; the first directory is primary for writes.
Local dev containers
When a locally-running service shares a remote (dev) database, every read/write
crosses the public network — and a test/e2e run that hammers the DB gets flaky
on the round trips. qy local runs Postgres/Redis in a docker container so the
service talks only to localhost:
qy local up shop # start local Postgres + register a shop `local` connection
qy connections # shop now shows a [local] env alongside [dev]
qy run active_customers --env local
qy local status # running? which port / image?
qy local sync shop # copy dev schema into local (staging db + rename swap)
qy local down # stop, keep the data volume (data survives)
qy local down --purge # stop + delete the volume (next up is an empty DB)One shared Postgres container hosts a logical database per connection key (fixed
port 5433; redis 6380), and data lives on a named docker volume. Requires a
docker daemon; the image tag is overridable with --image.
GUI

qy gui — a local, zero-build web GUI (Slate & Copper theme, light/dark):
Grouped sidebar tree with env switcher (prod turns red), connection health dots
Multi-tab editor — each tab remembers its SQL + connection, across restarts
SQL highlighting + local autocomplete (keywords / tables / columns)
EXPLAIN button — one click to the query plan
Type-aware data grid: sorting, column resize, keyboard navigation (arrows + Enter), cell inspection with a collapsible JSON tree
CSV/JSON export, searchable query history (with connection + time)
TYPE-aware Redis key browsing
Update check — a background thread polls PyPI once every 24h and shows a header badge (with the upgrade command + release notes) when a newer
quarry-dbis out. Editable/dev installs are skipped automatically; setQUARRY_UPDATE_CHECK=0to disable it entirely.
Roadmap
Column types in the result contract for all engines
SQLite & DuckDB engines (zero-setup local demo)
Redis key-namespace folding tree
Cross-environment schema/data diff
Write audit log (who ran what, where, when)
Single-binary distribution
Development & testing
pip install -e ".[dev]"
createdb quarry_test && psql quarry_test -f tests/seed.sql # or: make seed
make test # layered run with a per-layer PASS/FAIL summary723 tests in four layers, each auto-classified so you can run any slice:
Layer | Count | Covers | Needs |
| 568 | pure logic + mocked engines (safety rails, SQL skeleton, params, formatters, cache) | nothing |
| 110 | in-process against a real DB, incl. the GUI HTTP API and CLI/MCP dispatch | Postgres |
| 45 | the real | Postgres |
| 20 | the real GUI frontend driven in headless Chromium (Playwright) | Postgres + Playwright |
DB/engine-backed tests skip automatically when the engine is unreachable, so the suite stays green on a bare machine; CI provides the engines and runs everything.
Coverage is gated at ≥95% (unit + integration) and currently sits at 99.6%.
Seeing test status at a glance
On GitHub: the CI badge above is live — it goes red if any layer or the coverage gate fails. Per-commit and per-PR results show under the Actions tab and as PR checks.
Locally, pass/fail:
make testprints a colored per-layer summary; run one layer withmake test-unit/test-integration/test-e2e/test-browser.Locally, coverage:
make covenforces the gate and writes an HTML report — openhtmlcov/index.htmlfor a line-by-line view of exactly what's covered.
See TESTING.md for the full architecture, fixtures, and CI layout, and CONTRIBUTING.md for contribution guidelines.
Quarry is developed and tested on macOS and Linux. Windows is currently untested (the psql/ssh integration and port takeover are Unix-flavored) — PRs welcome.
License
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Flicense-qualityDmaintenanceAn MCP server that enables AI assistants to query and interact with SQLite databases through natural language. It includes built-in security guardrails such as PII redaction, SQL injection blocking, and query rate limiting.Last updated
- Alicense-qualityCmaintenanceAn MCP server that enables AI agents to interact with SQLite databases by querying schemas, executing SQL, and inspecting table metadata. It supports safe database access through configurable read-only modes, query timeouts, and dry-run execution plans.Last updatedMIT
- AlicenseAqualityAmaintenanceAn MCP server that gives AI agents access to configured databases (PostgreSQL, MySQL, Redshift, SQL Server) with SSH/AWS SSM tunnels, pluggable secret providers, and strict per-instance isolation.Last updated10MIT
- Alicense-qualityBmaintenanceOctoQuery is an MCP server that converts databases into AI-accessible tools by exposing each configured database as a tool that accepts SQL queries and returns JSON results, enabling AI agents to query your data directly.Last updated2MIT
Related MCP Connectors
GibsonAI MCP server: manage your databases with natural language
Analytical memory for AI agents: a real Postgres queried in plain English over MCP. One command.
Driflyte MCP server which lets AI assistants query topic-specific knowledge from web and GitHub.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/yiminspace/quarry'
If you have feedback or need assistance with the MCP directory API, please join our Discord server