@bytebase/dbhub 0.4.11 → 0.6.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.
Files changed (3) hide show
  1. package/README.md +43 -41
  2. package/dist/index.js +125 -28
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -28,9 +28,9 @@ DBHub is a universal database gateway implementing the Model Context Protocol (M
28
28
  MCP Clients MCP Server Databases
29
29
  ```
30
30
 
31
- ## Demo SSE Endpoint
31
+ ## Demo HTTP Endpoint
32
32
 
33
- https://demo.dbhub.ai/sse connects a [sample employee database](https://github.com/bytebase/employee-sample-database). You can point Cursor or MCP Inspector to it to see it in action.
33
+ https://demo.dbhub.ai/message connects a [sample employee database](https://github.com/bytebase/employee-sample-database). You can point Cursor or MCP Inspector to it to see it in action.
34
34
 
35
35
  ![mcp-inspector](https://raw.githubusercontent.com/bytebase/dbhub/main/resources/images/mcp-inspector.webp)
36
36
 
@@ -49,10 +49,10 @@ https://demo.dbhub.ai/sse connects a [sample employee database](https://github.c
49
49
 
50
50
  ### Database Tools
51
51
 
52
- | Tool | Command Name | PostgreSQL | MySQL | MariaDB | SQL Server | SQLite | Oracle |
53
- | --------------- | ----------------- | :--------: | :---: | :-----: | :--------: | ------ | :----: |
54
- | Execute SQL | `execute_sql` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
55
- | List Connectors | `list_connectors` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
52
+ | Tool | Command Name | Description | PostgreSQL | MySQL | MariaDB | SQL Server | SQLite | Oracle |
53
+ | --------------- | ----------------- | ------------------------------------------------------------------- | :--------: | :---: | :-----: | :--------: | ------ | :----: |
54
+ | Execute SQL | `execute_sql` | Execute single or multiple SQL statements (separated by semicolons) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
55
+ | List Connectors | `list_connectors` | List all available database connectors | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
56
56
 
57
57
  ### Prompt Capabilities
58
58
 
@@ -71,7 +71,7 @@ docker run --rm --init \
71
71
  --name dbhub \
72
72
  --publish 8080:8080 \
73
73
  bytebase/dbhub \
74
- --transport sse \
74
+ --transport http \
75
75
  --port 8080 \
76
76
  --dsn "postgres://user:password@localhost:5432/dbname?sslmode=disable"
77
77
  ```
@@ -82,7 +82,7 @@ docker run --rm --init \
82
82
  --name dbhub \
83
83
  --publish 8080:8080 \
84
84
  bytebase/dbhub \
85
- --transport sse \
85
+ --transport http \
86
86
  --port 8080 \
87
87
  --demo
88
88
  ```
@@ -93,18 +93,18 @@ docker run --rm --init \
93
93
  --name dbhub \
94
94
  --publish 8080:8080 \
95
95
  bytebase/dbhub \
96
- --transport sse \
96
+ --transport http \
97
97
  --port 8080 \
98
98
  --dsn "oracle://username:password@localhost:1521/service_name"
99
99
  ```
100
100
 
101
101
  ```bash
102
- # Oracle example with thick mode for connecting to 11g or older
102
+ # Oracle example with thick mode for connecting to 11g or older
103
103
  docker run --rm --init \
104
104
  --name dbhub \
105
105
  --publish 8080:8080 \
106
106
  bytebase/dbhub-oracle-thick \
107
- --transport sse \
107
+ --transport http \
108
108
  --port 8080 \
109
109
  --dsn "oracle://username:password@localhost:1521/service_name"
110
110
  ```
@@ -113,12 +113,12 @@ docker run --rm --init \
113
113
 
114
114
  ```bash
115
115
  # PostgreSQL example
116
- npx @bytebase/dbhub --transport sse --port 8080 --dsn "postgres://user:password@localhost:5432/dbname?sslmode=disable"
116
+ npx @bytebase/dbhub --transport http --port 8080 --dsn "postgres://user:password@localhost:5432/dbname?sslmode=disable"
117
117
  ```
118
118
 
119
119
  ```bash
120
120
  # Demo mode with sample employee database
121
- npx @bytebase/dbhub --transport sse --port 8080 --demo
121
+ npx @bytebase/dbhub --transport http --port 8080 --demo
122
122
  ```
123
123
 
124
124
  > Note: The demo mode includes a bundled SQLite sample "employee" database with tables for employees, departments, salaries, and more.
@@ -170,7 +170,7 @@ npx @bytebase/dbhub --transport sse --port 8080 --demo
170
170
 
171
171
  ![cursor](https://raw.githubusercontent.com/bytebase/dbhub/main/resources/images/cursor.webp)
172
172
 
173
- - Cursor supports both `stdio` and `sse`.
173
+ - Cursor supports both `stdio` and `http`.
174
174
  - Follow [Cursor MCP guide](https://docs.cursor.com/context/model-context-protocol) and make sure to use [Agent](https://docs.cursor.com/chat/agent) mode.
175
175
 
176
176
  ## Usage
@@ -179,14 +179,14 @@ npx @bytebase/dbhub --transport sse --port 8080 --demo
179
179
 
180
180
  You can specify the SSL mode using the `sslmode` parameter in your DSN string:
181
181
 
182
- | Database | `sslmode=disable` | `sslmode=require` | Default SSL Behavior |
183
- |------------|:----------------:|:----------------:|:-------------------:|
184
- | PostgreSQL | | | Certificate verification |
185
- | MySQL | | | Certificate verification |
186
- | MariaDB | | | Certificate verification |
187
- | SQL Server | | | Certificate verification |
188
- | Oracle | | | N/A (use Oracle client config) |
189
- | SQLite | | | N/A (file-based) |
182
+ | Database | `sslmode=disable` | `sslmode=require` | Default SSL Behavior |
183
+ | ---------- | :---------------: | :---------------: | :----------------------------: |
184
+ | PostgreSQL | | | Certificate verification |
185
+ | MySQL | | | Certificate verification |
186
+ | MariaDB | | | Certificate verification |
187
+ | SQL Server | | | Certificate verification |
188
+ | Oracle | | | N/A (use Oracle client config) |
189
+ | SQLite | | | N/A (file-based) |
190
190
 
191
191
  **SSL Mode Options:**
192
192
 
@@ -196,6 +196,7 @@ You can specify the SSL mode using the `sslmode` parameter in your DSN string:
196
196
  Without specifying `sslmode`, most databases default to certificate verification, which provides the highest level of security.
197
197
 
198
198
  Example usage:
199
+
199
200
  ```bash
200
201
  # Disable SSL
201
202
  postgres://user:password@localhost:5432/dbname?sslmode=disable
@@ -255,14 +256,14 @@ For real databases, a Database Source Name (DSN) is required. You can provide th
255
256
 
256
257
  DBHub supports the following database connection string formats:
257
258
 
258
- | Database | DSN Format | Example |
259
- | ---------- | --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
260
- | MySQL | `mysql://[user]:[password]@[host]:[port]/[database]` | `mysql://user:password@localhost:3306/dbname?sslmode=disable` |
261
- | MariaDB | `mariadb://[user]:[password]@[host]:[port]/[database]` | `mariadb://user:password@localhost:3306/dbname?sslmode=disable` |
262
- | PostgreSQL | `postgres://[user]:[password]@[host]:[port]/[database]` | `postgres://user:password@localhost:5432/dbname?sslmode=disable` |
263
- | SQL Server | `sqlserver://[user]:[password]@[host]:[port]/[database]` | `sqlserver://user:password@localhost:1433/dbname?sslmode=disable` |
264
- | SQLite | `sqlite:///[path/to/file]` or `sqlite:///:memory:` | `sqlite:///path/to/database.db`, `sqlite:C:/Users/YourName/data/database.db (windows)` or `sqlite:///:memory:` |
265
- | Oracle | `oracle://[user]:[password]@[host]:[port]/[service_name]` | `oracle://username:password@localhost:1521/service_name?sslmode=disable` |
259
+ | Database | DSN Format | Example |
260
+ | ---------- | --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
261
+ | MySQL | `mysql://[user]:[password]@[host]:[port]/[database]` | `mysql://user:password@localhost:3306/dbname?sslmode=disable` |
262
+ | MariaDB | `mariadb://[user]:[password]@[host]:[port]/[database]` | `mariadb://user:password@localhost:3306/dbname?sslmode=disable` |
263
+ | PostgreSQL | `postgres://[user]:[password]@[host]:[port]/[database]` | `postgres://user:password@localhost:5432/dbname?sslmode=disable` |
264
+ | SQL Server | `sqlserver://[user]:[password]@[host]:[port]/[database]` | `sqlserver://user:password@localhost:1433/dbname?sslmode=disable` |
265
+ | SQLite | `sqlite:///[path/to/file]` or `sqlite:///:memory:` | `sqlite:///path/to/database.db`, `sqlite:C:/Users/YourName/data/database.db (windows)` or `sqlite:///:memory:` |
266
+ | Oracle | `oracle://[user]:[password]@[host]:[port]/[service_name]` | `oracle://username:password@localhost:1521/service_name?sslmode=disable` |
266
267
 
267
268
  #### Oracle
268
269
 
@@ -301,9 +302,9 @@ Extra query parameters:
301
302
  npx @bytebase/dbhub --transport stdio --dsn "postgres://user:password@localhost:5432/dbname?sslmode=disable"
302
303
  ```
303
304
 
304
- - **sse** - for browser and network clients:
305
+ - **http** - for browser and network clients:
305
306
  ```bash
306
- npx @bytebase/dbhub --transport sse --port 5678 --dsn "postgres://user:password@localhost:5432/dbname?sslmode=disable"
307
+ npx @bytebase/dbhub --transport http --port 5678 --dsn "postgres://user:password@localhost:5432/dbname?sslmode=disable"
307
308
  ```
308
309
 
309
310
  ### Command line options
@@ -312,8 +313,8 @@ Extra query parameters:
312
313
  | --------- | --------------------------------------------------------------- | ---------------------------- |
313
314
  | demo | Run in demo mode with sample employee database | `false` |
314
315
  | dsn | Database connection string | Required if not in demo mode |
315
- | transport | Transport mode: `stdio` or `sse` | `stdio` |
316
- | port | HTTP server port (only applicable when using `--transport=sse`) | `8080` |
316
+ | transport | Transport mode: `stdio` or `http` | `stdio` |
317
+ | port | HTTP server port (only applicable when using `--transport=http`) | `8080` |
317
318
  | readonly | Restrict SQL execution to read-only operations | `false` |
318
319
 
319
320
  The demo mode uses an in-memory SQLite database loaded with the [sample employee database](https://github.com/bytebase/dbhub/tree/main/resources/employee-sqlite) that includes tables for employees, departments, titles, salaries, department employees, and department managers. The sample database includes SQL scripts for table creation, data loading, and testing.
@@ -340,16 +341,17 @@ The demo mode uses an in-memory SQLite database loaded with the [sample employee
340
341
 
341
342
  ### Testing
342
343
 
343
- The project uses Vitest for testing:
344
+ The project uses Vitest for comprehensive unit testing:
344
345
 
345
- - Run tests: `pnpm test`
346
- - Run tests in watch mode: `pnpm test:watch`
346
+ - **Run all tests**: `pnpm test`
347
+ - **Run tests in watch mode**: `pnpm test:watch`
347
348
 
348
349
  #### Pre-commit Hooks (for Developers)
349
350
 
350
351
  The project includes pre-commit hooks to run tests automatically before each commit:
351
352
 
352
353
  1. After cloning the repository, set up the pre-commit hooks:
354
+
353
355
  ```bash
354
356
  ./scripts/setup-husky.sh
355
357
  ```
@@ -365,17 +367,17 @@ The project includes pre-commit hooks to run tests automatically before each com
365
367
  TRANSPORT=stdio DSN="postgres://user:password@localhost:5432/dbname?sslmode=disable" npx @modelcontextprotocol/inspector node /path/to/dbhub/dist/index.js
366
368
  ```
367
369
 
368
- #### SSE
370
+ #### HTTP
369
371
 
370
372
  ```bash
371
- # Start DBHub with SSE transport
372
- pnpm dev --transport=sse --port=8080
373
+ # Start DBHub with HTTP transport
374
+ pnpm dev --transport=http --port=8080
373
375
 
374
376
  # Start the MCP Inspector in another terminal
375
377
  npx @modelcontextprotocol/inspector
376
378
  ```
377
379
 
378
- Connect to the DBHub server `/sse` endpoint
380
+ Connect to the DBHub server `/message` endpoint
379
381
 
380
382
  ## Contributors
381
383
 
package/dist/index.js CHANGED
@@ -457,7 +457,26 @@ var PostgresConnector = class {
457
457
  }
458
458
  const client = await this.pool.connect();
459
459
  try {
460
- return await client.query(sql2);
460
+ const statements = sql2.split(";").map((statement) => statement.trim()).filter((statement) => statement.length > 0);
461
+ if (statements.length === 1) {
462
+ return await client.query(statements[0]);
463
+ } else {
464
+ let allRows = [];
465
+ await client.query("BEGIN");
466
+ try {
467
+ for (const statement of statements) {
468
+ const result = await client.query(statement);
469
+ if (result.rows && result.rows.length > 0) {
470
+ allRows.push(...result.rows);
471
+ }
472
+ }
473
+ await client.query("COMMIT");
474
+ } catch (error) {
475
+ await client.query("ROLLBACK");
476
+ throw error;
477
+ }
478
+ return { rows: allRows };
479
+ }
461
480
  } finally {
462
481
  client.release();
463
482
  }
@@ -1004,8 +1023,31 @@ var SQLiteConnector = class {
1004
1023
  throw new Error("Not connected to SQLite database");
1005
1024
  }
1006
1025
  try {
1007
- const rows = this.db.prepare(sql2).all();
1008
- return { rows };
1026
+ const statements = sql2.split(";").map((statement) => statement.trim()).filter((statement) => statement.length > 0);
1027
+ if (statements.length === 1) {
1028
+ const rows = this.db.prepare(statements[0]).all();
1029
+ return { rows };
1030
+ } else {
1031
+ const readStatements = [];
1032
+ const writeStatements = [];
1033
+ for (const statement of statements) {
1034
+ const trimmedStatement = statement.toLowerCase().trim();
1035
+ if (trimmedStatement.startsWith("select") || trimmedStatement.startsWith("with") || trimmedStatement.startsWith("explain") || trimmedStatement.startsWith("analyze") || trimmedStatement.startsWith("pragma")) {
1036
+ readStatements.push(statement);
1037
+ } else {
1038
+ writeStatements.push(statement);
1039
+ }
1040
+ }
1041
+ if (writeStatements.length > 0) {
1042
+ this.db.exec(writeStatements.join("; "));
1043
+ }
1044
+ let allRows = [];
1045
+ for (const statement of readStatements) {
1046
+ const result = this.db.prepare(statement).all();
1047
+ allRows.push(...result);
1048
+ }
1049
+ return { rows: allRows };
1050
+ }
1009
1051
  } catch (error) {
1010
1052
  throw error;
1011
1053
  }
@@ -1029,7 +1071,9 @@ var MySQLDSNParser = class {
1029
1071
  database: url.pathname ? url.pathname.substring(1) : "",
1030
1072
  // Remove leading '/' if exists
1031
1073
  user: url.username,
1032
- password: url.password
1074
+ password: url.password,
1075
+ multipleStatements: true
1076
+ // Enable native multi-statement support
1033
1077
  };
1034
1078
  url.forEachSearchParam((value, key) => {
1035
1079
  if (key === "sslmode") {
@@ -1359,8 +1403,19 @@ var MySQLConnector = class {
1359
1403
  throw new Error("Not connected to database");
1360
1404
  }
1361
1405
  try {
1362
- const [rows, fields] = await this.pool.query(sql2);
1363
- return { rows, fields };
1406
+ const results = await this.pool.query(sql2);
1407
+ const [firstResult] = results;
1408
+ if (Array.isArray(firstResult) && firstResult.length > 0 && Array.isArray(firstResult[0]) && firstResult[0].length === 2) {
1409
+ let allRows = [];
1410
+ for (const [rows, _fields] of firstResult) {
1411
+ if (Array.isArray(rows)) {
1412
+ allRows.push(...rows);
1413
+ }
1414
+ }
1415
+ return { rows: allRows };
1416
+ } else {
1417
+ return { rows: Array.isArray(firstResult) ? firstResult : [] };
1418
+ }
1364
1419
  } catch (error) {
1365
1420
  console.error("Error executing query:", error);
1366
1421
  throw error;
@@ -1385,7 +1440,9 @@ var MariadbDSNParser = class {
1385
1440
  database: url.pathname ? url.pathname.substring(1) : "",
1386
1441
  // Remove leading '/' if exists
1387
1442
  user: url.username,
1388
- password: url.password
1443
+ password: url.password,
1444
+ multipleStatements: true
1445
+ // Enable native multi-statement support
1389
1446
  };
1390
1447
  url.forEachSearchParam((value, key) => {
1391
1448
  if (key === "sslmode") {
@@ -1716,8 +1773,19 @@ var MariaDBConnector = class {
1716
1773
  throw new Error("Not connected to database");
1717
1774
  }
1718
1775
  try {
1719
- const [rows, fields] = await this.pool.query(sql2);
1720
- return { rows, fields };
1776
+ const results = await this.pool.query(sql2);
1777
+ const [firstResult] = results;
1778
+ if (Array.isArray(firstResult) && firstResult.length > 0 && Array.isArray(firstResult[0]) && firstResult[0].length === 2) {
1779
+ let allRows = [];
1780
+ for (const [rows, _fields] of firstResult) {
1781
+ if (Array.isArray(rows)) {
1782
+ allRows.push(...rows);
1783
+ }
1784
+ }
1785
+ return { rows: allRows };
1786
+ } else {
1787
+ return { rows: Array.isArray(firstResult) ? firstResult : [] };
1788
+ }
1721
1789
  } catch (error) {
1722
1790
  console.error("Error executing query:", error);
1723
1791
  throw error;
@@ -2228,7 +2296,7 @@ ConnectorRegistry.register(new OracleConnector());
2228
2296
 
2229
2297
  // src/server.ts
2230
2298
  import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
2231
- import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
2299
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
2232
2300
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2233
2301
  import express from "express";
2234
2302
  import path3 from "path";
@@ -2405,11 +2473,11 @@ function resolveDSN() {
2405
2473
  function resolveTransport() {
2406
2474
  const args = parseCommandLineArgs();
2407
2475
  if (args.transport) {
2408
- const type = args.transport === "sse" ? "sse" : "stdio";
2476
+ const type = args.transport === "http" ? "http" : "stdio";
2409
2477
  return { type, source: "command line argument" };
2410
2478
  }
2411
2479
  if (process.env.TRANSPORT) {
2412
- const type = process.env.TRANSPORT === "sse" ? "sse" : "stdio";
2480
+ const type = process.env.TRANSPORT === "http" ? "http" : "stdio";
2413
2481
  return { type, source: "environment variable" };
2414
2482
  }
2415
2483
  return { type: "stdio", source: "default" };
@@ -2836,18 +2904,25 @@ var allowedKeywords = {
2836
2904
 
2837
2905
  // src/tools/execute-sql.ts
2838
2906
  var executeSqlSchema = {
2839
- sql: z.string().describe("SQL query to execute (SELECT only)")
2907
+ sql: z.string().describe("SQL query or multiple SQL statements to execute (separated by semicolons)")
2840
2908
  };
2909
+ function splitSQLStatements(sql2) {
2910
+ return sql2.split(";").map((statement) => statement.trim()).filter((statement) => statement.length > 0);
2911
+ }
2841
2912
  function isReadOnlySQL(sql2, connectorType) {
2842
2913
  const normalizedSQL = sql2.trim().toLowerCase();
2843
2914
  const firstWord = normalizedSQL.split(/\s+/)[0];
2844
2915
  const keywordList = allowedKeywords[connectorType] || allowedKeywords.default || [];
2845
2916
  return keywordList.includes(firstWord);
2846
2917
  }
2918
+ function areAllStatementsReadOnly(sql2, connectorType) {
2919
+ const statements = splitSQLStatements(sql2);
2920
+ return statements.every((statement) => isReadOnlySQL(statement, connectorType));
2921
+ }
2847
2922
  async function executeSqlToolHandler({ sql: sql2 }, _extra) {
2848
2923
  const connector = ConnectorManager.getCurrentConnector();
2849
2924
  try {
2850
- if (isReadOnlyMode() && !isReadOnlySQL(sql2, connector.id)) {
2925
+ if (isReadOnlyMode() && !areAllStatementsReadOnly(sql2, connector.id)) {
2851
2926
  return createToolErrorResponse(
2852
2927
  `Read-only mode is enabled. Only the following SQL operations are allowed: ${allowedKeywords[connector.id]?.join(", ") || "none"}`,
2853
2928
  "READONLY_VIOLATION"
@@ -3399,27 +3474,49 @@ See documentation for more details on configuring database connections.
3399
3474
  console.error(`Running in ${activeModes.join(" and ")} mode - ${modeDescriptions.join(", ")}`);
3400
3475
  }
3401
3476
  console.error(generateBanner(SERVER_VERSION, activeModes));
3402
- if (transportData.type === "sse") {
3477
+ if (transportData.type === "http") {
3403
3478
  const app = express();
3404
- let transport;
3405
- app.get("/sse", async (req, res) => {
3406
- transport = new SSEServerTransport("/message", res);
3407
- console.error("Client connected", transport?.["_sessionId"]);
3408
- await server.connect(transport);
3409
- res.on("close", () => {
3410
- console.error("Client Disconnected", transport?.["_sessionId"]);
3411
- });
3479
+ app.use(express.json());
3480
+ app.use((req, res, next) => {
3481
+ const origin = req.headers.origin;
3482
+ if (origin && !origin.startsWith("http://localhost") && !origin.startsWith("https://localhost")) {
3483
+ return res.status(403).json({ error: "Forbidden origin" });
3484
+ }
3485
+ res.header("Access-Control-Allow-Origin", origin || "http://localhost");
3486
+ res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
3487
+ res.header("Access-Control-Allow-Headers", "Content-Type, Mcp-Session-Id");
3488
+ res.header("Access-Control-Allow-Credentials", "true");
3489
+ if (req.method === "OPTIONS") {
3490
+ return res.sendStatus(200);
3491
+ }
3492
+ next();
3412
3493
  });
3413
- app.post("/message", async (req, res) => {
3414
- console.error("Client Message", transport?.["_sessionId"]);
3415
- await transport.handlePostMessage(req, res, req.body);
3494
+ const transport = new StreamableHTTPServerTransport({
3495
+ sessionIdGenerator: () => `session_${Date.now()}_${Math.random().toString(36).substring(7)}`,
3496
+ onsessioninitialized: (sessionId) => {
3497
+ console.error(`Session initialized: ${sessionId}`);
3498
+ },
3499
+ enableJsonResponse: false
3500
+ // Use SSE streaming
3501
+ });
3502
+ await server.connect(transport);
3503
+ app.all("/message", async (req, res) => {
3504
+ try {
3505
+ const parsedBody = req.method === "POST" ? req.body : void 0;
3506
+ await transport.handleRequest(req, res, parsedBody);
3507
+ } catch (error) {
3508
+ console.error("Error handling request:", error);
3509
+ if (!res.headersSent) {
3510
+ res.status(500).json({ error: "Internal server error" });
3511
+ }
3512
+ }
3416
3513
  });
3417
3514
  const portData = resolvePort();
3418
3515
  const port = portData.port;
3419
3516
  console.error(`Port source: ${portData.source}`);
3420
- app.listen(port, () => {
3517
+ app.listen(port, "localhost", () => {
3421
3518
  console.error(`DBHub server listening at http://localhost:${port}`);
3422
- console.error(`Connect to MCP server at http://localhost:${port}/sse`);
3519
+ console.error(`Connect to MCP server at http://localhost:${port}/message`);
3423
3520
  });
3424
3521
  } else {
3425
3522
  const transport = new StdioServerTransport();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bytebase/dbhub",
3
- "version": "0.4.11",
3
+ "version": "0.6.0",
4
4
  "description": "Universal Database MCP Server",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -17,7 +17,7 @@
17
17
  "license": "MIT",
18
18
  "dependencies": {
19
19
  "@azure/identity": "^4.8.0",
20
- "@modelcontextprotocol/sdk": "^1.6.1",
20
+ "@modelcontextprotocol/sdk": "^1.12.1",
21
21
  "better-sqlite3": "^11.9.0",
22
22
  "dotenv": "^16.4.7",
23
23
  "express": "^4.18.2",