metabase-ai-assistant 3.4.1 → 3.4.3
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 +5 -1
- package/package.json +1 -1
- package/src/mcp/server.js +37 -3
- package/src/metabase/client.js +33 -0
package/README_MCP.md
CHANGED
|
@@ -180,6 +180,9 @@ After updating the configuration file, restart your MCP client to load the new s
|
|
|
180
180
|
## Features Summary
|
|
181
181
|
|
|
182
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)
|
|
183
186
|
- Metabase API integration
|
|
184
187
|
- SQL query execution
|
|
185
188
|
- Question/Dashboard creation
|
|
@@ -213,7 +216,8 @@ After updating the configuration file, restart your MCP client to load the new s
|
|
|
213
216
|
```json
|
|
214
217
|
{
|
|
215
218
|
"database_id": 1,
|
|
216
|
-
"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)
|
|
217
221
|
}
|
|
218
222
|
```
|
|
219
223
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "metabase-ai-assistant",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.3",
|
|
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
|
@@ -3943,7 +3943,13 @@ class MetabaseMCPServer {
|
|
|
3943
3943
|
output += `⏱️ Elapsed: ${elapsedSeconds} seconds\\n`;
|
|
3944
3944
|
|
|
3945
3945
|
if (job.status === 'running' || job.status === 'pending') {
|
|
3946
|
-
|
|
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)`;
|
|
3947
3953
|
} else if (job.status === 'complete') {
|
|
3948
3954
|
const rows = job.result?.data?.rows || [];
|
|
3949
3955
|
const columns = job.result?.data?.cols || [];
|
|
@@ -4192,11 +4198,39 @@ class MetabaseMCPServer {
|
|
|
4192
4198
|
|
|
4193
4199
|
async handleAddCardToDashboard(args) {
|
|
4194
4200
|
try {
|
|
4201
|
+
// Normalize position parameters (support both flat and nested structure)
|
|
4202
|
+
// AI sometimes sends flat: { row: 0, col: 0, size_x: 4 }
|
|
4203
|
+
// Or nested: { position: { row: 0, col: 0, sizeX: 4 } }
|
|
4204
|
+
let position = args.position || {};
|
|
4205
|
+
|
|
4206
|
+
// If args has direct position props, merge them
|
|
4207
|
+
if (args.row !== undefined) position.row = args.row;
|
|
4208
|
+
if (args.col !== undefined) position.col = args.col;
|
|
4209
|
+
|
|
4210
|
+
// Handle size_x vs sizeX and size_y vs sizeY
|
|
4211
|
+
if (args.size_x !== undefined) position.sizeX = args.size_x;
|
|
4212
|
+
if (args.size_y !== undefined) position.sizeY = args.size_y;
|
|
4213
|
+
if (args.sizeX !== undefined) position.sizeX = args.sizeX;
|
|
4214
|
+
if (args.sizeY !== undefined) position.sizeY = args.sizeY;
|
|
4215
|
+
|
|
4216
|
+
// Map back to format expected by client
|
|
4217
|
+
// The client expects: Options object with optional row, col, sizeX, sizeY
|
|
4218
|
+
// But we need to make sure we pass the right keys to client.addCardToDashboard
|
|
4219
|
+
|
|
4220
|
+
// Create a normalized options object for the client
|
|
4221
|
+
const options = {
|
|
4222
|
+
row: position.row,
|
|
4223
|
+
col: position.col,
|
|
4224
|
+
sizeX: position.sizeX || position.size_x,
|
|
4225
|
+
sizeY: position.sizeY || position.size_y,
|
|
4226
|
+
parameter_mappings: args.parameter_mappings || []
|
|
4227
|
+
};
|
|
4228
|
+
|
|
4195
4229
|
const result = await this.metabaseClient.addCardToDashboard(
|
|
4196
4230
|
args.dashboard_id,
|
|
4197
4231
|
args.question_id,
|
|
4198
|
-
args
|
|
4199
|
-
args.parameter_mappings
|
|
4232
|
+
options, // Pass normalized options instead of raw args
|
|
4233
|
+
args.parameter_mappings // Double pass, just in case (client signature check needed)
|
|
4200
4234
|
);
|
|
4201
4235
|
|
|
4202
4236
|
// VERIFICATION: Check if card was actually added
|
package/src/metabase/client.js
CHANGED
|
@@ -60,6 +60,39 @@ export class MetabaseClient {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Generic request wrapper for Metabase API
|
|
65
|
+
* Used by MCP handlers that need arbitrary API access
|
|
66
|
+
*/
|
|
67
|
+
async request(method, endpoint, data = null, config = {}) {
|
|
68
|
+
await this.ensureAuthenticated();
|
|
69
|
+
|
|
70
|
+
// Normalize method
|
|
71
|
+
const methodUpper = method.toUpperCase();
|
|
72
|
+
|
|
73
|
+
const requestConfig = {
|
|
74
|
+
...config,
|
|
75
|
+
method: methodUpper,
|
|
76
|
+
url: endpoint,
|
|
77
|
+
data: data
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// For GET requests with data, move to params if not already set
|
|
81
|
+
if (methodUpper === 'GET' && data && !requestConfig.params) {
|
|
82
|
+
requestConfig.params = data;
|
|
83
|
+
delete requestConfig.data;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
const response = await this.client.request(requestConfig);
|
|
88
|
+
return response.data;
|
|
89
|
+
} catch (error) {
|
|
90
|
+
const errorMsg = error.response?.data?.message || error.message;
|
|
91
|
+
logger.error(`API Request Failed: ${methodUpper} ${endpoint}`, { error: errorMsg });
|
|
92
|
+
throw new Error(`Metabase API Error: ${errorMsg}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
63
96
|
// Database Operations
|
|
64
97
|
async getDatabases() {
|
|
65
98
|
await this.ensureAuthenticated();
|