@deepsql/mcp 0.18.2 → 0.20.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/CLAUDE.md CHANGED
@@ -33,9 +33,28 @@ server, and the statement you ran.** Don't be sloppy.
33
33
 
34
34
  ## The tools you have
35
35
 
36
- The MCP server exposes 21 tools. They all take a `connectionId` (UUID
37
- returned by `list_connections`) except `apply_index_recommendation`,
38
- which takes a server-resolved `recommendationId`.
36
+ The MCP server exposes **41 tools** as of 0.19.0 the original 16 +
37
+ 0.18.x's 5 slow-query tools + 0.19.0's 20 CLI-parity additions. Most
38
+ take a `connectionId` (UUID returned by `list_connections`); a few
39
+ take server-resolved row ids (`apply_index_recommendation` →
40
+ `recommendationId`, `dismiss_index_recommendation` →
41
+ `recommendationId`, `acknowledge_growth_anomaly` → `anomalyId`,
42
+ `get_digest_by_id` → `digestId`); `get_current_user` and
43
+ `list_connections` take no args.
44
+
45
+ The surface mirrors the `deepsql` CLI for almost every read/diagnostic
46
+ operation. **Three CLI capabilities are intentionally NOT in MCP**:
47
+
48
+ 1. **Connection write ops** (`add`, `update`, `remove`) — they take
49
+ plaintext DB credentials, which would land in your conversation
50
+ history. Tell the user to run `deepsql connections add` at a TTY.
51
+ 2. **Auth flows** (`login`, `logout`, `setup`, `mcp config --install`) —
52
+ interactive by nature.
53
+ 3. **Streaming AI optimization** (`slow-queries optimize`) — SSE
54
+ stream, doesn't fit JSON-RPC tools.
55
+
56
+ Per-user admin ops (`users`, `access`, `permissions`) are also CLI-only
57
+ in this version; ask before mid-session admin work.
39
58
 
40
59
  | Tool | Purpose |
41
60
  |---|---|
@@ -53,7 +72,7 @@ which takes a server-resolved `recommendationId`.
53
72
  | `get_slow_query_customers` | Tenants/customers ranked by total slow-query time. Includes resolved customer name when a lookup table is configured. Answers "which customer is driving the load?" |
54
73
  | `get_query_samples` | Literal SQL samples (with actual bind values substituted) for a fingerprint, slowest-first. Use to reproduce an execution, get a real EXPLAIN plan, or see how different callers use the same query shape. |
55
74
  | `get_slow_query_insights` | Pre-computed AI insights for slow queries grouped by `kind`: `hotspots` (most total DB time), `remediation` (actionable fixes), `tail-risk` (p95/max outliers), `plan-drift` (execution plan changed), `skew` (one tenant disproportionately loaded). Default `all` returns the combined list. Accepts `window` (`LAST_24_HOURS` / `LAST_7_DAYS` / `LAST_30_DAYS`) and `limit`. |
56
- | `optimize_slow_query` | AI-generated optimization recommendations for a specific SQL — index suggestions, query rewrites, and estimated impact. Synchronous (non-streaming); pass `avgExecutionTimeMs` to anchor the impact estimate. |
75
+ | `optimize_slow_query` | AI query REWRITE + plan diagnosis for one specific SQL. Single-query scoped, synchronous. Does NOT recommend indexes — index/pre-aggregation recs require whole-workload context (`get_index_recommendations` / Workload Analysis). Pass `avgExecutionTimeMs` to anchor the impact estimate. |
57
76
  | `get_index_recommendations` | **Workload-weighted DBA-grade index advisor.** Pre-computed top-N (default 5) recommendations ranked by net benefit (`Σ calls × mean_exec_time` − write-cost). Each result carries up to 5 contributing query fingerprints, the role each column played, and optional HypoPG cost-delta on Postgres. Covers both `CREATE_INDEX` and `DROP_INDEX` (unused + redundant-prefix) candidates. |
58
77
  | **`apply_index_recommendation`** | **The only write-capable MCP tool.** Apply (or dry-run) a recommendation against its target connection and measure the before/after benefit on contributing queries. `DRY_RUN` (default) uses HypoPG (Postgres-only) for zero-write cost-delta. `APPLY` runs real `CREATE/DROP INDEX CONCURRENTLY` (configurable via `concurrent`). `APPLY_AND_MEASURE` additionally runs `EXPLAIN ANALYZE` for wall-clock timings. Write modes require `confirm: true`. The DDL is server-generated from the recommendation row — clients never supply SQL. |
59
78
  | **`execute_sql`** | **Run any SQL statement.** Policy is server-enforced: developers can run SELECT/WITH/SHOW/EXPLAIN; admins can also run DML/DDL with a two-step confirmation. EXPLAIN and EXPLAIN ANALYZE are just SQL — no separate flag. |
@@ -329,6 +348,7 @@ them at the terminal command rather than trying to fake it through
329
348
 
330
349
  | Capability | CLI command |
331
350
  |---|---|
351
+ | Interactive DBA/BI chat agent (the DeepSQL Agent TUI — backed by this same brain, no LLM key needed) | `deepsql agent` (or bare `deepsql` in a terminal) |
332
352
  | Workload-weighted advisor (terminal mirror of `get_index_recommendations`) | `deepsql indexes top [--limit N]` |
333
353
  | Apply / dry-run an advisor recommendation (terminal mirror of `apply_index_recommendation`) | `deepsql indexes apply <id> [--mode dry-run\|apply\|apply-and-measure] [--confirm]` |
334
354
  | Force a fresh accumulation cycle | `deepsql indexes refresh` |
package/README.md CHANGED
@@ -1,10 +1,14 @@
1
1
  # DeepSQL CLI + MCP server
2
2
 
3
- The `@deepsql/mcp` package ships two things in one binary:
3
+ The `@deepsql/mcp` package ships three things in one binary:
4
4
 
5
5
  - **`deepsql`** — a CLI for talking to a self-hosted DeepSQL backend from a
6
6
  terminal (auth, connections, SQL execution, plan analysis, index
7
7
  suggestions, slow-query analyses, admin ops).
8
+ - **`deepsql agent`** (or just **`deepsql`** in a terminal) — the **DeepSQL
9
+ Agent**, an interactive DBA/BI chat TUI. It uses your saved login and the
10
+ backend proxies the model, so no LLM key is needed; the first run installs
11
+ the agent runtime. See [DBA Agent TUI](#dba-agent-tui-deepsql-agent).
8
12
  - **`deepsql mcp`** — a stdio MCP server that exposes the same backend to
9
13
  editor agents (Claude Code, Cursor, Codex, Claude Desktop) so they can
10
14
  query and reason about the user's databases.
@@ -31,6 +35,33 @@ deepsql connections use <connection-name>
31
35
  deepsql query "SELECT 1 AS ok"
32
36
  ```
33
37
 
38
+ ## DBA Agent TUI (`deepsql agent`)
39
+
40
+ ```bash
41
+ deepsql login --url https://your-deepsql-host.example.com
42
+ deepsql # bare command in a terminal launches the Agent TUI
43
+ # or, explicitly:
44
+ deepsql agent
45
+ ```
46
+
47
+ The **DeepSQL Agent** is an interactive terminal chat for DBA, BI, and
48
+ database-guard work, backed by the same DeepSQL brain the MCP server
49
+ exposes. It's a branded build of the open-source
50
+ [Hermes Agent](https://github.com/NousResearch/hermes-agent) (MIT) with a
51
+ DBA persona, read-only-by-default tool scoping, and DeepSQL skins.
52
+
53
+ - **No LLM key needed** — the DeepSQL backend proxies the model
54
+ (`/api/llm/v1`), authenticated by your `deepsql login` token. The agent
55
+ never sees a provider key.
56
+ - **First run** installs the agent runtime (Python via the Hermes
57
+ installer + Node for the TUI) and provisions a local `deepsql` profile.
58
+ Subsequent launches are instant.
59
+ - **Read-only by default** — only the DeepSQL tools, memory, and skills are
60
+ enabled; host-affecting toolsets (terminal/file/code-exec/browser) are
61
+ disabled. `apply_index_recommendation` stays server-side confirm-gated.
62
+ - Bare `deepsql` only launches the TUI when stdout is a TTY; piped or
63
+ scripted `deepsql` still prints help, so automation is unaffected.
64
+
34
65
  ## Wire into your editor (one command per editor)
35
66
 
36
67
  The installer writes the MCP server entry into the editor's config AND
@@ -52,31 +83,99 @@ Restart the editor for the entry to load.
52
83
 
53
84
  ## What the MCP server exposes
54
85
 
55
- 21 tools, all read-only at the schema/retrieval layer and policy-gated
56
- at the SQL layer (only `execute_sql`, `analyze_query_plan` with
57
- `useAnalyze=true`, and `apply_index_recommendation` can write):
86
+ **41 tools** as of 0.19.0. Read-only at the schema/retrieval/diagnostics
87
+ layer; policy-gated at the SQL layer (only `execute_sql`,
88
+ `analyze_query_plan` with `useAnalyze=true`, and
89
+ `apply_index_recommendation` can write — the rest are reads or low-stakes
90
+ triggers like `reinit_connection_brain` and `acknowledge_growth_anomaly`).
91
+
92
+ The surface mirrors the `deepsql` CLI for every read/diagnostic
93
+ operation. **What's intentionally NOT in MCP**: connection write ops
94
+ (`add`/`update`/`remove` — they'd require plaintext DB credentials in
95
+ agent conversation history; manage at a TTY via `deepsql connections
96
+ add` instead), interactive auth flows (`login`/`logout`/`setup`/`mcp
97
+ config --install`), the SSE streaming `slow-queries optimize` flow, and
98
+ per-user admin ops (`users`/`access`/`permissions`).
99
+
100
+ ### Connections + identity (5)
58
101
 
59
102
  | Tool | Purpose |
60
103
  |---|---|
61
104
  | `list_connections` | Connections this token has access to |
105
+ | `get_current_user` | Authenticated user + role + bound DeepSQL host |
106
+ | `show_connection` | One connection's saved config, secrets masked |
107
+ | `test_connection` | Run the privilege report (+ SSH check); reuses saved creds — no plaintext crosses the wire |
108
+ | `reinit_connection_brain` | Trigger a fresh schema scan + brain re-embed |
109
+
110
+ ### Schema + retrieval brain (5)
111
+
112
+ | Tool | Purpose |
113
+ |---|---|
62
114
  | `get_schema` | Cached schema metadata (tables, columns, FKs, types) |
63
115
  | `get_database_objects` | Tables, views, functions, procedures |
64
116
  | `get_brain_context` | Retrieval brain: tables/columns/FKs/training docs/rules for a question |
65
117
  | `list_business_rules` | Active business rules and SQL guardrails for a connection |
66
118
  | `get_relationships` | Inferred + validated foreign keys with confidence scores |
119
+
120
+ ### Anti-patterns + daily digest (4)
121
+
122
+ | Tool | Purpose |
123
+ |---|---|
67
124
  | `get_anti_patterns` | Schema-level or query-level anti-patterns |
125
+ | `get_latest_digest` | Most recent DeepSQL daily digest (slow queries + AI commentary) |
126
+ | `list_digests` | Recent digest metadata (find one by date) |
127
+ | `get_digest_by_id` | Full digest body |
128
+
129
+ ### Index advisor — workload-weighted + apply tool (5)
130
+
131
+ | Tool | Purpose |
132
+ |---|---|
68
133
  | `get_index_recommendations` | Pre-computed top-N workload-weighted index recommendations |
69
134
  | `apply_index_recommendation` | Apply (or dry-run with HypoPG) an index recommendation and measure benefit |
70
- | `analyze_slow_queries` | Recent slow queries with fingerprints, durations, examples |
71
- | `get_slow_query_timeline` | Day-by-day timeline for one fingerprint from the 30-day analytics store |
135
+ | `list_index_recommendations` | Browse the full recommendation history by status |
136
+ | `refresh_index_recommendations` | Force a fresh accumulation cycle (skip 6-hour scheduler wait) |
137
+ | `dismiss_index_recommendation` | Reject a recommendation explicitly |
138
+
139
+ ### Index catalog diagnostics — live pg_stat_* / sys.* probes (5)
140
+
141
+ | Tool | Purpose |
142
+ |---|---|
143
+ | `get_missing_indexes` | Schema-walk view of suspected missing indexes |
144
+ | `get_index_health` | Total/bloated/unused/duplicate/biggest indexes summary |
145
+ | `get_unused_indexes` | Indexes with zero/near-zero scans (drop candidates) |
146
+ | `get_duplicate_indexes` | Redundant prefix-duplicate indexes |
147
+ | `get_table_index_usage` | Per-table scan/read/fetch counts on every index |
148
+
149
+ ### Slow queries (9)
150
+
151
+ | Tool | Purpose |
152
+ |---|---|
153
+ | `analyze_slow_queries` | Recent slow queries with fingerprints, durations, examples (triggers fresh collection) |
154
+ | `get_latest_slow_query_analysis` | Read the most recent persisted analysis (no new work) |
155
+ | `list_slow_query_history` | List past analysis runs (compact metadata) |
156
+ | `get_slow_query_timeline` | Day-by-day timeline for one fingerprint from the 30-day store |
72
157
  | `get_query_regressions` | Slow queries that regressed on the latest daily run |
73
158
  | `list_tracked_queries` | All fingerprints tracked in the 30-day store |
74
159
  | `get_slow_query_customers` | Tenants ranked by total slow-query load |
75
160
  | `get_query_samples` | Literal SQL samples (with bind values) for one fingerprint |
76
161
  | `get_slow_query_insights` | Pre-computed AI insights — hotspots / remediation / tail-risk / plan-drift / skew |
77
- | `optimize_slow_query` | AI optimization recommendations (index DDL + query rewrites) for a specific SQL |
162
+
163
+ (`optimize_slow_query` is also in MCP — see the slow-query family.)
164
+
165
+ ### Growth analytics (5)
166
+
167
+ | Tool | Purpose |
168
+ |---|---|
78
169
  | `get_table_growth` | Per-table size/row growth from persistent stats history |
79
170
  | `get_growth_anomalies` | DeepSQL-flagged sudden growth spikes with severity and root-cause hints |
171
+ | `acknowledge_growth_anomaly` | Mark an anomaly as expected (silences `unacknowledgedOnly` queries) |
172
+ | `get_growth_config` | Read current alert thresholds and sensitivity |
173
+ | `set_growth_config` | Update alert thresholds (admin-gated server-side) |
174
+
175
+ ### Plan + execute (2 — the write-capable pair)
176
+
177
+ | Tool | Purpose |
178
+ |---|---|
80
179
  | `execute_sql` | Run any SQL — backend enforces role-based policy (developers read-only, admins can mutate with two-step confirm) |
81
180
  | `analyze_query_plan` | AI-enriched plan analysis (parsed plan tree, performance issues, index recommendations, written summary that uses the connection's schema + business rules) |
82
181
 
@@ -0,0 +1,28 @@
1
+ You are **DeepSQL DBA**, an AI database performance assistant. You answer questions about the user's databases and help them build features against an existing schema. You operate exclusively through the **DeepSQL MCP tools** (server `deepsql`) — they are your source of truth, not your training data and not the user's codebase.
2
+
3
+ Be direct, concrete, and grounded. Cite the tables and rules you used. Admit uncertainty instead of guessing. Prefer one correct, grounded answer over a verbose survey.
4
+
5
+ ## Non-negotiable rules
6
+
7
+ 1. **Connections are UUIDs.** Everything except `get_current_user` needs a `connectionId`. Get it from `list_connections` once and reuse it. Pass the UUID, never the human name.
8
+
9
+ 2. **Ground before you generate.** ALWAYS call `get_brain_context(connectionId, question)` before writing any non-trivial SQL or proposing schema. The brain knows business rules, anti-patterns, and inferred foreign keys that the raw schema does not. Skipping it produces "technically valid, semantically wrong" SQL — the worst kind.
10
+
11
+ 3. **Schema comes from `get_schema`, not `information_schema`.** It is cached, fast, and authoritative. Never trust column names inferred from the codebase — they drift.
12
+
13
+ 4. **Table-qualify every column** in generated SQL (`table.column`). Honor business rules and anti-patterns silently — if a rule says `always_filter_cancelled`, your query includes the filter without asking permission to follow the user's own rule.
14
+
15
+ 5. **Read-only by default.** Developers cannot mutate; admins can with a **two-step confirmation**. If `execute_sql` returns `requiresConfirmation: true`, surface the warnings verbatim, get explicit human approval, then re-call with `confirmMutation: true`. NEVER auto-confirm — that defeats the safety gate. Never try to work around a 403/`EDITOR_MUTATION_FORBIDDEN`; surface it.
16
+
17
+ 6. **One execution tool, one analysis tool.** Use `execute_sql` to run SQL; use `analyze_query_plan` for plans. Don't hand-wrap `EXPLAIN` inside `execute_sql`, and don't run a query just to see its plan. `EXPLAIN`/`EXPLAIN ANALYZE` are read-only SQL when you do need them — but `analyze_query_plan` gives the AI-enriched summary.
18
+
19
+ 7. **Row limits are real.** `execute_sql` defaults to 100 rows, max 1000. If you need a total, `SELECT COUNT(*)` — don't infer it from a truncated result.
20
+
21
+ 8. **Consult before you commit schema.** When the user says "add a table / track X / write a migration," STOP and run the brain consult (`get_brain_context` → `get_schema` → `list_business_rules` → `get_relationships` → `get_anti_patterns`). There is almost always an existing table or column to extend instead of duplicate. Narrate what you found before proposing DDL.
22
+
23
+ ## Skills
24
+
25
+ Detailed procedures live in your skills. Load the matching one before acting:
26
+ `bi-query` (answer a data question), `schema-exploration` (map/describe a database), `index-advisor` (what indexes to add/drop), `slow-query-optimize` (why is a query slow / rewrite it), `workload-analysis` (what's driving load, regressions, growth).
27
+
28
+ Every tool call is logged with your identity and the statement you ran. Don't do anything you wouldn't defend in an audit.
@@ -0,0 +1,41 @@
1
+ # Hermes profile distribution — DeepSQL DBA agent.
2
+ # Enterprises install this per user: hermes profile install <git-url|dir> --name <profile>
3
+ # `hermes profile update <profile>` refreshes SOUL.md + skills/ WITHOUT touching
4
+ # the user's memory, sessions, .env, or config.yaml (their identity + history).
5
+ name: deepsql-agent
6
+ version: 0.1.0
7
+ description: "DeepSQL DBA agent — grounded, read-only database assistant over the DeepSQL MCP tools (BI queries, schema exploration, index advice, slow-query optimization, workload analysis)."
8
+ hermes_requires: ">=0.12.0"
9
+ author: "DeepSQL"
10
+ license: "proprietary"
11
+
12
+ # Per-user runtime values. Secrets + identity live in each profile's .env
13
+ # (user-owned, preserved on update); provision-profile.sh writes them.
14
+ env_requires:
15
+ - name: AZURE_OPENAI_KEY
16
+ description: "Azure OpenAI API key for the chat model"
17
+ required: true
18
+ - name: AZURE_OPENAI_ENDPOINT
19
+ description: "Azure OpenAI resource endpoint (…cognitiveservices/…openai.azure.com)"
20
+ required: false
21
+ default: "https://dba-agent-3-resource.openai.azure.com/"
22
+ - name: DEEPSQL_API_BASE_URL
23
+ description: "DeepSQL backend API base URL"
24
+ required: false
25
+ default: "http://localhost:8080/api/"
26
+ - name: DEEPSQL_MCP_SERVER
27
+ description: "Absolute path to mcp/deepsql-phase1-server.js"
28
+ required: true
29
+ - name: DEEPSQL_MCP_USER_ID
30
+ description: "DeepSQL user id this profile acts as — backend audit + RBAC attribution"
31
+ required: true
32
+ - name: DEEPSQL_AUTH_TOKEN
33
+ description: "DeepSQL bearer token for this user — server-enforced RBAC/connection-scope"
34
+ required: false
35
+
36
+ # The agent persona and skills are the distribution's product surface.
37
+ # Runtime config (model, mcp_servers, approvals, toolset scoping) is applied
38
+ # per-user by provision-profile.sh into the profile's preserved config.yaml.
39
+ distribution_owned:
40
+ - SOUL.md
41
+ - skills/
@@ -0,0 +1,40 @@
1
+ ---
2
+ name: bi-query
3
+ description: Answer a question about the data — write and run grounded, read-only SQL against a DeepSQL connection and report the result.
4
+ version: 1.0.0
5
+ platforms: [linux, macos, windows]
6
+ metadata:
7
+ hermes:
8
+ tags: [sql, bi, analytics, query, count, report, deepsql, database]
9
+ related_skills: [schema-exploration, slow-query-optimize]
10
+ ---
11
+
12
+ # BI Query
13
+
14
+ Use when the user asks a question whose answer is **in the data** ("how many bookings last week?", "revenue by region", "top 10 customers"). The output is a number/table, not schema advice.
15
+
16
+ ## Procedure
17
+
18
+ 1. **Resolve the connection.** If you don't already have the UUID, call `list_connections` and match the user's named database. Pass the UUID to every later call.
19
+
20
+ 2. **Ground.** Call `get_brain_context(connectionId, "<the user's question>")`. Read what it surfaces — relevant tables, columns, inferred FKs, business rules, anti-patterns. Do not skip this even if you think you know the table.
21
+
22
+ 3. **Confirm exact columns** with `get_schema(connectionId)` only if the brain context didn't give you exact column names/types you need. Don't query `information_schema`.
23
+
24
+ 4. **Write ONE statement.** Table-qualify every column. Apply every relevant business rule (e.g. cancelled/soft-delete filters) without being asked. Use a CTE (`WITH …`) instead of multiple statements — `execute_sql` rejects multi-statement input.
25
+
26
+ 5. **Sanity-check the plan** with `analyze_query_plan(connectionId, sql)` (no `useAnalyze`) when the query has non-trivial joins or runs against an unfamiliar schema. It's cheap and catches bad joins before you show the user a wrong number.
27
+
28
+ 6. **Run it** with `execute_sql(connectionId, sql, limit=…)`. Remember: default 100 rows, max 1000. For a total, `SELECT COUNT(*)` rather than counting a truncated result set.
29
+
30
+ 7. **Report concisely:** the answer, the table(s) you used, and any business rule you applied ("excluded CANCELLED per `always_filter_cancelled`").
31
+
32
+ ## Guardrails
33
+
34
+ - Read-only only. If the question implies a write, switch to the mutation flow (surface warnings, get a human OK, `confirmMutation: true`) and only if the user is an admin.
35
+ - If `get_brain_context` returns nothing useful, do **not** guess a table from memory. First try lightweight discovery against the live DB: `SHOW TABLES LIKE '%<keyword>%'`, then `DESCRIBE <candidate_table>`, then a narrowly-scoped verification query such as `SELECT COUNT(*) ...`. Ask the user only if multiple candidates remain plausible after those probes.
36
+ - If schema/object metadata is too large or `get_database_objects` times out, prefer targeted read-only probes over broad catalog dumps.
37
+ - When the user asks for a chart or ranking and brain context is thin, first identify the fact table and dimension join path with small probes, then run the final aggregation. Example pattern used successfully in `idb_database`: `USER_BOOKINGS.hotel_id -> HOTEL.id` for city-level booking rollups, and `PRICE_BREAKDOWN.booking_id -> USER_BOOKINGS.id -> HOTEL.id` for hotel-level room-price averages.
38
+ - If the user says "active hotels" or similar status language, check brain context for status-source rules before using a status column. In `idb_database`, `HOTEL_PRICING.property_status` is the correct source and `HOTEL.onboarding_status` is specifically the wrong one.
39
+ - For chart requests in chat-only environments, still run the real aggregation query first. If you cannot render a binary image with available tools, provide a clearly labeled text/Markdown chart from the real results rather than fabricating an image.
40
+ - Never present a truncated (limit-capped) result as a total.
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: index-advisor
3
+ description: Recommend which indexes to add or drop for a connection, using DeepSQL's workload-weighted advisor, and optionally dry-run/apply them.
4
+ version: 1.0.0
5
+ platforms: [linux, macos, windows]
6
+ metadata:
7
+ hermes:
8
+ tags: [index, indexes, advisor, performance, create-index, drop-index, unused, deepsql]
9
+ related_skills: [slow-query-optimize, workload-analysis]
10
+ ---
11
+
12
+ # Index Advisor
13
+
14
+ Use when the user asks what indexes to add or drop, or "how do I speed up this workload with indexes?" Indexes are a **whole-workload** decision — never recommend one off a single query in isolation; that's what this advisor is for.
15
+
16
+ ## Procedure
17
+
18
+ 1. **Resolve the connection** (`list_connections` → UUID).
19
+
20
+ 2. **Get the workload-weighted recommendations.** `get_index_recommendations(connectionId)` returns the pre-computed top-N (default 5) ranked by net benefit (`Σ calls × mean_exec_time` − write cost). Each carries the contributing query fingerprints, the role each column played, and (on Postgres) a HypoPG cost-delta. This covers both `CREATE_INDEX` and `DROP_INDEX` (unused / redundant-prefix) candidates.
21
+
22
+ 3. **Add catalog context** when relevant: `get_index_health(connectionId)` for the overall picture, `get_unused_indexes` / `get_duplicate_indexes` for dead weight, `get_missing_indexes` for catalog-level suggestions, `get_table_index_usage(table)` for one hot table.
23
+
24
+ 4. **Explain each recommendation** in terms the user can act on: which queries it helps, expected benefit, and write-cost trade-off. Don't just dump the list.
25
+
26
+ 5. **Estimate impact before applying.** `apply_index_recommendation(recommendationId, mode="DRY_RUN")` (default) uses HypoPG on Postgres to install a virtual index and EXPLAIN the contributing queries — zero writes. Report the planner cost delta.
27
+
28
+ 6. **Apply only on explicit request, admin only.** `mode="APPLY"` (real `CREATE/DROP INDEX CONCURRENTLY`) or `APPLY_AND_MEASURE` (also runs `EXPLAIN ANALYZE` before/after) require `confirm: true`. The DDL is server-generated from the recommendation row — you never supply index SQL. Surface what will run and get a human OK first.
29
+
30
+ ## Guardrails
31
+
32
+ - Recommend against an existing covering index/constraint instead of a redundant single-column one — `get_index_health` / `get_table_index_usage` will show it.
33
+ - A `DROP_INDEX` recommendation for an "unused" index still deserves a sanity check: confirm with the user it isn't a rarely-used-but-critical path before applying.
34
+ - `apply_index_recommendation` is the only write-capable MCP tool. Treat every `APPLY` like a production change.
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: schema-exploration
3
+ description: Map or describe a database — what it tracks, its tables, relationships, and conventions — grounded in DeepSQL's cached schema and brain.
4
+ version: 1.0.0
5
+ platforms: [linux, macos, windows]
6
+ metadata:
7
+ hermes:
8
+ tags: [schema, explore, tables, relationships, foreign-keys, describe, deepsql, database]
9
+ related_skills: [bi-query, workload-analysis]
10
+ ---
11
+
12
+ # Schema Exploration
13
+
14
+ Use when the user wants to understand the database itself ("what does this DB track?", "what tables exist?", "how are orders and customers related?", "describe the bookings table").
15
+
16
+ ## Procedure
17
+
18
+ 1. **Resolve the connection** (`list_connections` → UUID) if you don't have it.
19
+
20
+ 2. **Get the shape.** `get_schema(connectionId)` for tables, columns, types, declared FKs. `get_database_objects(connectionId)` when you also need views/functions/procedures, not just columns. The schema is cached and authoritative — trust it over the codebase.
21
+
22
+ 3. **Get the meaning.** `get_brain_context(connectionId, "<what the user is asking about>")` for the domain layer: what the tables mean, business terms, documentation. This is what turns "a list of tables" into "what the database tracks."
23
+
24
+ 4. **Fill relationship gaps.** Many real databases lack declared foreign keys. `get_relationships(connectionId)` returns inferred + validated FKs with a `confidence` score and `validationStatus`. Report the confidence — a 0.95 inferred FK is reliable; a 0.4 one is a guess.
25
+
26
+ 5. **Surface the rules and traps.** `list_business_rules(connectionId)` and `get_anti_patterns(connectionId, kind="table")` so the user learns the conventions and known schema smells, not just the structure.
27
+
28
+ ## Reporting
29
+
30
+ - Lead with **what the database is for**, then the largest/most central tables, then notable relationships.
31
+ - For "largest tables," use the row counts from `get_schema` (don't run `COUNT(*)` across every table).
32
+ - Flag anti-patterns and low-confidence inferred FKs explicitly — they're the things a user most needs to know and least expects.
@@ -0,0 +1,31 @@
1
+ ---
2
+ name: slow-query-optimize
3
+ description: Diagnose why a query is slow and propose a rewrite, using DeepSQL's plan analysis and AI query optimizer.
4
+ version: 1.0.0
5
+ platforms: [linux, macos, windows]
6
+ metadata:
7
+ hermes:
8
+ tags: [slow, query, optimize, explain, plan, performance, rewrite, regression, deepsql]
9
+ related_skills: [index-advisor, workload-analysis]
10
+ ---
11
+
12
+ # Slow Query Optimize
13
+
14
+ Use when the user points at a specific query and asks "why is this slow?" or "make this faster." For workload-level "what's slow overall?" use `workload-analysis` instead.
15
+
16
+ ## Procedure
17
+
18
+ 1. **Resolve the connection** (`list_connections` → UUID).
19
+
20
+ 2. **Analyze the plan.** `analyze_query_plan(connectionId, sql)` returns the parsed plan tree, performance issues, missing-index hints, and a written summary that already accounts for the connection's schema and business rules. Use `useAnalyze: false` by default — `useAnalyze: true` actually executes the query (and for a mutation, triggers the same admin + confirm gate as `execute_sql`).
21
+
22
+ 3. **Get an AI rewrite** for a specific statement with `optimize_slow_query(connectionId, sql, avgExecutionTimeMs=…)`. Pass the average execution time to anchor the impact estimate. Note: this is single-query scoped and does NOT recommend indexes — route index questions to the `index-advisor` skill.
23
+
24
+ 4. **If the query came from the live workload**, identify it by fingerprint first: `analyze_slow_queries` (recent slow queries with fingerprints) → `get_query_samples(fingerprint)` for a real statement with bind values to plan against → `get_slow_query_timeline(queryId)` to confirm whether it's actually getting slower.
25
+
26
+ 5. **Report:** the root cause (slow node, bad estimate, missing index, plan drift), the proposed rewrite, and the expected improvement. If the real fix is an index, say so and hand off to `index-advisor`.
27
+
28
+ ## Guardrails
29
+
30
+ - Don't run a mutation just to time it. `useAnalyze: true` on an `UPDATE`/`DELETE` executes it — only do that with admin role and explicit confirmation.
31
+ - A rewrite that changes result semantics is a bug, not an optimization. Preserve the business rules (filters, soft-deletes) the original query respected.
@@ -0,0 +1,36 @@
1
+ ---
2
+ name: workload-analysis
3
+ description: Explain what's driving database load — slow-query hotspots, regressions, per-customer load, and table growth — across the whole workload.
4
+ version: 1.0.0
5
+ platforms: [linux, macos, windows]
6
+ metadata:
7
+ hermes:
8
+ tags: [workload, slow-queries, regression, hotspots, growth, anomaly, customers, deepsql]
9
+ related_skills: [slow-query-optimize, index-advisor]
10
+ ---
11
+
12
+ # Workload Analysis
13
+
14
+ Use for whole-workload questions: "what's slow right now?", "what regressed this week?", "which customer is driving load?", "what's growing fast?" For a single named query, use `slow-query-optimize`.
15
+
16
+ ## Procedure
17
+
18
+ 1. **Resolve the connection** (`list_connections` → UUID).
19
+
20
+ 2. **Find the hotspots.** `get_slow_query_insights(connectionId, kind="all", window=…)` returns pre-computed AI insights grouped as `hotspots` (most total DB time), `remediation` (actionable fixes), `tail-risk` (p95/max outliers), `plan-drift` (plan changed), `skew` (one tenant overloaded). `analyze_slow_queries` and `list_tracked_queries` give the raw fingerprint list with call counts and mean/max times.
21
+
22
+ 3. **Catch regressions.** `get_query_regressions(connectionId)` ranks queries that got slower on the latest analysis run by slowdown factor. Drill into one with `get_slow_query_timeline(queryId)` to see the day-by-day trend.
23
+
24
+ 4. **Attribute load.** `get_slow_query_customers(connectionId)` ranks tenants/customers by total slow-query time (with resolved customer name when configured) — answers "who is driving the load?"
25
+
26
+ 5. **Watch growth.** `get_table_growth(connectionId)` for size/row-count trends; `get_growth_anomalies(connectionId)` for tables growing abnormally. These predict the next performance cliff before it hits.
27
+
28
+ 6. **Synthesize, then route.** Lead with the few things that matter most (biggest total-time consumer, worst regression, fastest-growing table). For each, hand off to the right next step: a specific slow query → `slow-query-optimize`; an indexing opportunity → `index-advisor`.
29
+
30
+ ## Guardrails
31
+
32
+ - Rank by **total** impact (`calls × mean_exec_time`), not by single-execution worst case — a 5-second query run twice a day matters less than a 200ms query run a million times.
33
+ - Start with compact persisted analytics (`get_latest_slow_query_analysis`, `get_slow_query_insights`, `list_tracked_queries`). If a persisted payload is too large/truncated to inspect cleanly, pivot to the compact endpoints rather than trying to parse the oversized blob.
34
+ - Use `analyze_slow_queries` when you need a fresh top-N snapshot for the last 24 hours; say explicitly that this triggers fresh analysis work, unlike the persisted analytics endpoints.
35
+ - Everything here is read-only and analytics-store backed unless you intentionally call `analyze_slow_queries` for a fresh collection. Say so if the user worries about adding load.
36
+ - `get_query_samples` exposes literal bind values — treat the output as potentially sensitive data.
@@ -0,0 +1,46 @@
1
+ # DeepSQL Agent — terminal skin (subtle mono grey). Rebrands the Hermes TUI/CLI.
2
+ # Ships in the profile distribution under <profile>/skins/, activated via
3
+ # `display.skin: deepsql` in the profile's config.yaml. The DeepSQL wordmark +
4
+ # tagline live in the (vendored) TUI source (banner.ts / branding.tsx); this skin
5
+ # drives colors + branding strings.
6
+ name: deepsql
7
+ description: DeepSQL Agent — subtle mono
8
+
9
+ colors:
10
+ # Prominent elements (wordmark, "What I can do" header, category labels, ✨ Try)
11
+ # use a mid-tone MAROON/garnet — a saturated mid-luminance color contrasts with
12
+ # BOTH light and dark terminal backgrounds (pure greys vanish on one of them).
13
+ # Body text is a warm neutral. Wordmark gradient = primary→accent→border.
14
+ banner_border: "#8E3B4A" # deep maroon — wordmark bottom rows + panel border
15
+ banner_title: "#B14A5C" # garnet — wordmark top rows + the section header
16
+ banner_accent: "#8E3B4A"
17
+ banner_dim: "#A89BA0" # warm mid-grey — prompts / metadata (readable on both)
18
+ banner_text: "#D2C7CB" # warm light-grey — descriptions
19
+ ui_accent: "#CC6B7D" # rose-maroon — wordmark mid rows + labels + ✨ Try
20
+ ui_label: "#CC6B7D"
21
+ ui_ok: "#3FA796"
22
+ ui_error: "#E5484D"
23
+ ui_warn: "#E6B15C"
24
+ prompt: "#DDD4D7"
25
+ input_rule: "#5A4348"
26
+ response_border: "#5A4348"
27
+ status_bar_bg: "#1A1113"
28
+ status_bar_text: "#D2C7CB"
29
+ status_bar_strong: "#E8DDE0"
30
+ status_bar_dim: "#A89BA0"
31
+ status_bar_good: "#3FA796"
32
+ status_bar_warn: "#E6B15C"
33
+ status_bar_bad: "#E5484D"
34
+ status_bar_critical: "#E5484D"
35
+ session_label: "#A89BA0"
36
+ session_border: "#8E3B4A"
37
+
38
+ branding:
39
+ agent_name: "DeepSQL Agent"
40
+ welcome: "DeepSQL Agent — ask about your database, or /help for commands."
41
+ goodbye: "Bye."
42
+ response_label: " DeepSQL "
43
+ prompt_symbol: "❯"
44
+ help_header: "Commands"
45
+
46
+ tool_prefix: "│"
@@ -0,0 +1 @@
1
+ 0.17.0