mirror of
https://github.com/executeautomation/mcp-database-server.git
synced 2025-12-09 21:12:57 +08:00
Refactor code for extensability
Refactor code for extensability
This commit is contained in:
66
src/handlers/resourceHandlers.ts
Normal file
66
src/handlers/resourceHandlers.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { dbAll } from '../db/index.js';
|
||||
import { getDatabasePath } from '../db/index.js';
|
||||
|
||||
/**
|
||||
* Handle listing resources request
|
||||
* @returns List of available resources
|
||||
*/
|
||||
export async function handleListResources() {
|
||||
try {
|
||||
const databasePath = getDatabasePath();
|
||||
const resourceBaseUrl = new URL(`sqlite:///${databasePath}`);
|
||||
const SCHEMA_PATH = "schema";
|
||||
|
||||
const result = await dbAll(
|
||||
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'"
|
||||
);
|
||||
|
||||
return {
|
||||
resources: result.map((row: any) => ({
|
||||
uri: new URL(`${row.name}/${SCHEMA_PATH}`, resourceBaseUrl).href,
|
||||
mimeType: "application/json",
|
||||
name: `"${row.name}" database schema`,
|
||||
})),
|
||||
};
|
||||
} catch (error: any) {
|
||||
throw new Error(`Error listing resources: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle reading a specific resource
|
||||
* @param uri URI of the resource to read
|
||||
* @returns Resource contents
|
||||
*/
|
||||
export async function handleReadResource(uri: string) {
|
||||
try {
|
||||
const resourceUrl = new URL(uri);
|
||||
const SCHEMA_PATH = "schema";
|
||||
|
||||
const pathComponents = resourceUrl.pathname.split("/");
|
||||
const schema = pathComponents.pop();
|
||||
const tableName = pathComponents.pop();
|
||||
|
||||
if (schema !== SCHEMA_PATH) {
|
||||
throw new Error("Invalid resource URI");
|
||||
}
|
||||
|
||||
// Query to get column information for a table
|
||||
const result = await dbAll(`PRAGMA table_info("${tableName}")`);
|
||||
|
||||
return {
|
||||
contents: [
|
||||
{
|
||||
uri,
|
||||
mimeType: "application/json",
|
||||
text: JSON.stringify(result.map((column: any) => ({
|
||||
column_name: column.name,
|
||||
data_type: column.type
|
||||
})), null, 2),
|
||||
},
|
||||
],
|
||||
};
|
||||
} catch (error: any) {
|
||||
throw new Error(`Error reading resource: ${error.message}`);
|
||||
}
|
||||
}
|
||||
170
src/handlers/toolHandlers.ts
Normal file
170
src/handlers/toolHandlers.ts
Normal file
@@ -0,0 +1,170 @@
|
||||
import { formatErrorResponse } from '../utils/formatUtils.js';
|
||||
|
||||
// Import all tool implementations
|
||||
import { readQuery, writeQuery, exportQuery } from '../tools/queryTools.js';
|
||||
import { createTable, alterTable, dropTable, listTables, describeTable } from '../tools/schemaTools.js';
|
||||
import { appendInsight, listInsights } from '../tools/insightTools.js';
|
||||
|
||||
/**
|
||||
* Handle listing available tools
|
||||
* @returns List of available tools
|
||||
*/
|
||||
export function handleListTools() {
|
||||
return {
|
||||
tools: [
|
||||
{
|
||||
name: "read_query",
|
||||
description: "Execute SELECT queries to read data from the database",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
query: { type: "string" },
|
||||
},
|
||||
required: ["query"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "write_query",
|
||||
description: "Execute INSERT, UPDATE, or DELETE queries",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
query: { type: "string" },
|
||||
},
|
||||
required: ["query"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "create_table",
|
||||
description: "Create new tables in the database",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
query: { type: "string" },
|
||||
},
|
||||
required: ["query"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "alter_table",
|
||||
description: "Modify existing table schema (add columns, rename tables, etc.)",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
query: { type: "string" },
|
||||
},
|
||||
required: ["query"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "drop_table",
|
||||
description: "Remove a table from the database with safety confirmation",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
table_name: { type: "string" },
|
||||
confirm: { type: "boolean" },
|
||||
},
|
||||
required: ["table_name", "confirm"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "export_query",
|
||||
description: "Export query results to various formats (CSV, JSON)",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
query: { type: "string" },
|
||||
format: { type: "string", enum: ["csv", "json"] },
|
||||
},
|
||||
required: ["query", "format"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list_tables",
|
||||
description: "Get a list of all tables in the database",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "describe_table",
|
||||
description: "View schema information for a specific table",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
table_name: { type: "string" },
|
||||
},
|
||||
required: ["table_name"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "append_insight",
|
||||
description: "Add a business insight to the memo",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
insight: { type: "string" },
|
||||
},
|
||||
required: ["insight"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list_insights",
|
||||
description: "List all business insights in the memo",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle tool call requests
|
||||
* @param name Name of the tool to call
|
||||
* @param args Arguments for the tool
|
||||
* @returns Tool execution result
|
||||
*/
|
||||
export async function handleToolCall(name: string, args: any) {
|
||||
try {
|
||||
switch (name) {
|
||||
case "read_query":
|
||||
return await readQuery(args.query);
|
||||
|
||||
case "write_query":
|
||||
return await writeQuery(args.query);
|
||||
|
||||
case "create_table":
|
||||
return await createTable(args.query);
|
||||
|
||||
case "alter_table":
|
||||
return await alterTable(args.query);
|
||||
|
||||
case "drop_table":
|
||||
return await dropTable(args.table_name, args.confirm);
|
||||
|
||||
case "export_query":
|
||||
return await exportQuery(args.query, args.format);
|
||||
|
||||
case "list_tables":
|
||||
return await listTables();
|
||||
|
||||
case "describe_table":
|
||||
return await describeTable(args.table_name);
|
||||
|
||||
case "append_insight":
|
||||
return await appendInsight(args.insight);
|
||||
|
||||
case "list_insights":
|
||||
return await listInsights();
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown tool: ${name}`);
|
||||
}
|
||||
} catch (error: any) {
|
||||
return formatErrorResponse(error);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user