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 +36 -2
- package/package.json +1 -1
- package/src/mcp/server.js +32 -5
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 (
|
|
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.
|
|
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
|
|
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(
|
|
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
|
-
|
|
3732
|
-
|
|
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
|
-
|
|
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 || [];
|