@zz1996/dbhub-dameng 0.1.0 → 0.1.2
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
CHANGED
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
> This package is a local Dameng/DM8 connector fork of Bytebase DBHub. Use
|
|
6
6
|
> `npx -y @zz1996/dbhub-dameng --transport stdio --config ./dbhub.dameng.toml`
|
|
7
7
|
> for Dameng MCP usage.
|
|
8
|
+
>
|
|
9
|
+
> Dameng DSN format: `dameng://user:password@host:5236/schema`. Prefer a
|
|
10
|
+
> least-privilege read-only Dameng account for production or shared databases,
|
|
11
|
+
> even when the `execute_sql` tool is configured with `readonly = true`.
|
|
8
12
|
|
|
9
13
|
<p align="center">
|
|
10
14
|
<a href="https://dbhub.ai/" target="_blank">
|
|
@@ -30,6 +34,7 @@
|
|
|
30
34
|
| | | | | |
|
|
31
35
|
| Copilot CLI +--->+ +--->+ MariaDB |
|
|
32
36
|
| | | | | |
|
|
37
|
+
| +--->+ +--->+ Dameng / DM8 |
|
|
33
38
|
| | | | | |
|
|
34
39
|
+------------------+ +--------------+ +------------------+
|
|
35
40
|
MCP Clients MCP Server Databases
|
|
@@ -38,14 +43,14 @@
|
|
|
38
43
|
DBHub is a zero-dependency, token efficient MCP server implementing the Model Context Protocol (MCP) server interface. This lightweight gateway allows MCP-compatible clients to connect to and explore different databases:
|
|
39
44
|
|
|
40
45
|
- **Local Development First**: Zero dependency, token efficient with just two MCP tools to maximize context window
|
|
41
|
-
- **Multi-Database**: PostgreSQL, MySQL, MariaDB, SQL Server, and
|
|
46
|
+
- **Multi-Database**: PostgreSQL, MySQL, MariaDB, SQL Server, SQLite, and Dameng/DM8 through a single interface
|
|
42
47
|
- **Multi-Connection**: Connect to multiple databases simultaneously with TOML configuration
|
|
43
48
|
- **Guardrails**: Read-only mode, row limiting, and query timeout to prevent runaway operations
|
|
44
49
|
- **Secure Access**: SSH tunneling and SSL/TLS encryption
|
|
45
50
|
|
|
46
51
|
## Supported Databases
|
|
47
52
|
|
|
48
|
-
PostgreSQL, MySQL, SQL Server, MariaDB, and
|
|
53
|
+
PostgreSQL, MySQL, SQL Server, MariaDB, SQLite, and Dameng/DM8.
|
|
49
54
|
|
|
50
55
|
## MCP Tools
|
|
51
56
|
|
|
@@ -85,6 +90,41 @@ docker run --rm --init \
|
|
|
85
90
|
npx @bytebase/dbhub@latest --transport http --port 8080 --dsn "postgres://user:password@localhost:5432/dbname?sslmode=disable"
|
|
86
91
|
```
|
|
87
92
|
|
|
93
|
+
**Dameng / DM8 fork:**
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
npx -y @zz1996/dbhub-dameng --transport stdio --config ./dbhub.dameng.toml
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Minimal Dameng TOML configuration:
|
|
100
|
+
|
|
101
|
+
```toml
|
|
102
|
+
[[sources]]
|
|
103
|
+
id = "dm8_readonly"
|
|
104
|
+
description = "Dameng DM8 database for schema discovery and read-only SQL queries"
|
|
105
|
+
dsn = "dameng://${DM8_USER}:${DM8_PASSWORD}@${DM8_HOST}:5236/${DM8_SCHEMA}"
|
|
106
|
+
query_timeout = 30
|
|
107
|
+
lazy = true
|
|
108
|
+
|
|
109
|
+
[[tools]]
|
|
110
|
+
name = "search_objects"
|
|
111
|
+
source = "dm8_readonly"
|
|
112
|
+
|
|
113
|
+
[[tools]]
|
|
114
|
+
name = "execute_sql"
|
|
115
|
+
source = "dm8_readonly"
|
|
116
|
+
readonly = true
|
|
117
|
+
max_rows = 100
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
To verify the local Dameng connector against a real DM8 instance without
|
|
121
|
+
committing credentials, set `DAMENG_DSN` or point to a local TOML file:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
DAMENG_DSN="dameng://user:password@host:5236/schema" pnpm verify:dameng
|
|
125
|
+
pnpm verify:dameng -- --config ./dbhub.dameng.toml --source dm8_readonly
|
|
126
|
+
```
|
|
127
|
+
|
|
88
128
|
**Demo Mode:**
|
|
89
129
|
|
|
90
130
|
```bash
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
id = "dm8_dev"
|
|
6
6
|
description = "Dameng DM8 development database. Read-only access for agent schema discovery and SQL queries."
|
|
7
7
|
dsn = "dameng://${DM8_USER}:${DM8_PASSWORD}@${DM8_HOST}:5236/${DM8_SCHEMA}"
|
|
8
|
+
connection_timeout = 5
|
|
8
9
|
query_timeout = 30
|
|
9
10
|
lazy = true
|
|
10
11
|
|
|
@@ -65,6 +65,7 @@ var DamengConnector = class _DamengConnector {
|
|
|
65
65
|
this.pool = null;
|
|
66
66
|
this.sourceId = "default";
|
|
67
67
|
this.defaultSchema = null;
|
|
68
|
+
this.poolAlias = null;
|
|
68
69
|
}
|
|
69
70
|
getId() {
|
|
70
71
|
return this.sourceId;
|
|
@@ -73,13 +74,20 @@ var DamengConnector = class _DamengConnector {
|
|
|
73
74
|
return new _DamengConnector();
|
|
74
75
|
}
|
|
75
76
|
async connect(dsn, initScript, config) {
|
|
77
|
+
let createdPool = null;
|
|
76
78
|
try {
|
|
77
79
|
const connectionConfig = await this.dsnParser.parse(dsn, config);
|
|
80
|
+
connectionConfig.poolAlias = this.buildPoolAlias();
|
|
78
81
|
this.defaultSchema = connectionConfig.schema ?? null;
|
|
82
|
+
this.poolAlias = connectionConfig.poolAlias;
|
|
83
|
+
this.queryTimeoutMs = void 0;
|
|
79
84
|
if (config?.queryTimeoutSeconds !== void 0) {
|
|
80
85
|
this.queryTimeoutMs = config.queryTimeoutSeconds * 1e3;
|
|
81
86
|
}
|
|
82
|
-
|
|
87
|
+
await this.closeRegisteredPool(connectionConfig.poolAlias);
|
|
88
|
+
await this.validateDirectConnection(connectionConfig);
|
|
89
|
+
createdPool = await dmdb.createPool(connectionConfig);
|
|
90
|
+
this.pool = createdPool;
|
|
83
91
|
await this.withConnection(async (conn) => {
|
|
84
92
|
await conn.execute("SELECT 1 AS OK", [], this.executeOptions());
|
|
85
93
|
if (!this.defaultSchema) {
|
|
@@ -97,15 +105,26 @@ var DamengConnector = class _DamengConnector {
|
|
|
97
105
|
}
|
|
98
106
|
});
|
|
99
107
|
} catch (error) {
|
|
108
|
+
if (createdPool) {
|
|
109
|
+
await this.closePoolQuietly(createdPool);
|
|
110
|
+
} else if (this.poolAlias) {
|
|
111
|
+
await this.closeRegisteredPool(this.poolAlias);
|
|
112
|
+
}
|
|
113
|
+
this.pool = null;
|
|
114
|
+
this.poolAlias = null;
|
|
100
115
|
console.error("Failed to connect to Dameng database:", error);
|
|
101
116
|
throw error;
|
|
102
117
|
}
|
|
103
118
|
}
|
|
104
119
|
async disconnect() {
|
|
105
120
|
if (this.pool) {
|
|
106
|
-
await this.pool
|
|
121
|
+
await this.closePoolQuietly(this.pool);
|
|
107
122
|
this.pool = null;
|
|
108
123
|
}
|
|
124
|
+
if (this.poolAlias) {
|
|
125
|
+
await this.closeRegisteredPool(this.poolAlias);
|
|
126
|
+
this.poolAlias = null;
|
|
127
|
+
}
|
|
109
128
|
}
|
|
110
129
|
async getSchemas() {
|
|
111
130
|
const rows = await this.queryRows(`
|
|
@@ -366,6 +385,38 @@ var DamengConnector = class _DamengConnector {
|
|
|
366
385
|
...extra
|
|
367
386
|
};
|
|
368
387
|
}
|
|
388
|
+
async validateDirectConnection(config) {
|
|
389
|
+
let conn = null;
|
|
390
|
+
try {
|
|
391
|
+
conn = await dmdb.getConnection(config.connectString);
|
|
392
|
+
await conn.execute("SELECT 1 AS OK", [], this.executeOptions());
|
|
393
|
+
} finally {
|
|
394
|
+
if (conn) {
|
|
395
|
+
await conn.close();
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
buildPoolAlias() {
|
|
400
|
+
const safeSourceId = this.sourceId.replace(/[^a-zA-Z0-9_-]/g, "_") || "default";
|
|
401
|
+
return `dbhub_dameng_${safeSourceId}`;
|
|
402
|
+
}
|
|
403
|
+
async closeRegisteredPool(poolAlias) {
|
|
404
|
+
if (!dmdb.pools?.has?.(poolAlias)) {
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
const pool = dmdb.pools.get(poolAlias);
|
|
408
|
+
await this.closePoolQuietly(pool);
|
|
409
|
+
dmdb.pools?.delete?.(poolAlias);
|
|
410
|
+
}
|
|
411
|
+
async closePoolQuietly(pool) {
|
|
412
|
+
try {
|
|
413
|
+
await pool.close(0);
|
|
414
|
+
} catch {
|
|
415
|
+
if (pool.poolAlias) {
|
|
416
|
+
dmdb.pools?.delete?.(pool.poolAlias);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
369
420
|
async resolveSchema(schema) {
|
|
370
421
|
const resolved = schema || this.defaultSchema || await this.getDefaultSchema();
|
|
371
422
|
if (!resolved) {
|
package/dist/index.js
CHANGED
|
@@ -1833,7 +1833,7 @@ var connectorModules = [
|
|
|
1833
1833
|
{ load: () => import("./sqlite-IOUAYHGE.js"), name: "SQLite", driver: "node:sqlite" },
|
|
1834
1834
|
{ load: () => import("./mysql-A43SL7UM.js"), name: "MySQL", driver: "mysql2" },
|
|
1835
1835
|
{ load: () => import("./mariadb-7F72IRB4.js"), name: "MariaDB", driver: "mariadb" },
|
|
1836
|
-
{ load: () => import("./dameng-
|
|
1836
|
+
{ load: () => import("./dameng-UJELBZ5R.js"), name: "Dameng", driver: "dmdb" }
|
|
1837
1837
|
];
|
|
1838
1838
|
loadConnectors(connectorModules).then(() => main()).catch((error) => {
|
|
1839
1839
|
console.error("Fatal error:", error);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zz1996/dbhub-dameng",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"mcpName": "io.github.zuozh11/dbhub-dameng",
|
|
5
5
|
"description": "Local fork of DBHub with Dameng/DM8 database connector support",
|
|
6
6
|
"repository": {
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"test:watch": "vitest",
|
|
42
42
|
"test:integration": "vitest run --project integration",
|
|
43
43
|
"test:build": "node scripts/smoke-test-build.mjs",
|
|
44
|
+
"verify:dameng": "tsx scripts/verify-dameng.mjs",
|
|
44
45
|
"prepublishOnly": "npm run build:backend"
|
|
45
46
|
},
|
|
46
47
|
"engines": {
|