mcp-database-inspector 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +197 -0
- package/dist/database/connection.d.ts +13 -0
- package/dist/database/connection.d.ts.map +1 -0
- package/dist/database/connection.js +155 -0
- package/dist/database/connection.js.map +1 -0
- package/dist/database/manager.d.ts +28 -0
- package/dist/database/manager.d.ts.map +1 -0
- package/dist/database/manager.js +621 -0
- package/dist/database/manager.js.map +1 -0
- package/dist/database/postgres-connection.d.ts +10 -0
- package/dist/database/postgres-connection.d.ts.map +1 -0
- package/dist/database/postgres-connection.js +113 -0
- package/dist/database/postgres-connection.js.map +1 -0
- package/dist/database/types.d.ts +84 -0
- package/dist/database/types.d.ts.map +1 -0
- package/dist/database/types.js +6 -0
- package/dist/database/types.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +120 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +14 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +186 -0
- package/dist/server.js.map +1 -0
- package/dist/test-defaults.d.ts +2 -0
- package/dist/test-defaults.d.ts.map +1 -0
- package/dist/test-defaults.js +57 -0
- package/dist/test-defaults.js.map +1 -0
- package/dist/tools/analyze-query.d.ts +27 -0
- package/dist/tools/analyze-query.d.ts.map +1 -0
- package/dist/tools/analyze-query.js +71 -0
- package/dist/tools/analyze-query.js.map +1 -0
- package/dist/tools/execute-query.d.ts +33 -0
- package/dist/tools/execute-query.d.ts.map +1 -0
- package/dist/tools/execute-query.js +57 -0
- package/dist/tools/execute-query.js.map +1 -0
- package/dist/tools/get-foreign-keys.d.ts +38 -0
- package/dist/tools/get-foreign-keys.d.ts.map +1 -0
- package/dist/tools/get-foreign-keys.js +391 -0
- package/dist/tools/get-foreign-keys.js.map +1 -0
- package/dist/tools/get-indexes.d.ts +38 -0
- package/dist/tools/get-indexes.d.ts.map +1 -0
- package/dist/tools/get-indexes.js +472 -0
- package/dist/tools/get-indexes.js.map +1 -0
- package/dist/tools/information-schema-query.d.ts +33 -0
- package/dist/tools/information-schema-query.d.ts.map +1 -0
- package/dist/tools/information-schema-query.js +76 -0
- package/dist/tools/information-schema-query.js.map +1 -0
- package/dist/tools/inspect-table.d.ts +38 -0
- package/dist/tools/inspect-table.d.ts.map +1 -0
- package/dist/tools/inspect-table.js +351 -0
- package/dist/tools/inspect-table.js.map +1 -0
- package/dist/tools/list-databases.d.ts +14 -0
- package/dist/tools/list-databases.d.ts.map +1 -0
- package/dist/tools/list-databases.js +83 -0
- package/dist/tools/list-databases.js.map +1 -0
- package/dist/tools/list-tables.d.ts +19 -0
- package/dist/tools/list-tables.d.ts.map +1 -0
- package/dist/tools/list-tables.js +130 -0
- package/dist/tools/list-tables.js.map +1 -0
- package/dist/utils/errors.d.ts +32 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +98 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +28 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +132 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/validators/input-validator.d.ts +76 -0
- package/dist/validators/input-validator.d.ts.map +1 -0
- package/dist/validators/input-validator.js +295 -0
- package/dist/validators/input-validator.js.map +1 -0
- package/dist/validators/query-validator.d.ts +19 -0
- package/dist/validators/query-validator.d.ts.map +1 -0
- package/dist/validators/query-validator.js +229 -0
- package/dist/validators/query-validator.js.map +1 -0
- package/enhanced_sql_prompt.md +324 -0
- package/examples/claude-config.json +23 -0
- package/examples/roo-config.json +16 -0
- package/package.json +42 -0
- package/src/database/connection.ts +165 -0
- package/src/database/manager.ts +682 -0
- package/src/database/postgres-connection.ts +123 -0
- package/src/database/types.ts +93 -0
- package/src/index.ts +136 -0
- package/src/server.ts +254 -0
- package/src/test-defaults.ts +63 -0
- package/src/tools/analyze-query.test.ts +100 -0
- package/src/tools/analyze-query.ts +112 -0
- package/src/tools/execute-query.ts +91 -0
- package/src/tools/get-foreign-keys.test.ts +51 -0
- package/src/tools/get-foreign-keys.ts +488 -0
- package/src/tools/get-indexes.test.ts +51 -0
- package/src/tools/get-indexes.ts +570 -0
- package/src/tools/information-schema-query.ts +125 -0
- package/src/tools/inspect-table.test.ts +59 -0
- package/src/tools/inspect-table.ts +440 -0
- package/src/tools/list-databases.ts +119 -0
- package/src/tools/list-tables.ts +181 -0
- package/src/utils/errors.ts +103 -0
- package/src/utils/logger.ts +158 -0
- package/src/validators/input-validator.ts +318 -0
- package/src/validators/query-validator.ts +267 -0
- package/tsconfig.json +30 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { InputValidator } from '../validators/input-validator.js';
|
|
3
|
+
import { Logger } from '../utils/logger.js';
|
|
4
|
+
import { ToolError } from '../utils/errors.js';
|
|
5
|
+
// Tool schema
|
|
6
|
+
const ListTablesArgsSchema = z.object({
|
|
7
|
+
database: z.string().min(1, 'Database name is required')
|
|
8
|
+
});
|
|
9
|
+
export const listTablesToolDefinition = {
|
|
10
|
+
name: 'list_tables',
|
|
11
|
+
description: 'List all tables in the specified database with metadata',
|
|
12
|
+
inputSchema: {
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {
|
|
15
|
+
database: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
description: 'Name of the database to list tables from'
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
required: ['database']
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
export async function handleListTables(args, dbManager) {
|
|
24
|
+
try {
|
|
25
|
+
Logger.info('Executing list_tables tool');
|
|
26
|
+
// Validate arguments
|
|
27
|
+
const validationResult = ListTablesArgsSchema.safeParse(args);
|
|
28
|
+
if (!validationResult.success) {
|
|
29
|
+
Logger.warn('Invalid arguments for list_tables', validationResult.error);
|
|
30
|
+
throw new ToolError(`Invalid arguments: ${validationResult.error.issues.map(e => `${e.path.join('.')}: ${e.message}`).join(', ')}`, 'list_tables');
|
|
31
|
+
}
|
|
32
|
+
const { database } = validationResult.data;
|
|
33
|
+
// Sanitize database name
|
|
34
|
+
const sanitizedDatabase = InputValidator.sanitizeString(database);
|
|
35
|
+
// Validate database name format
|
|
36
|
+
const dbNameValidation = InputValidator.validateDatabaseName(sanitizedDatabase);
|
|
37
|
+
if (!dbNameValidation.isValid) {
|
|
38
|
+
throw new ToolError(`Invalid database name: ${dbNameValidation.error}`, 'list_tables');
|
|
39
|
+
}
|
|
40
|
+
Logger.info(`Listing tables for database: ${sanitizedDatabase}`);
|
|
41
|
+
Logger.time('list_tables_execution');
|
|
42
|
+
// Get tables from database
|
|
43
|
+
const tables = await dbManager.getTables(sanitizedDatabase);
|
|
44
|
+
Logger.timeEnd('list_tables_execution');
|
|
45
|
+
Logger.info(`Found ${tables.length} tables in database: ${sanitizedDatabase}`);
|
|
46
|
+
// Group tables by type
|
|
47
|
+
const tablesByType = tables.reduce((acc, table) => {
|
|
48
|
+
const type = table.tableType;
|
|
49
|
+
if (!acc[type]) {
|
|
50
|
+
acc[type] = [];
|
|
51
|
+
}
|
|
52
|
+
acc[type].push(table);
|
|
53
|
+
return acc;
|
|
54
|
+
}, {});
|
|
55
|
+
// Calculate statistics
|
|
56
|
+
const stats = {
|
|
57
|
+
totalTables: tables.length,
|
|
58
|
+
baseTables: (tablesByType['BASE TABLE'] || []).length,
|
|
59
|
+
views: (tablesByType['VIEW'] || []).length,
|
|
60
|
+
systemTables: (tablesByType['SYSTEM TABLE'] || []).length,
|
|
61
|
+
totalEstimatedRows: tables.reduce((sum, table) => sum + (table.tableRows || 0), 0)
|
|
62
|
+
};
|
|
63
|
+
// Format response
|
|
64
|
+
const response = {
|
|
65
|
+
database: sanitizedDatabase,
|
|
66
|
+
tables: tables.map(table => ({
|
|
67
|
+
name: table.tableName,
|
|
68
|
+
type: table.tableType,
|
|
69
|
+
engine: table.engine,
|
|
70
|
+
estimatedRows: table.tableRows,
|
|
71
|
+
comment: table.tableComment,
|
|
72
|
+
category: table.tableType === 'BASE TABLE' ? 'table' :
|
|
73
|
+
table.tableType === 'VIEW' ? 'view' :
|
|
74
|
+
'system'
|
|
75
|
+
})),
|
|
76
|
+
statistics: stats,
|
|
77
|
+
tablesByType: Object.keys(tablesByType).map(type => ({
|
|
78
|
+
type,
|
|
79
|
+
count: tablesByType[type].length,
|
|
80
|
+
tables: tablesByType[type].map(t => t.tableName)
|
|
81
|
+
})),
|
|
82
|
+
summary: {
|
|
83
|
+
hasData: tables.length > 0,
|
|
84
|
+
message: tables.length === 0
|
|
85
|
+
? `No tables found in database '${sanitizedDatabase}'. Database may be empty or inaccessible.`
|
|
86
|
+
: `Found ${tables.length} table(s) in database '${sanitizedDatabase}': ${stats.baseTables} base tables, ${stats.views} views.`
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
Logger.debug('list_tables completed successfully', {
|
|
90
|
+
database: sanitizedDatabase,
|
|
91
|
+
tableCount: tables.length,
|
|
92
|
+
baseTables: stats.baseTables,
|
|
93
|
+
views: stats.views
|
|
94
|
+
});
|
|
95
|
+
return {
|
|
96
|
+
content: [{
|
|
97
|
+
type: 'text',
|
|
98
|
+
text: JSON.stringify(response, null, 2)
|
|
99
|
+
}]
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
Logger.error('Error in list_tables tool', error);
|
|
104
|
+
if (error instanceof ToolError) {
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
107
|
+
throw new ToolError(`Failed to list tables: ${error instanceof Error ? error.message : 'Unknown error'}`, 'list_tables', error instanceof Error ? error : undefined);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
export async function getTablesSummary(dbManager, database) {
|
|
111
|
+
try {
|
|
112
|
+
const tables = await dbManager.getTables(database);
|
|
113
|
+
const baseTables = tables.filter(t => t.tableType === 'BASE TABLE').length;
|
|
114
|
+
const views = tables.filter(t => t.tableType === 'VIEW').length;
|
|
115
|
+
if (tables.length === 0) {
|
|
116
|
+
return `Database '${database}' has no tables`;
|
|
117
|
+
}
|
|
118
|
+
const parts = [];
|
|
119
|
+
if (baseTables > 0)
|
|
120
|
+
parts.push(`${baseTables} table(s)`);
|
|
121
|
+
if (views > 0)
|
|
122
|
+
parts.push(`${views} view(s)`);
|
|
123
|
+
return `Database '${database}' contains ${parts.join(', ')}: ${tables.slice(0, 5).map(t => t.tableName).join(', ')}${tables.length > 5 ? `, and ${tables.length - 5} more` : ''}`;
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
Logger.error(`Error getting table summary for ${database}`, error);
|
|
127
|
+
return `Error retrieving tables for database '${database}'`;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=list-tables.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-tables.js","sourceRoot":"","sources":["../../src/tools/list-tables.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export declare class DatabaseError extends Error {
|
|
2
|
+
readonly cause?: Error | undefined;
|
|
3
|
+
constructor(message: string, cause?: Error | undefined);
|
|
4
|
+
}
|
|
5
|
+
export declare class ValidationError extends Error {
|
|
6
|
+
readonly field?: string | undefined;
|
|
7
|
+
constructor(message: string, field?: string | undefined);
|
|
8
|
+
}
|
|
9
|
+
export declare class ConnectionError extends DatabaseError {
|
|
10
|
+
readonly host?: string | undefined;
|
|
11
|
+
readonly port?: number | undefined;
|
|
12
|
+
constructor(message: string, host?: string | undefined, port?: number | undefined, cause?: Error);
|
|
13
|
+
}
|
|
14
|
+
export declare class QueryError extends DatabaseError {
|
|
15
|
+
readonly query?: string | undefined;
|
|
16
|
+
constructor(message: string, query?: string | undefined, cause?: Error);
|
|
17
|
+
}
|
|
18
|
+
export declare class ConfigurationError extends Error {
|
|
19
|
+
readonly configKey?: string | undefined;
|
|
20
|
+
constructor(message: string, configKey?: string | undefined);
|
|
21
|
+
}
|
|
22
|
+
export declare class ToolError extends Error {
|
|
23
|
+
readonly toolName?: string | undefined;
|
|
24
|
+
constructor(message: string, toolName?: string | undefined, cause?: Error);
|
|
25
|
+
}
|
|
26
|
+
export declare function isRecoverableError(error: Error): boolean;
|
|
27
|
+
export declare function sanitizeErrorMessage(error: Error): string;
|
|
28
|
+
export declare function createErrorResponse(error: Error): {
|
|
29
|
+
error: string;
|
|
30
|
+
code?: string;
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,aAAc,SAAQ,KAAK;aACO,KAAK,CAAC,EAAE,KAAK;gBAA9C,OAAO,EAAE,MAAM,EAAkB,KAAK,CAAC,EAAE,KAAK,YAAA;CAQ3D;AAED,qBAAa,eAAgB,SAAQ,KAAK;aACK,KAAK,CAAC,EAAE,MAAM;gBAA/C,OAAO,EAAE,MAAM,EAAkB,KAAK,CAAC,EAAE,MAAM,YAAA;CAI5D;AAED,qBAAa,eAAgB,SAAQ,aAAa;aACH,IAAI,CAAC,EAAE,MAAM;aAAkB,IAAI,CAAC,EAAE,MAAM;gBAA7E,OAAO,EAAE,MAAM,EAAkB,IAAI,CAAC,EAAE,MAAM,YAAA,EAAkB,IAAI,CAAC,EAAE,MAAM,YAAA,EAAE,KAAK,CAAC,EAAE,KAAK;CAIzG;AAED,qBAAa,UAAW,SAAQ,aAAa;aACE,KAAK,CAAC,EAAE,MAAM;gBAA/C,OAAO,EAAE,MAAM,EAAkB,KAAK,CAAC,EAAE,MAAM,YAAA,EAAE,KAAK,CAAC,EAAE,KAAK;CAI3E;AAED,qBAAa,kBAAmB,SAAQ,KAAK;aACE,SAAS,CAAC,EAAE,MAAM;gBAAnD,OAAO,EAAE,MAAM,EAAkB,SAAS,CAAC,EAAE,MAAM,YAAA;CAIhE;AAED,qBAAa,SAAU,SAAQ,KAAK;aACW,QAAQ,CAAC,EAAE,MAAM;gBAAlD,OAAO,EAAE,MAAM,EAAkB,QAAQ,CAAC,EAAE,MAAM,YAAA,EAAE,KAAK,CAAC,EAAE,KAAK;CAQ9E;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAexD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CASzD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAwBlF"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
export class DatabaseError extends Error {
|
|
2
|
+
cause;
|
|
3
|
+
constructor(message, cause) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.cause = cause;
|
|
6
|
+
this.name = 'DatabaseError';
|
|
7
|
+
if (cause) {
|
|
8
|
+
this.stack = `${this.stack}\nCaused by: ${cause.stack}`;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class ValidationError extends Error {
|
|
13
|
+
field;
|
|
14
|
+
constructor(message, field) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.field = field;
|
|
17
|
+
this.name = 'ValidationError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export class ConnectionError extends DatabaseError {
|
|
21
|
+
host;
|
|
22
|
+
port;
|
|
23
|
+
constructor(message, host, port, cause) {
|
|
24
|
+
super(message, cause);
|
|
25
|
+
this.host = host;
|
|
26
|
+
this.port = port;
|
|
27
|
+
this.name = 'ConnectionError';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export class QueryError extends DatabaseError {
|
|
31
|
+
query;
|
|
32
|
+
constructor(message, query, cause) {
|
|
33
|
+
super(message, cause);
|
|
34
|
+
this.query = query;
|
|
35
|
+
this.name = 'QueryError';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export class ConfigurationError extends Error {
|
|
39
|
+
configKey;
|
|
40
|
+
constructor(message, configKey) {
|
|
41
|
+
super(message);
|
|
42
|
+
this.configKey = configKey;
|
|
43
|
+
this.name = 'ConfigurationError';
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export class ToolError extends Error {
|
|
47
|
+
toolName;
|
|
48
|
+
constructor(message, toolName, cause) {
|
|
49
|
+
super(message);
|
|
50
|
+
this.toolName = toolName;
|
|
51
|
+
this.name = 'ToolError';
|
|
52
|
+
if (cause) {
|
|
53
|
+
this.stack = `${this.stack}\nCaused by: ${cause.stack}`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export function isRecoverableError(error) {
|
|
58
|
+
// Determine if an error is recoverable (temporary) or fatal
|
|
59
|
+
if (error instanceof ConnectionError) {
|
|
60
|
+
// Network timeouts, temporary connection issues
|
|
61
|
+
return error.message.includes('timeout') ||
|
|
62
|
+
error.message.includes('ECONNREFUSED') ||
|
|
63
|
+
error.message.includes('ENOTFOUND');
|
|
64
|
+
}
|
|
65
|
+
if (error instanceof QueryError) {
|
|
66
|
+
// Syntax errors are not recoverable, but timeouts might be
|
|
67
|
+
return error.message.includes('timeout');
|
|
68
|
+
}
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
export function sanitizeErrorMessage(error) {
|
|
72
|
+
// Remove sensitive information from error messages
|
|
73
|
+
let message = error.message;
|
|
74
|
+
// Remove password information from connection strings
|
|
75
|
+
message = message.replace(/password=[^&\s]+/gi, 'password=***');
|
|
76
|
+
message = message.replace(/:([^@\s]+)@/g, ':***@');
|
|
77
|
+
return message;
|
|
78
|
+
}
|
|
79
|
+
export function createErrorResponse(error) {
|
|
80
|
+
const sanitized = sanitizeErrorMessage(error);
|
|
81
|
+
if (error instanceof ValidationError) {
|
|
82
|
+
return { error: sanitized, code: 'VALIDATION_ERROR' };
|
|
83
|
+
}
|
|
84
|
+
if (error instanceof ConnectionError) {
|
|
85
|
+
return { error: sanitized, code: 'CONNECTION_ERROR' };
|
|
86
|
+
}
|
|
87
|
+
if (error instanceof QueryError) {
|
|
88
|
+
return { error: sanitized, code: 'QUERY_ERROR' };
|
|
89
|
+
}
|
|
90
|
+
if (error instanceof DatabaseError) {
|
|
91
|
+
return { error: sanitized, code: 'DATABASE_ERROR' };
|
|
92
|
+
}
|
|
93
|
+
if (error instanceof ToolError) {
|
|
94
|
+
return { error: sanitized, code: 'TOOL_ERROR' };
|
|
95
|
+
}
|
|
96
|
+
return { error: sanitized, code: 'UNKNOWN_ERROR' };
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
interface LogEntry {
|
|
2
|
+
timestamp: string;
|
|
3
|
+
level: string;
|
|
4
|
+
message: string;
|
|
5
|
+
data?: any;
|
|
6
|
+
}
|
|
7
|
+
export declare class Logger {
|
|
8
|
+
private static logLevel;
|
|
9
|
+
private static logs;
|
|
10
|
+
private static maxLogs;
|
|
11
|
+
static setLogLevel(level: 'error' | 'warn' | 'info' | 'debug' | 'trace'): void;
|
|
12
|
+
static getLogLevel(): string;
|
|
13
|
+
private static shouldLog;
|
|
14
|
+
private static addLog;
|
|
15
|
+
private static formatLog;
|
|
16
|
+
static error(message: string, data?: any): void;
|
|
17
|
+
static warn(message: string, data?: any): void;
|
|
18
|
+
static info(message: string, data?: any): void;
|
|
19
|
+
static debug(message: string, data?: any): void;
|
|
20
|
+
static trace(message: string, data?: any): void;
|
|
21
|
+
static getLogs(limit?: number): LogEntry[];
|
|
22
|
+
static clearLogs(): void;
|
|
23
|
+
static time(label: string): void;
|
|
24
|
+
static timeEnd(label: string): void;
|
|
25
|
+
static safeLog(level: 'error' | 'warn' | 'info' | 'debug' | 'trace', message: string, data?: any): void;
|
|
26
|
+
}
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAQA,UAAU,QAAQ;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA2B;IAClD,OAAO,CAAC,MAAM,CAAC,IAAI,CAAkB;IACrC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAQ;IAE9B,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,IAAI;IAW9E,MAAM,CAAC,WAAW,IAAI,MAAM;IAK5B,OAAO,CAAC,MAAM,CAAC,SAAS;IAIxB,OAAO,CAAC,MAAM,CAAC,MAAM;IAoBrB,OAAO,CAAC,MAAM,CAAC,SAAS;IAWxB,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAM/C,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAM9C,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAM9C,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAM/C,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAM/C,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,EAAE;IAO1C,MAAM,CAAC,SAAS,IAAI,IAAI;IAKxB,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAMhC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAOnC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;CAyBxG"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
var LogLevel;
|
|
2
|
+
(function (LogLevel) {
|
|
3
|
+
LogLevel[LogLevel["ERROR"] = 0] = "ERROR";
|
|
4
|
+
LogLevel[LogLevel["WARN"] = 1] = "WARN";
|
|
5
|
+
LogLevel[LogLevel["INFO"] = 2] = "INFO";
|
|
6
|
+
LogLevel[LogLevel["DEBUG"] = 3] = "DEBUG";
|
|
7
|
+
LogLevel[LogLevel["TRACE"] = 4] = "TRACE";
|
|
8
|
+
})(LogLevel || (LogLevel = {}));
|
|
9
|
+
export class Logger {
|
|
10
|
+
static logLevel = LogLevel.INFO;
|
|
11
|
+
static logs = [];
|
|
12
|
+
static maxLogs = 1000;
|
|
13
|
+
static setLogLevel(level) {
|
|
14
|
+
const levelMap = {
|
|
15
|
+
error: LogLevel.ERROR,
|
|
16
|
+
warn: LogLevel.WARN,
|
|
17
|
+
info: LogLevel.INFO,
|
|
18
|
+
debug: LogLevel.DEBUG,
|
|
19
|
+
trace: LogLevel.TRACE
|
|
20
|
+
};
|
|
21
|
+
this.logLevel = levelMap[level] ?? LogLevel.INFO;
|
|
22
|
+
}
|
|
23
|
+
static getLogLevel() {
|
|
24
|
+
const levelNames = ['error', 'warn', 'info', 'debug', 'trace'];
|
|
25
|
+
return levelNames[this.logLevel] || 'info';
|
|
26
|
+
}
|
|
27
|
+
static shouldLog(level) {
|
|
28
|
+
return level <= this.logLevel;
|
|
29
|
+
}
|
|
30
|
+
static addLog(level, message, data) {
|
|
31
|
+
const entry = {
|
|
32
|
+
timestamp: new Date().toISOString(),
|
|
33
|
+
level,
|
|
34
|
+
message,
|
|
35
|
+
data
|
|
36
|
+
};
|
|
37
|
+
this.logs.push(entry);
|
|
38
|
+
// Keep only the most recent logs
|
|
39
|
+
if (this.logs.length > this.maxLogs) {
|
|
40
|
+
this.logs = this.logs.slice(-this.maxLogs);
|
|
41
|
+
}
|
|
42
|
+
// Output to stderr to avoid interfering with MCP protocol on stdout
|
|
43
|
+
const logMessage = this.formatLog(entry);
|
|
44
|
+
console.error(logMessage);
|
|
45
|
+
}
|
|
46
|
+
static formatLog(entry) {
|
|
47
|
+
const timestamp = entry.timestamp.split('T')[1].split('.')[0]; // HH:MM:SS format
|
|
48
|
+
let message = `[${timestamp}] ${entry.level.toUpperCase()}: ${entry.message}`;
|
|
49
|
+
if (entry.data !== undefined) {
|
|
50
|
+
message += ` ${JSON.stringify(entry.data)}`;
|
|
51
|
+
}
|
|
52
|
+
return message;
|
|
53
|
+
}
|
|
54
|
+
static error(message, data) {
|
|
55
|
+
if (this.shouldLog(LogLevel.ERROR)) {
|
|
56
|
+
this.addLog('error', message, data);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
static warn(message, data) {
|
|
60
|
+
if (this.shouldLog(LogLevel.WARN)) {
|
|
61
|
+
this.addLog('warn', message, data);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
static info(message, data) {
|
|
65
|
+
if (this.shouldLog(LogLevel.INFO)) {
|
|
66
|
+
this.addLog('info', message, data);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
static debug(message, data) {
|
|
70
|
+
if (this.shouldLog(LogLevel.DEBUG)) {
|
|
71
|
+
this.addLog('debug', message, data);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
static trace(message, data) {
|
|
75
|
+
if (this.shouldLog(LogLevel.TRACE)) {
|
|
76
|
+
this.addLog('trace', message, data);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
static getLogs(limit) {
|
|
80
|
+
if (limit && limit > 0) {
|
|
81
|
+
return this.logs.slice(-limit);
|
|
82
|
+
}
|
|
83
|
+
return [...this.logs];
|
|
84
|
+
}
|
|
85
|
+
static clearLogs() {
|
|
86
|
+
this.logs = [];
|
|
87
|
+
}
|
|
88
|
+
// Performance timing utilities
|
|
89
|
+
static time(label) {
|
|
90
|
+
if (this.shouldLog(LogLevel.DEBUG)) {
|
|
91
|
+
console.time(`[TIMER] ${label}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
static timeEnd(label) {
|
|
95
|
+
if (this.shouldLog(LogLevel.DEBUG)) {
|
|
96
|
+
console.timeEnd(`[TIMER] ${label}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Safe logging that won't throw errors
|
|
100
|
+
static safeLog(level, message, data) {
|
|
101
|
+
try {
|
|
102
|
+
switch (level) {
|
|
103
|
+
case 'error':
|
|
104
|
+
this.error(message, data);
|
|
105
|
+
break;
|
|
106
|
+
case 'warn':
|
|
107
|
+
this.warn(message, data);
|
|
108
|
+
break;
|
|
109
|
+
case 'info':
|
|
110
|
+
this.info(message, data);
|
|
111
|
+
break;
|
|
112
|
+
case 'debug':
|
|
113
|
+
this.debug(message, data);
|
|
114
|
+
break;
|
|
115
|
+
case 'trace':
|
|
116
|
+
this.trace(message, data);
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
// Fallback to console.error if our logging fails
|
|
122
|
+
console.error(`Logging failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
123
|
+
console.error(`Original message: ${message}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Initialize from environment variable
|
|
128
|
+
const envLogLevel = process.env.LOG_LEVEL?.toLowerCase();
|
|
129
|
+
if (envLogLevel && ['error', 'warn', 'info', 'debug', 'trace'].includes(envLogLevel)) {
|
|
130
|
+
Logger.setLogLevel(envLogLevel);
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ValidationResult } from '../database/types.js';
|
|
3
|
+
export declare class InputValidator {
|
|
4
|
+
static readonly connectionUrlSchema: z.ZodString;
|
|
5
|
+
static readonly databaseNameSchema: z.ZodString;
|
|
6
|
+
static readonly tableNameSchema: z.ZodString;
|
|
7
|
+
static readonly columnNameSchema: z.ZodString;
|
|
8
|
+
static readonly textInputSchema: z.ZodString;
|
|
9
|
+
/**
|
|
10
|
+
* Validate a connection URL
|
|
11
|
+
*/
|
|
12
|
+
static validateConnectionUrl(url: string): ValidationResult;
|
|
13
|
+
/**
|
|
14
|
+
* Validate a database name
|
|
15
|
+
*/
|
|
16
|
+
static validateDatabaseName(name: string): ValidationResult;
|
|
17
|
+
/**
|
|
18
|
+
* Validate a table name
|
|
19
|
+
*/
|
|
20
|
+
static validateTableName(name: string): ValidationResult;
|
|
21
|
+
/**
|
|
22
|
+
* Validate a column name
|
|
23
|
+
*/
|
|
24
|
+
static validateColumnName(name: string): ValidationResult;
|
|
25
|
+
/**
|
|
26
|
+
* Validate text input
|
|
27
|
+
*/
|
|
28
|
+
static validateTextInput(text: string): ValidationResult;
|
|
29
|
+
/**
|
|
30
|
+
* Sanitize string input by removing dangerous characters
|
|
31
|
+
*/
|
|
32
|
+
static sanitizeString(input: string): string;
|
|
33
|
+
/**
|
|
34
|
+
* Escape MySQL identifiers (table names, column names)
|
|
35
|
+
*/
|
|
36
|
+
static escapeIdentifier(identifier: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* Validate tool arguments based on schema
|
|
39
|
+
*/
|
|
40
|
+
static validateToolArgs<T>(args: unknown, schema: z.ZodSchema<T>): ValidationResult & {
|
|
41
|
+
data?: T;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Validate that a string represents a valid number
|
|
45
|
+
*/
|
|
46
|
+
static validateNumeric(value: string, options?: {
|
|
47
|
+
min?: number;
|
|
48
|
+
max?: number;
|
|
49
|
+
integer?: boolean;
|
|
50
|
+
}): ValidationResult;
|
|
51
|
+
/**
|
|
52
|
+
* Validate an array of values
|
|
53
|
+
*/
|
|
54
|
+
static validateArray<T>(values: unknown[], itemValidator: (item: unknown) => ValidationResult & {
|
|
55
|
+
data?: T;
|
|
56
|
+
}): ValidationResult & {
|
|
57
|
+
data?: T[];
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Validate email format (for potential user management features)
|
|
61
|
+
*/
|
|
62
|
+
static validateEmail(email: string): ValidationResult;
|
|
63
|
+
/**
|
|
64
|
+
* Validate URL format
|
|
65
|
+
*/
|
|
66
|
+
static validateUrl(url: string): ValidationResult;
|
|
67
|
+
/**
|
|
68
|
+
* Check if a string contains only safe characters for logging
|
|
69
|
+
*/
|
|
70
|
+
static isSafeForLogging(text: string): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Sanitize text for safe logging by masking sensitive information
|
|
73
|
+
*/
|
|
74
|
+
static sanitizeForLogging(text: string): string;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=input-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-validator.d.ts","sourceRoot":"","sources":["../../src/validators/input-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,qBAAa,cAAc;IAEzB,MAAM,CAAC,QAAQ,CAAC,mBAAmB,cAc9B;IAGL,MAAM,CAAC,QAAQ,CAAC,kBAAkB,cAGqC;IAGvE,MAAM,CAAC,QAAQ,CAAC,eAAe,cAG+C;IAG9E,MAAM,CAAC,QAAQ,CAAC,gBAAgB,cAG+C;IAG/E,MAAM,CAAC,QAAQ,CAAC,eAAe,cAI1B;IAEL;;OAEG;IACH,MAAM,CAAC,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB;IAkB3D;;OAEG;IACH,MAAM,CAAC,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB;IAkB3D;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB;IAkBxD;;OAEG;IACH,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB;IAkBzD;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB;IAkBxD;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAY5C;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAanD;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,gBAAgB,GAAG;QAAE,IAAI,CAAC,EAAE,CAAC,CAAA;KAAE;IAkBlG;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,gBAAgB;IAsBpH;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,CAAC,EACpB,MAAM,EAAE,OAAO,EAAE,EACjB,aAAa,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,gBAAgB,GAAG;QAAE,IAAI,CAAC,EAAE,CAAC,CAAA;KAAE,GAChE,gBAAgB,GAAG;QAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAA;KAAE;IAwBpC;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB;IAUrD;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB;IAUjD;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAc9C;;OAEG;IACH,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAahD"}
|