Skip to main content
Glama
YUChoe

SQLite MCP Server

by YUChoe
metaCommands.ts8.11 kB
/** * SQLite 메타 명령어 도구 * .tables, .schema, .indexes, .pragma 등의 SQLite 메타 명령어를 구현합니다. */ import { DatabaseManager } from '../database/DatabaseManager.js'; import { MetaCommandSchema, MetaResultSchema } from '../types/schemas.js'; import type { MetaCommandInput, MetaResultOutput } from '../types/schemas.js'; import type { ToolDefinition, ToolResult } from '../types/index.js'; import { zodToJsonSchema } from '../utils/schemaConverter.js'; /** * 메타 명령어 도구 정의 */ export const metaCommandTool: ToolDefinition = { name: 'meta_command', description: 'SQLite 메타 명령어(.tables, .schema, .indexes, .pragma)를 실행합니다', inputSchema: zodToJsonSchema(MetaCommandSchema), outputSchema: zodToJsonSchema(MetaResultSchema), handler: metaCommandHandler }; /** * 메타 명령어 핸들러 */ async function metaCommandHandler(params: MetaCommandInput): Promise<ToolResult> { const dbManager = new DatabaseManager(); try { // 입력 검증 const validatedInput = MetaCommandSchema.parse(params); const { dbPath, command, target } = validatedInput; let result: MetaCommandResult; switch (command) { case '.tables': result = await handleTablesCommand(dbManager, dbPath); break; case '.schema': result = await handleSchemaCommand(dbManager, dbPath, target); break; case '.indexes': result = await handleIndexesCommand(dbManager, dbPath, target); break; case '.pragma': result = await handlePragmaCommand(dbManager, dbPath, target); break; default: result = { success: false, result: '', error: `지원하지 않는 명령어입니다: ${command}` }; } return { content: [{ type: 'text', text: result.success ? result.result : `오류: ${result.error}` }], structuredContent: result }; } catch (error) { const errorMessage = error instanceof Error ? error.message : '알 수 없는 오류가 발생했습니다'; return { content: [{ type: 'text', text: `메타 명령어 실행 중 오류 발생: ${errorMessage}` }], structuredContent: { success: false, result: '', error: errorMessage } }; } } /** * .tables 명령어 처리 */ async function handleTablesCommand(dbManager: DatabaseManager, dbPath: string): Promise<MetaCommandResult> { const query = ` SELECT name, type FROM sqlite_master WHERE type IN ('table', 'view') AND name NOT LIKE 'sqlite_%' ORDER BY type, name `; const queryResult = await dbManager.executeQuery(dbPath, query); if (!queryResult.success) { return { success: false, result: '', error: queryResult.error || '.tables 명령 실행에 실패했습니다' }; } const tables = queryResult.data || []; if (tables.length === 0) { return { success: true, result: '테이블이 없습니다.' }; } const result = tables .map((row: any) => `${row.name} (${row.type})`) .join('\n'); return { success: true, result }; } /** * .schema 명령어 처리 */ async function handleSchemaCommand(dbManager: DatabaseManager, dbPath: string, target?: string): Promise<MetaCommandResult> { let query: string; let params: any[] = []; if (target) { // 특정 테이블/뷰의 스키마 query = ` SELECT sql FROM sqlite_master WHERE name = ? AND type IN ('table', 'view', 'index', 'trigger') AND sql IS NOT NULL `; params = [target]; } else { // 전체 데이터베이스 스키마 query = ` SELECT sql FROM sqlite_master WHERE type IN ('table', 'view', 'index', 'trigger') AND name NOT LIKE 'sqlite_%' AND sql IS NOT NULL ORDER BY type, name `; } const queryResult = await dbManager.executeQuery(dbPath, query, params); if (!queryResult.success) { return { success: false, result: '', error: queryResult.error || '.schema 명령 실행에 실패했습니다' }; } const schemas = queryResult.data || []; if (schemas.length === 0) { const message = target ? `'${target}'에 대한 스키마를 찾을 수 없습니다.` : '스키마가 없습니다.'; return { success: true, result: message }; } const result = schemas .map((row: any) => row.sql) .filter(Boolean) .join(';\n\n') + ';'; return { success: true, result }; } /** * .indexes 명령어 처리 */ async function handleIndexesCommand(dbManager: DatabaseManager, dbPath: string, target?: string): Promise<MetaCommandResult> { let query: string; let params: any[] = []; if (target) { // 특정 테이블의 인덱스 query = ` SELECT name, sql FROM sqlite_master WHERE type = 'index' AND tbl_name = ? AND name NOT LIKE 'sqlite_%' ORDER BY name `; params = [target]; } else { // 모든 인덱스 query = ` SELECT name, tbl_name, sql FROM sqlite_master WHERE type = 'index' AND name NOT LIKE 'sqlite_%' ORDER BY tbl_name, name `; } const queryResult = await dbManager.executeQuery(dbPath, query, params); if (!queryResult.success) { return { success: false, result: '', error: queryResult.error || '.indexes 명령 실행에 실패했습니다' }; } const indexes = queryResult.data || []; if (indexes.length === 0) { const message = target ? `'${target}' 테이블에 인덱스가 없습니다.` : '인덱스가 없습니다.'; return { success: true, result: message }; } const result = indexes .map((row: any) => { if (target) { return `${row.name}: ${row.sql || 'AUTO INDEX'}`; } else { return `${row.tbl_name}.${row.name}: ${row.sql || 'AUTO INDEX'}`; } }) .join('\n'); return { success: true, result }; } /** * .pragma 명령어 처리 */ async function handlePragmaCommand(dbManager: DatabaseManager, dbPath: string, target?: string): Promise<MetaCommandResult> { if (!target) { return { success: false, result: '', error: 'PRAGMA 명령어에는 대상이 필요합니다 (예: user_version, table_info(테이블명))' }; } try { const query = `PRAGMA ${target}`; const queryResult = await dbManager.executeQuery(dbPath, query); if (!queryResult.success) { return { success: false, result: '', error: queryResult.error || 'PRAGMA 명령 실행에 실패했습니다' }; } const data = queryResult.data || []; if (data.length === 0) { return { success: true, result: '결과가 없습니다.' }; } // 결과를 포맷팅 const result = data .map((row: any) => { const values = Object.values(row); return values.join(' | '); }) .join('\n'); return { success: true, result }; } catch (error) { return { success: false, result: '', error: error instanceof Error ? error.message : 'PRAGMA 명령 실행에 실패했습니다' }; } } /** * 메타 명령어 결과 타입 */ interface MetaCommandResult { success: boolean; result: string; error?: string; } /** * 메타 명령어 실행 함수 (MCP 서버에서 직접 호출용) */ export async function executeMetaCommand(params: MetaCommandInput): Promise<MetaResultOutput> { const result = await metaCommandHandler(params); return result.structuredContent as MetaResultOutput; }

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/YUChoe/sqlite-mcp'

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