@neverinfamous/mysql-mcp 2.2.0 → 2.3.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.
Files changed (213) hide show
  1. package/.github/workflows/docker-publish.yml +1 -2
  2. package/CHANGELOG.md +85 -0
  3. package/CODE_MODE.md +245 -0
  4. package/DOCKER_README.md +59 -36
  5. package/README.md +65 -42
  6. package/VERSION +1 -1
  7. package/dist/adapters/mysql/MySQLAdapter.d.ts +4 -0
  8. package/dist/adapters/mysql/MySQLAdapter.d.ts.map +1 -1
  9. package/dist/adapters/mysql/MySQLAdapter.js +9 -0
  10. package/dist/adapters/mysql/MySQLAdapter.js.map +1 -1
  11. package/dist/adapters/mysql/prompts/index.d.ts +8 -1
  12. package/dist/adapters/mysql/prompts/index.d.ts.map +1 -1
  13. package/dist/adapters/mysql/prompts/index.js +8 -1
  14. package/dist/adapters/mysql/prompts/index.js.map +1 -1
  15. package/dist/adapters/mysql/prompts/routerSetup.d.ts.map +1 -1
  16. package/dist/adapters/mysql/prompts/routerSetup.js +5 -0
  17. package/dist/adapters/mysql/prompts/routerSetup.js.map +1 -1
  18. package/dist/adapters/mysql/resources/capabilities.d.ts.map +1 -1
  19. package/dist/adapters/mysql/resources/capabilities.js +6 -5
  20. package/dist/adapters/mysql/resources/capabilities.js.map +1 -1
  21. package/dist/adapters/mysql/resources/index.d.ts +9 -1
  22. package/dist/adapters/mysql/resources/index.d.ts.map +1 -1
  23. package/dist/adapters/mysql/resources/index.js +9 -1
  24. package/dist/adapters/mysql/resources/index.js.map +1 -1
  25. package/dist/adapters/mysql/tools/admin/backup.d.ts.map +1 -1
  26. package/dist/adapters/mysql/tools/admin/backup.js +3 -3
  27. package/dist/adapters/mysql/tools/admin/backup.js.map +1 -1
  28. package/dist/adapters/mysql/tools/admin/maintenance.d.ts.map +1 -1
  29. package/dist/adapters/mysql/tools/admin/maintenance.js +5 -5
  30. package/dist/adapters/mysql/tools/admin/maintenance.js.map +1 -1
  31. package/dist/adapters/mysql/tools/cluster/innodb-cluster.d.ts.map +1 -1
  32. package/dist/adapters/mysql/tools/cluster/innodb-cluster.js +26 -5
  33. package/dist/adapters/mysql/tools/cluster/innodb-cluster.js.map +1 -1
  34. package/dist/adapters/mysql/tools/codemode/index.d.ts +38 -0
  35. package/dist/adapters/mysql/tools/codemode/index.d.ts.map +1 -0
  36. package/dist/adapters/mysql/tools/codemode/index.js +203 -0
  37. package/dist/adapters/mysql/tools/codemode/index.js.map +1 -0
  38. package/dist/adapters/mysql/tools/core.d.ts.map +1 -1
  39. package/dist/adapters/mysql/tools/core.js +32 -20
  40. package/dist/adapters/mysql/tools/core.js.map +1 -1
  41. package/dist/adapters/mysql/tools/events.js +18 -6
  42. package/dist/adapters/mysql/tools/events.js.map +1 -1
  43. package/dist/adapters/mysql/tools/json/core.d.ts.map +1 -1
  44. package/dist/adapters/mysql/tools/json/core.js +5 -5
  45. package/dist/adapters/mysql/tools/json/core.js.map +1 -1
  46. package/dist/adapters/mysql/tools/json/helpers.d.ts.map +1 -1
  47. package/dist/adapters/mysql/tools/json/helpers.js +9 -3
  48. package/dist/adapters/mysql/tools/json/helpers.js.map +1 -1
  49. package/dist/adapters/mysql/tools/partitioning.d.ts.map +1 -1
  50. package/dist/adapters/mysql/tools/partitioning.js +38 -6
  51. package/dist/adapters/mysql/tools/partitioning.js.map +1 -1
  52. package/dist/adapters/mysql/tools/performance/analysis.d.ts.map +1 -1
  53. package/dist/adapters/mysql/tools/performance/analysis.js +67 -20
  54. package/dist/adapters/mysql/tools/performance/analysis.js.map +1 -1
  55. package/dist/adapters/mysql/tools/performance/optimization.d.ts.map +1 -1
  56. package/dist/adapters/mysql/tools/performance/optimization.js +36 -6
  57. package/dist/adapters/mysql/tools/performance/optimization.js.map +1 -1
  58. package/dist/adapters/mysql/tools/security/data-protection.d.ts.map +1 -1
  59. package/dist/adapters/mysql/tools/security/data-protection.js +9 -4
  60. package/dist/adapters/mysql/tools/security/data-protection.js.map +1 -1
  61. package/dist/adapters/mysql/tools/shell/common.d.ts.map +1 -1
  62. package/dist/adapters/mysql/tools/shell/common.js +28 -2
  63. package/dist/adapters/mysql/tools/shell/common.js.map +1 -1
  64. package/dist/adapters/mysql/tools/shell/restore.d.ts.map +1 -1
  65. package/dist/adapters/mysql/tools/shell/restore.js +54 -4
  66. package/dist/adapters/mysql/tools/shell/restore.js.map +1 -1
  67. package/dist/adapters/mysql/tools/spatial/operations.d.ts.map +1 -1
  68. package/dist/adapters/mysql/tools/spatial/operations.js +10 -2
  69. package/dist/adapters/mysql/tools/spatial/operations.js.map +1 -1
  70. package/dist/adapters/mysql/tools/spatial/setup.d.ts.map +1 -1
  71. package/dist/adapters/mysql/tools/spatial/setup.js +18 -0
  72. package/dist/adapters/mysql/tools/spatial/setup.js.map +1 -1
  73. package/dist/adapters/mysql/tools/sysschema/resources.d.ts.map +1 -1
  74. package/dist/adapters/mysql/tools/sysschema/resources.js +5 -0
  75. package/dist/adapters/mysql/tools/sysschema/resources.js.map +1 -1
  76. package/dist/adapters/mysql/tools/text/fulltext.d.ts.map +1 -1
  77. package/dist/adapters/mysql/tools/text/fulltext.js +6 -4
  78. package/dist/adapters/mysql/tools/text/fulltext.js.map +1 -1
  79. package/dist/adapters/mysql/tools/text/processing.d.ts.map +1 -1
  80. package/dist/adapters/mysql/tools/text/processing.js +10 -45
  81. package/dist/adapters/mysql/tools/text/processing.js.map +1 -1
  82. package/dist/adapters/mysql/tools/transactions.d.ts.map +1 -1
  83. package/dist/adapters/mysql/tools/transactions.js +8 -8
  84. package/dist/adapters/mysql/tools/transactions.js.map +1 -1
  85. package/dist/adapters/mysql/types.d.ts +968 -78
  86. package/dist/adapters/mysql/types.d.ts.map +1 -1
  87. package/dist/adapters/mysql/types.js +1084 -78
  88. package/dist/adapters/mysql/types.js.map +1 -1
  89. package/dist/auth/scopes.d.ts.map +1 -1
  90. package/dist/auth/scopes.js +1 -0
  91. package/dist/auth/scopes.js.map +1 -1
  92. package/dist/cli/args.d.ts.map +1 -1
  93. package/dist/cli/args.js +12 -0
  94. package/dist/cli/args.js.map +1 -1
  95. package/dist/codemode/api.d.ts +69 -0
  96. package/dist/codemode/api.d.ts.map +1 -0
  97. package/dist/codemode/api.js +1035 -0
  98. package/dist/codemode/api.js.map +1 -0
  99. package/dist/codemode/index.d.ts +13 -0
  100. package/dist/codemode/index.d.ts.map +1 -0
  101. package/dist/codemode/index.js +17 -0
  102. package/dist/codemode/index.js.map +1 -0
  103. package/dist/codemode/sandbox-factory.d.ts +72 -0
  104. package/dist/codemode/sandbox-factory.d.ts.map +1 -0
  105. package/dist/codemode/sandbox-factory.js +88 -0
  106. package/dist/codemode/sandbox-factory.js.map +1 -0
  107. package/dist/codemode/sandbox.d.ts +96 -0
  108. package/dist/codemode/sandbox.d.ts.map +1 -0
  109. package/dist/codemode/sandbox.js +345 -0
  110. package/dist/codemode/sandbox.js.map +1 -0
  111. package/dist/codemode/security.d.ts +44 -0
  112. package/dist/codemode/security.d.ts.map +1 -0
  113. package/dist/codemode/security.js +149 -0
  114. package/dist/codemode/security.js.map +1 -0
  115. package/dist/codemode/types.d.ts +137 -0
  116. package/dist/codemode/types.d.ts.map +1 -0
  117. package/dist/codemode/types.js +46 -0
  118. package/dist/codemode/types.js.map +1 -0
  119. package/dist/codemode/worker-sandbox.d.ts +82 -0
  120. package/dist/codemode/worker-sandbox.d.ts.map +1 -0
  121. package/dist/codemode/worker-sandbox.js +244 -0
  122. package/dist/codemode/worker-sandbox.js.map +1 -0
  123. package/dist/codemode/worker-script.d.ts +8 -0
  124. package/dist/codemode/worker-script.d.ts.map +1 -0
  125. package/dist/codemode/worker-script.js +113 -0
  126. package/dist/codemode/worker-script.js.map +1 -0
  127. package/dist/constants/ServerInstructions.d.ts +1 -1
  128. package/dist/constants/ServerInstructions.d.ts.map +1 -1
  129. package/dist/constants/ServerInstructions.js +33 -9
  130. package/dist/constants/ServerInstructions.js.map +1 -1
  131. package/dist/filtering/ToolConstants.d.ts +11 -11
  132. package/dist/filtering/ToolConstants.d.ts.map +1 -1
  133. package/dist/filtering/ToolConstants.js +37 -19
  134. package/dist/filtering/ToolConstants.js.map +1 -1
  135. package/dist/filtering/ToolFilter.d.ts.map +1 -1
  136. package/dist/filtering/ToolFilter.js +12 -0
  137. package/dist/filtering/ToolFilter.js.map +1 -1
  138. package/dist/server/McpServer.js +1 -1
  139. package/dist/server/McpServer.js.map +1 -1
  140. package/dist/types/modules/server.d.ts +2 -0
  141. package/dist/types/modules/server.d.ts.map +1 -1
  142. package/dist/types/modules/tools.d.ts +1 -1
  143. package/dist/types/modules/tools.d.ts.map +1 -1
  144. package/dist/utils/logger.d.ts +1 -1
  145. package/dist/utils/logger.d.ts.map +1 -1
  146. package/dist/utils/logger.js.map +1 -1
  147. package/package.json +12 -7
  148. package/releases/v2.2.0-release-notes.md +18 -18
  149. package/releases/v2.3.0-release-notes.md +191 -0
  150. package/src/__tests__/perf.test.ts +12 -12
  151. package/src/adapters/mysql/MySQLAdapter.ts +10 -0
  152. package/src/adapters/mysql/__tests__/MySQLAdapter.test.ts +1 -1
  153. package/src/adapters/mysql/prompts/index.ts +8 -1
  154. package/src/adapters/mysql/prompts/routerSetup.ts +5 -0
  155. package/src/adapters/mysql/resources/__tests__/capabilities.test.ts +50 -1
  156. package/src/adapters/mysql/resources/capabilities.ts +6 -4
  157. package/src/adapters/mysql/resources/index.ts +9 -1
  158. package/src/adapters/mysql/tools/__tests__/core.test.ts +68 -0
  159. package/src/adapters/mysql/tools/__tests__/events.test.ts +56 -2
  160. package/src/adapters/mysql/tools/__tests__/json_core.test.ts +1 -1
  161. package/src/adapters/mysql/tools/__tests__/json_helpers.test.ts +46 -4
  162. package/src/adapters/mysql/tools/__tests__/replication.test.ts +144 -42
  163. package/src/adapters/mysql/tools/__tests__/security.test.ts +39 -0
  164. package/src/adapters/mysql/tools/__tests__/spatial.test.ts +39 -7
  165. package/src/adapters/mysql/tools/__tests__/spatial_handler.test.ts +35 -3
  166. package/src/adapters/mysql/tools/__tests__/transactions.test.ts +3 -5
  167. package/src/adapters/mysql/tools/admin/backup.ts +8 -3
  168. package/src/adapters/mysql/tools/admin/maintenance.ts +8 -4
  169. package/src/adapters/mysql/tools/cluster/__tests__/innodb-cluster.test.ts +35 -0
  170. package/src/adapters/mysql/tools/cluster/innodb-cluster.ts +26 -5
  171. package/src/adapters/mysql/tools/codemode/index.ts +249 -0
  172. package/src/adapters/mysql/tools/core.ts +44 -27
  173. package/src/adapters/mysql/tools/events.ts +23 -7
  174. package/src/adapters/mysql/tools/json/__tests__/helpers.test.ts +59 -14
  175. package/src/adapters/mysql/tools/json/core.ts +8 -4
  176. package/src/adapters/mysql/tools/json/helpers.ts +13 -3
  177. package/src/adapters/mysql/tools/partitioning.ts +53 -6
  178. package/src/adapters/mysql/tools/performance/__tests__/analysis.test.ts +227 -4
  179. package/src/adapters/mysql/tools/performance/__tests__/optimization.test.ts +35 -0
  180. package/src/adapters/mysql/tools/performance/analysis.ts +75 -21
  181. package/src/adapters/mysql/tools/performance/optimization.ts +44 -6
  182. package/src/adapters/mysql/tools/security/data-protection.ts +10 -4
  183. package/src/adapters/mysql/tools/shell/__tests__/common.test.ts +46 -0
  184. package/src/adapters/mysql/tools/shell/__tests__/restore.test.ts +28 -1
  185. package/src/adapters/mysql/tools/shell/common.ts +34 -2
  186. package/src/adapters/mysql/tools/shell/restore.ts +70 -7
  187. package/src/adapters/mysql/tools/spatial/__tests__/operations.test.ts +29 -0
  188. package/src/adapters/mysql/tools/spatial/operations.ts +13 -2
  189. package/src/adapters/mysql/tools/spatial/setup.ts +23 -0
  190. package/src/adapters/mysql/tools/sysschema/__tests__/resources.test.ts +21 -0
  191. package/src/adapters/mysql/tools/sysschema/resources.ts +5 -0
  192. package/src/adapters/mysql/tools/text/fulltext.ts +13 -5
  193. package/src/adapters/mysql/tools/text/processing.ts +20 -49
  194. package/src/adapters/mysql/tools/transactions.ts +11 -7
  195. package/src/adapters/mysql/types.ts +1241 -87
  196. package/src/auth/scopes.ts +1 -0
  197. package/src/cli/args.ts +14 -0
  198. package/src/codemode/api.ts +1224 -0
  199. package/src/codemode/index.ts +51 -0
  200. package/src/codemode/sandbox-factory.ts +146 -0
  201. package/src/codemode/sandbox.ts +450 -0
  202. package/src/codemode/security.ts +188 -0
  203. package/src/codemode/types.ts +194 -0
  204. package/src/codemode/worker-sandbox.ts +326 -0
  205. package/src/codemode/worker-script.ts +144 -0
  206. package/src/constants/ServerInstructions.ts +33 -9
  207. package/src/filtering/ToolConstants.ts +37 -19
  208. package/src/filtering/ToolFilter.ts +15 -0
  209. package/src/filtering/__tests__/ToolFilter.test.ts +65 -38
  210. package/src/server/McpServer.ts +1 -1
  211. package/src/types/modules/server.ts +3 -0
  212. package/src/types/modules/tools.ts +2 -1
  213. package/src/utils/logger.ts +2 -1
@@ -2,16 +2,135 @@
2
2
  * MySQL Adapter - Zod Schemas
3
3
  *
4
4
  * Input validation schemas for all MySQL tools.
5
+ *
6
+ * DUAL-SCHEMA PATTERN (Split Schema):
7
+ * Base schemas (SchemaBase) are exported for MCP inputSchema visibility.
8
+ * Transformed schemas (Schema) are exported for handler parsing with alias resolution.
9
+ * This ensures MCP clients see all parameter names (including aliases) while
10
+ * handlers receive normalized data with canonical parameter names.
5
11
  */
6
12
 
7
13
  import { z } from "zod";
8
14
 
15
+ // =============================================================================
16
+ // Preprocess Utilities
17
+ // =============================================================================
18
+
19
+ /**
20
+ * Convert undefined input to empty object for optional-param tools.
21
+ * Used with z.preprocess() to handle tools called with no arguments.
22
+ */
23
+ function defaultToEmpty(input: unknown): unknown {
24
+ return input ?? {};
25
+ }
26
+
27
+ /**
28
+ * Preprocess table parameters:
29
+ * - Alias: tableName/name → table
30
+ */
31
+ function preprocessTableParams(input: unknown): unknown {
32
+ if (typeof input !== "object" || input === null) return input;
33
+ const result = { ...(input as Record<string, unknown>) };
34
+ if (result["table"] === undefined) {
35
+ if (result["tableName"] !== undefined)
36
+ result["table"] = result["tableName"];
37
+ else if (result["name"] !== undefined) result["table"] = result["name"];
38
+ }
39
+ return result;
40
+ }
41
+
42
+ /**
43
+ * Preprocess query parameters:
44
+ * - Alias: sql → query
45
+ * - Alias: tx/txId → transactionId
46
+ */
47
+ function preprocessQueryParams(input: unknown): unknown {
48
+ if (typeof input !== "object" || input === null) return input;
49
+ const result = { ...(input as Record<string, unknown>) };
50
+ if (result["query"] === undefined && result["sql"] !== undefined) {
51
+ result["query"] = result["sql"];
52
+ }
53
+ if (result["transactionId"] === undefined) {
54
+ if (result["txId"] !== undefined) result["transactionId"] = result["txId"];
55
+ else if (result["tx"] !== undefined) result["transactionId"] = result["tx"];
56
+ }
57
+ return result;
58
+ }
59
+
60
+ /**
61
+ * Preprocess transaction ID parameters:
62
+ * - Alias: tx/txId → transactionId
63
+ */
64
+ function preprocessTransactionIdParams(input: unknown): unknown {
65
+ const normalized = defaultToEmpty(input) as Record<string, unknown>;
66
+ if (normalized["transactionId"] === undefined) {
67
+ if (normalized["txId"] !== undefined)
68
+ normalized["transactionId"] = normalized["txId"];
69
+ else if (normalized["tx"] !== undefined)
70
+ normalized["transactionId"] = normalized["tx"];
71
+ }
72
+ return normalized;
73
+ }
74
+
75
+ /**
76
+ * Preprocess savepoint parameters:
77
+ * - Alias: tx/txId → transactionId
78
+ * - Alias: name → savepoint
79
+ */
80
+ function preprocessSavepointParams(input: unknown): unknown {
81
+ if (typeof input !== "object" || input === null) return input;
82
+ const result = { ...(input as Record<string, unknown>) };
83
+ if (result["transactionId"] === undefined) {
84
+ if (result["txId"] !== undefined) result["transactionId"] = result["txId"];
85
+ else if (result["tx"] !== undefined) result["transactionId"] = result["tx"];
86
+ }
87
+ if (result["savepoint"] === undefined && result["name"] !== undefined) {
88
+ result["savepoint"] = result["name"];
89
+ }
90
+ return result;
91
+ }
92
+
93
+ /**
94
+ * Preprocess create table parameters:
95
+ * - Alias: table/tableName → name
96
+ */
97
+ function preprocessCreateTableParams(input: unknown): unknown {
98
+ if (typeof input !== "object" || input === null) return input;
99
+ const result = { ...(input as Record<string, unknown>) };
100
+ if (result["name"] === undefined) {
101
+ if (result["table"] !== undefined) result["name"] = result["table"];
102
+ else if (result["tableName"] !== undefined)
103
+ result["name"] = result["tableName"];
104
+ }
105
+ return result;
106
+ }
107
+
108
+ /**
109
+ * Preprocess transaction execute parameters:
110
+ * - Alias: queries/sqls → statements
111
+ */
112
+ function preprocessTransactionExecuteParams(input: unknown): unknown {
113
+ if (typeof input !== "object" || input === null) return input;
114
+ const result = { ...(input as Record<string, unknown>) };
115
+ if (result["statements"] === undefined) {
116
+ if (result["queries"] !== undefined)
117
+ result["statements"] = result["queries"];
118
+ else if (result["sqls"] !== undefined)
119
+ result["statements"] = result["sqls"];
120
+ }
121
+ return result;
122
+ }
123
+
9
124
  // =============================================================================
10
125
  // Core Tools Schemas
11
126
  // =============================================================================
12
127
 
13
- export const ReadQuerySchema = z.object({
14
- query: z.string().describe("SQL SELECT query to execute"),
128
+ // --- ReadQuery ---
129
+
130
+ // Base schema for MCP visibility (AI sees: query, sql, params, transactionId, txId, tx)
131
+ export const ReadQuerySchemaBase = z.object({
132
+ query: z.string().optional().describe("SQL SELECT query to execute"),
133
+ sql: z.string().optional().describe("Alias for query"),
15
134
  params: z
16
135
  .array(z.unknown())
17
136
  .optional()
@@ -20,10 +139,47 @@ export const ReadQuerySchema = z.object({
20
139
  .string()
21
140
  .optional()
22
141
  .describe("Optional transaction ID for executing within a transaction"),
142
+ txId: z.string().optional().describe("Alias for transactionId"),
143
+ tx: z.string().optional().describe("Alias for transactionId"),
23
144
  });
24
145
 
25
- export const WriteQuerySchema = z.object({
26
- query: z.string().describe("SQL INSERT/UPDATE/DELETE query"),
146
+ // Transformed schema for handler parsing (normalizes aliases)
147
+ export const ReadQuerySchema = z
148
+ .preprocess(
149
+ preprocessQueryParams,
150
+ z.object({
151
+ query: z.string().optional().describe("SQL SELECT query to execute"),
152
+ sql: z.string().optional().describe("Alias for query"),
153
+ params: z
154
+ .array(z.unknown())
155
+ .optional()
156
+ .describe("Query parameters for prepared statement"),
157
+ transactionId: z
158
+ .string()
159
+ .optional()
160
+ .describe("Optional transaction ID for executing within a transaction"),
161
+ txId: z.string().optional().describe("Alias for transactionId"),
162
+ tx: z.string().optional().describe("Alias for transactionId"),
163
+ }),
164
+ )
165
+ .transform((data) => ({
166
+ query: data.query ?? data.sql ?? "",
167
+ params: data.params,
168
+ transactionId: data.transactionId ?? data.txId ?? data.tx,
169
+ }))
170
+ .refine((data) => data.query !== "", {
171
+ message: "query (or sql alias) is required",
172
+ });
173
+
174
+ // --- WriteQuery ---
175
+
176
+ // Base schema for MCP visibility
177
+ export const WriteQuerySchemaBase = z.object({
178
+ query: z
179
+ .string()
180
+ .optional()
181
+ .describe("SQL INSERT/UPDATE/DELETE query to execute"),
182
+ sql: z.string().optional().describe("Alias for query"),
27
183
  params: z
28
184
  .array(z.unknown())
29
185
  .optional()
@@ -32,8 +188,43 @@ export const WriteQuerySchema = z.object({
32
188
  .string()
33
189
  .optional()
34
190
  .describe("Optional transaction ID for executing within a transaction"),
191
+ txId: z.string().optional().describe("Alias for transactionId"),
192
+ tx: z.string().optional().describe("Alias for transactionId"),
35
193
  });
36
194
 
195
+ // Transformed schema for handler parsing
196
+ export const WriteQuerySchema = z
197
+ .preprocess(
198
+ preprocessQueryParams,
199
+ z.object({
200
+ query: z
201
+ .string()
202
+ .optional()
203
+ .describe("SQL INSERT/UPDATE/DELETE query to execute"),
204
+ sql: z.string().optional().describe("Alias for query"),
205
+ params: z
206
+ .array(z.unknown())
207
+ .optional()
208
+ .describe("Query parameters for prepared statement"),
209
+ transactionId: z
210
+ .string()
211
+ .optional()
212
+ .describe("Optional transaction ID for executing within a transaction"),
213
+ txId: z.string().optional().describe("Alias for transactionId"),
214
+ tx: z.string().optional().describe("Alias for transactionId"),
215
+ }),
216
+ )
217
+ .transform((data) => ({
218
+ query: data.query ?? data.sql ?? "",
219
+ params: data.params,
220
+ transactionId: data.transactionId ?? data.txId ?? data.tx,
221
+ }))
222
+ .refine((data) => data.query !== "", {
223
+ message: "query (or sql alias) is required",
224
+ });
225
+
226
+ // --- ListTables ---
227
+
37
228
  export const ListTablesSchema = z.object({
38
229
  database: z
39
230
  .string()
@@ -41,12 +232,32 @@ export const ListTablesSchema = z.object({
41
232
  .describe("Database name (defaults to connected database)"),
42
233
  });
43
234
 
44
- export const DescribeTableSchema = z.object({
45
- table: z.string().describe("Table name to describe"),
235
+ // --- DescribeTable ---
236
+
237
+ // Base schema for MCP visibility
238
+ export const DescribeTableSchemaBase = z.object({
239
+ table: z.string().optional().describe("Table name to describe"),
240
+ tableName: z.string().optional().describe("Alias for table"),
241
+ name: z.string().optional().describe("Alias for table"),
46
242
  });
47
243
 
48
- export const CreateTableSchema = z.object({
49
- name: z.string().describe("Table name"),
244
+ // Transformed schema for handler parsing
245
+ export const DescribeTableSchema = z
246
+ .preprocess(preprocessTableParams, DescribeTableSchemaBase)
247
+ .transform((data) => ({
248
+ table: data.table ?? data.tableName ?? data.name ?? "",
249
+ }))
250
+ .refine((data) => data.table !== "", {
251
+ message: "table (or tableName/name alias) is required",
252
+ });
253
+
254
+ // --- CreateTable ---
255
+
256
+ // Base schema for MCP visibility
257
+ export const CreateTableSchemaBase = z.object({
258
+ name: z.string().optional().describe("Table name"),
259
+ table: z.string().optional().describe("Alias for name"),
260
+ tableName: z.string().optional().describe("Alias for name"),
50
261
  columns: z
51
262
  .array(
52
263
  z.object({
@@ -86,8 +297,29 @@ export const CreateTableSchema = z.object({
86
297
  .describe("Add IF NOT EXISTS clause"),
87
298
  });
88
299
 
89
- export const DropTableSchema = z.object({
90
- table: z.string().describe("Table name to drop"),
300
+ // Transformed schema for handler parsing
301
+ export const CreateTableSchema = z
302
+ .preprocess(preprocessCreateTableParams, CreateTableSchemaBase)
303
+ .transform((data) => ({
304
+ name: data.name ?? data.table ?? data.tableName ?? "",
305
+ columns: data.columns,
306
+ engine: data.engine,
307
+ charset: data.charset,
308
+ collate: data.collate,
309
+ comment: data.comment,
310
+ ifNotExists: data.ifNotExists,
311
+ }))
312
+ .refine((data) => data.name !== "", {
313
+ message: "name (or table/tableName alias) is required",
314
+ });
315
+
316
+ // --- DropTable ---
317
+
318
+ // Base schema for MCP visibility
319
+ export const DropTableSchemaBase = z.object({
320
+ table: z.string().optional().describe("Table name to drop"),
321
+ tableName: z.string().optional().describe("Alias for table"),
322
+ name: z.string().optional().describe("Alias for table"),
91
323
  ifExists: z
92
324
  .boolean()
93
325
  .optional()
@@ -95,9 +327,24 @@ export const DropTableSchema = z.object({
95
327
  .describe("Add IF EXISTS clause"),
96
328
  });
97
329
 
98
- export const CreateIndexSchema = z.object({
330
+ // Transformed schema for handler parsing
331
+ export const DropTableSchema = z
332
+ .preprocess(preprocessTableParams, DropTableSchemaBase)
333
+ .transform((data) => ({
334
+ table: data.table ?? data.tableName ?? data.name ?? "",
335
+ ifExists: data.ifExists,
336
+ }))
337
+ .refine((data) => data.table !== "", {
338
+ message: "table (or tableName/name alias) is required",
339
+ });
340
+
341
+ // --- CreateIndex ---
342
+
343
+ // Base schema for MCP visibility
344
+ export const CreateIndexSchemaBase = z.object({
99
345
  name: z.string().describe("Index name"),
100
- table: z.string().describe("Table name"),
346
+ table: z.string().optional().describe("Table name"),
347
+ tableName: z.string().optional().describe("Alias for table"),
101
348
  columns: z.array(z.string()).describe("Column names to index"),
102
349
  unique: z.boolean().optional().default(false).describe("Create unique index"),
103
350
  type: z
@@ -111,39 +358,115 @@ export const CreateIndexSchema = z.object({
111
358
  .describe("Add IF NOT EXISTS clause"),
112
359
  });
113
360
 
114
- export const GetIndexesSchema = z.object({
115
- table: z.string().describe("Table name"),
361
+ // Transformed schema for handler parsing
362
+ export const CreateIndexSchema = z
363
+ .preprocess(preprocessTableParams, CreateIndexSchemaBase)
364
+ .transform((data) => ({
365
+ name: data.name,
366
+ table: data.table ?? data.tableName ?? "",
367
+ columns: data.columns,
368
+ unique: data.unique,
369
+ type: data.type,
370
+ ifNotExists: data.ifNotExists,
371
+ }))
372
+ .refine((data) => data.table !== "", {
373
+ message: "table (or tableName alias) is required",
374
+ });
375
+
376
+ // --- GetIndexes ---
377
+
378
+ // Base schema for MCP visibility
379
+ export const GetIndexesSchemaBase = z.object({
380
+ table: z.string().optional().describe("Table name"),
381
+ tableName: z.string().optional().describe("Alias for table"),
116
382
  });
117
383
 
384
+ // Transformed schema for handler parsing
385
+ export const GetIndexesSchema = z
386
+ .preprocess(preprocessTableParams, GetIndexesSchemaBase)
387
+ .transform((data) => ({
388
+ table: data.table ?? data.tableName ?? "",
389
+ }))
390
+ .refine((data) => data.table !== "", {
391
+ message: "table (or tableName alias) is required",
392
+ });
393
+
118
394
  // =============================================================================
119
395
  // Transaction Schemas
120
396
  // =============================================================================
121
397
 
122
- export const TransactionBeginSchema = z.object({
123
- isolationLevel: z
124
- .enum([
125
- "READ UNCOMMITTED",
126
- "READ COMMITTED",
127
- "REPEATABLE READ",
128
- "SERIALIZABLE",
129
- ])
398
+ // --- TransactionBegin ---
399
+
400
+ export const TransactionBeginSchema = z.preprocess(
401
+ defaultToEmpty,
402
+ z.object({
403
+ isolationLevel: z
404
+ .enum([
405
+ "READ UNCOMMITTED",
406
+ "READ COMMITTED",
407
+ "REPEATABLE READ",
408
+ "SERIALIZABLE",
409
+ ])
410
+ .optional()
411
+ .describe("Transaction isolation level"),
412
+ }),
413
+ );
414
+
415
+ // --- TransactionId ---
416
+
417
+ // Base schema for MCP visibility
418
+ export const TransactionIdSchemaBase = z.object({
419
+ transactionId: z
420
+ .string()
130
421
  .optional()
131
- .describe("Transaction isolation level"),
422
+ .describe("Transaction ID from begin operation"),
423
+ txId: z.string().optional().describe("Alias for transactionId"),
424
+ tx: z.string().optional().describe("Alias for transactionId"),
132
425
  });
133
426
 
134
- export const TransactionIdSchema = z.object({
135
- transactionId: z.string().describe("Transaction ID from begin operation"),
136
- });
427
+ // Transformed schema for handler parsing
428
+ export const TransactionIdSchema = z
429
+ .preprocess(preprocessTransactionIdParams, TransactionIdSchemaBase)
430
+ .transform((data) => ({
431
+ transactionId: data.transactionId ?? data.txId ?? data.tx ?? "",
432
+ }))
433
+ .refine((data) => data.transactionId !== "", {
434
+ message:
435
+ "transactionId (or txId/tx alias) is required. Get one from mysql_transaction_begin first.",
436
+ });
437
+
438
+ // --- TransactionSavepoint ---
137
439
 
138
- export const TransactionSavepointSchema = z.object({
139
- transactionId: z.string().describe("Transaction ID"),
140
- savepoint: z.string().describe("Savepoint name"),
440
+ // Base schema for MCP visibility
441
+ export const TransactionSavepointSchemaBase = z.object({
442
+ transactionId: z.string().optional().describe("Transaction ID"),
443
+ txId: z.string().optional().describe("Alias for transactionId"),
444
+ tx: z.string().optional().describe("Alias for transactionId"),
445
+ savepoint: z.string().optional().describe("Savepoint name"),
446
+ name: z.string().optional().describe("Alias for savepoint"),
141
447
  });
142
448
 
143
- export const TransactionExecuteSchema = z.object({
449
+ // Transformed schema for handler parsing
450
+ export const TransactionSavepointSchema = z
451
+ .preprocess(preprocessSavepointParams, TransactionSavepointSchemaBase)
452
+ .transform((data) => ({
453
+ transactionId: data.transactionId ?? data.txId ?? data.tx ?? "",
454
+ savepoint: data.savepoint ?? data.name ?? "",
455
+ }))
456
+ .refine((data) => data.transactionId !== "" && data.savepoint !== "", {
457
+ message:
458
+ 'Both transactionId and savepoint are required. Example: {transactionId: "...", savepoint: "sp1"}',
459
+ });
460
+
461
+ // --- TransactionExecute ---
462
+
463
+ // Base schema for MCP visibility
464
+ export const TransactionExecuteSchemaBase = z.object({
144
465
  statements: z
145
466
  .array(z.string())
467
+ .optional()
146
468
  .describe("SQL statements to execute atomically"),
469
+ queries: z.array(z.string()).optional().describe("Alias for statements"),
147
470
  isolationLevel: z
148
471
  .enum([
149
472
  "READ UNCOMMITTED",
@@ -155,41 +478,204 @@ export const TransactionExecuteSchema = z.object({
155
478
  .describe("Transaction isolation level"),
156
479
  });
157
480
 
481
+ // Transformed schema for handler parsing
482
+ export const TransactionExecuteSchema = z
483
+ .preprocess(preprocessTransactionExecuteParams, TransactionExecuteSchemaBase)
484
+ .transform((data) => ({
485
+ statements: data.statements ?? data.queries ?? [],
486
+ isolationLevel: data.isolationLevel,
487
+ }));
488
+
489
+ // =============================================================================
490
+ // Preprocess: JSON/Text column params (table, column, where aliases)
491
+ // =============================================================================
492
+
493
+ function preprocessJsonColumnParams(val: unknown): unknown {
494
+ if (val == null || typeof val !== "object") return val ?? {};
495
+ const v = val as Record<string, unknown>;
496
+ return {
497
+ ...v,
498
+ table: v["table"] ?? v["tableName"] ?? v["name"],
499
+ column: v["column"] ?? v["col"],
500
+ where: v["where"] ?? v["filter"],
501
+ };
502
+ }
503
+
504
+ export function preprocessQueryOnlyParams(val: unknown): unknown {
505
+ if (val == null || typeof val !== "object") return val ?? {};
506
+ const v = val as Record<string, unknown>;
507
+ return {
508
+ ...v,
509
+ query: v["query"] ?? v["sql"],
510
+ };
511
+ }
512
+
158
513
  // =============================================================================
159
514
  // JSON Schemas
160
515
  // =============================================================================
161
516
 
162
- export const JsonExtractSchema = z.object({
163
- table: z.string().describe("Table name"),
164
- column: z.string().describe("JSON column name"),
517
+ // --- JsonExtract ---
518
+ export const JsonExtractSchemaBase = z.object({
519
+ table: z.string().optional().describe("Table name"),
520
+ tableName: z.string().optional().describe("Alias for table"),
521
+ name: z.string().optional().describe("Alias for table"),
522
+ column: z.string().optional().describe("JSON column name"),
523
+ col: z.string().optional().describe("Alias for column"),
165
524
  path: z.string().describe("JSON path (e.g., $.name or $[0])"),
166
525
  where: z.string().optional().describe("WHERE clause for filtering rows"),
526
+ filter: z.string().optional().describe("Alias for where"),
167
527
  });
168
528
 
169
- export const JsonSetSchema = z.object({
170
- table: z.string().describe("Table name"),
171
- column: z.string().describe("JSON column name"),
529
+ export const JsonExtractSchema = z
530
+ .preprocess(
531
+ preprocessJsonColumnParams,
532
+ z.object({
533
+ table: z.string().optional(),
534
+ tableName: z.string().optional(),
535
+ name: z.string().optional(),
536
+ column: z.string().optional(),
537
+ col: z.string().optional(),
538
+ path: z.string(),
539
+ where: z.string().optional(),
540
+ filter: z.string().optional(),
541
+ }),
542
+ )
543
+ .transform((data) => ({
544
+ table: data.table ?? data.tableName ?? data.name ?? "",
545
+ column: data.column ?? data.col ?? "",
546
+ path: data.path,
547
+ where: data.where ?? data.filter,
548
+ }))
549
+ .refine((data) => data.table !== "", {
550
+ message: "table (or tableName/name alias) is required",
551
+ })
552
+ .refine((data) => data.column !== "", {
553
+ message: "column (or col alias) is required",
554
+ });
555
+
556
+ // --- JsonSet ---
557
+ export const JsonSetSchemaBase = z.object({
558
+ table: z.string().optional().describe("Table name"),
559
+ tableName: z.string().optional().describe("Alias for table"),
560
+ name: z.string().optional().describe("Alias for table"),
561
+ column: z.string().optional().describe("JSON column name"),
562
+ col: z.string().optional().describe("Alias for column"),
172
563
  path: z.string().describe("JSON path to set"),
173
564
  value: z.unknown().describe("Value to set"),
174
- where: z.string().describe("WHERE clause to identify rows"),
565
+ where: z.string().optional().describe("WHERE clause to identify rows"),
566
+ filter: z.string().optional().describe("Alias for where"),
175
567
  });
176
568
 
177
- export const JsonContainsSchema = z.object({
178
- table: z.string().describe("Table name"),
179
- column: z.string().describe("JSON column name"),
569
+ export const JsonSetSchema = z
570
+ .preprocess(
571
+ preprocessJsonColumnParams,
572
+ z.object({
573
+ table: z.string().optional(),
574
+ tableName: z.string().optional(),
575
+ name: z.string().optional(),
576
+ column: z.string().optional(),
577
+ col: z.string().optional(),
578
+ path: z.string(),
579
+ value: z.unknown(),
580
+ where: z.string().optional(),
581
+ filter: z.string().optional(),
582
+ }),
583
+ )
584
+ .transform((data) => ({
585
+ table: data.table ?? data.tableName ?? data.name ?? "",
586
+ column: data.column ?? data.col ?? "",
587
+ path: data.path,
588
+ value: data.value,
589
+ where: data.where ?? data.filter ?? "",
590
+ }))
591
+ .refine((data) => data.table !== "", {
592
+ message: "table (or tableName/name alias) is required",
593
+ })
594
+ .refine((data) => data.column !== "", {
595
+ message: "column (or col alias) is required",
596
+ })
597
+ .refine((data) => data.where !== "", {
598
+ message: "where (or filter alias) is required",
599
+ });
600
+
601
+ // --- JsonContains ---
602
+ export const JsonContainsSchemaBase = z.object({
603
+ table: z.string().optional().describe("Table name"),
604
+ tableName: z.string().optional().describe("Alias for table"),
605
+ name: z.string().optional().describe("Alias for table"),
606
+ column: z.string().optional().describe("JSON column name"),
607
+ col: z.string().optional().describe("Alias for column"),
180
608
  value: z.unknown().describe("Value to search for"),
181
609
  path: z.string().optional().describe("Optional JSON path to search within"),
182
610
  });
183
611
 
184
- export const JsonKeysSchema = z.object({
185
- table: z.string().describe("Table name"),
186
- column: z.string().describe("JSON column name"),
612
+ export const JsonContainsSchema = z
613
+ .preprocess(
614
+ preprocessJsonColumnParams,
615
+ z.object({
616
+ table: z.string().optional(),
617
+ tableName: z.string().optional(),
618
+ name: z.string().optional(),
619
+ column: z.string().optional(),
620
+ col: z.string().optional(),
621
+ value: z.unknown(),
622
+ path: z.string().optional(),
623
+ }),
624
+ )
625
+ .transform((data) => ({
626
+ table: data.table ?? data.tableName ?? data.name ?? "",
627
+ column: data.column ?? data.col ?? "",
628
+ value: data.value,
629
+ path: data.path,
630
+ }))
631
+ .refine((data) => data.table !== "", {
632
+ message: "table (or tableName/name alias) is required",
633
+ })
634
+ .refine((data) => data.column !== "", {
635
+ message: "column (or col alias) is required",
636
+ });
637
+
638
+ // --- JsonKeys ---
639
+ export const JsonKeysSchemaBase = z.object({
640
+ table: z.string().optional().describe("Table name"),
641
+ tableName: z.string().optional().describe("Alias for table"),
642
+ name: z.string().optional().describe("Alias for table"),
643
+ column: z.string().optional().describe("JSON column name"),
644
+ col: z.string().optional().describe("Alias for column"),
187
645
  path: z.string().optional().describe("Optional JSON path (defaults to root)"),
188
646
  });
189
647
 
190
- export const JsonSearchSchema = z.object({
191
- table: z.string().describe("Table name"),
192
- column: z.string().describe("JSON column name"),
648
+ export const JsonKeysSchema = z
649
+ .preprocess(
650
+ preprocessJsonColumnParams,
651
+ z.object({
652
+ table: z.string().optional(),
653
+ tableName: z.string().optional(),
654
+ name: z.string().optional(),
655
+ column: z.string().optional(),
656
+ col: z.string().optional(),
657
+ path: z.string().optional(),
658
+ }),
659
+ )
660
+ .transform((data) => ({
661
+ table: data.table ?? data.tableName ?? data.name ?? "",
662
+ column: data.column ?? data.col ?? "",
663
+ path: data.path,
664
+ }))
665
+ .refine((data) => data.table !== "", {
666
+ message: "table (or tableName/name alias) is required",
667
+ })
668
+ .refine((data) => data.column !== "", {
669
+ message: "column (or col alias) is required",
670
+ });
671
+
672
+ // --- JsonSearch ---
673
+ export const JsonSearchSchemaBase = z.object({
674
+ table: z.string().optional().describe("Table name"),
675
+ tableName: z.string().optional().describe("Alias for table"),
676
+ name: z.string().optional().describe("Alias for table"),
677
+ column: z.string().optional().describe("JSON column name"),
678
+ col: z.string().optional().describe("Alias for column"),
193
679
  searchValue: z.string().describe("String value to search for"),
194
680
  mode: z
195
681
  .enum(["one", "all"])
@@ -198,6 +684,33 @@ export const JsonSearchSchema = z.object({
198
684
  .describe("Search mode"),
199
685
  });
200
686
 
687
+ export const JsonSearchSchema = z
688
+ .preprocess(
689
+ preprocessJsonColumnParams,
690
+ z.object({
691
+ table: z.string().optional(),
692
+ tableName: z.string().optional(),
693
+ name: z.string().optional(),
694
+ column: z.string().optional(),
695
+ col: z.string().optional(),
696
+ searchValue: z.string(),
697
+ mode: z.enum(["one", "all"]).optional().default("one"),
698
+ }),
699
+ )
700
+ .transform((data) => ({
701
+ table: data.table ?? data.tableName ?? data.name ?? "",
702
+ column: data.column ?? data.col ?? "",
703
+ searchValue: data.searchValue,
704
+ mode: data.mode,
705
+ }))
706
+ .refine((data) => data.table !== "", {
707
+ message: "table (or tableName/name alias) is required",
708
+ })
709
+ .refine((data) => data.column !== "", {
710
+ message: "column (or col alias) is required",
711
+ });
712
+
713
+ // --- JsonValidate (no table/column — no aliases needed) ---
201
714
  export const JsonValidateSchema = z.object({
202
715
  value: z.string().describe("JSON string to validate"),
203
716
  });
@@ -206,46 +719,317 @@ export const JsonValidateSchema = z.object({
206
719
  // Text Schemas
207
720
  // =============================================================================
208
721
 
209
- export const RegexpMatchSchema = z.object({
210
- table: z.string().describe("Table name"),
211
- column: z.string().describe("Column name"),
722
+ // --- RegexpMatch ---
723
+ export const RegexpMatchSchemaBase = z.object({
724
+ table: z.string().optional().describe("Table name"),
725
+ tableName: z.string().optional().describe("Alias for table"),
726
+ name: z.string().optional().describe("Alias for table"),
727
+ column: z.string().optional().describe("Column name"),
728
+ col: z.string().optional().describe("Alias for column"),
212
729
  pattern: z.string().describe("Regular expression pattern"),
213
730
  where: z
214
731
  .string()
215
732
  .optional()
216
733
  .describe("Additional WHERE clause for filtering"),
734
+ filter: z.string().optional().describe("Alias for where"),
217
735
  });
218
736
 
219
- export const LikeSearchSchema = z.object({
220
- table: z.string().describe("Table name"),
221
- column: z.string().describe("Column name"),
737
+ export const RegexpMatchSchema = z
738
+ .preprocess(
739
+ preprocessJsonColumnParams,
740
+ z.object({
741
+ table: z.string().optional(),
742
+ tableName: z.string().optional(),
743
+ name: z.string().optional(),
744
+ column: z.string().optional(),
745
+ col: z.string().optional(),
746
+ pattern: z.string(),
747
+ where: z.string().optional(),
748
+ filter: z.string().optional(),
749
+ }),
750
+ )
751
+ .transform((data) => ({
752
+ table: data.table ?? data.tableName ?? data.name ?? "",
753
+ column: data.column ?? data.col ?? "",
754
+ pattern: data.pattern,
755
+ where: data.where ?? data.filter,
756
+ }))
757
+ .refine((data) => data.table !== "", {
758
+ message: "table (or tableName/name alias) is required",
759
+ })
760
+ .refine((data) => data.column !== "", {
761
+ message: "column (or col alias) is required",
762
+ });
763
+
764
+ // --- LikeSearch ---
765
+ export const LikeSearchSchemaBase = z.object({
766
+ table: z.string().optional().describe("Table name"),
767
+ tableName: z.string().optional().describe("Alias for table"),
768
+ name: z.string().optional().describe("Alias for table"),
769
+ column: z.string().optional().describe("Column name"),
770
+ col: z.string().optional().describe("Alias for column"),
222
771
  pattern: z.string().describe("LIKE pattern with % and _ wildcards"),
223
772
  where: z
224
773
  .string()
225
774
  .optional()
226
775
  .describe("Additional WHERE clause for filtering"),
776
+ filter: z.string().optional().describe("Alias for where"),
227
777
  });
228
778
 
229
- export const SoundexSchema = z.object({
230
- table: z.string().describe("Table name"),
231
- column: z.string().describe("Column name"),
779
+ export const LikeSearchSchema = z
780
+ .preprocess(
781
+ preprocessJsonColumnParams,
782
+ z.object({
783
+ table: z.string().optional(),
784
+ tableName: z.string().optional(),
785
+ name: z.string().optional(),
786
+ column: z.string().optional(),
787
+ col: z.string().optional(),
788
+ pattern: z.string(),
789
+ where: z.string().optional(),
790
+ filter: z.string().optional(),
791
+ }),
792
+ )
793
+ .transform((data) => ({
794
+ table: data.table ?? data.tableName ?? data.name ?? "",
795
+ column: data.column ?? data.col ?? "",
796
+ pattern: data.pattern,
797
+ where: data.where ?? data.filter,
798
+ }))
799
+ .refine((data) => data.table !== "", {
800
+ message: "table (or tableName/name alias) is required",
801
+ })
802
+ .refine((data) => data.column !== "", {
803
+ message: "column (or col alias) is required",
804
+ });
805
+
806
+ // --- Soundex ---
807
+ export const SoundexSchemaBase = z.object({
808
+ table: z.string().optional().describe("Table name"),
809
+ tableName: z.string().optional().describe("Alias for table"),
810
+ name: z.string().optional().describe("Alias for table"),
811
+ column: z.string().optional().describe("Column name"),
812
+ col: z.string().optional().describe("Alias for column"),
232
813
  value: z.string().describe("Value to match phonetically"),
233
814
  where: z
234
815
  .string()
235
816
  .optional()
236
817
  .describe("Additional WHERE clause for filtering"),
818
+ filter: z.string().optional().describe("Alias for where"),
819
+ });
820
+
821
+ export const SoundexSchema = z
822
+ .preprocess(
823
+ preprocessJsonColumnParams,
824
+ z.object({
825
+ table: z.string().optional(),
826
+ tableName: z.string().optional(),
827
+ name: z.string().optional(),
828
+ column: z.string().optional(),
829
+ col: z.string().optional(),
830
+ value: z.string(),
831
+ where: z.string().optional(),
832
+ filter: z.string().optional(),
833
+ }),
834
+ )
835
+ .transform((data) => ({
836
+ table: data.table ?? data.tableName ?? data.name ?? "",
837
+ column: data.column ?? data.col ?? "",
838
+ value: data.value,
839
+ where: data.where ?? data.filter,
840
+ }))
841
+ .refine((data) => data.table !== "", {
842
+ message: "table (or tableName/name alias) is required",
843
+ })
844
+ .refine((data) => data.column !== "", {
845
+ message: "column (or col alias) is required",
846
+ });
847
+
848
+ // --- Substring ---
849
+ export const SubstringSchemaBase = z.object({
850
+ table: z.string().optional().describe("Table name"),
851
+ tableName: z.string().optional().describe("Alias for table"),
852
+ name: z.string().optional().describe("Alias for table"),
853
+ column: z.string().describe("Column name"),
854
+ start: z.number().describe("Starting position (1-indexed)"),
855
+ length: z.number().optional().describe("Number of characters"),
856
+ where: z
857
+ .string()
858
+ .optional()
859
+ .describe("Additional WHERE clause for filtering"),
860
+ filter: z.string().optional().describe("Alias for where"),
861
+ });
862
+
863
+ export const SubstringSchema = z
864
+ .preprocess(
865
+ preprocessJsonColumnParams,
866
+ z.object({
867
+ table: z.string().optional(),
868
+ tableName: z.string().optional(),
869
+ name: z.string().optional(),
870
+ column: z.string(),
871
+ start: z.number(),
872
+ length: z.number().optional(),
873
+ where: z.string().optional(),
874
+ filter: z.string().optional(),
875
+ }),
876
+ )
877
+ .transform((data) => ({
878
+ table: data.table ?? data.tableName ?? data.name ?? "",
879
+ column: data.column,
880
+ start: data.start,
881
+ length: data.length,
882
+ where: data.where ?? data.filter,
883
+ }))
884
+ .refine((data) => data.table !== "", {
885
+ message: "table (or tableName/name alias) is required",
886
+ });
887
+
888
+ // --- Concat ---
889
+ export const ConcatSchemaBase = z.object({
890
+ table: z.string().optional().describe("Table name"),
891
+ tableName: z.string().optional().describe("Alias for table"),
892
+ name: z.string().optional().describe("Alias for table"),
893
+ columns: z.array(z.string()).describe("Columns to concatenate"),
894
+ separator: z
895
+ .string()
896
+ .optional()
897
+ .default(" ")
898
+ .describe("Separator between values"),
899
+ alias: z
900
+ .string()
901
+ .optional()
902
+ .default("concatenated")
903
+ .describe("Result column name"),
904
+ where: z
905
+ .string()
906
+ .optional()
907
+ .describe("Additional WHERE clause for filtering"),
908
+ filter: z.string().optional().describe("Alias for where"),
909
+ includeSourceColumns: z
910
+ .boolean()
911
+ .optional()
912
+ .default(true)
913
+ .describe(
914
+ "Include individual source columns in output (default: true). Set to false for minimal payload.",
915
+ ),
916
+ });
917
+
918
+ export const ConcatSchema = z
919
+ .preprocess(
920
+ preprocessJsonColumnParams,
921
+ z.object({
922
+ table: z.string().optional(),
923
+ tableName: z.string().optional(),
924
+ name: z.string().optional(),
925
+ columns: z.array(z.string()),
926
+ separator: z.string().optional().default(" "),
927
+ alias: z.string().optional().default("concatenated"),
928
+ where: z.string().optional(),
929
+ filter: z.string().optional(),
930
+ includeSourceColumns: z.boolean().optional().default(true),
931
+ }),
932
+ )
933
+ .transform((data) => ({
934
+ table: data.table ?? data.tableName ?? data.name ?? "",
935
+ columns: data.columns,
936
+ separator: data.separator,
937
+ alias: data.alias,
938
+ where: data.where ?? data.filter,
939
+ includeSourceColumns: data.includeSourceColumns,
940
+ }))
941
+ .refine((data) => data.table !== "", {
942
+ message: "table (or tableName/name alias) is required",
943
+ });
944
+
945
+ // --- CollationConvert ---
946
+ export const CollationConvertSchemaBase = z.object({
947
+ table: z.string().optional().describe("Table name"),
948
+ tableName: z.string().optional().describe("Alias for table"),
949
+ name: z.string().optional().describe("Alias for table"),
950
+ column: z.string().optional().describe("Column name"),
951
+ col: z.string().optional().describe("Alias for column"),
952
+ charset: z.string().describe("Target character set (e.g., utf8mb4)"),
953
+ collation: z.string().optional().describe("Target collation"),
954
+ where: z
955
+ .string()
956
+ .optional()
957
+ .describe("Additional WHERE clause for filtering"),
958
+ filter: z.string().optional().describe("Alias for where"),
237
959
  });
238
960
 
239
- export const FulltextCreateSchema = z.object({
240
- table: z.string().describe("Table name"),
241
- columns: z.array(z.string()).describe("Columns to include in index"),
961
+ export const CollationConvertSchema = z
962
+ .preprocess(
963
+ preprocessJsonColumnParams,
964
+ z.object({
965
+ table: z.string().optional(),
966
+ tableName: z.string().optional(),
967
+ name: z.string().optional(),
968
+ column: z.string().optional(),
969
+ col: z.string().optional(),
970
+ charset: z.string(),
971
+ collation: z.string().optional(),
972
+ where: z.string().optional(),
973
+ filter: z.string().optional(),
974
+ }),
975
+ )
976
+ .transform((data) => ({
977
+ table: data.table ?? data.tableName ?? data.name ?? "",
978
+ column: data.column ?? data.col ?? "",
979
+ charset: data.charset,
980
+ collation: data.collation,
981
+ where: data.where ?? data.filter,
982
+ }))
983
+ .refine((data) => data.table !== "", {
984
+ message: "table (or tableName/name alias) is required",
985
+ })
986
+ .refine((data) => data.column !== "", {
987
+ message: "column (or col alias) is required",
988
+ });
989
+
990
+ // --- FulltextCreate ---
991
+ export const FulltextCreateSchemaBase = z.object({
992
+ table: z.string().optional().describe("Table name"),
993
+ tableName: z.string().optional().describe("Alias for table"),
994
+ name: z.string().optional().describe("Alias for table"),
995
+ columns: z
996
+ .array(z.string())
997
+ .optional()
998
+ .describe("Columns to include in index"),
242
999
  indexName: z.string().optional().describe("Optional index name"),
243
1000
  });
244
1001
 
245
- export const FulltextSearchSchema = z.object({
246
- table: z.string().describe("Table name"),
247
- columns: z.array(z.string()).describe("Columns to search"),
248
- query: z.string().describe("Search query"),
1002
+ export const FulltextCreateSchema = z
1003
+ .preprocess(
1004
+ preprocessTableParams,
1005
+ z.object({
1006
+ table: z.string().optional(),
1007
+ tableName: z.string().optional(),
1008
+ name: z.string().optional(),
1009
+ columns: z.array(z.string()).optional(),
1010
+ indexName: z.string().optional(),
1011
+ }),
1012
+ )
1013
+ .transform((data) => ({
1014
+ table: data.table ?? data.tableName ?? data.name ?? "",
1015
+ columns: data.columns ?? [],
1016
+ indexName: data.indexName,
1017
+ }))
1018
+ .refine((data) => data.table !== "", {
1019
+ message: "table (or tableName/name alias) is required",
1020
+ })
1021
+ .refine((data) => data.columns.length > 0, {
1022
+ message: "columns is required",
1023
+ });
1024
+
1025
+ // --- FulltextSearch ---
1026
+ export const FulltextSearchSchemaBase = z.object({
1027
+ table: z.string().optional().describe("Table name"),
1028
+ tableName: z.string().optional().describe("Alias for table"),
1029
+ name: z.string().optional().describe("Alias for table"),
1030
+ columns: z.array(z.string()).optional().describe("Columns to search"),
1031
+ query: z.string().optional().describe("Search query"),
1032
+ sql: z.string().optional().describe("Alias for query"),
249
1033
  mode: z
250
1034
  .enum(["NATURAL", "BOOLEAN", "EXPANSION"])
251
1035
  .optional()
@@ -253,12 +1037,47 @@ export const FulltextSearchSchema = z.object({
253
1037
  .describe("Search mode"),
254
1038
  });
255
1039
 
1040
+ export const FulltextSearchSchema = z
1041
+ .preprocess(
1042
+ (val) => {
1043
+ const v1 = preprocessTableParams(val);
1044
+ return preprocessQueryOnlyParams(v1);
1045
+ },
1046
+ z.object({
1047
+ table: z.string().optional(),
1048
+ tableName: z.string().optional(),
1049
+ name: z.string().optional(),
1050
+ columns: z.array(z.string()).optional(),
1051
+ query: z.string().optional(),
1052
+ sql: z.string().optional(),
1053
+ mode: z
1054
+ .enum(["NATURAL", "BOOLEAN", "EXPANSION"])
1055
+ .optional()
1056
+ .default("NATURAL"),
1057
+ }),
1058
+ )
1059
+ .transform((data) => ({
1060
+ table: data.table ?? data.tableName ?? data.name ?? "",
1061
+ columns: data.columns ?? [],
1062
+ query: data.query ?? data.sql ?? "",
1063
+ mode: data.mode,
1064
+ }))
1065
+ .refine((data) => data.table !== "", {
1066
+ message: "table (or tableName/name alias) is required",
1067
+ })
1068
+ .refine((data) => data.columns.length > 0, { message: "columns is required" })
1069
+ .refine((data) => data.query !== "", {
1070
+ message: "query (or sql alias) is required",
1071
+ });
1072
+
256
1073
  // =============================================================================
257
1074
  // Performance Schemas
258
1075
  // =============================================================================
259
1076
 
260
- export const ExplainSchema = z.object({
261
- query: z.string().describe("SQL query to explain"),
1077
+ // --- Explain ---
1078
+ export const ExplainSchemaBase = z.object({
1079
+ query: z.string().optional().describe("SQL query to explain"),
1080
+ sql: z.string().optional().describe("Alias for query"),
262
1081
  format: z
263
1082
  .enum(["TRADITIONAL", "JSON", "TREE"])
264
1083
  .optional()
@@ -266,6 +1085,55 @@ export const ExplainSchema = z.object({
266
1085
  .describe("Output format"),
267
1086
  });
268
1087
 
1088
+ export const ExplainSchema = z
1089
+ .preprocess(
1090
+ preprocessQueryOnlyParams,
1091
+ z.object({
1092
+ query: z.string().optional(),
1093
+ sql: z.string().optional(),
1094
+ format: z
1095
+ .enum(["TRADITIONAL", "JSON", "TREE"])
1096
+ .optional()
1097
+ .default("JSON"),
1098
+ }),
1099
+ )
1100
+ .transform((data) => ({
1101
+ query: data.query ?? data.sql ?? "",
1102
+ format: data.format,
1103
+ }))
1104
+ .refine((data) => data.query !== "", {
1105
+ message: "query (or sql alias) is required",
1106
+ });
1107
+
1108
+ // --- ExplainAnalyze ---
1109
+ export const ExplainAnalyzeSchemaBase = z.object({
1110
+ query: z.string().optional().describe("SQL query to analyze"),
1111
+ sql: z.string().optional().describe("Alias for query"),
1112
+ format: z
1113
+ .enum(["JSON", "TREE"])
1114
+ .optional()
1115
+ .default("TREE")
1116
+ .describe("Output format"),
1117
+ });
1118
+
1119
+ export const ExplainAnalyzeSchema = z
1120
+ .preprocess(
1121
+ preprocessQueryOnlyParams,
1122
+ z.object({
1123
+ query: z.string().optional(),
1124
+ sql: z.string().optional(),
1125
+ format: z.enum(["JSON", "TREE"]).optional().default("TREE"),
1126
+ }),
1127
+ )
1128
+ .transform((data) => ({
1129
+ query: data.query ?? data.sql ?? "",
1130
+ format: data.format,
1131
+ }))
1132
+ .refine((data) => data.query !== "", {
1133
+ message: "query (or sql alias) is required",
1134
+ });
1135
+
1136
+ // --- SlowQuery (no table/query aliases — simple passthrough) ---
269
1137
  export const SlowQuerySchema = z.object({
270
1138
  limit: z
271
1139
  .number()
@@ -275,8 +1143,11 @@ export const SlowQuerySchema = z.object({
275
1143
  minTime: z.number().optional().describe("Minimum query time in seconds"),
276
1144
  });
277
1145
 
278
- export const IndexUsageSchema = z.object({
1146
+ // --- IndexUsage ---
1147
+ export const IndexUsageSchemaBase = z.object({
279
1148
  table: z.string().optional().describe("Filter by table name"),
1149
+ tableName: z.string().optional().describe("Alias for table"),
1150
+ name: z.string().optional().describe("Alias for table"),
280
1151
  limit: z
281
1152
  .number()
282
1153
  .int()
@@ -286,37 +1157,177 @@ export const IndexUsageSchema = z.object({
286
1157
  .describe("Maximum number of indexes to return"),
287
1158
  });
288
1159
 
289
- export const TableStatsSchema = z.object({
290
- table: z.string().describe("Table name"),
1160
+ export const IndexUsageSchema = z
1161
+ .preprocess(
1162
+ preprocessTableParams,
1163
+ z.object({
1164
+ table: z.string().optional(),
1165
+ tableName: z.string().optional(),
1166
+ name: z.string().optional(),
1167
+ limit: z.number().int().positive().optional().default(10),
1168
+ }),
1169
+ )
1170
+ .transform((data) => ({
1171
+ table: data.table ?? data.tableName ?? data.name,
1172
+ limit: data.limit,
1173
+ }));
1174
+
1175
+ // --- TableStats ---
1176
+ export const TableStatsSchemaBase = z.object({
1177
+ table: z.string().optional().describe("Table name"),
1178
+ tableName: z.string().optional().describe("Alias for table"),
1179
+ name: z.string().optional().describe("Alias for table"),
291
1180
  });
292
1181
 
1182
+ export const TableStatsSchema = z
1183
+ .preprocess(
1184
+ preprocessTableParams,
1185
+ z.object({
1186
+ table: z.string().optional(),
1187
+ tableName: z.string().optional(),
1188
+ name: z.string().optional(),
1189
+ }),
1190
+ )
1191
+ .transform((data) => ({
1192
+ table: data.table ?? data.tableName ?? data.name ?? "",
1193
+ }))
1194
+ .refine((data) => data.table !== "", {
1195
+ message: "table (or tableName/name alias) is required",
1196
+ });
1197
+
1198
+ // =============================================================================
1199
+ // Preprocess: Admin table params (normalizes singular 'table' to 'tables' array)
1200
+ // =============================================================================
1201
+
1202
+ function preprocessAdminTableParams(val: unknown): unknown {
1203
+ if (val == null || typeof val !== "object") return val ?? {};
1204
+ const v = val as Record<string, unknown>;
1205
+ // If 'table' is passed as a string and 'tables' is not set, wrap it into an array
1206
+ if (typeof v["table"] === "string" && !Array.isArray(v["tables"])) {
1207
+ return { ...v, tables: [v["table"]] };
1208
+ }
1209
+ // Also support tableName/name aliases → tables
1210
+ if (typeof v["tableName"] === "string" && !Array.isArray(v["tables"])) {
1211
+ return { ...v, tables: [v["tableName"]] };
1212
+ }
1213
+ if (typeof v["name"] === "string" && !Array.isArray(v["tables"])) {
1214
+ return { ...v, tables: [v["name"]] };
1215
+ }
1216
+ return v;
1217
+ }
1218
+
293
1219
  // =============================================================================
294
1220
  // Admin Schemas
295
1221
  // =============================================================================
296
1222
 
297
- export const OptimizeTableSchema = z.object({
298
- tables: z.array(z.string()).describe("Table names to optimize"),
1223
+ // --- OptimizeTable ---
1224
+ export const OptimizeTableSchemaBase = z.object({
1225
+ tables: z.array(z.string()).optional().describe("Table names to optimize"),
1226
+ table: z.string().optional().describe("Single table name (alias for tables)"),
1227
+ tableName: z.string().optional().describe("Alias for table"),
1228
+ name: z.string().optional().describe("Alias for table"),
299
1229
  });
300
1230
 
301
- export const AnalyzeTableSchema = z.object({
302
- tables: z.array(z.string()).describe("Table names to analyze"),
1231
+ export const OptimizeTableSchema = z
1232
+ .preprocess(
1233
+ preprocessAdminTableParams,
1234
+ z.object({
1235
+ tables: z.array(z.string()).optional(),
1236
+ table: z.string().optional(),
1237
+ tableName: z.string().optional(),
1238
+ name: z.string().optional(),
1239
+ }),
1240
+ )
1241
+ .transform((data) => ({
1242
+ tables: data.tables ?? [],
1243
+ }))
1244
+ .refine((data) => data.tables.length > 0, {
1245
+ message: "tables (or table/tableName/name alias) is required",
1246
+ });
1247
+
1248
+ // --- AnalyzeTable ---
1249
+ export const AnalyzeTableSchemaBase = z.object({
1250
+ tables: z.array(z.string()).optional().describe("Table names to analyze"),
1251
+ table: z.string().optional().describe("Single table name (alias for tables)"),
1252
+ tableName: z.string().optional().describe("Alias for table"),
1253
+ name: z.string().optional().describe("Alias for table"),
303
1254
  });
304
1255
 
305
- export const CheckTableSchema = z.object({
306
- tables: z.array(z.string()).describe("Table names to check"),
1256
+ export const AnalyzeTableSchema = z
1257
+ .preprocess(
1258
+ preprocessAdminTableParams,
1259
+ z.object({
1260
+ tables: z.array(z.string()).optional(),
1261
+ table: z.string().optional(),
1262
+ tableName: z.string().optional(),
1263
+ name: z.string().optional(),
1264
+ }),
1265
+ )
1266
+ .transform((data) => ({
1267
+ tables: data.tables ?? [],
1268
+ }))
1269
+ .refine((data) => data.tables.length > 0, {
1270
+ message: "tables (or table/tableName/name alias) is required",
1271
+ });
1272
+
1273
+ // --- CheckTable ---
1274
+ export const CheckTableSchemaBase = z.object({
1275
+ tables: z.array(z.string()).optional().describe("Table names to check"),
1276
+ table: z.string().optional().describe("Single table name (alias for tables)"),
1277
+ tableName: z.string().optional().describe("Alias for table"),
1278
+ name: z.string().optional().describe("Alias for table"),
307
1279
  option: z
308
1280
  .enum(["QUICK", "FAST", "MEDIUM", "EXTENDED", "CHANGED"])
309
1281
  .optional()
310
1282
  .describe("Check option"),
311
1283
  });
312
1284
 
313
- export const FlushTablesSchema = z.object({
1285
+ export const CheckTableSchema = z
1286
+ .preprocess(
1287
+ preprocessAdminTableParams,
1288
+ z.object({
1289
+ tables: z.array(z.string()).optional(),
1290
+ table: z.string().optional(),
1291
+ tableName: z.string().optional(),
1292
+ name: z.string().optional(),
1293
+ option: z
1294
+ .enum(["QUICK", "FAST", "MEDIUM", "EXTENDED", "CHANGED"])
1295
+ .optional(),
1296
+ }),
1297
+ )
1298
+ .transform((data) => ({
1299
+ tables: data.tables ?? [],
1300
+ option: data.option,
1301
+ }))
1302
+ .refine((data) => data.tables.length > 0, {
1303
+ message: "tables (or table/tableName/name alias) is required",
1304
+ });
1305
+
1306
+ // --- FlushTables ---
1307
+ export const FlushTablesSchemaBase = z.object({
314
1308
  tables: z
315
1309
  .array(z.string())
316
1310
  .optional()
317
1311
  .describe("Specific tables to flush (empty for all)"),
1312
+ table: z.string().optional().describe("Single table name (alias for tables)"),
1313
+ tableName: z.string().optional().describe("Alias for table"),
1314
+ name: z.string().optional().describe("Alias for table"),
318
1315
  });
319
1316
 
1317
+ export const FlushTablesSchema = z
1318
+ .preprocess(
1319
+ preprocessAdminTableParams,
1320
+ z.object({
1321
+ tables: z.array(z.string()).optional(),
1322
+ table: z.string().optional(),
1323
+ tableName: z.string().optional(),
1324
+ name: z.string().optional(),
1325
+ }),
1326
+ )
1327
+ .transform((data) => ({
1328
+ tables: data.tables,
1329
+ }));
1330
+
320
1331
  export const KillQuerySchema = z.object({
321
1332
  processId: z.number().describe("Process ID to kill"),
322
1333
  connection: z
@@ -364,14 +1375,18 @@ export const ShowVariablesSchema = z.object({
364
1375
  // Backup Schemas
365
1376
  // =============================================================================
366
1377
 
367
- export const ExportTableSchema = z.object({
368
- table: z.string().describe("Table name"),
1378
+ // --- ExportTable ---
1379
+ export const ExportTableSchemaBase = z.object({
1380
+ table: z.string().optional().describe("Table name"),
1381
+ tableName: z.string().optional().describe("Alias for table"),
1382
+ name: z.string().optional().describe("Alias for table"),
369
1383
  format: z
370
1384
  .enum(["SQL", "CSV"])
371
1385
  .optional()
372
1386
  .default("SQL")
373
1387
  .describe("Export format"),
374
1388
  where: z.string().optional().describe("WHERE clause to filter rows"),
1389
+ filter: z.string().optional().describe("Alias for where"),
375
1390
  limit: z
376
1391
  .number()
377
1392
  .int()
@@ -383,13 +1398,57 @@ export const ExportTableSchema = z.object({
383
1398
  ),
384
1399
  });
385
1400
 
386
- export const ImportDataSchema = z.object({
387
- table: z.string().describe("Table name"),
1401
+ export const ExportTableSchema = z
1402
+ .preprocess(
1403
+ preprocessTableParams,
1404
+ z.object({
1405
+ table: z.string().optional(),
1406
+ tableName: z.string().optional(),
1407
+ name: z.string().optional(),
1408
+ format: z.enum(["SQL", "CSV"]).optional().default("SQL"),
1409
+ where: z.string().optional(),
1410
+ filter: z.string().optional(),
1411
+ limit: z.number().int().positive().optional().default(100),
1412
+ }),
1413
+ )
1414
+ .transform((data) => ({
1415
+ table: data.table ?? data.tableName ?? data.name ?? "",
1416
+ format: data.format,
1417
+ where: data.where ?? data.filter,
1418
+ limit: data.limit,
1419
+ }))
1420
+ .refine((data) => data.table !== "", {
1421
+ message: "table (or tableName/name alias) is required",
1422
+ });
1423
+
1424
+ // --- ImportData ---
1425
+ export const ImportDataSchemaBase = z.object({
1426
+ table: z.string().optional().describe("Table name"),
1427
+ tableName: z.string().optional().describe("Alias for table"),
1428
+ name: z.string().optional().describe("Alias for table"),
388
1429
  data: z
389
1430
  .array(z.record(z.string(), z.unknown()))
390
1431
  .describe("Array of row objects to insert"),
391
1432
  });
392
1433
 
1434
+ export const ImportDataSchema = z
1435
+ .preprocess(
1436
+ preprocessTableParams,
1437
+ z.object({
1438
+ table: z.string().optional(),
1439
+ tableName: z.string().optional(),
1440
+ name: z.string().optional(),
1441
+ data: z.array(z.record(z.string(), z.unknown())),
1442
+ }),
1443
+ )
1444
+ .transform((data) => ({
1445
+ table: data.table ?? data.tableName ?? data.name ?? "",
1446
+ data: data.data,
1447
+ }))
1448
+ .refine((data) => data.table !== "", {
1449
+ message: "table (or tableName/name alias) is required",
1450
+ });
1451
+
393
1452
  // =============================================================================
394
1453
  // Replication Schemas
395
1454
  // =============================================================================
@@ -410,12 +1469,34 @@ export const BinlogEventsSchema = z.object({
410
1469
  // Partitioning Schemas
411
1470
  // =============================================================================
412
1471
 
413
- export const PartitionInfoSchema = z.object({
414
- table: z.string().describe("Table name"),
1472
+ // --- PartitionInfo ---
1473
+ export const PartitionInfoSchemaBase = z.object({
1474
+ table: z.string().optional().describe("Table name"),
1475
+ tableName: z.string().optional().describe("Alias for table"),
1476
+ name: z.string().optional().describe("Alias for table"),
415
1477
  });
416
1478
 
417
- export const AddPartitionSchema = z.object({
418
- table: z.string().describe("Table name"),
1479
+ export const PartitionInfoSchema = z
1480
+ .preprocess(
1481
+ preprocessTableParams,
1482
+ z.object({
1483
+ table: z.string().optional(),
1484
+ tableName: z.string().optional(),
1485
+ name: z.string().optional(),
1486
+ }),
1487
+ )
1488
+ .transform((data) => ({
1489
+ table: data.table ?? data.tableName ?? data.name ?? "",
1490
+ }))
1491
+ .refine((data) => data.table !== "", {
1492
+ message: "table (or tableName/name alias) is required",
1493
+ });
1494
+
1495
+ // --- AddPartition ---
1496
+ export const AddPartitionSchemaBase = z.object({
1497
+ table: z.string().optional().describe("Table name"),
1498
+ tableName: z.string().optional().describe("Alias for table"),
1499
+ name: z.string().optional().describe("Alias for table"),
419
1500
  partitionName: z.string().describe("New partition name"),
420
1501
  partitionType: z
421
1502
  .enum(["RANGE", "LIST", "HASH", "KEY"])
@@ -427,16 +1508,62 @@ export const AddPartitionSchema = z.object({
427
1508
  ),
428
1509
  });
429
1510
 
430
- export const DropPartitionSchema = z.object({
431
- table: z.string().describe("Table name"),
1511
+ export const AddPartitionSchema = z
1512
+ .preprocess(
1513
+ preprocessTableParams,
1514
+ z.object({
1515
+ table: z.string().optional(),
1516
+ tableName: z.string().optional(),
1517
+ name: z.string().optional(),
1518
+ partitionName: z.string(),
1519
+ partitionType: z.enum(["RANGE", "LIST", "HASH", "KEY"]),
1520
+ value: z.string(),
1521
+ }),
1522
+ )
1523
+ .transform((data) => ({
1524
+ table: data.table ?? data.tableName ?? data.name ?? "",
1525
+ partitionName: data.partitionName,
1526
+ partitionType: data.partitionType,
1527
+ value: data.value,
1528
+ }))
1529
+ .refine((data) => data.table !== "", {
1530
+ message: "table (or tableName/name alias) is required",
1531
+ });
1532
+
1533
+ // --- DropPartition ---
1534
+ export const DropPartitionSchemaBase = z.object({
1535
+ table: z.string().optional().describe("Table name"),
1536
+ tableName: z.string().optional().describe("Alias for table"),
1537
+ name: z.string().optional().describe("Alias for table"),
432
1538
  partitionName: z.string().describe("Partition name to drop"),
433
1539
  });
434
1540
 
435
- export const ReorganizePartitionSchema = z.object({
436
- table: z.string().describe("Table name"),
1541
+ export const DropPartitionSchema = z
1542
+ .preprocess(
1543
+ preprocessTableParams,
1544
+ z.object({
1545
+ table: z.string().optional(),
1546
+ tableName: z.string().optional(),
1547
+ name: z.string().optional(),
1548
+ partitionName: z.string(),
1549
+ }),
1550
+ )
1551
+ .transform((data) => ({
1552
+ table: data.table ?? data.tableName ?? data.name ?? "",
1553
+ partitionName: data.partitionName,
1554
+ }))
1555
+ .refine((data) => data.table !== "", {
1556
+ message: "table (or tableName/name alias) is required",
1557
+ });
1558
+
1559
+ // --- ReorganizePartition ---
1560
+ export const ReorganizePartitionSchemaBase = z.object({
1561
+ table: z.string().optional().describe("Table name"),
1562
+ tableName: z.string().optional().describe("Alias for table"),
1563
+ name: z.string().optional().describe("Alias for table"),
437
1564
  fromPartitions: z.array(z.string()).describe("Source partition names"),
438
1565
  partitionType: z
439
- .enum(["RANGE", "LIST"])
1566
+ .enum(["RANGE", "LIST", "HASH", "KEY"])
440
1567
  .describe(
441
1568
  "Partition type (RANGE or LIST). HASH/KEY partitions cannot be reorganized.",
442
1569
  ),
@@ -453,3 +1580,30 @@ export const ReorganizePartitionSchema = z.object({
453
1580
  )
454
1581
  .describe("New partition definitions"),
455
1582
  });
1583
+
1584
+ export const ReorganizePartitionSchema = z
1585
+ .preprocess(
1586
+ preprocessTableParams,
1587
+ z.object({
1588
+ table: z.string().optional(),
1589
+ tableName: z.string().optional(),
1590
+ name: z.string().optional(),
1591
+ fromPartitions: z.array(z.string()),
1592
+ partitionType: z.enum(["RANGE", "LIST"]),
1593
+ toPartitions: z.array(
1594
+ z.object({
1595
+ name: z.string(),
1596
+ value: z.string(),
1597
+ }),
1598
+ ),
1599
+ }),
1600
+ )
1601
+ .transform((data) => ({
1602
+ table: data.table ?? data.tableName ?? data.name ?? "",
1603
+ fromPartitions: data.fromPartitions,
1604
+ partitionType: data.partitionType,
1605
+ toPartitions: data.toPartitions,
1606
+ }))
1607
+ .refine((data) => data.table !== "", {
1608
+ message: "table (or tableName/name alias) is required",
1609
+ });