@deepsql/mcp 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT-SETUP.md +15 -6
- package/CLAUDE.md +20 -6
- package/README.md +109 -25
- package/claude_desktop_config.customer.example.json +3 -11
- package/codex_config.customer.example.toml +12 -8
- package/deepsql-phase1-lib.js +225 -2
- package/deepsql-phase1-server.js +1 -1
- package/package.json +1 -1
- package/skills/SKILL_BODY.md +169 -33
- package/src/cli.js +34 -0
- package/src/commands/index-recommendations.js +426 -0
- package/src/commands/index-recommendations.test.js +323 -0
- package/src/commands/login.js +46 -7
- package/src/commands/login.test.js +111 -0
- package/src/commands/mcp.js +162 -10
- package/src/commands/mcp.test.js +145 -0
package/skills/SKILL_BODY.md
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
# DeepSQL — your database DBA consult
|
|
2
2
|
|
|
3
|
-
You have
|
|
4
|
-
the live schema, business rules, FK relationships, and anti-patterns of
|
|
5
|
-
the database the user is working against.** Treat it the way a thoughtful
|
|
6
|
-
engineer treats a DBA: consult before you commit anything schema-shaped.
|
|
3
|
+
You have two DeepSQL surfaces available:
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
1. **MCP tools** — JSON-RPC tools loaded into your session (10 of them).
|
|
6
|
+
Use these for in-session retrieval and SQL execution.
|
|
7
|
+
|
|
8
|
+
2. **`deepsql` CLI** — a shell binary on the user's PATH (~19 commands).
|
|
9
|
+
Use this for things the MCP doesn't expose (index health, daily
|
|
10
|
+
digest, slow-query streaming, connection management, admin ops, the
|
|
11
|
+
plan-analysis `analyze` command, etc.). You can shell out to the CLI
|
|
12
|
+
yourself when appropriate; you can also point the user at the
|
|
13
|
+
command if it's interactive.
|
|
14
|
+
|
|
15
|
+
**DeepSQL is the source of truth for the live schema, business rules, FK
|
|
16
|
+
relationships, and anti-patterns of the database the user is working
|
|
17
|
+
against.** Treat it the way a thoughtful engineer treats a DBA: consult
|
|
18
|
+
before you commit anything schema-shaped. This skill triggers any time
|
|
19
|
+
the user is doing database work. The rules below are non-negotiable.
|
|
10
20
|
|
|
11
21
|
---
|
|
12
22
|
|
|
@@ -65,21 +75,115 @@ usually doesn't know about either; that's exactly why DeepSQL exists.
|
|
|
65
75
|
|
|
66
76
|
---
|
|
67
77
|
|
|
68
|
-
##
|
|
78
|
+
## MCP tools — your in-session toolkit
|
|
69
79
|
|
|
70
|
-
|
|
|
80
|
+
| Tool | When to call |
|
|
71
81
|
|---|---|
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
|
|
|
82
|
+
| `list_connections` | Always first; get the UUID. |
|
|
83
|
+
| `get_brain_context(connectionId, question)` | Step 2 of the checklist above. The most important tool. |
|
|
84
|
+
| `get_schema(connectionId)` | Full column inventory for the tables you're touching. |
|
|
85
|
+
| `get_database_objects(connectionId)` | Tables/views/functions/procedures (broader than schema). |
|
|
86
|
+
| `list_business_rules(connectionId, question?)` | Rules the SQL must respect. |
|
|
87
|
+
| `get_relationships(connectionId)` | Foreign keys (declared + inferred-with-confidence). |
|
|
88
|
+
| `get_anti_patterns(connectionId, kind="table"\|"query")` | Patterns to avoid in this DB. |
|
|
89
|
+
| `analyze_slow_queries(connectionId, thresholdMs?, limit?)` | Snapshot of slow queries from live stats. |
|
|
90
|
+
| `execute_sql(connectionId, query, ...)` | Run any SQL — SELECT for everyone, DML/DDL for admins (two-step confirm). |
|
|
91
|
+
| `analyze_query_plan(connectionId, query, useAnalyze=false)` | AI-enriched plan analysis (issues + index recs + summary). |
|
|
75
92
|
|
|
76
93
|
`EXPLAIN` and `EXPLAIN ANALYZE` are just SQL — type them as the query if
|
|
77
94
|
you want raw plan output. Use `analyze_query_plan` when you want the
|
|
78
|
-
AI-enriched analysis
|
|
95
|
+
AI-enriched analysis.
|
|
79
96
|
|
|
80
|
-
|
|
97
|
+
---
|
|
81
98
|
|
|
82
|
-
`
|
|
99
|
+
## `deepsql` CLI — for everything the MCP doesn't expose
|
|
100
|
+
|
|
101
|
+
The CLI is the user's primary interface to DeepSQL. As a coding agent,
|
|
102
|
+
**you can shell out to it** to do things the MCP doesn't have, or to
|
|
103
|
+
help the user when interactive setup is required (login, MCP install,
|
|
104
|
+
new connection registration). Always pass `--caller-agent <your-name>`
|
|
105
|
+
on shell-outs so the audit log captures the chain ("deepsql query
|
|
106
|
+
called by claude-code via deepsql CLI").
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
deepsql query "SELECT 1" --connection prod-pg --caller-agent claude-code --json
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Command catalog (19 top-level commands)
|
|
113
|
+
|
|
114
|
+
| Command | What it does | MCP equivalent? |
|
|
115
|
+
|---|---|---|
|
|
116
|
+
| `deepsql login` | Authorize CLI against a DeepSQL host (browser PKCE / device code / password) | none — interactive only |
|
|
117
|
+
| `deepsql logout` | Revoke the saved token | none |
|
|
118
|
+
| `deepsql whoami` | Show the logged-in user, role, URL, pinned connection | none |
|
|
119
|
+
| `deepsql config show\|set-default <url>\|path` | Manage saved profiles | none |
|
|
120
|
+
| `deepsql mcp` | Run the stdio MCP server | this skill spawns it |
|
|
121
|
+
| `deepsql mcp config --install --for <editor>` | Install MCP entry + this skill into editor config | none — interactive |
|
|
122
|
+
| `deepsql connections list\|use\|current\|unset\|schema\|add\|update\|remove\|test\|show\|init` | Full connection CRUD | partial: `list_connections`, `get_schema` |
|
|
123
|
+
| `deepsql query "<sql>" --connection <c>` | Execute SQL (admin: `--write` for mutations) | `execute_sql` |
|
|
124
|
+
| `deepsql analyze "<sql>" --connection <c>` | AI plan analysis (`--analyze` for EXPLAIN ANALYZE) | `analyze_query_plan` |
|
|
125
|
+
| `deepsql schema [tables\|objects] --connection <c>` | Dump full schema as JSON | `get_schema` / `get_database_objects` |
|
|
126
|
+
| `deepsql brain-context "<question>" --connection <c>` | Same retrieval as the MCP tool | `get_brain_context` |
|
|
127
|
+
| `deepsql business-rules --connection <c>` | List active business rules | `list_business_rules` |
|
|
128
|
+
| `deepsql relationships --connection <c>` | Inferred + validated FKs | `get_relationships` |
|
|
129
|
+
| `deepsql anti-patterns --connection <c> [--kind table\|query]` | Anti-patterns | `get_anti_patterns` |
|
|
130
|
+
| `deepsql digest [N]\|list\|show <id>` | **CLI-only**: daily digest of slow queries + AI commentary | none |
|
|
131
|
+
| `deepsql indexes list\|missing\|health\|unused\|duplicates\|usage <table>` | **CLI-only**: index recommendations and usage stats | none |
|
|
132
|
+
| `deepsql slow-queries latest\|history\|analyze\|optimize\|delete` | Slow-query analyses; `optimize` streams AI optimization steps live (SSE) | partial: `analyze_slow_queries` |
|
|
133
|
+
| `deepsql users list\|get\|add\|set-role\|lock\|unlock\|disable\|resend-invite\|reset-password\|delete` | **Admin-only, CLI-only**: workspace user management | none |
|
|
134
|
+
| `deepsql access list\|grant\|revoke\|policy <user> <conn>` | **Admin-only, CLI-only**: per-connection access grants + chat policy editing in $EDITOR | none |
|
|
135
|
+
| `deepsql permissions list\|override\|reset` | **Admin-only, CLI-only**: role-based permission overrides | none |
|
|
136
|
+
| `deepsql setup` | **Admin-only**: post-install wizard for SMTP/email + Slack | none |
|
|
137
|
+
|
|
138
|
+
Run `deepsql <command> --help` for option-level detail. Run
|
|
139
|
+
`deepsql --help` for the live catalog (the CLI is the source of truth
|
|
140
|
+
if this table goes stale).
|
|
141
|
+
|
|
142
|
+
### CLI-only capabilities — point the user at these or run them
|
|
143
|
+
|
|
144
|
+
When the user asks for something only the CLI does, either run it via
|
|
145
|
+
shell-out (with `--caller-agent`) or tell the user the exact command:
|
|
146
|
+
|
|
147
|
+
| User asks for | Run / suggest |
|
|
148
|
+
|---|---|
|
|
149
|
+
| "What changed in the database recently?" / "Today's report" | `deepsql digest` (most recent) or `deepsql digest 7` (last week) |
|
|
150
|
+
| "What indexes are we missing?" / "Index advice" | `deepsql indexes missing --connection <c>` |
|
|
151
|
+
| "Are any indexes unused?" / "Index bloat" | `deepsql indexes unused --connection <c>` |
|
|
152
|
+
| "Duplicate indexes?" | `deepsql indexes duplicates --connection <c>` |
|
|
153
|
+
| "Index health on this connection" | `deepsql indexes health --connection <c>` |
|
|
154
|
+
| "Indexes on `<table>` and how often they're used" | `deepsql indexes usage <table> --connection <c>` |
|
|
155
|
+
| "Optimize this slow query with AI" / "Stream me a fix" | `deepsql slow-queries optimize --connection <c> --query-id <id>` |
|
|
156
|
+
| "Add a new database connection" | `deepsql connections add` (interactive) or `--from-file <path>` |
|
|
157
|
+
| "Test a connection without saving" | `deepsql connections test --from-file <path>` |
|
|
158
|
+
| "Trigger brain re-initialization for this connection" | `deepsql connections init <name> --wait` |
|
|
159
|
+
| "Add a user / change a user's role" | `deepsql users add` / `deepsql users set-role <ref> <role>` |
|
|
160
|
+
| "Grant / revoke connection access" | `deepsql access grant --user <ref> --connection <c> --level read\|write\|admin` |
|
|
161
|
+
| "Edit the chat data-access policy for `<user>` on `<conn>`" | `deepsql access policy <user> <conn>` (opens `$EDITOR`) |
|
|
162
|
+
|
|
163
|
+
### Shelling out from the agent — the convention
|
|
164
|
+
|
|
165
|
+
When you run `deepsql` yourself:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
deepsql <command> [options] --caller-agent <your-agent-id> --json
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
- **Always pass `--caller-agent`** (or set `DEEPSQL_CALLER_AGENT` env
|
|
172
|
+
var once) so the audit row captures the chain. Use a stable id like
|
|
173
|
+
`claude-code`, `cursor`, or `codex`.
|
|
174
|
+
- **Prefer `--json`** for parseable output. Without it, output is
|
|
175
|
+
pretty-printed for humans and harder to parse.
|
|
176
|
+
- **Don't chain destructive ops without confirmation.** `deepsql
|
|
177
|
+
connections remove`, `deepsql users delete`, `deepsql permissions
|
|
178
|
+
override --revoke`, etc. all support `--yes` to skip the prompt — but
|
|
179
|
+
YOU should not pass `--yes` unless the user has explicitly approved
|
|
180
|
+
the specific action.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Mutations are role-gated and two-step (both MCP and CLI)
|
|
185
|
+
|
|
186
|
+
`execute_sql` (MCP) and `deepsql query` (CLI) enforce the same policy:
|
|
83
187
|
|
|
84
188
|
- **Developer + SELECT/WITH/SHOW/EXPLAIN** → runs immediately.
|
|
85
189
|
- **Developer + DML/DDL** → 403 `EDITOR_MUTATION_FORBIDDEN`. Don't retry.
|
|
@@ -89,26 +193,51 @@ AI-enriched analysis (issues, index recommendations, written summary).
|
|
|
89
193
|
- **Admin + DML/DDL (no `confirmMutation`)** → returns
|
|
90
194
|
`requiresConfirmation: true` with a `warnings` array. **Show the
|
|
91
195
|
warnings to the user verbatim. Wait for explicit OK.** Then re-call
|
|
92
|
-
with `confirmMutation: true
|
|
93
|
-
|
|
196
|
+
with `confirmMutation: true` (MCP) or `--write` (CLI). **Do not
|
|
197
|
+
silently retry on the user's behalf** — that defeats the
|
|
94
198
|
confirmation step.
|
|
95
199
|
|
|
96
|
-
|
|
200
|
+
## Row limits
|
|
201
|
+
|
|
202
|
+
`execute_sql` / `deepsql query` defaults to 100 rows, max 1000. If you
|
|
203
|
+
asked for "all customers" and got 100, that's the limit kicking in —
|
|
204
|
+
not the real count. Either bump `--limit`/`limit:` or `SELECT COUNT(*)`
|
|
205
|
+
first.
|
|
97
206
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Helping the user when DeepSQL itself isn't set up
|
|
210
|
+
|
|
211
|
+
The user might not have DeepSQL fully wired up when they ask their
|
|
212
|
+
first database question. If you get a clear "not configured" error,
|
|
213
|
+
run / suggest these:
|
|
214
|
+
|
|
215
|
+
| Symptom | Fix |
|
|
216
|
+
|---|---|
|
|
217
|
+
| `deepsql --version` not found / not on PATH | `npm install -g @deepsql/mcp@latest` (Node ≥ 20). |
|
|
218
|
+
| MCP tools missing from your session | Run `deepsql mcp config --install --for claude-code` (or `cursor`/`codex`/`claude-desktop`) on the user's machine. They restart the editor. |
|
|
219
|
+
| CLI says "No saved DeepSQL profile" | `deepsql login --url https://<their-deepsql-host>` (browser flow on desktop, `--device` for SSH boxes). |
|
|
220
|
+
| MCP tools error with 401 | Token expired. `deepsql logout && deepsql login --url <host>` then restart the editor. |
|
|
221
|
+
| `connections list` is empty | Walk the user through `deepsql connections add` interactively, or use `--from-file <path>` with a JSON config file. |
|
|
222
|
+
| `connections test` reports "Missing privileges: SELECT, ..." | The DB user has insufficient grants. The connection saves anyway (read access is enough for some features), but flag it. |
|
|
223
|
+
| Connection config schema | `deepsql connections schema --json` (JSON Schema for the input format). |
|
|
101
224
|
|
|
102
225
|
---
|
|
103
226
|
|
|
104
|
-
## Every call is audited
|
|
227
|
+
## Every call is audited (both surfaces)
|
|
105
228
|
|
|
106
|
-
Every tool call
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
229
|
+
Every MCP tool call AND every `deepsql` CLI invocation that hits the
|
|
230
|
+
backend is logged to the DeepSQL `security_events` table with:
|
|
231
|
+
|
|
232
|
+
- the user's identity (from the bearer token or saved profile)
|
|
233
|
+
- the editor / agent that originated the request (`claude-code`,
|
|
234
|
+
`cursor`, `codex`, etc. — from the `--caller-agent` flag or
|
|
235
|
+
`DEEPSQL_MCP_USER_ID` env var)
|
|
236
|
+
- the surface (`mcp` vs `cli`)
|
|
237
|
+
- the connection, the truncated statement, and the outcome
|
|
238
|
+
|
|
239
|
+
Workspace admins can search this. Don't do anything through these
|
|
240
|
+
tools you wouldn't be willing to defend in that view.
|
|
112
241
|
|
|
113
242
|
---
|
|
114
243
|
|
|
@@ -116,10 +245,17 @@ view.
|
|
|
116
245
|
|
|
117
246
|
The complete runtime guide — every decision-tree branch, every foot-gun,
|
|
118
247
|
all three session playbooks (answer-a-question, mutation, DBA-consult) —
|
|
119
|
-
lives in `
|
|
120
|
-
|
|
248
|
+
lives in the package's `CLAUDE.md`. After install:
|
|
249
|
+
|
|
250
|
+
```
|
|
251
|
+
node_modules/@deepsql/mcp/CLAUDE.md # local install
|
|
252
|
+
$(npm root -g)/@deepsql/mcp/CLAUDE.md # global install
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
The CLI is its own source of truth too — if this table drifts from
|
|
256
|
+
reality, run:
|
|
121
257
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
258
|
+
```bash
|
|
259
|
+
deepsql --help # live command list
|
|
260
|
+
deepsql <command> --help # full options for one command
|
|
261
|
+
```
|
package/src/cli.js
CHANGED
|
@@ -36,6 +36,7 @@ const COMMANDS = {
|
|
|
36
36
|
access: () => require("./commands/access"),
|
|
37
37
|
permissions: () => require("./commands/permissions"),
|
|
38
38
|
"slow-queries": () => require("./commands/slow-queries"),
|
|
39
|
+
"index-recommendations": () => require("./commands/index-recommendations"),
|
|
39
40
|
setup: () => require("./commands/setup"),
|
|
40
41
|
};
|
|
41
42
|
|
|
@@ -60,6 +61,7 @@ const COMMAND_LIST = [
|
|
|
60
61
|
["relationships", false, "List inferred and validated FK relationships"],
|
|
61
62
|
["anti-patterns", false, "List schema- or query-level anti-patterns"],
|
|
62
63
|
["indexes", true, "Index suggestions, usage, and health (read-only)"],
|
|
64
|
+
["index-recommendations", true, "Workload-weighted index advisor + HypoPG-validated apply tool"],
|
|
63
65
|
["users", true, "Manage workspace users (admin)"],
|
|
64
66
|
["access", true, "Manage per-connection access grants (admin)"],
|
|
65
67
|
["permissions", true, "Manage role-based permission overrides (admin)"],
|
|
@@ -360,6 +362,34 @@ const COMMAND_HELP = {
|
|
|
360
362
|
],
|
|
361
363
|
notes: "Org and LLM config are set at install time and are NOT touched by this wizard.",
|
|
362
364
|
},
|
|
365
|
+
|
|
366
|
+
"index-recommendations": {
|
|
367
|
+
description:
|
|
368
|
+
"DBA-grade workload-weighted index advisor. Default `top` shows pending " +
|
|
369
|
+
"recommendations ranked by net benefit (workload − write-cost). `apply` " +
|
|
370
|
+
"is the only mutation — dry-run uses HypoPG (Postgres-only) so no writes " +
|
|
371
|
+
"leak; the two write modes require --confirm.",
|
|
372
|
+
usage:
|
|
373
|
+
"deepsql index-recommendations <top|list|show|refresh|apply|dismiss> [options]",
|
|
374
|
+
subcommands: [
|
|
375
|
+
["top --connection <name> [--limit N]", "Pre-computed top-N (default 5, max 50), evidence-bearing"],
|
|
376
|
+
["list --connection <name>", "All pending recommendations for the connection"],
|
|
377
|
+
["show <id> --connection <name>", "Full detail: workload, HypoPG cost, contributing queries"],
|
|
378
|
+
["refresh --connection <name>", "Force a fresh accumulation cycle (POST /generate)"],
|
|
379
|
+
["apply <id> [--mode <m>] [--confirm]", "Run / dry-run with before/after measurement"],
|
|
380
|
+
["dismiss <id>", "Mark a recommendation as DISMISSED"],
|
|
381
|
+
],
|
|
382
|
+
options: [
|
|
383
|
+
["--limit <n>", "top: number of recommendations (default 5, max 50)"],
|
|
384
|
+
["--mode <m>", "apply: dry-run (default) | apply | apply-and-measure"],
|
|
385
|
+
["--confirm", "apply: required for apply / apply-and-measure (write modes)"],
|
|
386
|
+
["--no-concurrent", "apply: skip CREATE/DROP INDEX CONCURRENTLY (dev / small tables)"],
|
|
387
|
+
["--json", "Emit raw backend JSON instead of the terminal-friendly table"],
|
|
388
|
+
],
|
|
389
|
+
notes:
|
|
390
|
+
"Complements `deepsql indexes` (catalog-level usage / health). " +
|
|
391
|
+
"This namespace surfaces the workload-weighted advisor + the apply tool.",
|
|
392
|
+
},
|
|
363
393
|
};
|
|
364
394
|
|
|
365
395
|
// ─── Color helpers ──────────────────────────────────────────────────────────
|
|
@@ -564,6 +594,10 @@ function buildOpts(parsed) {
|
|
|
564
594
|
skipComplete: !!f.skipComplete,
|
|
565
595
|
// Confirmations
|
|
566
596
|
yes: !!f.yes || !!f.y,
|
|
597
|
+
// Index recommendations (apply tool)
|
|
598
|
+
mode: f.mode || null,
|
|
599
|
+
confirm: !!f.confirm,
|
|
600
|
+
noConcurrent: !!f.noConcurrent,
|
|
567
601
|
// Connection management
|
|
568
602
|
fromFile: f.fromFile || null,
|
|
569
603
|
fromStdin: !!f.fromStdin,
|