@conte777/db-view-mcp 1.0.0 → 1.2.0
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/config.example.json +15 -3
- package/dist/config/loader.d.ts +1 -0
- package/dist/config/loader.js +25 -1
- package/dist/config/loader.js.map +1 -1
- package/dist/config/types.d.ts +53 -15
- package/dist/config/types.js +31 -14
- package/dist/config/types.js.map +1 -1
- package/dist/connectors/clickhouse.d.ts +2 -2
- package/dist/connectors/clickhouse.js +14 -3
- package/dist/connectors/clickhouse.js.map +1 -1
- package/dist/connectors/instrumented.d.ts +18 -0
- package/dist/connectors/instrumented.js +52 -0
- package/dist/connectors/instrumented.js.map +1 -0
- package/dist/connectors/interface.d.ts +2 -2
- package/dist/connectors/manager.d.ts +11 -0
- package/dist/connectors/manager.js +81 -5
- package/dist/connectors/manager.js.map +1 -1
- package/dist/connectors/postgresql.d.ts +2 -2
- package/dist/connectors/postgresql.js +57 -19
- package/dist/connectors/postgresql.js.map +1 -1
- package/dist/index.js +75 -16
- package/dist/index.js.map +1 -1
- package/dist/server.js.map +1 -1
- package/dist/tools/readonly/explain.d.ts +2 -0
- package/dist/tools/readonly/explain.js +2 -1
- package/dist/tools/readonly/explain.js.map +1 -1
- package/dist/tools/readonly/performance.d.ts +1 -2
- package/dist/tools/readonly/performance.js +7 -9
- package/dist/tools/readonly/performance.js.map +1 -1
- package/dist/tools/readonly/schema.d.ts +2 -0
- package/dist/tools/readonly/schema.js +2 -1
- package/dist/tools/readonly/schema.js.map +1 -1
- package/dist/tools/registry.d.ts +1 -1
- package/dist/tools/registry.js +2 -2
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/write/transaction.d.ts +18 -0
- package/dist/tools/write/transaction.js +70 -13
- package/dist/tools/write/transaction.js.map +1 -1
- package/dist/transport/http.d.ts +2 -0
- package/dist/transport/http.js +28 -14
- package/dist/transport/http.js.map +1 -1
- package/dist/utils/logger.d.ts +15 -0
- package/dist/utils/logger.js +52 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/sql-validator.js +39 -10
- package/dist/utils/sql-validator.js.map +1 -1
- package/package.json +15 -3
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
import { PostgresConnector } from "./postgresql.js";
|
|
2
2
|
import { ClickHouseConnector } from "./clickhouse.js";
|
|
3
|
+
import { InstrumentedConnector } from "./instrumented.js";
|
|
4
|
+
import { PerformanceTracker } from "../tools/readonly/performance.js";
|
|
5
|
+
import { getLogger } from "../utils/logger.js";
|
|
6
|
+
const CONNECTION_ERROR_CODES = new Set(["ECONNREFUSED", "ECONNRESET", "EPIPE", "ETIMEDOUT"]);
|
|
7
|
+
function isConnectionError(err) {
|
|
8
|
+
if (err instanceof Error) {
|
|
9
|
+
const code = err.code;
|
|
10
|
+
if (code && CONNECTION_ERROR_CODES.has(code))
|
|
11
|
+
return true;
|
|
12
|
+
if (err.message.includes("Connection terminated"))
|
|
13
|
+
return true;
|
|
14
|
+
if (err.message.includes("connection refused"))
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
3
19
|
export class ConnectorManager {
|
|
4
20
|
configs = new Map();
|
|
5
21
|
connectors = new Map();
|
|
22
|
+
rawConnectors = new Map();
|
|
23
|
+
tracker = new PerformanceTracker();
|
|
6
24
|
constructor(databases) {
|
|
7
25
|
for (const db of databases) {
|
|
8
26
|
this.configs.set(db.id, db);
|
|
@@ -17,6 +35,9 @@ export class ConnectorManager {
|
|
|
17
35
|
getAllConfigs() {
|
|
18
36
|
return Array.from(this.configs.values());
|
|
19
37
|
}
|
|
38
|
+
getPerformanceTracker() {
|
|
39
|
+
return this.tracker;
|
|
40
|
+
}
|
|
20
41
|
async getConnector(dbId) {
|
|
21
42
|
const existing = this.connectors.get(dbId);
|
|
22
43
|
if (existing)
|
|
@@ -24,10 +45,36 @@ export class ConnectorManager {
|
|
|
24
45
|
const config = this.configs.get(dbId);
|
|
25
46
|
if (!config)
|
|
26
47
|
throw new Error(`Unknown database: ${dbId}`);
|
|
27
|
-
const
|
|
28
|
-
await
|
|
29
|
-
this.
|
|
30
|
-
|
|
48
|
+
const raw = this.createConnector(config);
|
|
49
|
+
await raw.connect();
|
|
50
|
+
this.rawConnectors.set(dbId, raw);
|
|
51
|
+
const instrumented = new InstrumentedConnector(raw, this.tracker, dbId);
|
|
52
|
+
this.connectors.set(dbId, instrumented);
|
|
53
|
+
return instrumented;
|
|
54
|
+
}
|
|
55
|
+
async withConnector(dbId, fn) {
|
|
56
|
+
const connector = await this.getConnector(dbId);
|
|
57
|
+
try {
|
|
58
|
+
return await fn(connector);
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
if (isConnectionError(err)) {
|
|
62
|
+
const logger = getLogger();
|
|
63
|
+
logger.warn("Connection error, retrying", { database: dbId, error: String(err) });
|
|
64
|
+
this.invalidateConnector(dbId);
|
|
65
|
+
const retryConnector = await this.getConnector(dbId);
|
|
66
|
+
return await fn(retryConnector);
|
|
67
|
+
}
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
invalidateConnector(dbId) {
|
|
72
|
+
const raw = this.rawConnectors.get(dbId);
|
|
73
|
+
if (raw) {
|
|
74
|
+
raw.disconnect().catch(() => { });
|
|
75
|
+
this.rawConnectors.delete(dbId);
|
|
76
|
+
}
|
|
77
|
+
this.connectors.delete(dbId);
|
|
31
78
|
}
|
|
32
79
|
createConnector(config) {
|
|
33
80
|
if (config.type === "postgresql") {
|
|
@@ -38,14 +85,43 @@ export class ConnectorManager {
|
|
|
38
85
|
}
|
|
39
86
|
throw new Error(`Unsupported database type: ${config.type}`);
|
|
40
87
|
}
|
|
88
|
+
updateDatabases(newConfigs) {
|
|
89
|
+
const newMap = new Map(newConfigs.map((c) => [c.id, c]));
|
|
90
|
+
const added = [];
|
|
91
|
+
const removed = [];
|
|
92
|
+
const changed = [];
|
|
93
|
+
// Removed databases
|
|
94
|
+
for (const id of this.configs.keys()) {
|
|
95
|
+
if (!newMap.has(id)) {
|
|
96
|
+
removed.push(id);
|
|
97
|
+
this.invalidateConnector(id);
|
|
98
|
+
this.configs.delete(id);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Added and changed databases
|
|
102
|
+
for (const [id, cfg] of newMap) {
|
|
103
|
+
const old = this.configs.get(id);
|
|
104
|
+
if (!old) {
|
|
105
|
+
added.push(id);
|
|
106
|
+
this.configs.set(id, cfg);
|
|
107
|
+
}
|
|
108
|
+
else if (JSON.stringify(old) !== JSON.stringify(cfg)) {
|
|
109
|
+
changed.push(id);
|
|
110
|
+
this.invalidateConnector(id);
|
|
111
|
+
this.configs.set(id, cfg);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return { added, removed, changed };
|
|
115
|
+
}
|
|
41
116
|
async connectEager() {
|
|
42
117
|
const eagerDbs = Array.from(this.configs.values()).filter((c) => !c.lazyConnection);
|
|
43
118
|
await Promise.all(eagerDbs.map((db) => this.getConnector(db.id)));
|
|
44
119
|
}
|
|
45
120
|
async disconnectAll() {
|
|
46
|
-
const tasks = Array.from(this.
|
|
121
|
+
const tasks = Array.from(this.rawConnectors.values()).map((c) => c.disconnect());
|
|
47
122
|
await Promise.all(tasks);
|
|
48
123
|
this.connectors.clear();
|
|
124
|
+
this.rawConnectors.clear();
|
|
49
125
|
}
|
|
50
126
|
}
|
|
51
127
|
//# sourceMappingURL=manager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/connectors/manager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/connectors/manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,7 +14,7 @@ export declare class PostgresConnector implements Connector {
|
|
|
14
14
|
execute(sql: string, params?: string[]): Promise<QueryResult>;
|
|
15
15
|
listTables(schema?: string): Promise<TableInfo[]>;
|
|
16
16
|
describeTable(table: string, schema?: string): Promise<ColumnInfo[]>;
|
|
17
|
-
getSchema(): Promise<string>;
|
|
18
|
-
explain(sql: string): Promise<ExplainResult>;
|
|
17
|
+
getSchema(schema?: string): Promise<string>;
|
|
18
|
+
explain(sql: string, analyze?: boolean): Promise<ExplainResult>;
|
|
19
19
|
beginTransaction(): Promise<TransactionHandle>;
|
|
20
20
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import pg from "pg";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
3
4
|
export class PostgresConnector {
|
|
4
5
|
type = "postgresql";
|
|
5
6
|
pool = null;
|
|
@@ -12,15 +13,36 @@ export class PostgresConnector {
|
|
|
12
13
|
this.maxRows = maxRows;
|
|
13
14
|
}
|
|
14
15
|
async connect() {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
const sslConfig = this.config.ssl
|
|
17
|
+
? {
|
|
18
|
+
rejectUnauthorized: this.config.sslRejectUnauthorized,
|
|
19
|
+
...(this.config.sslCa && {
|
|
20
|
+
ca: this.config.sslCa.startsWith("-----BEGIN")
|
|
21
|
+
? this.config.sslCa
|
|
22
|
+
: readFileSync(this.config.sslCa, "utf-8"),
|
|
23
|
+
}),
|
|
24
|
+
}
|
|
25
|
+
: undefined;
|
|
26
|
+
const poolOptions = this.config.connectionString
|
|
27
|
+
? {
|
|
28
|
+
connectionString: this.config.connectionString,
|
|
29
|
+
ssl: sslConfig,
|
|
30
|
+
max: 10,
|
|
31
|
+
statement_timeout: this.queryTimeout,
|
|
32
|
+
query_timeout: this.queryTimeout,
|
|
33
|
+
}
|
|
34
|
+
: {
|
|
35
|
+
host: this.config.host,
|
|
36
|
+
port: this.config.port,
|
|
37
|
+
database: this.config.database,
|
|
38
|
+
user: this.config.user,
|
|
39
|
+
password: this.config.password,
|
|
40
|
+
ssl: sslConfig,
|
|
41
|
+
max: 10,
|
|
42
|
+
statement_timeout: this.queryTimeout,
|
|
43
|
+
query_timeout: this.queryTimeout,
|
|
44
|
+
};
|
|
45
|
+
this.pool = new pg.Pool(poolOptions);
|
|
24
46
|
// Verify connection
|
|
25
47
|
const client = await this.pool.connect();
|
|
26
48
|
client.release();
|
|
@@ -87,11 +109,12 @@ export class PostgresConnector {
|
|
|
87
109
|
isPrimaryKey: r.is_primary_key,
|
|
88
110
|
}));
|
|
89
111
|
}
|
|
90
|
-
async getSchema() {
|
|
112
|
+
async getSchema(schema) {
|
|
113
|
+
const s = schema ?? "public";
|
|
91
114
|
const result = await this.getPool().query(`SELECT table_name, column_name, data_type, is_nullable, column_default
|
|
92
115
|
FROM information_schema.columns
|
|
93
|
-
WHERE table_schema =
|
|
94
|
-
ORDER BY table_name, ordinal_position
|
|
116
|
+
WHERE table_schema = $1
|
|
117
|
+
ORDER BY table_name, ordinal_position`, [s]);
|
|
95
118
|
const tables = new Map();
|
|
96
119
|
for (const row of result.rows) {
|
|
97
120
|
const t = row.table_name;
|
|
@@ -109,14 +132,21 @@ export class PostgresConnector {
|
|
|
109
132
|
}
|
|
110
133
|
return lines.join("\n");
|
|
111
134
|
}
|
|
112
|
-
async explain(sql) {
|
|
113
|
-
const
|
|
135
|
+
async explain(sql, analyze = false) {
|
|
136
|
+
const prefix = analyze ? "EXPLAIN ANALYZE" : "EXPLAIN";
|
|
137
|
+
const result = await this.getPool().query(`${prefix} ${sql}`);
|
|
114
138
|
const plan = result.rows.map((r) => r["QUERY PLAN"]).join("\n");
|
|
115
139
|
return { plan };
|
|
116
140
|
}
|
|
117
141
|
async beginTransaction() {
|
|
118
142
|
const client = await this.getPool().connect();
|
|
119
|
-
|
|
143
|
+
try {
|
|
144
|
+
await client.query("BEGIN");
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
client.release();
|
|
148
|
+
throw err;
|
|
149
|
+
}
|
|
120
150
|
const id = randomUUID();
|
|
121
151
|
return {
|
|
122
152
|
id,
|
|
@@ -125,12 +155,20 @@ export class PostgresConnector {
|
|
|
125
155
|
return { rows: result.rows ?? [], rowCount: result.rowCount ?? 0 };
|
|
126
156
|
},
|
|
127
157
|
async commit() {
|
|
128
|
-
|
|
129
|
-
|
|
158
|
+
try {
|
|
159
|
+
await client.query("COMMIT");
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
client.release();
|
|
163
|
+
}
|
|
130
164
|
},
|
|
131
165
|
async rollback() {
|
|
132
|
-
|
|
133
|
-
|
|
166
|
+
try {
|
|
167
|
+
await client.query("ROLLBACK");
|
|
168
|
+
}
|
|
169
|
+
finally {
|
|
170
|
+
client.release();
|
|
171
|
+
}
|
|
134
172
|
},
|
|
135
173
|
};
|
|
136
174
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgresql.js","sourceRoot":"","sources":["../../src/connectors/postgresql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"postgresql.js","sourceRoot":"","sources":["../../src/connectors/postgresql.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,40 +1,99 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { watch } from "node:fs";
|
|
2
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
4
|
import { loadConfig, parseCliArgs } from "./config/loader.js";
|
|
5
|
+
import { resolveDbConfig } from "./config/types.js";
|
|
4
6
|
import { createServer } from "./server.js";
|
|
7
|
+
import { transactionStore } from "./tools/write/transaction.js";
|
|
5
8
|
import { startHttpTransport } from "./transport/http.js";
|
|
9
|
+
import { initLogger } from "./utils/logger.js";
|
|
6
10
|
async function main() {
|
|
7
11
|
const { configPath, transport: cliTransport } = parseCliArgs(process.argv.slice(2));
|
|
8
12
|
const config = loadConfig(configPath);
|
|
13
|
+
const logger = initLogger(config.defaults.logLevel);
|
|
14
|
+
logger.info("Starting db-view-mcp", { transport: config.transport.type });
|
|
9
15
|
// CLI --transport overrides config
|
|
10
16
|
const transportType = cliTransport ?? config.transport.type;
|
|
17
|
+
let manager;
|
|
18
|
+
let shutdown;
|
|
11
19
|
if (transportType === "http") {
|
|
12
20
|
const transportConfig = config.transport.type === "http"
|
|
13
21
|
? config.transport
|
|
14
|
-
: { type: "http", port: 3000, host: "127.0.0.1", stateless: false };
|
|
15
|
-
const { httpServer, manager } = await startHttpTransport(config, transportConfig);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
22
|
+
: { type: "http", port: 3000, host: "127.0.0.1", stateless: false, sessionTimeout: 30 * 60 * 1000 };
|
|
23
|
+
const { httpServer, manager: m, sessions, cleanupInterval } = await startHttpTransport(config, transportConfig);
|
|
24
|
+
manager = m;
|
|
25
|
+
shutdown = async () => {
|
|
26
|
+
logger.info("Shutting down HTTP server...");
|
|
27
|
+
await new Promise((resolve, reject) => {
|
|
28
|
+
httpServer.close((err) => (err ? reject(err) : resolve()));
|
|
29
|
+
});
|
|
30
|
+
for (const [sid, entry] of sessions) {
|
|
31
|
+
await entry.transport.close().catch(() => { });
|
|
32
|
+
await entry.server.close().catch(() => { });
|
|
33
|
+
sessions.delete(sid);
|
|
34
|
+
}
|
|
35
|
+
if (cleanupInterval)
|
|
36
|
+
clearInterval(cleanupInterval);
|
|
37
|
+
await transactionStore.cleanupAll();
|
|
19
38
|
await manager.disconnectAll();
|
|
20
|
-
process.exit(0);
|
|
21
39
|
};
|
|
22
|
-
process.on("SIGINT", shutdown);
|
|
23
|
-
process.on("SIGTERM", shutdown);
|
|
24
40
|
}
|
|
25
41
|
else {
|
|
26
|
-
const { server, manager } = await createServer(config);
|
|
42
|
+
const { server, manager: m } = await createServer(config);
|
|
43
|
+
manager = m;
|
|
27
44
|
const transport = new StdioServerTransport();
|
|
28
45
|
await server.connect(transport);
|
|
29
|
-
|
|
46
|
+
shutdown = async () => {
|
|
47
|
+
logger.info("Shutting down stdio server...");
|
|
48
|
+
await server.close();
|
|
49
|
+
await transport.close();
|
|
50
|
+
await transactionStore.cleanupAll();
|
|
30
51
|
await manager.disconnectAll();
|
|
31
|
-
|
|
32
|
-
});
|
|
33
|
-
process.on("SIGTERM", async () => {
|
|
34
|
-
await manager.disconnectAll();
|
|
35
|
-
process.exit(0);
|
|
36
|
-
});
|
|
52
|
+
};
|
|
37
53
|
}
|
|
54
|
+
// Unified shutdown handler with timeout and duplicate protection
|
|
55
|
+
let shutdownInProgress = false;
|
|
56
|
+
const gracefulShutdown = async () => {
|
|
57
|
+
if (shutdownInProgress) {
|
|
58
|
+
logger.warn("Shutdown already in progress, forcing exit");
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
shutdownInProgress = true;
|
|
62
|
+
const timer = setTimeout(() => {
|
|
63
|
+
logger.error("Shutdown timed out after 10s, forcing exit");
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}, 10_000);
|
|
66
|
+
timer.unref();
|
|
67
|
+
try {
|
|
68
|
+
await shutdown();
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
logger.error("Error during shutdown", { error: String(err) });
|
|
72
|
+
}
|
|
73
|
+
clearTimeout(timer);
|
|
74
|
+
process.exit(0);
|
|
75
|
+
};
|
|
76
|
+
process.on("SIGINT", gracefulShutdown);
|
|
77
|
+
process.on("SIGTERM", gracefulShutdown);
|
|
78
|
+
// Config hot reload via file watcher
|
|
79
|
+
let reloadTimeout = null;
|
|
80
|
+
const watcher = watch(configPath, () => {
|
|
81
|
+
if (reloadTimeout)
|
|
82
|
+
clearTimeout(reloadTimeout);
|
|
83
|
+
reloadTimeout = setTimeout(async () => {
|
|
84
|
+
logger.info("Config file changed, reloading...");
|
|
85
|
+
try {
|
|
86
|
+
const newConfig = loadConfig(configPath);
|
|
87
|
+
const newResolved = newConfig.databases.map((db) => resolveDbConfig(db, newConfig.defaults));
|
|
88
|
+
const diff = manager.updateDatabases(newResolved);
|
|
89
|
+
logger.info("Config reloaded", { added: diff.added, removed: diff.removed, changed: diff.changed });
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
logger.error("Failed to reload config", { error: String(err) });
|
|
93
|
+
}
|
|
94
|
+
}, 500);
|
|
95
|
+
});
|
|
96
|
+
watcher.unref();
|
|
38
97
|
}
|
|
39
98
|
main().catch((err) => {
|
|
40
99
|
console.error("Failed to start db-view-mcp:", err);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAkB,MAAM,mBAAmB,CAAC;AAEpE,MAAM,UAAU,sBAAsB,CAAC,MAAiB;IACtD,MAAM,WAAW,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAkB,MAAM,mBAAmB,CAAC;AAEpE,MAAM,UAAU,sBAAsB,CAAC,MAAiB;IACtD,MAAM,WAAW,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IACvF,OAAO,IAAI,gBAAgB,CAAC,WAAW,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAyB,EAAE,MAAiB;IAClF,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IACH,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAiB;IAClD,MAAM,OAAO,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,uBAAuB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAExD,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC;IAE7B,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC7B,CAAC"}
|
|
@@ -5,10 +5,12 @@ export declare function createExplainParams(dbIds: string[]): {
|
|
|
5
5
|
[x: string]: string;
|
|
6
6
|
}>;
|
|
7
7
|
sql: z.ZodString;
|
|
8
|
+
analyze: z.ZodOptional<z.ZodBoolean>;
|
|
8
9
|
};
|
|
9
10
|
export declare function explainHandler(manager: ConnectorManager): (params: {
|
|
10
11
|
database: string;
|
|
11
12
|
sql: string;
|
|
13
|
+
analyze?: boolean;
|
|
12
14
|
}) => Promise<{
|
|
13
15
|
content: {
|
|
14
16
|
type: "text";
|
|
@@ -5,6 +5,7 @@ export function createExplainParams(dbIds) {
|
|
|
5
5
|
return {
|
|
6
6
|
database: z.enum(dbIds).describe(`Database ID. Available: ${dbIds.join(", ")}`),
|
|
7
7
|
sql: z.string().describe("SQL query to explain"),
|
|
8
|
+
analyze: z.boolean().optional().describe("Run EXPLAIN ANALYZE (actually executes the query). Default: false"),
|
|
8
9
|
};
|
|
9
10
|
}
|
|
10
11
|
export function explainHandler(manager) {
|
|
@@ -15,7 +16,7 @@ export function explainHandler(manager) {
|
|
|
15
16
|
}
|
|
16
17
|
try {
|
|
17
18
|
const connector = await manager.getConnector(params.database);
|
|
18
|
-
const result = await connector.explain(params.sql);
|
|
19
|
+
const result = await connector.explain(params.sql, params.analyze ?? false);
|
|
19
20
|
return formatSuccess({ data: result.plan, database: params.database });
|
|
20
21
|
}
|
|
21
22
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"explain.js","sourceRoot":"","sources":["../../../src/tools/readonly/explain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE,MAAM,UAAU,mBAAmB,CAAC,KAAe;IACjD,OAAO;QACL,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,KAA8B,CAAC,CAAC,QAAQ,CAAC,2BAA2B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACxG,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"explain.js","sourceRoot":"","sources":["../../../src/tools/readonly/explain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE,MAAM,UAAU,mBAAmB,CAAC,KAAe;IACjD,OAAO;QACL,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,KAA8B,CAAC,CAAC,QAAQ,CAAC,2BAA2B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACxG,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QAChD,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mEAAmE,CAAC;KAC9G,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAyB;IACtD,OAAO,KAAK,EAAE,MAA4D,EAAE,EAAE;QAC5E,MAAM,UAAU,GAAG,mBAAmB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnD,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;YACtB,OAAO,WAAW,CAAC,UAAU,CAAC,KAAM,EAAE,oBAAoB,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC9D,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,IAAI,KAAK,CAAC,CAAC;YAC5E,OAAO,aAAa,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QACzE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAClC,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -6,7 +6,7 @@ interface SlowQuery {
|
|
|
6
6
|
timestamp: Date;
|
|
7
7
|
database: string;
|
|
8
8
|
}
|
|
9
|
-
declare class PerformanceTracker {
|
|
9
|
+
export declare class PerformanceTracker {
|
|
10
10
|
private slowQueries;
|
|
11
11
|
private threshold;
|
|
12
12
|
recordQuery(sql: string, duration: number, database: string): void;
|
|
@@ -15,7 +15,6 @@ declare class PerformanceTracker {
|
|
|
15
15
|
getThreshold(): number;
|
|
16
16
|
reset(): void;
|
|
17
17
|
}
|
|
18
|
-
export declare const performanceTracker: PerformanceTracker;
|
|
19
18
|
export declare function createPerformanceParams(dbIds: string[]): {
|
|
20
19
|
database: z.ZodEnum<{
|
|
21
20
|
[x: string]: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { formatSuccess, formatError } from "../../utils/response.js";
|
|
3
|
-
class PerformanceTracker {
|
|
3
|
+
export class PerformanceTracker {
|
|
4
4
|
slowQueries = [];
|
|
5
5
|
threshold = 1000; // ms
|
|
6
6
|
recordQuery(sql, duration, database) {
|
|
@@ -11,9 +11,7 @@ class PerformanceTracker {
|
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
getSlowQueries(database, limit = 20) {
|
|
14
|
-
const filtered = database
|
|
15
|
-
? this.slowQueries.filter((q) => q.database === database)
|
|
16
|
-
: this.slowQueries;
|
|
14
|
+
const filtered = database ? this.slowQueries.filter((q) => q.database === database) : this.slowQueries;
|
|
17
15
|
return filtered.slice(-limit);
|
|
18
16
|
}
|
|
19
17
|
setThreshold(ms) {
|
|
@@ -26,7 +24,6 @@ class PerformanceTracker {
|
|
|
26
24
|
this.slowQueries = [];
|
|
27
25
|
}
|
|
28
26
|
}
|
|
29
|
-
export const performanceTracker = new PerformanceTracker();
|
|
30
27
|
export function createPerformanceParams(dbIds) {
|
|
31
28
|
return {
|
|
32
29
|
database: z.enum(dbIds).describe(`Database ID. Available: ${dbIds.join(", ")}`),
|
|
@@ -36,29 +33,30 @@ export function createPerformanceParams(dbIds) {
|
|
|
36
33
|
};
|
|
37
34
|
}
|
|
38
35
|
export function performanceHandler(manager) {
|
|
36
|
+
const tracker = manager.getPerformanceTracker();
|
|
39
37
|
return async (params) => {
|
|
40
38
|
try {
|
|
41
39
|
switch (params.action) {
|
|
42
40
|
case "getSlowQueries":
|
|
43
41
|
return formatSuccess({
|
|
44
|
-
data:
|
|
42
|
+
data: tracker.getSlowQueries(params.database, params.limit),
|
|
45
43
|
database: params.database,
|
|
46
44
|
});
|
|
47
45
|
case "getMetrics":
|
|
48
46
|
return formatSuccess({
|
|
49
47
|
data: {
|
|
50
|
-
slowQueryThreshold:
|
|
48
|
+
slowQueryThreshold: tracker.getThreshold(),
|
|
51
49
|
connectedDatabases: manager.getDatabaseIds(),
|
|
52
50
|
},
|
|
53
51
|
database: params.database,
|
|
54
52
|
});
|
|
55
53
|
case "reset":
|
|
56
|
-
|
|
54
|
+
tracker.reset();
|
|
57
55
|
return formatSuccess({ data: "Performance metrics reset" });
|
|
58
56
|
case "setThreshold":
|
|
59
57
|
if (!params.threshold)
|
|
60
58
|
return formatError("threshold is required for setThreshold");
|
|
61
|
-
|
|
59
|
+
tracker.setThreshold(params.threshold);
|
|
62
60
|
return formatSuccess({ data: `Threshold set to ${params.threshold}ms` });
|
|
63
61
|
default:
|
|
64
62
|
return formatError(`Unknown action: ${params.action}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"performance.js","sourceRoot":"","sources":["../../../src/tools/readonly/performance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AASrE,MAAM,kBAAkB;
|
|
1
|
+
{"version":3,"file":"performance.js","sourceRoot":"","sources":["../../../src/tools/readonly/performance.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,9 +4,11 @@ export declare function createSchemaParams(dbIds: string[]): {
|
|
|
4
4
|
database: z.ZodEnum<{
|
|
5
5
|
[x: string]: string;
|
|
6
6
|
}>;
|
|
7
|
+
schema: z.ZodOptional<z.ZodString>;
|
|
7
8
|
};
|
|
8
9
|
export declare function schemaHandler(manager: ConnectorManager): (params: {
|
|
9
10
|
database: string;
|
|
11
|
+
schema?: string;
|
|
10
12
|
}) => Promise<{
|
|
11
13
|
content: {
|
|
12
14
|
type: "text";
|
|
@@ -3,13 +3,14 @@ import { formatSuccess, formatError } from "../../utils/response.js";
|
|
|
3
3
|
export function createSchemaParams(dbIds) {
|
|
4
4
|
return {
|
|
5
5
|
database: z.enum(dbIds).describe(`Database ID. Available: ${dbIds.join(", ")}`),
|
|
6
|
+
schema: z.string().optional().describe("Schema name (default: 'public' for PostgreSQL, ignored for ClickHouse)"),
|
|
6
7
|
};
|
|
7
8
|
}
|
|
8
9
|
export function schemaHandler(manager) {
|
|
9
10
|
return async (params) => {
|
|
10
11
|
try {
|
|
11
12
|
const connector = await manager.getConnector(params.database);
|
|
12
|
-
const ddl = await connector.getSchema();
|
|
13
|
+
const ddl = await connector.getSchema(params.schema);
|
|
13
14
|
return formatSuccess({ data: ddl, database: params.database });
|
|
14
15
|
}
|
|
15
16
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/tools/readonly/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAErE,MAAM,UAAU,kBAAkB,CAAC,KAAe;IAChD,OAAO;QACL,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,KAA8B,CAAC,CAAC,QAAQ,CAAC,2BAA2B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/tools/readonly/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAErE,MAAM,UAAU,kBAAkB,CAAC,KAAe;IAChD,OAAO;QACL,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,KAA8B,CAAC,CAAC,QAAQ,CAAC,2BAA2B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACxG,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wEAAwE,CAAC;KACjH,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAyB;IACrD,OAAO,KAAK,EAAE,MAA6C,EAAE,EAAE;QAC7D,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC9D,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACrD,OAAO,aAAa,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QACjE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAClC,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/tools/registry.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import type { ConnectorManager } from "../connectors/manager.js";
|
|
3
3
|
import type { Defaults } from "../config/types.js";
|
|
4
4
|
export declare function registerTools(server: McpServer, manager: ConnectorManager, defaults: Defaults): void;
|
package/dist/tools/registry.js
CHANGED
|
@@ -35,8 +35,8 @@ function registerPerDatabaseTools(server, manager, dbIds) {
|
|
|
35
35
|
server.tool(`query_${dbId}`, `Execute a read-only SQL query on ${dbId}${desc}`, { sql: createQueryToolParams(singleDbIds).sql, maxRows: createQueryToolParams(singleDbIds).maxRows }, async (params) => queryToolHandler(manager)({ database: dbId, ...params }));
|
|
36
36
|
server.tool(`list_tables_${dbId}`, `List tables on ${dbId}${desc}`, { schema: createListTablesParams(singleDbIds).schema }, async (params) => listTablesHandler(manager)({ database: dbId, ...params }));
|
|
37
37
|
server.tool(`describe_table_${dbId}`, `Describe table structure on ${dbId}${desc}`, { table: createDescribeTableParams(singleDbIds).table, schema: createDescribeTableParams(singleDbIds).schema }, async (params) => describeTableHandler(manager)({ database: dbId, ...params }));
|
|
38
|
-
server.tool(`schema_${dbId}`, `Get full schema of ${dbId}${desc}`, {}, async () => schemaHandler(manager)({ database: dbId }));
|
|
39
|
-
server.tool(`explain_query_${dbId}`, `Run EXPLAIN on ${dbId}${desc}`, { sql: createExplainParams(singleDbIds).sql }, async (params) => explainHandler(manager)({ database: dbId, ...params }));
|
|
38
|
+
server.tool(`schema_${dbId}`, `Get full schema of ${dbId}${desc}`, { schema: createSchemaParams(singleDbIds).schema }, async (params) => schemaHandler(manager)({ database: dbId, ...params }));
|
|
39
|
+
server.tool(`explain_query_${dbId}`, `Run EXPLAIN on ${dbId}${desc}`, { sql: createExplainParams(singleDbIds).sql, analyze: createExplainParams(singleDbIds).analyze }, async (params) => explainHandler(manager)({ database: dbId, ...params }));
|
|
40
40
|
server.tool(`performance_${dbId}`, `Performance metrics for ${dbId}${desc}`, {
|
|
41
41
|
action: createPerformanceParams(singleDbIds).action,
|
|
42
42
|
threshold: createPerformanceParams(singleDbIds).threshold,
|