Skip to main content
Glama
handlers.ts5.42 kB
import { Pool } from 'mysql2/promise'; import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js'; import pino from 'pino'; const logger = pino.default({ level: 'info' }, pino.destination({ dest: 'server.log', mkdir: true })); export interface QueryArgs { sql: string; params?: Array<string | number | boolean | null>; } export interface ExecuteArgs { sql: string; params?: Array<string | number | boolean | null>; } export interface DescribeTableArgs { table: string; } export interface HandlerResult { content: Array<{ type: 'text'; text: string }>; } export interface ShowArgs { sql: string; } export interface ExplainArgs { sql: string; } export interface ExplainArgs { sql: string; } export async function handleQuery(pool: Pool, args: QueryArgs): Promise<HandlerResult> { if (!args.sql) { throw new McpError(ErrorCode.InvalidParams, 'SQL query is required'); } if (!args.sql.trim().toUpperCase().startsWith('SELECT')) { throw new McpError( ErrorCode.InvalidParams, 'Only SELECT queries are allowed with query tool' ); } try { const [rows] = await pool.query(args.sql, args.params || []); return { content: [ { type: 'text', text: JSON.stringify(rows, null, 2), }, ], }; } catch (error) { logger.error({ msg: 'Query execution failed', sql: args.sql, params: args.params, error: error instanceof Error ? error.message : String(error) }); throw new McpError( ErrorCode.InternalError, error instanceof Error ? error.message : String(error) ); } } export async function handleExecute(pool: Pool, args: ExecuteArgs): Promise<HandlerResult> { if (!args.sql) { throw new McpError(ErrorCode.InvalidParams, 'SQL query is required'); } const sql = args.sql.trim().toUpperCase(); if (sql.startsWith('SELECT')) { throw new McpError( ErrorCode.InvalidParams, 'Use query tool for SELECT statements' ); } try { const [result] = await pool.query(args.sql, args.params || []); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { logger.error({ msg: 'Execute execution failed', sql: args.sql, params: args.params, error: error instanceof Error ? error.message : String(error) }); throw new McpError( ErrorCode.InternalError, error instanceof Error ? error.message : String(error) ); } } export async function handleListTables(pool: Pool): Promise<HandlerResult> { try { const [rows] = await pool.query('SHOW TABLES'); return { content: [ { type: 'text', text: JSON.stringify(rows, null, 2), }, ], }; } catch (error) { logger.error({ msg: 'List tables failed', sql: 'SHOW TABLES', error: error instanceof Error ? error.message : String(error) }); throw new McpError( ErrorCode.InternalError, error instanceof Error ? error.message : String(error) ); } } export async function handleDescribeTable(pool: Pool, args: DescribeTableArgs): Promise<HandlerResult> { if (!args.table) { throw new McpError(ErrorCode.InvalidParams, 'Table name is required'); } try { const [rows] = await pool.query('DESCRIBE ??', [args.table]); return { content: [ { type: 'text', text: JSON.stringify(rows, null, 2), }, ], }; } catch (error) { logger.error({ msg: 'Describe table failed', sql: 'DESCRIBE ??', params: [args.table], error: error instanceof Error ? error.message : String(error) }); throw new McpError( ErrorCode.InternalError, error instanceof Error ? error.message : String(error) ); } } export async function handleExplain(pool: Pool, args: ExplainArgs): Promise<HandlerResult> { if (!args.sql) { throw new McpError(ErrorCode.InvalidParams, 'SQL query is required for EXPLAIN'); } try { const explainSql = `EXPLAIN ${args.sql}`; const [rows] = await pool.query(explainSql); return { content: [ { type: 'text', text: JSON.stringify(rows, null, 2), }, ], }; } catch (error) { logger.error({ msg: 'EXPLAIN execution failed', sql: args.sql, error: error instanceof Error ? error.message : String(error) }); throw new McpError( ErrorCode.InternalError, error instanceof Error ? error.message : String(error) ); } } export async function handleShowStatement(pool: Pool, args: ShowArgs): Promise<HandlerResult> { if (!args.sql || !args.sql.trim().toUpperCase().startsWith('SHOW')) { throw new McpError(ErrorCode.InvalidParams, '只允许执行 SHOW 开头的语句'); } try { const [rows] = await pool.query(args.sql); return { content: [ { type: 'text', text: JSON.stringify(rows, null, 2), }, ], }; } catch (error) { logger.error({ msg: 'SHOW 语句执行失败', sql: args.sql, error: error instanceof Error ? error.message : String(error) }); throw new McpError( ErrorCode.InternalError, error instanceof Error ? error.message : String(error) ); } }

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/huangfeng19820712/mcp-mysql-server'

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