db-cli · diff

git:20260925.4315506 to git:20260925.7787f92

19 added, 32 removed. Audit A to A.

---
name: db-cli
description: Query the petclinic Postgres database (owners, pets, vets, visits, types, specialties) by calling the project's Postgres MCP server as a shell command. Use whenever a task needs to read or inspect petclinic data or schema AND no database MCP tools are available (no mcp__postgres-db__* tools). Also use when explicitly asked to "use the db-cli skill".
- allowed-tools: Bash(.claude/skills/db-cli/db-cli.sh:*), Bash(mcptools:*), Bash(jq:*)
+ allowed-tools: Bash(.claude/skills/db-cli/db-cli.py:*), Bash(jq:*)
---
# Database access when MCP servers are disabled
The `postgres-db` MCP server declared in `.mcp.json` is not connected in this
- session. The **same server** is still reachable from the shell through
- [`mcptools`](https://github.com/f/mcptools), an MCP-to-CLI bridge. Same tools,
- same parameters, same JSON responses — only the transport differs, and nothing
- about the server changes once MCP access is restored.
+ session. The **same server** is still reachable from the shell: `db-cli.py` starts
+ it and speaks MCP to it over stdio (stdlib-only Python, needs just `python3` and
+ `npx`). Same tools, same parameters, same JSON responses — only the transport
+ differs, and nothing about the server changes once MCP access is restored.
Run everything below from the repo root.
## 1. Discover what the server offers
```bash
- .claude/skills/db-cli/db-cli.sh tools
+ .claude/skills/db-cli/db-cli.py tools
```
Prints every tool with its parameter signature and description — the same
information an MCP client would put in your tool list. Run this first if you
are unsure what is available.
## 2. Call a tool
```bash
- .claude/skills/db-cli/db-cli.sh call <tool_name> --params '<json>'
+ .claude/skills/db-cli/db-cli.py call <tool_name> --params '<json>'
```
The two tools this server exposes:
```bash
# run SQL
- .claude/skills/db-cli/db-cli.sh call execute_sql \
+ .claude/skills/db-cli/db-cli.py call execute_sql \
--params '{"sql":"select count(*) from owners"}'
# explore the schema without guessing table names
- .claude/skills/db-cli/db-cli.sh call search_objects \
+ .claude/skills/db-cli/db-cli.py call search_objects \
--params '{"object_type":"table"}'
```
## 3. Keep the output small
The JSON envelope is verbose. Take only the rows:
```bash
- .claude/skills/db-cli/db-cli.sh call execute_sql \
+ .claude/skills/db-cli/db-cli.py call execute_sql \
--params '{"sql":"select name from types"}' | jq -c '.data.statements[0].rows'
```
- ## What the wrapper actually runs
-
- There is nothing magic in it — this is the underlying call, and you can run it
- directly if you prefer:
-
- ```bash
- mcptools call execute_sql --params '{"sql":"select 1"}' \
- npx -y @bytebase/dbhub@1.2.0 --transport stdio \
- --dsn postgres://petclinic:petclinic@localhost:5432/petclinic
- ```
+ ## When it fails
- The wrapper exists only to survive a hostile environment, and every line of it
- earns its place from a failure that actually happened:
+ The script prints dbhub's own stderr, so read that first. Two causes have bitten
+ before, and the script already handles both:
- - `mcptools` lives in `~/go/bin` and `npx` under `nvm` — **neither is on a
- non-interactive agent shell's PATH**, because that shell never sources
- `~/.zshrc`. When mcptools cannot spawn `npx`, the MCP handshake never
- completes and it fails as `Error: initialization timed out`, which looks like
- a broken server rather than a broken PATH.
- - On a machine that has never run this version, `npx` **downloads** the package
- on first use, which takes longer than mcptools' ~10s init timeout — the
- identical misleading error, with nothing wrong at all.
+ - `npx` lives under `nvm`, which is **not on a non-interactive agent shell's
+ PATH** (that shell never sources `~/.zshrc`). The script looks in
+ `~/.nvm/versions/node/*/bin` itself.
+ - On a machine that has never run this dbhub version, `npx` **downloads** it on
+ first use. The script waits up to 120s (`DB_CLI_TIMEOUT`) for the first answer.
- If you hit `initialization timed out`, it is almost certainly one of those two.
- Do not reinstall `mcptools`; check `command -v npx` first.
+ `ECONNREFUSED` in the output means Postgres is not running: `./start-database.sh`.
## Schema cheat-sheet
`owners`, `pets` (`type_id` → `types`, `owner_id` → `owners`), `visits`
(`pet_id`), `vets`, `specialties`, `vet_specialties`, `users`, `roles`.
Full model: see the ER model section in `AGENTS.md`.
## Rules
- **Read-only.** No INSERT / UPDATE / DELETE / DDL unless explicitly asked.
- Prefer one aggregated SQL query over several small ones — each call pays a
~2s server startup.
- An empty database is usually not a bug: Flyway seeds it when the **backend**
boots (see `AGENTS.md` → Database).
## Why not a direct Postgres client
There is deliberately only **one** way into the database: the `dbhub` MCP
server. It is reachable two ways — as an MCP tool where the harness supports
MCP, and through this CLI bridge where it does not. Both hit the same server,
so its guardrails and behaviour are identical either way.