Skip to main content
Glama

execute_query

Execute SQL queries on connected SQL Server databases to retrieve, analyze, or modify data with configurable security levels for database operations.

Instructions

Execute a SQL query on the connected SQL Server database

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
databaseNoOptional: Database name to use for this query
queryYesThe SQL query to execute

Implementation Reference

  • Core handler function that executes the SQL query: performs safety validation, connects to database pool, executes query, handles performance logging, formats results as text table, and manages errors.
    async executeQuery(query, database = null) { // Validate query first const validation = this.validateQuery(query); if (!validation.allowed) { this.logger.security('QUERY_BLOCKED', 'Query blocked by safety policy', { query: query.substring(0, 200), reason: validation.reason, queryType: validation.queryType }); throw new Error(`Query blocked by safety policy: ${validation.reason}`); } const startTime = Date.now(); this.logger.debug('Executing query', { tool: 'execute_query', database, queryLength: query.length, queryType: validation.queryType }); try { const pool = await this.connectionManager.connect(); const request = pool.request(); // Switch database if specified if (database) { await request.query(`USE [${database}]`); } const result = await request.query(query); const executionTime = Date.now() - startTime; // Log successful query execution this.logger.logQueryExecution( 'execute_query', query, { database, securityLevel: validation.queryType }, { success: true, duration: executionTime, rowsAffected: result.rowsAffected } ); // Track performance (don't let performance monitoring failures break query execution) try { this.performanceMonitor.recordQuery({ tool: 'execute_query', query, executionTime, success: true, database, timestamp: new Date(startTime) }); } catch (perfError) { this.logger.warn('Performance monitoring failed', { error: perfError.message }); } // Format results if (!result.recordset || result.recordset.length === 0) { return { content: [ { type: 'text', text: `Query executed successfully. ${result.rowsAffected} rows affected.` } ] }; } return this.formatQueryResults(result.recordset); } catch (error) { const executionTime = Date.now() - startTime; // Log failed query execution this.logger.logQueryExecution( 'execute_query', query, { database, securityLevel: validation.queryType }, { success: false, duration: executionTime, error } ); // Track failed query (don't let performance monitoring failures break error handling) try { this.performanceMonitor.recordQuery({ tool: 'execute_query', query, executionTime, success: false, error: error.message, database, timestamp: new Date(startTime) }); } catch (perfError) { this.logger.warn('Performance monitoring failed during error handling', { error: perfError.message }); } throw new McpError(ErrorCode.InternalError, `Query execution failed: ${error.message}`); } }
  • Dispatch handler in the MCP tool call switch statement that invokes the executeQuery method.
    case 'execute_query': { const queryResult = await this.executeQuery(args.query, args.database); return { content: queryResult.content }; }
  • Tool registration definition including name, description, and input schema. Returned by getAllTools() for MCP list_tools.
    name: 'execute_query', description: 'Execute a SQL query on the connected SQL Server database', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'The SQL query to execute' }, database: { type: 'string', description: 'Optional: Database name to use for this query' } }, required: ['query'] } },
  • Helper function for query safety validation based on security configuration levels (read-only, DML, DDL restrictions).
    validateQuery(query) { const trimmedQuery = query.trim(); if (!trimmedQuery) { return { allowed: true, reason: 'Empty query' }; } // Use direct property access for tests that override properties const readOnlyMode = this.readOnlyMode; const allowDestructiveOperations = this.allowDestructiveOperations; const allowSchemaChanges = this.allowSchemaChanges; // 🚀 OPTIMIZATION: Skip all parsing when in "full destruction mode" // When all safety restrictions are disabled, bypass expensive parsing if (!readOnlyMode && allowDestructiveOperations && allowSchemaChanges) { return { allowed: true, reason: 'Full destruction mode - all restrictions disabled, query validation bypassed', queryType: 'unrestricted', optimized: true }; } const securityConfig = this.config.getSecurityConfig(); // First, determine the query type const queryType = this._getQueryType(trimmedQuery, securityConfig); // Check read-only mode first (most restrictive) if (readOnlyMode) { if (queryType !== 'select') { return { allowed: false, reason: 'Read-only mode is enabled. Only SELECT queries are allowed. Set SQL_SERVER_READ_ONLY=false to disable.', queryType: queryType === 'select' ? 'select' : 'non-select' // Keep original type for read-only violations }; } return { allowed: true, reason: 'Query validation passed', queryType }; } // If not in read-only mode, check specific operation restrictions // Check for destructive operations if (queryType === 'destructive' && !allowDestructiveOperations) { return { allowed: false, reason: 'Destructive operations (INSERT/UPDATE/DELETE) are disabled. Set SQL_SERVER_ALLOW_DESTRUCTIVE_OPERATIONS=true to enable.', queryType: 'destructive' }; } // Check for schema changes if (queryType === 'schema' && !allowSchemaChanges) { return { allowed: false, reason: 'Schema changes (CREATE/DROP/ALTER) are disabled. Set SQL_SERVER_ALLOW_SCHEMA_CHANGES=true to enable.', queryType: 'schema' }; } return { allowed: true, reason: 'Query validation passed', queryType }; }
  • Helper function to format query results as a text-based table for MCP response.
    formatQueryResults(data) { if (data.length === 0) { return { content: [{ type: 'text', text: 'No data returned' }] }; } const headers = Object.keys(data[0]); const rows = data.map(row => headers.map(header => String(row[header] || ''))); return { content: [ { type: 'text', text: this.createTextTable(headers, rows) } ] }; }

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/egarcia74/warp-sql-server-mcp'

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