metabase-ai-assistant 3.4.2 → 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/package.json +1 -1
- package/src/mcp/server.js +30 -2
- package/src/metabase/client.js +33 -0
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
|
@@ -4198,11 +4198,39 @@ class MetabaseMCPServer {
|
|
|
4198
4198
|
|
|
4199
4199
|
async handleAddCardToDashboard(args) {
|
|
4200
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
|
+
|
|
4201
4229
|
const result = await this.metabaseClient.addCardToDashboard(
|
|
4202
4230
|
args.dashboard_id,
|
|
4203
4231
|
args.question_id,
|
|
4204
|
-
args
|
|
4205
|
-
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)
|
|
4206
4234
|
);
|
|
4207
4235
|
|
|
4208
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();
|