Skip to main content
Glama

execute_query

Run SQL queries on Turso databases directly from LLMs using the MCP server. Input the query, optional database name, and parameters to retrieve or modify data efficiently.

Instructions

Executes a SQL query against a database

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
databaseNoDatabase name (optional, uses context if not provided)
paramsNoQuery parameters (optional)
queryYesSQL query to execute

Implementation Reference

  • Core implementation that executes the SQL query against the Turso database client, handling read-only detection, permission selection, parameter conversion, and error wrapping.
    export async function execute_query( database_name: string, query: string, params: Record<string, any> = {}, ): Promise<ResultSet> { try { // Determine if this is a read-only query const is_read_only = query .trim() .toLowerCase() .startsWith('select'); const permission = is_read_only ? 'read-only' : 'full-access'; const client = await get_database_client( database_name, permission, ); // Execute the query return await client.execute({ sql: query, args: convert_parameters(params), }); } catch (error) { throw new TursoApiError( `Failed to execute query for database ${database_name}: ${ (error as Error).message }`, 500, ); } }
  • MCP tool registration for 'execute_query', including input schema reference, safety validation to prevent read-only misuse, database context resolution, delegation to core handler, result formatting, and error handling.
    server.tool( { name: 'execute_query', description: `⚠️ DESTRUCTIVE: Execute SQL that can modify/delete data (INSERT, UPDATE, DELETE, DROP, ALTER). Always confirm with user before destructive operations.`, schema: QuerySchema, }, async ({ query, params = {}, database }) => { try { // Validate that this is not a read-only query const normalized_query = query.trim().toLowerCase(); if ( normalized_query.startsWith('select') || normalized_query.startsWith('pragma') ) { throw new Error( 'SELECT and PRAGMA queries should use execute_read_only_query', ); } const database_name = resolve_database_name(database); if (database) set_current_database(database); const result = await database_client.execute_query( database_name, query, params, ); const formatted_result = format_query_result(result); return create_tool_response({ database: database_name, query, result: formatted_result, }); } catch (error) { return create_tool_error_response(error); } }, );
  • Zod input schema validation for the execute_query tool parameters.
    const QuerySchema = z.object({ query: z.string().describe('SQL query to execute'), params: z.record(z.string(), z.any()).optional().describe('Query parameters (optional) - Use parameterized queries for security'), database: z.string().optional().describe('Database name (optional, uses context if not provided)'), });
  • Utility to convert input parameters to libsql client expected format (named object or positional array).
    function convert_parameters(params: Record<string, any>): any { if (!params || Object.keys(params).length === 0) { return {}; } // Check if parameters are positional (numbered keys like "1", "2", etc.) const keys = Object.keys(params); const is_positional = keys.every((key) => /^\d+$/.test(key)); if (is_positional) { // Convert to array for positional parameters const max_index = Math.max(...keys.map((k) => parseInt(k))); const param_array: any[] = new Array(max_index); for (const [key, value] of Object.entries(params)) { const index = parseInt(key) - 1; // Convert 1-based to 0-based indexing param_array[index] = value; } return param_array; } // Return as-is for named parameters return params; }
  • Formats the libsql ResultSet for JSON-safe tool response, converting BigInt to string.
    function format_query_result(result: ResultSet): any { // Convert BigInt to string to avoid serialization issues const lastInsertRowid = result.lastInsertRowid !== null && typeof result.lastInsertRowid === 'bigint' ? result.lastInsertRowid.toString() : result.lastInsertRowid; return { rows: result.rows, rowsAffected: result.rowsAffected, lastInsertRowid: lastInsertRowid, columns: result.columns, }; }

Other Tools

Related Tools

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/spences10/mcp-turso-cloud'

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