@bytebase/dbhub 0.11.0 → 0.11.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 +18 -0
- package/dist/index.js +109 -3
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -217,6 +217,24 @@ postgres://user:password@localhost:5432/dbname
|
|
|
217
217
|
|
|
218
218
|
DBHub supports connecting to databases through SSH tunnels, enabling secure access to databases in private networks or behind firewalls.
|
|
219
219
|
|
|
220
|
+
#### Using SSH Config File (Recommended)
|
|
221
|
+
|
|
222
|
+
DBHub can read SSH connection settings from your `~/.ssh/config` file. Simply use the host alias from your SSH config:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
# If you have this in ~/.ssh/config:
|
|
226
|
+
# Host mybastion
|
|
227
|
+
# HostName bastion.example.com
|
|
228
|
+
# User ubuntu
|
|
229
|
+
# IdentityFile ~/.ssh/id_rsa
|
|
230
|
+
|
|
231
|
+
npx @bytebase/dbhub \
|
|
232
|
+
--dsn "postgres://dbuser:dbpass@database.internal:5432/mydb" \
|
|
233
|
+
--ssh-host mybastion
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
DBHub will automatically use the settings from your SSH config, including hostname, user, port, and identity file. If no identity file is specified in the config, DBHub will try common default locations (`~/.ssh/id_rsa`, `~/.ssh/id_ed25519`, etc.).
|
|
237
|
+
|
|
220
238
|
#### SSH with Password Authentication
|
|
221
239
|
|
|
222
240
|
```bash
|
package/dist/index.js
CHANGED
|
@@ -1881,7 +1881,7 @@ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/
|
|
|
1881
1881
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
1882
1882
|
import express from "express";
|
|
1883
1883
|
import path3 from "path";
|
|
1884
|
-
import { readFileSync as
|
|
1884
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
1885
1885
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
1886
1886
|
|
|
1887
1887
|
// src/utils/ssh-tunnel.ts
|
|
@@ -2031,6 +2031,102 @@ import dotenv from "dotenv";
|
|
|
2031
2031
|
import path from "path";
|
|
2032
2032
|
import fs from "fs";
|
|
2033
2033
|
import { fileURLToPath } from "url";
|
|
2034
|
+
|
|
2035
|
+
// src/utils/ssh-config-parser.ts
|
|
2036
|
+
import { readFileSync as readFileSync2, existsSync } from "fs";
|
|
2037
|
+
import { homedir } from "os";
|
|
2038
|
+
import { join } from "path";
|
|
2039
|
+
import SSHConfig from "ssh-config";
|
|
2040
|
+
var DEFAULT_SSH_KEYS = [
|
|
2041
|
+
"~/.ssh/id_rsa",
|
|
2042
|
+
"~/.ssh/id_ed25519",
|
|
2043
|
+
"~/.ssh/id_ecdsa",
|
|
2044
|
+
"~/.ssh/id_dsa"
|
|
2045
|
+
];
|
|
2046
|
+
function expandTilde(filePath) {
|
|
2047
|
+
if (filePath.startsWith("~/")) {
|
|
2048
|
+
return join(homedir(), filePath.substring(2));
|
|
2049
|
+
}
|
|
2050
|
+
return filePath;
|
|
2051
|
+
}
|
|
2052
|
+
function fileExists(filePath) {
|
|
2053
|
+
try {
|
|
2054
|
+
return existsSync(expandTilde(filePath));
|
|
2055
|
+
} catch {
|
|
2056
|
+
return false;
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
function findDefaultSSHKey() {
|
|
2060
|
+
for (const keyPath of DEFAULT_SSH_KEYS) {
|
|
2061
|
+
if (fileExists(keyPath)) {
|
|
2062
|
+
return expandTilde(keyPath);
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2065
|
+
return void 0;
|
|
2066
|
+
}
|
|
2067
|
+
function parseSSHConfig(hostAlias, configPath) {
|
|
2068
|
+
const sshConfigPath = configPath || join(homedir(), ".ssh", "config");
|
|
2069
|
+
if (!existsSync(sshConfigPath)) {
|
|
2070
|
+
return null;
|
|
2071
|
+
}
|
|
2072
|
+
try {
|
|
2073
|
+
const configContent = readFileSync2(sshConfigPath, "utf8");
|
|
2074
|
+
const config = SSHConfig.parse(configContent);
|
|
2075
|
+
const hostConfig = config.compute(hostAlias);
|
|
2076
|
+
if (!hostConfig || !hostConfig.HostName && !hostConfig.User) {
|
|
2077
|
+
return null;
|
|
2078
|
+
}
|
|
2079
|
+
const sshConfig = {};
|
|
2080
|
+
if (hostConfig.HostName) {
|
|
2081
|
+
sshConfig.host = hostConfig.HostName;
|
|
2082
|
+
} else {
|
|
2083
|
+
sshConfig.host = hostAlias;
|
|
2084
|
+
}
|
|
2085
|
+
if (hostConfig.Port) {
|
|
2086
|
+
sshConfig.port = parseInt(hostConfig.Port, 10);
|
|
2087
|
+
}
|
|
2088
|
+
if (hostConfig.User) {
|
|
2089
|
+
sshConfig.username = hostConfig.User;
|
|
2090
|
+
}
|
|
2091
|
+
if (hostConfig.IdentityFile) {
|
|
2092
|
+
const identityFile = Array.isArray(hostConfig.IdentityFile) ? hostConfig.IdentityFile[0] : hostConfig.IdentityFile;
|
|
2093
|
+
const expandedPath = expandTilde(identityFile);
|
|
2094
|
+
if (fileExists(expandedPath)) {
|
|
2095
|
+
sshConfig.privateKey = expandedPath;
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
if (!sshConfig.privateKey) {
|
|
2099
|
+
const defaultKey = findDefaultSSHKey();
|
|
2100
|
+
if (defaultKey) {
|
|
2101
|
+
sshConfig.privateKey = defaultKey;
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
if (hostConfig.ProxyJump || hostConfig.ProxyCommand) {
|
|
2105
|
+
console.error("Warning: ProxyJump/ProxyCommand in SSH config is not yet supported by DBHub");
|
|
2106
|
+
}
|
|
2107
|
+
if (!sshConfig.host || !sshConfig.username) {
|
|
2108
|
+
return null;
|
|
2109
|
+
}
|
|
2110
|
+
return sshConfig;
|
|
2111
|
+
} catch (error) {
|
|
2112
|
+
console.error(`Error parsing SSH config: ${error instanceof Error ? error.message : String(error)}`);
|
|
2113
|
+
return null;
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
function looksLikeSSHAlias(host) {
|
|
2117
|
+
if (host.includes(".")) {
|
|
2118
|
+
return false;
|
|
2119
|
+
}
|
|
2120
|
+
if (/^[\d:]+$/.test(host)) {
|
|
2121
|
+
return false;
|
|
2122
|
+
}
|
|
2123
|
+
if (/^[0-9a-fA-F:]+$/.test(host) && host.includes(":")) {
|
|
2124
|
+
return false;
|
|
2125
|
+
}
|
|
2126
|
+
return true;
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2129
|
+
// src/config/env.ts
|
|
2034
2130
|
var __filename = fileURLToPath(import.meta.url);
|
|
2035
2131
|
var __dirname = path.dirname(__filename);
|
|
2036
2132
|
function parseCommandLineArgs() {
|
|
@@ -2151,15 +2247,25 @@ function resolveSSHConfig() {
|
|
|
2151
2247
|
if (!hasSSHArgs) {
|
|
2152
2248
|
return null;
|
|
2153
2249
|
}
|
|
2154
|
-
|
|
2250
|
+
let config = {};
|
|
2155
2251
|
let sources = [];
|
|
2252
|
+
let sshConfigHost;
|
|
2156
2253
|
if (args["ssh-host"]) {
|
|
2254
|
+
sshConfigHost = args["ssh-host"];
|
|
2157
2255
|
config.host = args["ssh-host"];
|
|
2158
2256
|
sources.push("ssh-host from command line");
|
|
2159
2257
|
} else if (process.env.SSH_HOST) {
|
|
2258
|
+
sshConfigHost = process.env.SSH_HOST;
|
|
2160
2259
|
config.host = process.env.SSH_HOST;
|
|
2161
2260
|
sources.push("SSH_HOST from environment");
|
|
2162
2261
|
}
|
|
2262
|
+
if (sshConfigHost && looksLikeSSHAlias(sshConfigHost)) {
|
|
2263
|
+
const sshConfigData = parseSSHConfig(sshConfigHost);
|
|
2264
|
+
if (sshConfigData) {
|
|
2265
|
+
config = { ...sshConfigData };
|
|
2266
|
+
sources.push(`SSH config for host '${sshConfigHost}'`);
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2163
2269
|
if (args["ssh-port"]) {
|
|
2164
2270
|
config.port = parseInt(args["ssh-port"], 10);
|
|
2165
2271
|
sources.push("ssh-port from command line");
|
|
@@ -3197,7 +3303,7 @@ function registerPrompts(server) {
|
|
|
3197
3303
|
var __filename3 = fileURLToPath3(import.meta.url);
|
|
3198
3304
|
var __dirname3 = path3.dirname(__filename3);
|
|
3199
3305
|
var packageJsonPath = path3.join(__dirname3, "..", "package.json");
|
|
3200
|
-
var packageJson = JSON.parse(
|
|
3306
|
+
var packageJson = JSON.parse(readFileSync3(packageJsonPath, "utf8"));
|
|
3201
3307
|
var SERVER_NAME = "DBHub MCP Server";
|
|
3202
3308
|
var SERVER_VERSION = packageJson.version;
|
|
3203
3309
|
function generateBanner(version, modes = []) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bytebase/dbhub",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "Universal Database MCP Server",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"mssql": "^11.0.1",
|
|
26
26
|
"mysql2": "^3.13.0",
|
|
27
27
|
"pg": "^8.13.3",
|
|
28
|
+
"ssh-config": "^5.0.3",
|
|
28
29
|
"ssh2": "^1.16.0",
|
|
29
30
|
"zod": "^3.24.2"
|
|
30
31
|
},
|