Skip to main content
Glama

execute-query

Execute SQL queries on Firebird databases with parameterized inputs for security and FIRST/ROWS pagination support.

Instructions

Executes a SQL query in the Firebird database. Uses FIRST/ROWS for pagination.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
sqlYesSQL query to execute (Firebird uses FIRST/ROWS for pagination instead of LIMIT)
paramsNoParameters for parameterized queries to prevent SQL injection

Implementation Reference

  • Primary handler implementation for the 'execute-query' MCP tool. Validates input SQL for security, executes the query using the database layer, logs activity, handles errors, and returns formatted results in MCP content format.
    tools.set("execute-query", {
        name: "execute-query",
        description: "Executes a SQL query in the Firebird database. Uses FIRST/ROWS for pagination.",
        inputSchema: ExecuteQueryArgsSchema,
        handler: async (args: z.infer<typeof ExecuteQueryArgsSchema>) => {
            const { sql, params = [] }: { sql: string; params?: (string | number | boolean | null)[] } = args;
            logger.info(`Executing query: ${sql.substring(0, 100)}${sql.length > 100 ? '...' : ''}`);
    
            try {
                if (typeof sql !== 'string' || !validateSql(sql)) {
                    throw new FirebirdError(
                        `Potentially unsafe SQL query: ${sql.substring(0, 100)}${sql.length > 100 ? '...' : ''}`,
                        'SECURITY_ERROR'
                    );
                }
    
                const result = await executeQuery(sql, params);
                logger.info(`Query executed successfully, ${result.length} rows returned`);
    
                return {
                    content: [{
                        type: "text",
                        text: formatForClaude(result)
                    }]
                };
            } catch (error) {
                const errorResponse = wrapError(error);
                logger.error(`Error ejecutando consulta: ${errorResponse.error} [${errorResponse.errorType || 'UNKNOWN'}]`);
    
                return {
                    content: [{
                        type: "text",
                        text: formatForClaude(errorResponse)
                    }]
                };
            }
        }
    });
  • Zod schema defining the input parameters for the 'execute-query' tool: sql (required string) and optional params array.
    export const ExecuteQueryArgsSchema = z.object({
        sql: z.string().min(1).describe("SQL query to execute (Firebird uses FIRST/ROWS for pagination instead of LIMIT)"),
        params: z.array(z.string().or(z.number()).or(z.boolean()).or(z.null())).optional().describe("Parameters for parameterized queries to prevent SQL injection")
    });
  • Registers the 'execute-query' tool (included in databaseTools from setupDatabaseTools()) to the MCP server by iterating over the tools map and calling registerTool for each.
    const databaseTools = setupDatabaseTools();
    const metadataTools = setupMetadataTools(databaseTools);
    const simpleTools = setupSimpleTools();
    
    // Register all tools using the helper function
    for (const [name, toolDef] of databaseTools.entries()) {
        registerTool(name, toolDef);
    }
  • Supporting function executeQuery that handles DB connection, SQL validation, actual query execution via queryDatabase, error handling, and connection cleanup. Called by the tool handler.
    export const executeQuery = async (sql: string, params: any[] = [], config = DEFAULT_CONFIG): Promise<any[]> => {
        // Try to load config from global variable first
        const globalConfig = getGlobalConfig();
        if (globalConfig && globalConfig.database) {
            logger.info(`Using global configuration for executeQuery: ${globalConfig.database}`);
            config = globalConfig;
        }
        let db: FirebirdDatabase | null = null;
        try {
            // Validar la consulta SQL para prevenir inyección
            if (!validateSql(sql)) {
                throw new FirebirdError(
                    `Consulta SQL potencialmente insegura: ${sql.substring(0, 100)}${sql.length > 100 ? '...' : ''}`,
                    'SECURITY_ERROR'
                );
            }
    
            db = await connectToDatabase(config);
            const result = await queryDatabase(db, sql, params);
            return result;
        } catch (error: any) {
            // Propagar el error original si ya es un FirebirdError
            if (error instanceof FirebirdError) {
                throw error;
            }
    
            // Categorizar el error
            const errorMessage = `Error ejecutando consulta: ${error.message || error}`;
            logger.error(errorMessage);
            throw new FirebirdError(errorMessage, 'QUERY_ERROR', error);
        } finally {
            // Cerrar la conexión en un bloque finally para asegurar que siempre se cierre
            if (db) {
                try {
                    await new Promise<void>((resolve) => {
                        db?.detach((err) => {
                            if (err) {
                                logger.error(`Error al cerrar la conexión: ${err.message}`);
                            }
                            resolve();
                        });
                    });
                } catch (detachError: any) {
                    logger.error(`Error al cerrar la conexión: ${detachError.message}`);
                }
            }
        }
    };

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/PuroDelphi/mcpFirebird'

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