import { createMySQLAdapter } from "../adapters/mysql";
const db = createMySQLAdapter();
// SQLの種類を判定する関数
function isReadOnlyQuery(sql: string): boolean {
const trimmed = sql.trim().toUpperCase();
// SELECTで始まるクエリのみを読み取り専用として許可
return trimmed.startsWith("SELECT") || trimmed.startsWith("SHOW") || trimmed.startsWith("DESCRIBE") || trimmed.startsWith("DESC") || trimmed.startsWith("EXPLAIN");
}
// 読み取り専用クエリのバリデーション
function validateReadOnlyQuery(sql: string): { valid: boolean; error?: string } {
const trimmed = sql.trim().toUpperCase();
if (!isReadOnlyQuery(sql)) {
return {
valid: false,
error: "This tool only accepts SELECT, SHOW, DESCRIBE, DESC, or EXPLAIN queries. Use run_query_write for INSERT, UPDATE, DELETE, or other write operations."
};
}
return { valid: true };
}
// 書き込みクエリのバリデーション(SELECTは許可しない)
function validateWriteQuery(sql: string): { valid: boolean; error?: string } {
const trimmed = sql.trim().toUpperCase();
if (trimmed.startsWith("SELECT") || trimmed.startsWith("SHOW") || trimmed.startsWith("DESCRIBE") || trimmed.startsWith("DESC") || trimmed.startsWith("EXPLAIN")) {
return {
valid: false,
error: "This tool does not accept SELECT queries. Use run_query_readonly for read-only operations."
};
}
return { valid: true };
}
// 共通のクエリ実行ハンドラー
async function executeQuery(sql: string) {
try {
const rows = await db.query(sql);
return { rows };
} catch (error: any) {
return { error: error.message };
}
}
// 読み取り専用ツール
export const runQueryReadonlyTool = {
name: "run_query_readonly",
description: "Execute a read-only SQL query (SELECT, SHOW, DESCRIBE, DESC, EXPLAIN only) and return rows. This tool does not require approval.",
parameters: {
type: "object",
properties: {
sql: { type: "string" }
},
required: ["sql"]
},
handler: async ({ sql }: { sql: string }) => {
const validation = validateReadOnlyQuery(sql);
if (!validation.valid) {
return { error: validation.error };
}
return await executeQuery(sql);
},
};
// 書き込みツール
export const runQueryWriteTool = {
name: "run_query_write",
description: "Execute a write SQL query (INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, etc.) and return results. This tool requires user approval.",
parameters: {
type: "object",
properties: {
sql: { type: "string" }
},
required: ["sql"]
},
handler: async ({ sql }: { sql: string }) => {
const validation = validateWriteQuery(sql);
if (!validation.valid) {
return { error: validation.error };
}
return await executeQuery(sql);
},
};
// 後方互換性のため、既存のrunQueryToolも残す(非推奨)
export const runQueryTool = {
name: "run_query",
description: "[DEPRECATED] Execute a SQL query and return rows. Use run_query_readonly for SELECT queries or run_query_write for write operations.",
parameters: {
type: "object",
properties: {
sql: { type: "string" }
},
required: ["sql"]
},
handler: async ({ sql }: { sql: string }) => {
return await executeQuery(sql);
},
};