metabase-ai-assistant 3.4.0 → 3.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README_MCP.md CHANGED
@@ -45,7 +45,7 @@ After updating the configuration file, restart your MCP client to load the new s
45
45
 
46
46
  ---
47
47
 
48
- ## Available Tools (107 Total)
48
+ ## Available Tools (111 Total)
49
49
 
50
50
  ### Database Operations
51
51
  - **db_list**: List all databases in Metabase
@@ -55,6 +55,10 @@ After updating the configuration file, restart your MCP client to load the new s
55
55
 
56
56
  ### SQL Operations
57
57
  - **sql_execute**: Execute native SQL query
58
+ - **sql_submit**: Asynchronously create a long-running SQL query job
59
+ - **sql_status**: Check the status of a SQL job
60
+ - **sql_cancel**: Cancel a running SQL job
61
+ - **db_table_profile**: Profile a table (smart dim/ref detection)
58
62
  - **ai_sql_generate**: Generate SQL from natural language description
59
63
  - **ai_sql_optimize**: Optimize SQL query for performance
60
64
  - **ai_sql_explain**: Explain what a SQL query does
@@ -176,6 +180,9 @@ After updating the configuration file, restart your MCP client to load the new s
176
180
  ## Features Summary
177
181
 
178
182
  ### Currently Available
183
+ - **Async Query Management** (for long-running queries)
184
+ - **Smart Response Optimization** (no truncation for DDL/definitions)
185
+ - **Table Profiling** (dim/ref table detection)
179
186
  - Metabase API integration
180
187
  - SQL query execution
181
188
  - Question/Dashboard creation
@@ -209,7 +216,34 @@ After updating the configuration file, restart your MCP client to load the new s
209
216
  ```json
210
217
  {
211
218
  "database_id": 1,
212
- "sql": "SELECT * FROM table_name LIMIT 10"
219
+ "sql": "SELECT * FROM table_name LIMIT 10",
220
+ "full_results": false // Optional: Set true to disable truncation (useful for DDL)
221
+ }
222
+ ```
223
+
224
+ ### sql_submit (Async Query)
225
+ ```json
226
+ {
227
+ "database_id": 1,
228
+ "sql": "SELECT SLEEP(120)",
229
+ "timeout_seconds": 300
230
+ }
231
+ ```
232
+
233
+ ### sql_status
234
+ ```json
235
+ {
236
+ "job_id": "550e8400-e29b-41d4-a716-446655440000"
237
+ }
238
+ ```
239
+
240
+ ### db_table_profile
241
+ ```json
242
+ {
243
+ "database_id": 1,
244
+ "schema": "public",
245
+ "table": "dim_customers",
246
+ "sample_rows": 3
213
247
  }
214
248
  ```
215
249
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metabase-ai-assistant",
3
- "version": "3.4.0",
3
+ "version": "3.4.2",
4
4
  "mcpName": "io.github.enessari/metabase-ai-assistant",
5
5
  "description": "The most powerful MCP Server for Metabase - 111+ tools for AI-powered SQL generation, dashboard automation, user management & enterprise BI. Works with Claude, Cursor, and any MCP-compatible AI.",
6
6
  "main": "src/index.js",
package/src/mcp/server.js CHANGED
@@ -258,6 +258,10 @@ class MetabaseMCPServer {
258
258
  type: 'string',
259
259
  description: 'SQL query to execute',
260
260
  },
261
+ full_results: {
262
+ type: 'boolean',
263
+ description: 'Set to true to disable result truncation (useful for DDL/definitions)',
264
+ },
261
265
  },
262
266
  required: ['database_id', 'sql'],
263
267
  },
@@ -3237,7 +3241,7 @@ class MetabaseMCPServer {
3237
3241
 
3238
3242
  // SQL execution
3239
3243
  case 'sql_execute':
3240
- return await this.handleExecuteSQL(args.database_id, args.sql);
3244
+ return await this.handleExecuteSQL(args);
3241
3245
  case 'sql_submit':
3242
3246
  return await this.handleSQLSubmit(args);
3243
3247
  case 'sql_status':
@@ -3667,9 +3671,13 @@ class MetabaseMCPServer {
3667
3671
  };
3668
3672
  }
3669
3673
 
3670
- async handleExecuteSQL(databaseId, sql) {
3674
+ async handleExecuteSQL(args) {
3671
3675
  await this.ensureInitialized();
3672
3676
 
3677
+ const databaseId = args.database_id;
3678
+ const sql = args.sql;
3679
+ const fullResults = args.full_results === true;
3680
+
3673
3681
  if (this.initError) {
3674
3682
  throw new McpError(ErrorCode.InternalError, `Failed to initialize: ${this.initError.message}`);
3675
3683
  }
@@ -3728,8 +3736,21 @@ class MetabaseMCPServer {
3728
3736
  rows.slice(0, 5).forEach((row) => {
3729
3737
  const formattedRow = row.map(cell => {
3730
3738
  if (cell === null) return 'NULL';
3731
- if (typeof cell === 'string' && cell.length > 30) {
3732
- return cell.substring(0, 27) + '...';
3739
+
3740
+ // Smart truncation logic
3741
+ let truncateLimit = 100; // Increased base limit from 30
3742
+
3743
+ // Disable truncation for small result sets (DDL/procedures) or explicit full_results
3744
+ if (fullResults || rows.length <= 2) {
3745
+ truncateLimit = 50000;
3746
+ }
3747
+ // Check specific DDL-related column names
3748
+ else if (columns.some(c => /definition|ddl|source|create_statement|routine_definition/i.test(c.name))) {
3749
+ truncateLimit = 10000;
3750
+ }
3751
+
3752
+ if (typeof cell === 'string' && cell.length > truncateLimit) {
3753
+ return cell.substring(0, truncateLimit - 3) + '...';
3733
3754
  }
3734
3755
  return String(cell);
3735
3756
  });
@@ -3922,7 +3943,13 @@ class MetabaseMCPServer {
3922
3943
  output += `⏱️ Elapsed: ${elapsedSeconds} seconds\\n`;
3923
3944
 
3924
3945
  if (job.status === 'running' || job.status === 'pending') {
3925
- output += `\\n💡 Query is still running. Check again later or use \`sql_cancel\` to stop.`;
3946
+ let waitSeconds = 3;
3947
+ if (elapsedSeconds > 60) waitSeconds = 30;
3948
+ else if (elapsedSeconds > 30) waitSeconds = 10;
3949
+ else if (elapsedSeconds > 10) waitSeconds = 5;
3950
+
3951
+ output += `\\n💡 Query is still running. Please wait **${waitSeconds} seconds** before checking again.\\n`;
3952
+ output += `(Use \`sql_cancel\` to stop if needed)`;
3926
3953
  } else if (job.status === 'complete') {
3927
3954
  const rows = job.result?.data?.rows || [];
3928
3955
  const columns = job.result?.data?.cols || [];