execute_select
Run read-only SQL queries (SELECT, SHOW, DESCRIBE, EXPLAIN) on MariaDB/MySQL databases with enforced row limits for safe data exploration.
Instructions
Executes a read-only SELECT/SHOW/DESCRIBE/EXPLAIN query. Row limit is enforced.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| connection | Yes | ||
| query | Yes | ||
| database | No | ||
| row_limit | No |
Implementation Reference
- src/tools.js:48-62 (schema)Input schema/definition for the 'execute_select' tool. Defines the name, description, and inputSchema (connection, query, database, row_limit).
{ name: "execute_select", description: "Executes a read-only SELECT/SHOW/DESCRIBE/EXPLAIN query. Row limit is enforced.", inputSchema: { type: "object", properties: { connection: { type: "string", enum: readableConnections }, query: { type: "string" }, database: { type: "string" }, row_limit: { type: "number" }, }, required: ["connection", "query"], }, }, - src/index.js:93-129 (handler)Handler implementation for 'execute_select'. Extracts args, validates using validateReadQuery, optionally applies row limit via resolveRowLimit/buildLimitedQuery, runs query via db.runReadOnly, and returns results with row_count/rows.
case "execute_select": { const connection = args?.connection; const query = args?.query; const database = args?.database; const requestedRowLimit = args?.row_limit; if (!connection) return fail("'connection' field is required."); if (!query) return fail("'query' field is required."); const connectionConfig = db.getConnectionConfig(connection); const validatedQuery = validateReadQuery(query); const upper = validatedQuery.trim().toUpperCase(); let finalQuery = validatedQuery; let appliedRowLimit = null; if (upper.startsWith("SELECT") || upper.startsWith("WITH")) { appliedRowLimit = resolveRowLimit( requestedRowLimit, connectionConfig, ); if (appliedRowLimit !== null) { finalQuery = buildLimitedQuery(validatedQuery, appliedRowLimit); } } const rows = await db.runReadOnly(connection, finalQuery, { database }); const result = { row_count: Array.isArray(rows) ? rows.length : 0, rows, }; if (appliedRowLimit !== null) { result.row_limit = appliedRowLimit; } return ok(result); } - src/sqlGuard.js:29-46 (helper)validateReadQuery helper used by execute_select to ensure only SELECT/SHOW/DESCRIBE/EXPLAIN queries are allowed.
export function validateReadQuery(rawQuery) { if (typeof rawQuery !== "string") { throw new Error("Query must be a string."); } const query = rawQuery.trim(); if (!query) { throw new Error("Query must not be empty."); } if (!isReadQuery(query)) { throw new Error( "Only SELECT/SHOW/DESCRIBE/EXPLAIN queries are allowed." ); } return query; } - src/sqlGuard.js:81-99 (helper)resolveRowLimit helper used by execute_select to determine the effective row limit based on connection config defaults/max.
export function resolveRowLimit(requestedRowLimit, connectionConfig) { const defaultLimit = connectionConfig.default_row_limit || 0; const maxLimit = connectionConfig.max_row_limit || 0; if (requestedRowLimit != null) { const n = Number(requestedRowLimit); if (!Number.isFinite(n) || n <= 0) { throw new Error("row_limit must be a positive number."); } const chosen = Math.floor(n); return maxLimit > 0 ? Math.min(chosen, maxLimit) : chosen; } if (defaultLimit > 0) { return maxLimit > 0 ? Math.min(defaultLimit, maxLimit) : defaultLimit; } return null; } - src/sqlGuard.js:101-103 (helper)buildLimitedQuery helper wraps a query with LIMIT to enforce row limits.
export function buildLimitedQuery(query, rowLimit) { return `SELECT * FROM (${query}) AS mcp_query LIMIT ${rowLimit}`; }