UNPKG

mcp-product-manager

Version:

MCP Orchestrator for task and project management with web interface

97 lines 3.38 kB
// execute.js - POST /api/database/execute import { Router } from 'express'; import { query, get, run } from '../../utils/database.js'; import { success, error, asyncHandler } from '../../utils/response.js'; const router = Router(); // Execute SQLite query router.post('/api/database/execute', asyncHandler(async (req, res) => { const { sql, params = [], mode = 'all' } = req.body; // Basic security: check if query contains write operations const upperSQL = sql.toUpperCase(); const isReadOnly = !upperSQL.includes('UPDATE') && !upperSQL.includes('INSERT') && !upperSQL.includes('DELETE') && !upperSQL.includes('CREATE') && !upperSQL.includes('DROP') && !upperSQL.includes('ALTER'); if (!isReadOnly && process.env.NODE_ENV === 'production') { return res.status(403).json(error('Only SELECT queries are allowed in production', 403)); } try { let result; // For write operations (UPDATE, INSERT, DELETE), use run() if (!isReadOnly) { result = await run(sql, params); // Get query metadata for write operations const metadata = { rowCount: result.changes || 0, mode, isReadOnly, lastID: result.lastID, changes: result.changes }; res.json(success({ result, metadata })); return; } // For read operations, use get() or query() if (mode === 'single') { result = await get(sql, params); } else { result = await query(sql, params); } // Get query metadata const metadata = { rowCount: Array.isArray(result) ? result.length : (result ? 1 : 0), mode, isReadOnly }; res.json(success({ result, metadata })); } catch (err) { console.error('Failed to execute query:', err); const errorResponse = error('Failed to execute query', 500, { error: err.message, sql: sql.substring(0, 100) + (sql.length > 100 ? '...' : '') }); res.status(errorResponse.status).json(errorResponse.body); } })); // MCP tool definition export const tool = { name: 'execute_sqlite', description: 'Execute SQLite queries on the coordination database. Use mode="single" for queries expecting one row, mode="all" for multiple rows.', inputSchema: { type: 'object', properties: { sql: { type: 'string', description: 'The SQL query to execute' }, params: { type: 'array', description: 'Parameters for parameterized queries (optional)', items: { type: ['string', 'number', 'boolean', 'null'] }, default: [] }, mode: { type: 'string', enum: ['all', 'single'], description: 'Query mode: "all" returns all matching rows, "single" returns first row only', default: 'all' } }, required: ['sql'] } }; export { router }; export default router; //# sourceMappingURL=execute.js.map