Skip to main content
Glama

MCP Server for MySQL

index.ts4.78 kB
import { SchemaPermissions } from "../types/index.js"; type LogType = "info" | "error"; // @INFO: Enable logging if ENABLE_LOGGING is true const ENABLE_LOGGING = process.env.ENABLE_LOGGING === "true" || process.env.ENABLE_LOGGING === "1"; export function log(type: LogType = "info", ...args: any[]): void { if (!ENABLE_LOGGING) return; switch (type) { case "info": console.info(...args); break; case "error": console.error(...args); break; default: console.log(...args); } } // Function to parse schema-specific permissions from environment variables export function parseSchemaPermissions( permissionsString?: string, ): SchemaPermissions { const permissions: SchemaPermissions = {}; if (!permissionsString) { return permissions; } // Format: "schema1:true,schema2:false" const permissionPairs = permissionsString.split(","); for (const pair of permissionPairs) { const [schema, value] = pair.split(":"); if (schema && value) { permissions[schema.trim()] = value.trim() === "true"; } } return permissions; } // MySQL connection configuration type export interface MySQLConnectionConfig { host?: string; port?: number; user?: string; password?: string; database?: string; socketPath?: string; } // Function to parse MySQL connection string (mysql CLI format) // Example: mysql --default-auth=mysql_native_password -A -hrdsproxy.staging.luno.com -P3306 -uUSER -pPASS database_name export function parseMySQLConnectionString( connectionString: string, ): MySQLConnectionConfig { const config: MySQLConnectionConfig = {}; // Remove 'mysql' command at the start if present let cleanedString = connectionString.trim().replace(/^mysql\s+/, ''); // Parse flags and options const tokens = []; let currentToken = ''; let inQuotes = false; let quoteChar: string | null = null; for (let i = 0; i < cleanedString.length; i++) { const char = cleanedString[i]; if ((char === '"' || char === "'") && (!inQuotes || char === quoteChar)) { // Toggle quote state without adding the quote character inQuotes = !inQuotes; quoteChar = inQuotes ? char : null; } else if (char === ' ' && !inQuotes) { if (currentToken) { tokens.push(currentToken); currentToken = ''; } } else { currentToken += char; } } if (currentToken) { tokens.push(currentToken); } // Process tokens for (let i = 0; i < tokens.length; i++) { const token = tokens[i]; // Check for combined short options (e.g., -uUSER, -pPASS, -hHOST, -PPORT) if (token.startsWith('-') && !token.startsWith('--')) { const flag = token[1]; let value = token.substring(2); // If no value attached, check next token if (!value && i + 1 < tokens.length && !tokens[i + 1].startsWith('-')) { value = tokens[i + 1]; i++; } switch (flag) { case 'h': config.host = value; break; case 'P': { const port = parseInt(value, 10); if (Number.isNaN(port) || !Number.isFinite(port) || port < 1 || port > 65535) { throw new Error(`Invalid port: ${value}`); } config.port = port; break; } case 'u': config.user = value; break; case 'p': config.password = value; break; case 'S': config.socketPath = value; break; } } // Check for long options (e.g., --host=HOST, --port=PORT) else if (token.startsWith('--')) { const [flag, ...valueParts] = token.substring(2).split('='); let value = valueParts.join('='); // If no value with =, check next token if (!value && i + 1 < tokens.length && !tokens[i + 1].startsWith('-')) { value = tokens[i + 1]; i++; } switch (flag) { case 'host': config.host = value; break; case 'port': { const port = parseInt(value, 10); if (Number.isNaN(port) || !Number.isFinite(port) || port < 1 || port > 65535) { throw new Error(`Invalid port: ${value}`); } config.port = port; break; } case 'user': config.user = value; break; case 'password': config.password = value; break; case 'socket': config.socketPath = value; break; } } // Last positional argument (not starting with -) is the database name else if (!token.startsWith('-')) { // Only consider it a database if it's one of the last arguments and not part of a flag config.database = token; } } return config; }

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

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