@berthojoris/mcp-mysql-server 1.40.7 → 1.42.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.
@@ -18,7 +18,7 @@ const toolArgumentValidation_js_1 = require("./tools/toolArgumentValidation.js")
18
18
  const permissions = process.env.MCP_PERMISSIONS || process.env.MCP_CONFIG || "";
19
19
  const categories = process.env.MCP_CATEGORIES || "";
20
20
  const SERVER_NAME = "mysql-mcp-server";
21
- const SERVER_VERSION = "1.40.7";
21
+ const SERVER_VERSION = "1.42.0";
22
22
  // Declare the MySQL MCP instance (will be initialized in main())
23
23
  let mysqlMCP;
24
24
  // Define all available tools with their schemas
@@ -406,6 +406,293 @@ const TOOLS = [
406
406
  required: ["table_name", "condition_sets"],
407
407
  },
408
408
  },
409
+ {
410
+ name: "plan_seed_data",
411
+ description: "🌱 RELATIONAL SEEDER: Analyzes target tables, foreign keys, constraints, and row counts to build a safe parent-first seed plan. Use this before generating preview or inserting dummy relational data.",
412
+ inputSchema: {
413
+ type: "object",
414
+ properties: {
415
+ database: {
416
+ type: "string",
417
+ description: "Optional: specific connected database name",
418
+ },
419
+ target_tables: {
420
+ type: "array",
421
+ description: "Target tables to seed",
422
+ minItems: 1,
423
+ items: { type: "string" },
424
+ },
425
+ rows_per_table: {
426
+ oneOf: [
427
+ { type: "number", minimum: 0 },
428
+ { type: "object", additionalProperties: { type: "number", minimum: 0 } },
429
+ ],
430
+ description: "Rows to create for target tables, either a single number or table-to-count map (default: 10)",
431
+ },
432
+ include_dependencies: {
433
+ type: "boolean",
434
+ description: "Include parent tables required by foreign keys (default: true)",
435
+ },
436
+ include_children: {
437
+ type: "boolean",
438
+ description: "Include child tables that reference included tables for nested relational seeding (default: false)",
439
+ },
440
+ child_rows_per_parent: {
441
+ type: "number",
442
+ description: "Rows to create in child tables for each parent row (default: 2)",
443
+ minimum: 1,
444
+ maximum: 20,
445
+ },
446
+ respect_existing_data: {
447
+ type: "boolean",
448
+ description: "Reuse existing parent records when possible instead of creating new parent rows (default: true)",
449
+ },
450
+ strategy: {
451
+ type: "string",
452
+ enum: ["append"],
453
+ description: "Seed strategy (currently append)",
454
+ },
455
+ random_seed: {
456
+ type: "number",
457
+ description: "Deterministic seed for repeatable preview and execution (default: 42)",
458
+ },
459
+ max_rows_per_table: {
460
+ type: "number",
461
+ description: "Safety cap for generated rows per table (default: 1000)",
462
+ minimum: 1,
463
+ maximum: 10000,
464
+ },
465
+ max_related_tables: {
466
+ type: "number",
467
+ description: "Safety cap for dependency/child expansion (default: 25)",
468
+ minimum: 1,
469
+ maximum: 100,
470
+ },
471
+ seed_rules: {
472
+ type: "object",
473
+ description: "Optional generator overrides keyed by table.column or column name",
474
+ additionalProperties: true,
475
+ },
476
+ require_confirmation: {
477
+ type: "boolean",
478
+ description: "Require confirm_token for non-dry-run execution (default: true)",
479
+ },
480
+ },
481
+ required: ["target_tables"],
482
+ },
483
+ },
484
+ {
485
+ name: "generate_seed_preview",
486
+ description: "🌱 RELATIONAL SEEDER: Generates deterministic dummy row previews from a seed plan without writing to the database. Shows symbolic foreign-key placeholders for review before execution.",
487
+ inputSchema: {
488
+ type: "object",
489
+ properties: {
490
+ plan_id: {
491
+ type: "string",
492
+ description: "Seed plan ID returned by plan_seed_data",
493
+ },
494
+ locale: {
495
+ type: "string",
496
+ description: "Optional locale hint for generated values (default: en_US)",
497
+ },
498
+ realistic: {
499
+ type: "boolean",
500
+ description: "Whether to prefer realistic generated values (default: true)",
501
+ },
502
+ max_preview_rows_per_table: {
503
+ type: "number",
504
+ description: "Maximum preview rows per table (default: 3)",
505
+ minimum: 1,
506
+ maximum: 25,
507
+ },
508
+ email_domain: {
509
+ type: "string",
510
+ description: "Safe email domain for generated emails (default: example.test)",
511
+ },
512
+ },
513
+ required: ["plan_id"],
514
+ },
515
+ },
516
+ {
517
+ name: "execute_seed_plan",
518
+ description: "🌱 RELATIONAL SEEDER: Executes a confirmed seed plan with dry-run enabled by default, production-name guard, transaction rollback on errors, and foreign-key ID resolution.",
519
+ inputSchema: {
520
+ type: "object",
521
+ properties: {
522
+ plan_id: {
523
+ type: "string",
524
+ description: "Seed plan ID returned by plan_seed_data",
525
+ },
526
+ dry_run: {
527
+ type: "boolean",
528
+ description: "If true, returns execution preview without inserting rows (default: true)",
529
+ },
530
+ use_transaction: {
531
+ type: "boolean",
532
+ description: "Use a transaction and rollback on error (default: true)",
533
+ },
534
+ batch_size: {
535
+ type: "number",
536
+ description: "Reserved batch-size hint for large plans (default: 1 for ID-safe inserts)",
537
+ minimum: 1,
538
+ maximum: 10000,
539
+ },
540
+ on_error: {
541
+ type: "string",
542
+ enum: ["rollback", "stop"],
543
+ description: "Error behavior (default: rollback)",
544
+ },
545
+ confirm_token: {
546
+ type: "string",
547
+ description: "Confirmation token returned by plan_seed_data; required when dry_run is false",
548
+ },
549
+ allow_production: {
550
+ type: "boolean",
551
+ description: "Allow writes to production-like database names (default: false)",
552
+ },
553
+ email_domain: {
554
+ type: "string",
555
+ description: "Safe email domain for generated emails (default: example.test)",
556
+ },
557
+ },
558
+ required: ["plan_id"],
559
+ },
560
+ },
561
+ {
562
+ name: "validate_seed_integrity",
563
+ description: "🌱 RELATIONAL SEEDER: Validates seed results with FK orphan checks, required-column checks, unique-collision checks, and inserted row-count checks.",
564
+ inputSchema: {
565
+ type: "object",
566
+ properties: {
567
+ plan_id: {
568
+ type: "string",
569
+ description: "Seed plan ID returned by plan_seed_data",
570
+ },
571
+ tables: {
572
+ type: "array",
573
+ description: "Optional table subset to validate",
574
+ items: { type: "string" },
575
+ },
576
+ check_foreign_keys: {
577
+ type: "boolean",
578
+ description: "Check foreign key integrity (default: true)",
579
+ },
580
+ check_orphans: {
581
+ type: "boolean",
582
+ description: "Alias for check_foreign_keys",
583
+ },
584
+ check_required_columns: {
585
+ type: "boolean",
586
+ description: "Check NOT NULL required columns (default: true)",
587
+ },
588
+ check_unique_collisions: {
589
+ type: "boolean",
590
+ description: "Check unique index collisions (default: true)",
591
+ },
592
+ check_row_counts: {
593
+ type: "boolean",
594
+ description: "Check inserted row counts when execution metadata is available (default: true)",
595
+ },
596
+ },
597
+ required: ["plan_id"],
598
+ },
599
+ },
600
+ {
601
+ name: "infer_seed_rules",
602
+ description: "🌱 ADVANCED SEEDER: Infers safe seed generator rules from schema metadata, sample row patterns, unique constraints, and optional ecommerce/POS/CRM domain presets without returning raw PII samples.",
603
+ inputSchema: {
604
+ type: "object",
605
+ properties: {
606
+ database: {
607
+ type: "string",
608
+ description: "Optional: specific connected database name",
609
+ },
610
+ tables: {
611
+ type: "array",
612
+ description: "Optional table subset to analyze; defaults to schema tables up to max_tables",
613
+ items: { type: "string" },
614
+ },
615
+ domain: {
616
+ type: "string",
617
+ enum: ["auto", "generic", "ecommerce", "pos", "crm"],
618
+ description: "Optional domain preset for better business-like dummy data (default: auto)",
619
+ },
620
+ sample_size: {
621
+ type: "number",
622
+ description: "Number of sample rows per table used to infer ranges and enum-like choices (default: 25, max: 100)",
623
+ minimum: 0,
624
+ maximum: 100,
625
+ },
626
+ max_tables: {
627
+ type: "number",
628
+ description: "Maximum number of tables to analyze when tables is omitted (default: 50)",
629
+ minimum: 1,
630
+ maximum: 200,
631
+ },
632
+ },
633
+ },
634
+ },
635
+ {
636
+ name: "seed_from_template",
637
+ description: "🌱 TEMPLATE SEEDER: Creates a plan-first FK-aware seed workflow from ecommerce, POS, or CRM templates. It detects matching tables, applies domain rules, and returns a seed plan for preview/execution.",
638
+ inputSchema: {
639
+ type: "object",
640
+ properties: {
641
+ database: {
642
+ type: "string",
643
+ description: "Optional: specific connected database name",
644
+ },
645
+ template: {
646
+ type: "string",
647
+ enum: ["ecommerce", "pos", "crm"],
648
+ description: "Business seed template to apply",
649
+ },
650
+ scale: {
651
+ type: "string",
652
+ enum: ["small", "medium", "large"],
653
+ description: "Template size preset (default: small)",
654
+ },
655
+ include: {
656
+ type: "array",
657
+ description: "Optional concrete table list to seed instead of auto-detected template matches",
658
+ items: { type: "string" },
659
+ },
660
+ exclude: {
661
+ type: "array",
662
+ description: "Optional table names to ignore during template matching",
663
+ items: { type: "string" },
664
+ },
665
+ rows_per_table: {
666
+ oneOf: [
667
+ { type: "number", minimum: 0 },
668
+ { type: "object", additionalProperties: { type: "number", minimum: 0 } },
669
+ ],
670
+ description: "Optional row-count override for the generated plan",
671
+ },
672
+ include_dependencies: {
673
+ type: "boolean",
674
+ description: "Include parent tables required by foreign keys (default: true)",
675
+ },
676
+ include_children: {
677
+ type: "boolean",
678
+ description: "Include child tables that reference included template tables (default: false)",
679
+ },
680
+ respect_existing_data: {
681
+ type: "boolean",
682
+ description: "Reuse existing parent records when possible instead of creating new parent rows (default: true)",
683
+ },
684
+ random_seed: {
685
+ type: "number",
686
+ description: "Deterministic seed for repeatable preview and execution",
687
+ },
688
+ require_confirmation: {
689
+ type: "boolean",
690
+ description: "Require confirm_token for non-dry-run execution (default: true)",
691
+ },
692
+ },
693
+ required: ["template"],
694
+ },
695
+ },
409
696
  {
410
697
  name: "run_select_query",
411
698
  description: "⚡ PRIMARY TOOL FOR SELECT QUERIES. Executes read-only SELECT statements with parameterization, optimizer hints, query caching, and dry-run mode. Supports complex queries with JOINs, subqueries, and aggregations. ⚠️ ONLY for SELECT - use execute_write_query for INSERT/UPDATE/DELETE, use execute_ddl for CREATE/ALTER/DROP.",
@@ -2048,6 +2335,24 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
2048
2335
  case "bulk_delete":
2049
2336
  result = await mysqlMCP.bulkDelete((args || {}));
2050
2337
  break;
2338
+ case "plan_seed_data":
2339
+ result = await mysqlMCP.planSeedData(args || {});
2340
+ break;
2341
+ case "generate_seed_preview":
2342
+ result = await mysqlMCP.generateSeedPreview(args || {});
2343
+ break;
2344
+ case "execute_seed_plan":
2345
+ result = await mysqlMCP.executeSeedPlan(args || {});
2346
+ break;
2347
+ case "validate_seed_integrity":
2348
+ result = await mysqlMCP.validateSeedIntegrity(args || {});
2349
+ break;
2350
+ case "infer_seed_rules":
2351
+ result = await mysqlMCP.inferSeedRules(args || {});
2352
+ break;
2353
+ case "seed_from_template":
2354
+ result = await mysqlMCP.seedFromTemplate(args || {});
2355
+ break;
2051
2356
  // Query Tools
2052
2357
  case "run_select_query":
2053
2358
  result = await mysqlMCP.runSelectQuery((args || {}));
@@ -0,0 +1,207 @@
1
+ import SecurityLayer from "../security/securityLayer";
2
+ type RowsPerTable = number | Record<string, number>;
3
+ type SeedDomain = "auto" | "generic" | "ecommerce" | "pos" | "crm";
4
+ type SeedTemplate = "ecommerce" | "pos" | "crm";
5
+ type TemplateScale = "small" | "medium" | "large";
6
+ interface SeedRule {
7
+ generator?: string;
8
+ values?: any[];
9
+ value?: any;
10
+ min?: number;
11
+ max?: number;
12
+ start?: string;
13
+ end?: string;
14
+ prefix?: string;
15
+ pattern?: string;
16
+ domain?: string;
17
+ nullable?: boolean;
18
+ source?: string;
19
+ }
20
+ interface TableRequirement {
21
+ table: string;
22
+ rows_to_create: number;
23
+ reason: string;
24
+ existing_rows: number;
25
+ }
26
+ interface SeedPlan {
27
+ plan_id: string;
28
+ database: string;
29
+ dependency_order: string[];
30
+ tables_required: TableRequirement[];
31
+ constraints_detected: {
32
+ foreign_keys: string[];
33
+ unique: string[];
34
+ required_columns: string[];
35
+ };
36
+ seed_rules: Record<string, SeedRule>;
37
+ warnings: string[];
38
+ requires_confirmation: boolean;
39
+ confirm_token: string;
40
+ random_seed: number;
41
+ options: {
42
+ strategy: string;
43
+ respect_existing_data: boolean;
44
+ include_dependencies: boolean;
45
+ include_children: boolean;
46
+ child_rows_per_parent: number;
47
+ max_rows_per_table: number;
48
+ };
49
+ }
50
+ interface PlanSeedDataParams {
51
+ database?: string;
52
+ target_tables: string[];
53
+ rows_per_table?: RowsPerTable;
54
+ include_dependencies?: boolean;
55
+ include_children?: boolean;
56
+ child_rows_per_parent?: number;
57
+ respect_existing_data?: boolean;
58
+ strategy?: "append";
59
+ random_seed?: number;
60
+ max_rows_per_table?: number;
61
+ max_related_tables?: number;
62
+ seed_rules?: Record<string, SeedRule>;
63
+ require_confirmation?: boolean;
64
+ }
65
+ interface GenerateSeedPreviewParams {
66
+ plan_id: string;
67
+ locale?: string;
68
+ realistic?: boolean;
69
+ max_preview_rows_per_table?: number;
70
+ email_domain?: string;
71
+ }
72
+ interface ExecuteSeedPlanParams {
73
+ plan_id: string;
74
+ dry_run?: boolean;
75
+ use_transaction?: boolean;
76
+ batch_size?: number;
77
+ on_error?: "rollback" | "stop";
78
+ confirm_token?: string;
79
+ allow_production?: boolean;
80
+ email_domain?: string;
81
+ }
82
+ interface ValidateSeedIntegrityParams {
83
+ plan_id: string;
84
+ tables?: string[];
85
+ check_foreign_keys?: boolean;
86
+ check_orphans?: boolean;
87
+ check_required_columns?: boolean;
88
+ check_unique_collisions?: boolean;
89
+ check_row_counts?: boolean;
90
+ }
91
+ interface InferSeedRulesParams {
92
+ database?: string;
93
+ tables?: string[];
94
+ domain?: SeedDomain;
95
+ sample_size?: number;
96
+ max_tables?: number;
97
+ }
98
+ interface SeedFromTemplateParams {
99
+ database?: string;
100
+ template: SeedTemplate;
101
+ scale?: TemplateScale;
102
+ include?: string[];
103
+ exclude?: string[];
104
+ rows_per_table?: RowsPerTable;
105
+ include_dependencies?: boolean;
106
+ include_children?: boolean;
107
+ respect_existing_data?: boolean;
108
+ random_seed?: number;
109
+ require_confirmation?: boolean;
110
+ }
111
+ export declare class RelationalSeederTools {
112
+ private static planCounter;
113
+ private db;
114
+ private security;
115
+ private plans;
116
+ constructor(security: SecurityLayer);
117
+ planSeedData(params: PlanSeedDataParams): Promise<{
118
+ status: string;
119
+ data?: SeedPlan;
120
+ error?: string;
121
+ }>;
122
+ generateSeedPreview(params: GenerateSeedPreviewParams): Promise<{
123
+ status: string;
124
+ data?: any;
125
+ error?: string;
126
+ }>;
127
+ executeSeedPlan(params: ExecuteSeedPlanParams): Promise<{
128
+ status: string;
129
+ data?: any;
130
+ error?: string;
131
+ }>;
132
+ validateSeedIntegrity(params: ValidateSeedIntegrityParams): Promise<{
133
+ status: string;
134
+ data?: any;
135
+ error?: string;
136
+ }>;
137
+ inferSeedRules(params: InferSeedRulesParams): Promise<{
138
+ status: string;
139
+ data?: any;
140
+ error?: string;
141
+ }>;
142
+ seedFromTemplate(params: SeedFromTemplateParams): Promise<{
143
+ status: string;
144
+ data?: any;
145
+ error?: string;
146
+ }>;
147
+ private resolveDatabase;
148
+ private loadSchema;
149
+ private groupForeignKeys;
150
+ private topologicalSort;
151
+ private calculateRowsToCreate;
152
+ private buildInferredSeedRules;
153
+ private inferRuleForColumn;
154
+ private detectConstraints;
155
+ private buildPreview;
156
+ private buildRowsForTable;
157
+ private resolveForeignKeyTuple;
158
+ private generateValue;
159
+ private preloadExistingParentIds;
160
+ private ensureIdMapForTable;
161
+ private loadExistingKeyTuples;
162
+ private insertRow;
163
+ private trackInsertedKeys;
164
+ private countForeignKeyOrphans;
165
+ private countNullValues;
166
+ private findUniqueCollisions;
167
+ private getValidationRowCount;
168
+ private getRequiredColumns;
169
+ private shouldSkipColumn;
170
+ private isIntegerColumn;
171
+ private isNumberColumn;
172
+ private isBooleanColumn;
173
+ private extractEnumValues;
174
+ private isForeignKeyColumn;
175
+ private keySignature;
176
+ private formatForeignKey;
177
+ private tupleFromRow;
178
+ private storeTuples;
179
+ private buildTupleWhereClause;
180
+ private getSelectableTables;
181
+ private loadSampleRows;
182
+ private refineRulesFromSamples;
183
+ private isSensitiveColumn;
184
+ private canUseChoiceFromSamples;
185
+ private inferPatternFromSamples;
186
+ private detectDomainFromTables;
187
+ private getDomainRule;
188
+ private detectTemplateTables;
189
+ private getTemplateKeywords;
190
+ private getScaleRows;
191
+ private buildTemplateRules;
192
+ private requirementsToInsertMap;
193
+ private countResolvedForeignKeys;
194
+ private getExplicitOrDefaultRows;
195
+ private assertIdentifier;
196
+ private getStoredPlan;
197
+ private createPlanId;
198
+ private createConfirmToken;
199
+ private isProductionLikeDatabase;
200
+ private clampNumber;
201
+ private makeRng;
202
+ private hashString;
203
+ private truncate;
204
+ private pickPersonName;
205
+ private formatDate;
206
+ }
207
+ export {};