Skip to main content
Glama

export

Export large SQL query results or saved Metabase cards to CSV, JSON, or XLSX format. Automatically saves files to the Downloads/Metabase folder, supporting up to 1 million rows.

Instructions

Unified command to export large SQL query results or saved cards using Metabase export endpoints (supports up to 1M rows). Returns data in specified format (CSV, JSON, or XLSX) and automatically saves to Downloads/Metabase folder.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
database_idNoDatabase ID to export query from (SQL mode only)
queryNoSQL query to execute and export (SQL mode only)
card_idNoID of saved card to export (card mode only)
native_parametersNoParameters for SQL template variables like {{variable_name}} (SQL mode only)
card_parametersNoParameters for filtering card results before export (card mode only). Each parameter must follow Metabase format: {id: "uuid", slug: "param_name", target: ["dimension", ["template-tag", "param_name"]], type: "param_type", value: "param_value"}
formatNoExport format: csv (text), json (structured data), or xlsx (Excel file)csv
filenameNoCustom filename (without extension) for the saved file. If not provided, a timestamp-based name will be used.

Implementation Reference

  • Primary handler function for the 'export' MCP tool. Validates parameters and dispatches to either SQL query export (exportSqlQuery) or card export (exportCard) based on whether card_id or database_id+query is provided. Handles CSV, JSON, XLSX formats.
    export async function handleExport( request: CallToolRequest, requestId: string, apiClient: MetabaseApiClient, logDebug: (message: string, data?: unknown) => void, logInfo: (message: string, data?: unknown) => void, logWarn: (message: string, data?: unknown, error?: Error) => void, logError: (message: string, error: unknown) => void ): Promise<ExportResponse> { const args = request.params?.arguments as ExportRequest; const databaseId = args?.database_id; const query = args?.query; const cardId = args?.card_id; const nativeParameters = Array.isArray(args?.native_parameters) ? args.native_parameters : []; const cardParameters = Array.isArray(args?.card_parameters) ? args.card_parameters : []; const format = validateEnumValue( args?.format || 'csv', ['csv', 'json', 'xlsx'] as const, 'format', requestId, logWarn ); const filename = args?.filename; // Validate that either query+database_id or card_id is provided (but not considering 0 as falsy for this check) if (cardId === undefined && databaseId === undefined) { logWarn('Missing required parameters: either card_id or database_id must be provided', { requestId, }); throw new McpError( ErrorCode.InvalidParams, 'Either card_id or database_id parameter is required' ); } if (cardId !== undefined && databaseId !== undefined) { logWarn('Both card_id and database_id provided - only one is allowed', { requestId }); throw new McpError( ErrorCode.InvalidParams, 'Cannot specify both card_id and database_id - choose one export method' ); } // Validate positive integer parameters if (cardId !== undefined) { validatePositiveInteger(cardId, 'card_id', requestId, logWarn); } if (databaseId !== undefined) { validatePositiveInteger(databaseId, 'database_id', requestId, logWarn); } // Strict parameter validation for card export mode if (cardId !== undefined) { // For card export, only card_id, card_parameters, format, and filename are allowed if (query || databaseId !== undefined || (nativeParameters && nativeParameters.length > 0)) { logWarn('Invalid parameters for card export mode', { requestId, invalidParams: { query: query ? 'provided' : 'not provided', database_id: databaseId ? 'provided' : 'not provided', native_parameters: nativeParameters?.length > 0 ? 'provided' : 'not provided', }, }); throw new McpError( ErrorCode.InvalidParams, 'Card export mode only allows card_id, card_parameters, format, and filename parameters' ); } } // Strict parameter validation for SQL export mode if (databaseId !== undefined) { // For SQL export, only database_id, query, native_parameters, format, and filename are allowed if (cardId !== undefined || (cardParameters && cardParameters.length > 0)) { logWarn('Invalid parameters for SQL export mode', { requestId, invalidParams: { card_id: cardId ? 'provided' : 'not provided', card_parameters: cardParameters?.length > 0 ? 'provided' : 'not provided', }, }); throw new McpError( ErrorCode.InvalidParams, 'SQL export mode only allows database_id, query, native_parameters, format, and filename parameters' ); } } // If exporting a card if (cardId !== undefined) { validatePositiveInteger(cardId, 'card_id', requestId, logWarn); // Validate card parameters format if provided if (cardParameters.length > 0) { try { validateCardParameters(cardParameters, requestId, logWarn); } catch (error) { logWarn(`Card parameter validation failed for card ${cardId}`, { error, requestId }); throw new McpError( ErrorCode.InvalidParams, `Invalid card parameters format. If parameter issues persist, consider using export_query with the card's underlying SQL query instead, which provides more reliable parameter handling. Original error: ${error instanceof Error ? error.message : String(error)}` ); } } const cardParams: CardExportParams = { cardId, cardParameters, format: format as 'csv' | 'json' | 'xlsx', filename, }; return await exportCard(cardParams, requestId, apiClient, logDebug, logInfo, logWarn, logError); } // If exporting a SQL query if (!query || typeof query !== 'string') { logWarn('Missing or invalid query parameter in export request', { requestId }); throw new McpError( ErrorCode.InvalidParams, 'SQL query parameter is required and must be a string' ); } validatePositiveInteger(databaseId, 'database_id', requestId, logWarn); const sqlParams: SqlExportParams = { databaseId: databaseId as number, query, nativeParameters, format: format as 'csv' | 'json' | 'xlsx', filename, }; return await exportSqlQuery( sqlParams, requestId, apiClient, logDebug, logInfo, logWarn, logError ); }
  • Official tool schema served in ListTools response, defining name 'export', description, annotations, and detailed inputSchema matching ExportRequest type.
    name: 'export', description: 'Unified command to export large SQL query results or saved cards using Metabase export endpoints (supports up to 1M rows). Returns data in specified format (CSV, JSON, or XLSX) and automatically saves to Downloads/Metabase folder.', annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: false, openWorldHint: true, }, inputSchema: { type: 'object', properties: { database_id: { type: 'number', description: 'Database ID to export query from (SQL mode only)', }, query: { type: 'string', description: 'SQL query to execute and export (SQL mode only)', }, card_id: { type: 'number', description: 'ID of saved card to export (card mode only)', }, native_parameters: { type: 'array', items: { type: 'object' }, description: 'Parameters for SQL template variables like {{variable_name}} (SQL mode only)', }, card_parameters: { type: 'array', items: { type: 'object' }, description: 'Parameters for filtering card results before export (card mode only). Each parameter must follow Metabase format: {id: "uuid", slug: "param_name", target: ["dimension", ["template-tag", "param_name"]], type: "param_type", value: "param_value"}', }, format: { type: 'string', enum: ['csv', 'json', 'xlsx'], description: 'Export format: csv (text), json (structured data), or xlsx (Excel file)', default: 'csv', }, filename: { type: 'string', description: 'Custom filename (without extension) for the saved file. If not provided, a timestamp-based name will be used.', }, }, required: [], }, },
  • src/server.ts:543-554 (registration)
    Tool registration in CallToolRequestHandler switch statement, mapping tool name 'export' to handleExport function call.
    case 'export': return safeCall(() => handleExport( request, requestId, this.apiClient, this.logDebug.bind(this), this.logInfo.bind(this), this.logWarn.bind(this), this.logError.bind(this) ) );
  • TypeScript interface defining the input parameters for the export tool, used internally for type safety.
    export interface ExportRequest { database_id?: number; query?: string; card_id?: number; native_parameters?: any[]; card_parameters?: any[]; format?: 'csv' | 'json' | 'xlsx'; filename?: string; }
  • Delegation to helper functions: exportCard for card exports (line 126) and exportSqlQuery for SQL exports (line 148). Actual API calls and file saving logic in exportCard.ts and exportQuery.ts.
    return await exportCard(cardParams, requestId, apiClient, logDebug, logInfo, logWarn, logError); } // If exporting a SQL query if (!query || typeof query !== 'string') { logWarn('Missing or invalid query parameter in export request', { requestId }); throw new McpError( ErrorCode.InvalidParams, 'SQL query parameter is required and must be a string' ); } validatePositiveInteger(databaseId, 'database_id', requestId, logWarn); const sqlParams: SqlExportParams = { databaseId: databaseId as number, query, nativeParameters, format: format as 'csv' | 'json' | 'xlsx', filename, }; return await exportSqlQuery( sqlParams, requestId, apiClient, logDebug, logInfo, logWarn, logError ); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jerichosequitin/Metabase'

If you have feedback or need assistance with the MCP directory API, please join our Discord server