mysql_query
Execute read-only SQL queries against a local WordPress database to retrieve posts, users, options, and other data for development and analysis.
Instructions
Execute a read-only SQL query against the Local WordPress database
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | Single read-only SQL statement (SELECT/SHOW/DESCRIBE/EXPLAIN). | |
| params | No | Optional parameter values for placeholders (?). |
Implementation Reference
- src/index.ts:115-125 (handler)MCP server handler for the 'mysql_query' tool call. Parses arguments and delegates to MySQLClient.executeReadOnlyQuery.case 'mysql_query': { const sql = String(args.sql); const params = Array.isArray(args.params) ? args.params : undefined; debugLog('Executing mysql_query'); const result = await mysql.executeReadOnlyQuery(sql, params); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2) }, ], }; }
- src/mysql-client.ts:46-74 (helper)Core helper function implementing the read-only SQL query execution with safety checks for single statement and read-only operations.async executeReadOnlyQuery(sql: string, params?: any[]): Promise<any[]> { const trimmed = sql.trim(); if (!trimmed) { throw new Error('SQL is empty'); } // Disallow multiple statements entirely for safety if (trimmed.includes(';')) { // Allow a trailing semicolon only const statements = trimmed.split(';').filter(s => s.trim().length > 0); if (statements.length > 1) { throw new Error('Multiple statements are not allowed. Submit a single read-only query.'); } } const firstToken = trimmed .replace(/^\/\*[\s\S]*?\*\//g, '') // strip block comments .replace(/^--.*$/gm, '') // strip line comments .trim() .toLowerCase() .split(/\s+/)[0]; const allowed = new Set(['select', 'show', 'describe', 'desc', 'explain']); if (!allowed.has(firstToken)) { throw new Error('Only read-only queries are permitted (SELECT/SHOW/DESCRIBE/EXPLAIN).'); } return await this.query(sql, params); }
- src/index.ts:62-80 (schema)Input schema definition for the mysql_query tool, specifying sql and optional params.{ name: 'mysql_query', description: 'Execute a read-only SQL query against the Local WordPress database', inputSchema: { type: 'object', properties: { sql: { type: 'string', description: 'Single read-only SQL statement (SELECT/SHOW/DESCRIBE/EXPLAIN).', }, params: { type: 'array', description: 'Optional parameter values for placeholders (?).', items: { type: 'string' }, }, }, required: ['sql'], }, },
- src/index.ts:97-101 (registration)Registration of the listTools handler, which returns the tools array including mysql_query.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools, }; });
- src/mysql-client.ts:33-44 (helper)Underlying query execution method used by executeReadOnlyQuery.async query<T = any>(sql: string, params?: any[]): Promise<T[]> { if (!this.connection) { throw new Error('Not connected to database'); } try { const [rows] = await this.connection.execute(sql, params); return rows as T[]; } catch (error: any) { throw new Error(`Query failed: ${error.message}`); } }