-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmcp_server.py
More file actions
2552 lines (2234 loc) · 92.6 KB
/
Copy pathmcp_server.py
File metadata and controls
2552 lines (2234 loc) · 92.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/usr/bin/env python3
"""
RDST MCP Server - Model Context Protocol server for RDST (Readyset Data and SQL Toolkit)
This server exposes RDST functionality to AI assistants like Claude through the MCP protocol.
It provides tools for database diagnostics, query analysis, and performance tuning.
INSTALLATION:
pip install rdst
REGISTRATION WITH CLAUDE CODE:
claude mcp add rdst -- python3 -m rdst.mcp_server
WHAT THIS PROVIDES:
- Database target configuration management
- SQL query analysis with AI-powered recommendations
- Live slow query monitoring (top)
- Query registry management
- Performance tuning suggestions
- Database health auditing (metrics, sizing, cache opportunity, index recommendations)
- Fleet management (multi-target operations, fleet-wide audits, snapshot comparison)
CONFIG LOCATION:
~/.rdst/config.toml - Contains database targets and settings
~/.rdst/queries.toml - Query registry storage
PASSWORD HANDLING:
Passwords are NEVER stored in config files. Instead, each target specifies a
password_env field containing the name of an environment variable that holds
the password. Before running RDST commands, ensure the required environment
variables are exported.
"""
import json
import sys
import os
import subprocess
from typing import Any, Dict, List, Optional
# MCP Protocol constants
JSONRPC_VERSION = "2.0"
MCP_VERSION = "2024-11-05"
# Single source of truth for the slow query workflow
SLOW_QUERY_WORKFLOW = """1. `rdst_query_list` → Check saved queries FIRST
2. If queries exist → `rdst_analyze` with `name` parameter
3. If empty → `rdst_top` (defaults to historical, INSTANT)
4. ONLY if historical empty → `rdst_top` with `duration=30`
5. Then `rdst_analyze` with `name` or `hash`
6. If STILL no queries found → Ask user to provide a slow query, then use `rdst_analyze` with `query` parameter"""
SLOW_QUERY_WORKFLOW_DETAILED = f"""### MANDATORY Workflow for Slow Query Analysis
**CRITICAL: Follow this exact order. Do NOT skip steps or go straight to live monitoring.**
{SLOW_QUERY_WORKFLOW}
**WRONG**: Going straight to `rdst_top` without checking registry first
**WRONG**: Suggesting users run CLI commands manually when MCP tools work"""
# RDST context information for the AI
RDST_CONTEXT = f"""
## RDST (Readyset Data and SQL Toolkit) - Context for AI Assistants
### What is RDST?
RDST is a command-line tool for database diagnostics and SQL query optimization.
It connects to PostgreSQL or MySQL databases and provides AI-powered analysis
of query performance, index recommendations, and caching suggestions.
### Installation & Upgrade
- Install: `pip install rdst`
- Upgrade: `pip install --upgrade rdst`
- Check version: `rdst version`
{SLOW_QUERY_WORKFLOW_DETAILED}
### CRITICAL: COMMAND SYNTAX
RDST CLI uses SUBCOMMANDS (not flags):
CORRECT:
- `rdst configure list` (subcommand)
- `rdst query list` (subcommand)
- `rdst analyze --name my-query` (analyze saved query by name)
- `rdst analyze --hash abc123` (analyze saved query by hash)
- `rdst analyze -q "SELECT ..."` (analyze inline query)
WRONG - DO NOT USE:
- `rdst configure --list` (WRONG - no such flag)
- `rdst query --list` (WRONG - no such flag)
- `rdst analyze --query-id X` (WRONG - use --name or --hash)
- `rdst_help` as CLI command (WRONG - MCP tool only, `rdst help` is the CLI command)
### MCP Tools vs CLI Commands
MCP tool names use underscores; CLI commands use spaces:
- MCP `rdst_query_list` → CLI `rdst query list`
- MCP `rdst_analyze` → CLI `rdst analyze`
- MCP `rdst_help` → CLI `rdst help`
### What is RDST?
A CLI tool for database diagnostics and SQL optimization. Connects to PostgreSQL
or MySQL and provides AI-powered query analysis, index recommendations, and
caching suggestions.
### Configuration
- Config: `~/.rdst/config.toml`
- Query registry: `~/.rdst/queries.toml`
- Conversation history: `~/.rdst/conversations/`
### Password Handling (CRITICAL)
RDST never stores passwords in config files. Instead, each database target
specifies a `password_env` field with the name of an environment variable.
Example config entry:
```toml
[targets.my-database]
name = "my-database"
engine = "postgresql"
host = "db.example.com"
port = 5432
user = "admin"
database = "mydb"
password_env = "MY_DB_PASSWORD" # <-- User must export this env var
```
Before running commands, the user must:
```bash
export MY_DB_PASSWORD="actual-password-here"
```
If a command fails with authentication error, check:
1. Is the password_env variable exported?
2. Is the password correct?
3. Can the host/port be reached?
### LLM Setup (CRITICAL)
RDST requires an LLM provider for query analysis. Two options:
**Option 1: RDST Free Trial (Recommended for new users)**
- Run `rdst configure llm` in terminal (INTERACTIVE - cannot be done via MCP)
- Select "Sign up for free RDST trial"
- Enter email → receive verification code → enter code
- Business emails get $5.00 in credits, personal emails get $1.50
- No API key needed after setup - RDST uses a trial proxy
- Check balance anytime: `rdst configure llm`
**Option 2: Your Own Anthropic API Key**
- Export: `export ANTHROPIC_API_KEY="sk-ant-..."`
- No credit limits, direct API access
If a user has no ANTHROPIC_API_KEY and hasn't set up a trial, tell them to run
`rdst configure llm` in their terminal to set up free trial credits.
### Common CLI Workflows
1. **First-time setup**: `rdst init` - Interactive wizard
2. **Add a database target**: `rdst configure add --target NAME --engine postgresql --host HOST --port PORT --user USER --database DB --password-env VAR_NAME`
3. **List targets**: `rdst configure list`
4. **Analyze a query**: `rdst analyze -q "SELECT * FROM users WHERE id = 1" --target my-target`
5. **Save query for later**: `rdst query add my-query -q "SELECT ..." --target my-target`
### CLI-Only Features (Tell user to run in terminal)
- `rdst ask "question" --target mydb` - Natural language to SQL
- `rdst schema annotate --target mydb` - Add descriptions
- `rdst schema edit --target mydb` - Edit in $EDITOR
"""
def read_message() -> Optional[Dict[str, Any]]:
"""Read a JSON-RPC message from stdin."""
try:
line = sys.stdin.readline()
if not line:
return None
return json.loads(line)
except json.JSONDecodeError:
return None
def write_message(message: Dict[str, Any]) -> None:
"""Write a JSON-RPC message to stdout."""
sys.stdout.write(json.dumps(message) + "\n")
sys.stdout.flush()
def make_response(id: Any, result: Any) -> Dict[str, Any]:
"""Create a JSON-RPC response."""
return {
"jsonrpc": JSONRPC_VERSION,
"id": id,
"result": result
}
def make_error(id: Any, code: int, message: str, data: Any = None) -> Dict[str, Any]:
"""Create a JSON-RPC error response."""
error = {"code": code, "message": message}
if data is not None:
error["data"] = data
return {
"jsonrpc": JSONRPC_VERSION,
"id": id,
"error": error
}
def _get_rdst_command() -> List[str]:
"""Get the command to run RDST.
Prefers local rdst.py (development mode) over installed rdst command.
This ensures MCP uses the same version as the local development environment.
"""
# Check for rdst.py in the same directory as this script
script_dir = os.path.dirname(os.path.abspath(__file__))
local_rdst = os.path.join(script_dir, "rdst.py")
if os.path.exists(local_rdst):
# Use local development version
return [sys.executable, local_rdst]
# Fall back to installed rdst command
return ["rdst"]
def run_rdst_command(args: List[str]) -> Dict[str, Any]:
"""Execute an RDST CLI command and return the result."""
try:
cmd = _get_rdst_command() + args
result = subprocess.run(
cmd,
capture_output=True,
text=True,
timeout=300, # 5 minute timeout for long-running commands
env=os.environ.copy() # Pass through environment variables
)
return {
"success": result.returncode == 0,
"stdout": result.stdout,
"stderr": result.stderr,
"returncode": result.returncode
}
except subprocess.TimeoutExpired:
return {
"success": False,
"stdout": "",
"stderr": "Command timed out after 5 minutes",
"returncode": -1
}
except FileNotFoundError:
return {
"success": False,
"stdout": "",
"stderr": "RDST not found. Install with: pip install rdst",
"returncode": -1
}
except Exception as e:
return {
"success": False,
"stdout": "",
"stderr": str(e),
"returncode": -1
}
def get_tools() -> List[Dict[str, Any]]:
"""Return the list of available MCP tools."""
return [
{
"name": "rdst_configure_add",
"description": """Add a new database target configuration to RDST.
This creates a connection profile that RDST will use to connect to your database.
The password is NOT stored - instead you specify an environment variable name
that will contain the password at runtime.
IMPORTANT: After adding a target, the user must export the password environment
variable before running other RDST commands:
export PASSWORD_ENV_NAME="actual-password"
Example:
rdst_configure_add(
target="prod-db",
engine="postgresql",
host="db.example.com",
port=5432,
user="admin",
database="myapp",
password_env="PROD_DB_PASSWORD"
)
Then user runs: export PROD_DB_PASSWORD="secret123"
""",
"inputSchema": {
"type": "object",
"properties": {
"target": {
"type": "string",
"description": "Unique name for this database target (e.g., 'prod-db', 'staging')"
},
"engine": {
"type": "string",
"enum": ["postgresql", "mysql"],
"description": "Database engine type"
},
"host": {
"type": "string",
"description": "Database host address (IP or hostname)"
},
"port": {
"type": "integer",
"description": "Database port (default: 5432 for PostgreSQL, 3306 for MySQL)"
},
"user": {
"type": "string",
"description": "Database username"
},
"database": {
"type": "string",
"description": "Database name to connect to"
},
"password_env": {
"type": "string",
"description": "Name of environment variable containing the password (NOT the password itself)"
},
"make_default": {
"type": "boolean",
"description": "Set as the default target for commands"
}
},
"required": ["target", "engine", "host", "user", "database", "password_env"]
}
},
{
"name": "rdst_configure_list",
"description": """List all configured database targets.
Shows all database connection profiles that have been configured in RDST.
For each target, displays: name, engine (postgresql/mysql), host, port,
database name, and which environment variable holds the password.
The output also indicates which target is set as the default.
Use this to:
- See what databases are configured
- Find the password_env variable name for a target
- Identify the default target
""",
"inputSchema": {
"type": "object",
"properties": {},
"required": []
}
},
{
"name": "rdst_configure_remove",
"description": """Remove a database target configuration.
Deletes the specified target from RDST configuration. This only removes
the configuration - it does not affect the actual database.
Use --confirm to skip the interactive confirmation prompt.
""",
"inputSchema": {
"type": "object",
"properties": {
"target": {
"type": "string",
"description": "Name of the target to remove"
},
"confirm": {
"type": "boolean",
"description": "Skip confirmation prompt"
}
},
"required": ["target"]
}
},
{
"name": "rdst_configure_llm",
"description": """Configure the LLM (AI) provider for RDST analysis.
RDST uses AI to analyze query execution plans and provide recommendations.
By default, it uses Claude (Anthropic). This command configures the AI provider.
SUPPORTED PROVIDERS:
- claude: Anthropic's Claude (default, requires ANTHROPIC_API_KEY env var)
- openai: OpenAI's GPT models (requires OPENAI_API_KEY env var)
- lmstudio: Local LM Studio server (no API key needed)
- trial: RDST free trial credits (no API key needed)
TRIAL SIGNUP (INTERACTIVE - must be done in user's terminal):
Users who don't have an ANTHROPIC_API_KEY can sign up for free RDST trial credits.
The trial signup is INTERACTIVE and cannot be done via MCP. Tell the user:
"Run `rdst configure llm` in your terminal and select the free trial option"
The trial flow:
1. User runs `rdst configure llm` in their terminal
2. Selects "Sign up for free RDST trial"
3. Enters their email address
4. Gets a verification code sent to their email
5. Enters the code
6. Gets free credits ($5.00 for business emails, $1.50 for personal emails)
7. No ANTHROPIC_API_KEY needed after this - RDST uses a trial proxy
EXAMPLES:
rdst configure llm --provider claude --model claude-sonnet-4-6
rdst configure llm --provider openai --model gpt-4
rdst configure llm --provider lmstudio --base-url http://localhost:1234
rdst configure llm (interactive - includes trial signup option)
REQUIRED ENV VARS:
- For Claude: export ANTHROPIC_API_KEY="sk-ant-..."
- For OpenAI: export OPENAI_API_KEY="sk-..."
- For LM Studio: No API key needed, just base_url
- For Trial: No env var needed - credits are managed by RDST
""",
"inputSchema": {
"type": "object",
"properties": {
"provider": {
"type": "string",
"enum": ["claude", "openai", "lmstudio", "trial"],
"description": "LLM provider to use. Use 'trial' for free RDST trial credits (but trial signup is INTERACTIVE - tell user to run `rdst configure llm` in their terminal instead)"
},
"model": {
"type": "string",
"description": "Model name (e.g., claude-sonnet-4-6, gpt-4)"
},
"base_url": {
"type": "string",
"description": "Base URL for API (required for lmstudio, optional for others)"
}
},
"required": ["provider"]
}
},
{
"name": "rdst_configure_default",
"description": """Set the default database target.
When running RDST commands without --target, this target will be used.
""",
"inputSchema": {
"type": "object",
"properties": {
"target": {
"type": "string",
"description": "Name of target to set as default"
}
},
"required": ["target"]
}
},
{
"name": "rdst_analyze",
"description": """Analyze a SQL query for performance optimization.
PREFERRED: Analyze queries from the registry using `name` or `hash` parameter.
Call `rdst_query_list` first to see saved queries, then analyze by name/hash.
INPUT OPTIONS (use ONE):
- `name`: Analyze a saved query by name (PREFERRED)
- `hash`: Analyze a saved query by hash (PREFERRED)
- `query`: Analyze an inline SQL query
WORKFLOW:
1. Call `rdst_query_list` to see saved queries
2. Call `rdst_analyze` with `name="query-name"` to analyze
CLI EQUIVALENT:
- `rdst analyze --name my-query --target mydb`
- `rdst analyze --hash abc123 --target mydb`
- `rdst analyze -q "SELECT ..." --target mydb`
WRONG (do not use):
- `rdst analyze --query-id X` (no such flag - use --name or --hash)
WHAT IT DOES:
1. Runs EXPLAIN ANALYZE on the query
2. AI analyzes the execution plan
3. Returns index recommendations, query rewrites, caching suggestions
AFTER ANALYSIS: ALWAYS display the key findings to the user:
- Performance issues found
- CREATE INDEX statements
- Query rewrites if suggested
The user wants to SEE the analysis, not just know it completed.
READYSET CACHING:
If the query takes >1 second (1000ms), suggest testing Readyset caching using
the --readyset-cache flag. This will:
1. Pull Readyset Docker containers (first run downloads images - may take a while)
2. Create a test replica of the user's database schema
3. Attempt to cache the query in Readyset
4. Run a performance comparison (original DB vs Readyset cached)
5. Show whether the query is cacheable and the speedup achieved
Warn the user this process may take a while, especially on first run.
PREREQUISITES:
- A database target must be configured (use rdst_configure_add first)
- The password environment variable must be exported
COMMON ISSUES:
- "Authentication failed" → Check if password_env is exported
- "Connection refused" → Check host/port accessibility
- Timeout → Query may be too slow; consider adding --fast flag
""",
"inputSchema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Query name from registry (PREFERRED - call rdst_query_list first)"
},
"hash": {
"type": "string",
"description": "Query hash from registry (alternative to name)"
},
"query": {
"type": "string",
"description": "Inline SQL query (use name/hash for saved queries instead)"
},
"target": {
"type": "string",
"description": "Database target name (uses default if not specified)"
},
"fast": {
"type": "boolean",
"description": "Skip slow EXPLAIN ANALYZE queries (timeout after 10s)"
},
"readyset_cache": {
"type": "boolean",
"description": """Test if this query can be cached by Readyset and show performance improvement.
This process:
1. Pulls Readyset Docker containers (first run downloads images - may take a while)
2. Creates a test replica of the user's database schema
3. Attempts to cache the query in Readyset
4. Runs a performance comparison (original DB vs Readyset cached)
REQUIRES: Docker must be installed and running.
WARNING: This may take a while, especially on first run. Warn the user before running.
OUTPUT INCLUDES:
- Whether query is cacheable (and the reason if not)
- Performance comparison: original DB vs Readyset cache
- CREATE CACHE command for production deployment"""
}
},
"required": []
}
},
{
"name": "rdst_top",
"description": """Capture slow queries from the database.
DEFAULT: Historical mode (instant results from pg_stat_statements).
Only use `duration` parameter as fallback when historical returns nothing.
DATA SOURCES:
- **Historical mode** (default, instant): Queries pg_stat_statements (PostgreSQL) or
performance_schema.events_statements_summary_by_digest (MySQL). Shows aggregated
statistics of ALL queries that have run since stats were last reset.
- **Live monitoring mode** (with duration): Polls pg_stat_activity (PostgreSQL) or
INFORMATION_SCHEMA.PROCESSLIST (MySQL) repeatedly. Only captures queries actively
running during the monitoring window - fast queries may be missed.
MYSQL SLOW LOG (optional source='slowlog'):
For MySQL, you can also query individual slow queries from mysql.slow_log table.
This requires enabling the MySQL slow query log with TABLE output:
- For self-hosted: SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 1; SET GLOBAL log_output = 'TABLE';
- For RDS/Aurora: Modify parameter group (slow_query_log=1, long_query_time=1, log_output=TABLE)
No restart required - changes take effect immediately.
Use source='slowlog' parameter to enable. If not enabled, RDST will show setup instructions.
OUTPUT INCLUDES (JSON):
- query_hash: Unique identifier for the query pattern
- normalized_query: Query with parameters replaced by $1, $2, etc.
- max_duration_ms: Slowest observed execution
- avg_duration_ms: Average execution time
- observation_count: How many times query was seen (historical) or caught running (live)
If using duration, tell user "Monitoring for N seconds..." BEFORE calling.
Use this to identify which queries to optimize with rdst_analyze.
Captured queries auto-save to registry for later analysis with rdst_analyze.
""",
"inputSchema": {
"type": "object",
"properties": {
"target": {
"type": "string",
"description": "Database target name"
},
"limit": {
"type": "integer",
"description": "Number of queries to show (default: 10)"
},
"sort": {
"type": "string",
"enum": ["freq", "total_time", "avg_time", "load"],
"description": "Sort field (default: total_time)"
},
"filter": {
"type": "string",
"description": "Regex to filter query text"
},
"source": {
"type": "string",
"enum": ["auto", "pg_stat", "activity", "digest", "slowlog"],
"description": "Data source (database-specific): auto (default - picks correct source), pg_stat (PostgreSQL only), activity (both), digest (MySQL only), slowlog (MySQL only, requires setup)"
},
"historical": {
"type": "boolean",
"description": "Use historical statistics (default, non-interactive)"
},
"duration": {
"type": "integer",
"description": "Run real-time monitoring for N seconds then output"
}
},
"required": []
}
},
{
"name": "rdst_query_add",
"description": """Save a SQL query to the registry for later use.
The query registry allows you to store frequently-used queries with names
for easy reference. Queries can then be analyzed by name or hash.
Each saved query includes:
- Name (user-provided identifier)
- SQL text
- Target database (optional)
- Hash (auto-generated unique identifier)
- Metadata (creation date, source, etc.)
""",
"inputSchema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name for the query (e.g., 'user-lookup', 'order-summary')"
},
"query": {
"type": "string",
"description": "The SQL query to save"
},
"target": {
"type": "string",
"description": "Associated database target (optional)"
}
},
"required": ["name", "query"]
}
},
{
"name": "rdst_query_list",
"description": """List all queries in the registry.
Shows saved queries with their names, hashes, and targets.
Use --filter to search across query text, names, and tags.
Use --target to filter by database target.
""",
"inputSchema": {
"type": "object",
"properties": {
"target": {
"type": "string",
"description": "Filter queries by target database"
},
"filter": {
"type": "string",
"description": "Search filter (matches SQL, names, tags)"
},
"limit": {
"type": "integer",
"description": "Maximum queries to show (default: 10)"
}
},
"required": []
}
},
{
"name": "rdst_query_delete",
"description": """Delete a query from the registry.
Removes a saved query by name or hash.
Use --force to skip confirmation prompt.
""",
"inputSchema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Query name to delete"
},
"hash": {
"type": "string",
"description": "Query hash to delete (alternative to name)"
},
"force": {
"type": "boolean",
"description": "Skip confirmation prompt"
}
},
"required": []
}
},
{
"name": "rdst_version",
"description": """Show RDST version information.
Displays the installed version of RDST. Use this to:
- Verify RDST is installed correctly
- Check if an upgrade is available
- Report version for troubleshooting
To upgrade: pip install --upgrade rdst
""",
"inputSchema": {
"type": "object",
"properties": {},
"required": []
}
},
{
"name": "rdst_read_config",
"description": """Read the RDST configuration file.
Returns the contents of ~/.rdst/config.toml which contains:
- Database target configurations
- Default target setting
- LLM provider settings
Use this to understand:
- What targets are configured
- Which environment variables are needed for passwords
- What the current default target is
NOTE: Passwords are never stored in config - only password_env variable names.
""",
"inputSchema": {
"type": "object",
"properties": {},
"required": []
}
},
{
"name": "rdst_set_env",
"description": """Set an environment variable for database password authentication.
When a target's password_env is not set, use this tool to set it so that
subsequent RDST commands can authenticate to the database.
WORKFLOW:
1. Call rdst_help to see which targets need passwords
2. Ask the user for the password value
3. Call rdst_set_env with the env var name and password value
4. Now rdst_analyze, rdst_top, etc. will work for that target
The env var persists for the lifetime of this MCP session.
""",
"inputSchema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Environment variable name (e.g., PROD_DB_PASSWORD)"
},
"value": {
"type": "string",
"description": "The value to set (e.g., the actual password)"
}
},
"required": ["name", "value"]
}
},
{
"name": "rdst_help",
"description": """Get RDST status and configured targets.
MCP-only tool (no CLI equivalent). Shows configured database targets and setup status.
This tool:
1. Reads the user's RDST configuration
2. Checks which password environment variables are set vs missing
3. Returns a summary of configured targets and their readiness
4. Provides guidance on what the user can do next
After calling this tool, you'll know:
- Which database targets are available
- Which ones are ready to use (env vars set)
- What actions you can take to help the user
""",
"inputSchema": {
"type": "object",
"properties": {},
"required": []
}
},
{
"name": "rdst_test_connection",
"description": """Test database connection for a configured target.
Use this after rdst_configure_add to verify the password is correct and the
database is reachable. Returns a simple success/failure with details.
WORKFLOW:
1. Configure a target with rdst_configure_add (uses --skip-verify)
2. Set the password with rdst_set_env
3. Call rdst_test_connection to verify connectivity
4. If successful, the target is ready for rdst_analyze and rdst_top
COMMON FAILURE REASONS:
- Password env var not set → Use rdst_set_env first
- Wrong password → Ask user to verify the password
- Connection refused → Check host/port, firewall rules
- Timeout → Database may be unreachable or slow
Returns JSON:
{
"connected": true/false,
"target": "target-name",
"engine": "postgresql/mysql",
"host": "host:port",
"database": "database-name",
"server_version": "PostgreSQL 15.2..." (if connected),
"error": "error message" (if failed)
}
""",
"inputSchema": {
"type": "object",
"properties": {
"target": {
"type": "string",
"description": "Name of the target to test (uses default if not specified)"
}
},
"required": []
}
},
{
"name": "rdst_report",
"description": """Submit feedback about RDST or a specific query analysis.
Use this when the user wants to:
- Report a bug or issue with RDST
- Provide feedback (positive or negative) about analysis results
- Suggest improvements or features
The feedback is sent to the RDST team for review. Users can optionally
include their email for follow-up.
WORKFLOW:
1. Ask the user what feedback they want to provide
2. Ask if it's positive or negative feedback
3. Optionally ask for their email if they want follow-up
4. Call rdst_report with the details
Example: User says "The index recommendation was wrong"
→ Call rdst_report(reason="Index recommendation was incorrect - suggested index already exists", negative=True)
""",
"inputSchema": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"description": "The feedback message describing the issue or suggestion"
},
"hash": {
"type": "string",
"description": "Query hash if feedback is about a specific analysis (optional)"
},
"email": {
"type": "string",
"description": "User's email for follow-up (optional)"
},
"positive": {
"type": "boolean",
"description": "Set to true for positive feedback"
},
"negative": {
"type": "boolean",
"description": "Set to true for negative feedback"
},
"include_query": {
"type": "boolean",
"description": "Include the raw SQL in the feedback (if hash provided)"
},
"include_plan": {
"type": "boolean",
"description": "Include the execution plan in the feedback (if hash provided)"
}
},
"required": ["reason"]
}
},
{
"name": "rdst_init",
"description": """Run the RDST first-time setup wizard.
This interactive wizard helps new users configure RDST by:
1. Setting up the LLM provider (Claude, OpenAI, LM Studio, or free RDST trial)
2. Adding their first database target
3. Testing the connection
The init wizard includes the trial signup option - users without an
ANTHROPIC_API_KEY can sign up for free RDST trial credits during init.
Trial credits: $5.00 for business emails, $1.50 for personal emails.
Use this when:
- User is setting up RDST for the first time
- User wants to reconfigure their LLM provider
- User says "help me set up RDST" or similar
NOTE: This runs an interactive wizard - best used when the user
explicitly asks to set up or reconfigure RDST. Tell the user to run
`rdst init` in their terminal for the full interactive experience.
""",
"inputSchema": {
"type": "object",
"properties": {},
"required": []
}
},
{
"name": "rdst_schema",
"description": """Manage semantic layer for better SQL generation.
The semantic layer stores information about your database schema including:
- Table and column descriptions
- Enum value meanings
- Business terminology
- Relationships between tables
This metadata helps generate better SQL queries and understand the database.
SUBCOMMANDS (available via MCP):
- show: Display semantic layer (all or specific table)
- init: Initialize from database introspection
- export: Export as YAML/JSON
- delete: Remove semantic layer
- list: List all semantic layers
CLI-ONLY FEATURES (tell user to run these in their terminal):
- `rdst schema annotate --target <target>` - Interactive wizard to add descriptions
- `rdst schema annotate --target <target> --use-llm` - AI-generated descriptions
- `rdst schema edit --target <target>` - Opens in $EDITOR
- `rdst ask "question" --target <target>` - Natural language to SQL (interactive)
The `rdst ask` command converts natural language questions into SQL queries.
It requires an interactive terminal for its multi-step flow (clarifications,
execution confirmation, result display). Tell users to run it directly in CLI.
EXAMPLES:
rdst_schema(subcommand="init", target="mydb")
rdst_schema(subcommand="show", target="mydb", table="customers")
rdst_schema(subcommand="export", target="mydb", output_format="yaml")
""",
"inputSchema": {
"type": "object",
"properties": {
"subcommand": {
"type": "string",
"enum": ["show", "init", "export", "delete", "list"],
"description": "Schema subcommand to run (annotate/edit require CLI)"
},
"target": {
"type": "string",
"description": "Database target name"
},
"table": {
"type": "string",
"description": "Specific table (for show)"
},
"force": {
"type": "boolean",
"description": "Overwrite existing (for init, delete)"
},
"output_format": {
"type": "string",
"enum": ["yaml", "json"],
"description": "Export format (for export)"
}
},
"required": ["subcommand"]
}
},
{
"name": "rdst_agent_list",
"description": """List all configured data agents.
Data agents provide safe, scalable database access for AI applications.
Each agent wraps a database target with safety policies like row limits,
column restrictions, and read-only enforcement.
Use this to see what agents are available for querying.