From f71f4554094ad0d28f3e150f38c8dd12371f9811 Mon Sep 17 00:00:00 2001 From: laserduor <312182928+laserduor@users.noreply.github.com> Date: Tue, 4 Aug 2026 16:38:36 +0000 Subject: [PATCH 1/4] docs: add HTTP server deployment guide Add a dedicated HTTP MCP server configuration page covering: - When to use HTTP vs stdio transport - All endpoints (/mcp, /healthz, /api/*) - Security: DNS-rebinding protection, bearer token auth, CORS - Production deployment: reverse proxy, Docker, multi-instance - Client configuration for HTTP transport - Complete command-line reference --- docs/config/http-server.mdx | 268 ++++++++++++++++++++++++++++++++++++ docs/docs.json | 2 +- 2 files changed, 269 insertions(+), 1 deletion(-) create mode 100644 docs/config/http-server.mdx diff --git a/docs/config/http-server.mdx b/docs/config/http-server.mdx new file mode 100644 index 00000000..63ded431 --- /dev/null +++ b/docs/config/http-server.mdx @@ -0,0 +1,268 @@ +--- +title: "HTTP Server" +description: "Run DBHub as an HTTP MCP server — endpoints, security, and production deployment" +--- + +DBHub supports two transport modes. This page covers the **HTTP transport** — running DBHub as a standalone HTTP server that serves the MCP endpoint, a web-based Workbench, and REST APIs. + +For the stdio transport (the default), see the [Installation](/installation) guide. + +## When to use HTTP + +| Scenario | Transport | +|----------|-----------| +| Local desktop app (Claude Desktop, VS Code, Cursor) | stdio | +| Shared team server, remote access | **http** | +| Web clients (Dify, LibreChat, custom web UIs) | **http** | +| Multi-process / load-balanced deployment | **http** | +| Workbench (browser-based tool execution) | **http** | + +## Quick Start + +```bash +# Start with a single database +npx @bytebase/dbhub@latest --transport http --port 8080 --dsn "postgres://user:***@localhost:5432/dbname" + +# Demo mode (no database needed) +npx @bytebase/dbhub@latest --transport http --port 8080 --demo +``` + +The server prints startup information: + +``` +Workbench at http://localhost:8080/ +MCP server endpoint at http://localhost:8080/mcp +``` + +## Endpoints + +| Path | Method | Description | +|------|--------|-------------| +| `/` | GET | Workbench (SPA) | +| `/mcp` | POST | MCP protocol endpoint | +| `/healthz` | GET | Health check (always returns `200 OK`) | +| `/api/sources` | GET | List configured database sources | +| `/api/sources/:sourceId` | GET | Get a specific source's details | +| `/api/requests` | GET | Recent tool execution traces | + +### MCP Endpoint (`/mcp`) + +The single `/mcp` POST endpoint serves both MCP protocol eras: + +- **2026-07-28** (native): stateless by design — a fresh server instance per request, no `Mcp-Session-Id`. Clients send `Mcp-Method` / `Mcp-Name` headers on every request, enabling a fronting gateway or WAF to route and rate-limit `execute_sql` separately from `search_objects` without parsing JSON bodies. +- **2025-era** (legacy fallback): served through the default `legacy: 'stateless'` fallback on the same endpoint. + + +The `tools/list` response includes cache hints (5-minute TTL, `private` scope) for 2026-07-28 clients. After a TOML config hot-reload adds or removes tools, clients may serve a stale tool list for up to 5 minutes. + + +### Health Check (`/healthz`) + +Returns `200 OK` without any authentication. Uptime monitors and load balancer probes can use this endpoint without a token. + +### API Endpoints (`/api/*`) + +REST endpoints for source management and request tracing. Used by the Workbench frontend. See [Workbench](/workbench/overview). + +## Security + +### DNS-Rebinding Protection + +By default, the HTTP transport only accepts requests whose `Host` header is a loopback address (`localhost`, `127.0.0.1`, `[::1]`). When bound to `0.0.0.0` (the default), this machine's own hostname and external IP addresses are also allowed automatically. + +To serve DBHub behind a reverse proxy or public DNS name, add the hostname with `--allowed-hosts`: + +```bash +npx @bytebase/dbhub@latest --transport http --port 8080 \ + --allowed-hosts "dbhub.example.com" \ + --dsn "postgres://user:***@localhost:5432/dbname" +``` + +Multiple hostnames: + +```bash +--allowed-hosts "dbhub.example.com,db.internal.corp" +``` + +Disable the check entirely (only when fronted by your own authentication): + +```bash +--allowed-hosts "*" +``` + + +`--allowed-hosts "*"` turns off DNS-rebinding protection. Use it only when DBHub sits behind your own authentication and/or proxy. + + +### Bearer Token Authentication + +Require a bearer token on every request (except `/healthz`): + +```bash +npx @bytebase/dbhub@latest --transport http --port 8080 \ + --auth-token "s3cr3t-token" \ + --dsn "postgres://user:***@localhost:5432/dbname" +``` + +Multiple tokens for rotation or per-client tokens: + +```bash +--auth-token "token-for-ci,token-for-agent" +``` + +Clients send the token as: + +```bash +curl -H "Authorization: Bearer s3cr3t-token" http://localhost:8080/api/sources +``` + + +Configuring a token is the opt-in — there is no separate "require auth" flag. A comma-separated list lets you rotate tokens without downtime or hand different tokens to different clients for independent revocation. + + + +This is a flat shared-secret check, not OAuth. For real identity-based authorization, front DBHub with your own OAuth-aware proxy or IdP-integrated gateway. + + +### CORS + +The HTTP transport reflects validated origins in `Access-Control-Allow-Origin` headers and supports preflight (`OPTIONS`). The allowed headers include `Mcp-Method`, `Mcp-Name`, `Mcp-Session-Id`, `MCP-Protocol-Version`, `Authorization`, and `Content-Type`. + +## Production Deployment + +### Bind to Loopback + Reverse Proxy + +For production, bind to `127.0.0.1` and front DBHub with a reverse proxy (nginx, Caddy, or your cloud provider's load balancer): + +```bash +npx @bytebase/dbhub@latest --transport http --host 127.0.0.1 --port 8080 --dsn "..." +``` + +### Docker + +```bash +docker run --rm --init \ + --name dbhub \ + --publish 8080:8080 \ + bytebase/dbhub \ + --transport http \ + --port 8080 \ + --dsn "postgres://user:***@localhost:5432/dbname?sslmode=disable" +``` + + +When connecting to databases on your host machine from Docker, use `host.docker.internal` instead of `localhost`. + + +### Docker Compose + +```yaml docker-compose.yml +services: + dbhub: + image: bytebase/dbhub:latest + container_name: dbhub + ports: + - "8080:8080" + command: + - --transport + - http + - --port + - "8080" + - --dsn + - "postgres://user:***@database:5432/dbname" + depends_on: + - database + + database: + image: postgres:15-alpine + environment: + POSTGRES_PASSWORD: password + POSTGRES_DB: dbname +``` + +### Multi-Database with TOML + +```bash +npx @bytebase/dbhub@latest --transport http --port 8080 --config ./dbhub.toml +``` + +See [TOML Configuration](/config/toml) for the complete reference. + +### Multi-Instance + +Run multiple DBHub instances on different ports, each with a different database: + +```bash +# Instance 1: production +npx @bytebase/dbhub@latest --transport http --port 8080 --id prod --dsn "postgres://..." + +# Instance 2: staging +npx @bytebase/dbhub@latest --transport http --port 8081 --id staging --dsn "postgres://..." +``` + +## Client Configuration + +When DBHub runs with HTTP transport, configure your MCP client to connect via HTTP instead of stdio: + +### Claude Code + +```bash +claude mcp add --transport http dbhub http://localhost:8080/mcp +``` + +### Project .mcp.json + +```json +{ + "mcpServers": { + "dbhub": { + "type": "http", + "url": "http://localhost:8080/mcp" + } + } +} +``` + +### Cursor + +Edit `~/.cursor/mcp.json`: + +```json +{ + "mcpServers": { + "dbhub": { + "url": "http://localhost:8080/mcp" + } + } +} +``` + +### VS Code + +Create `.vscode/mcp.json`: + +```json +{ + "servers": { + "dbhub": { + "type": "http", + "url": "http://localhost:8080/mcp" + } + } +} +``` + +## Command-Line Reference + +| Flag | Env | Default | Description | +|------|-----|---------|-------------| +| `--transport http` | `TRANSPORT` | `stdio` | Enable HTTP transport | +| `--port` | `PORT` | `8080` | HTTP server port | +| `--host` | `DBHUB_HOST` | `0.0.0.0` | HTTP bind address | +| `--allowed-hosts` | `DBHUB_ALLOWED_HOSTS` | loopback + self | Extra hostnames for DNS-rebinding protection | +| `--auth-token` | `DBHUB_AUTH_TOKEN` | (disabled) | Comma-separated bearer tokens | +| `--demo` | — | `false` | Use bundled sample employee database | +| `--config` | — | — | Path to TOML config file | +| `--dsn` | `DSN` | — | Database connection string | + +See [Command-Line Options](/config/command-line) for all available flags including SSH tunnel configuration. \ No newline at end of file diff --git a/docs/docs.json b/docs/docs.json index 475da462..6464693d 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -37,7 +37,7 @@ }, { "group": "Configuration", - "pages": ["config/command-line", "config/toml", "config/debug"] + "pages": ["config/command-line", "config/http-server", "config/toml", "config/debug"] } ] }, From 465ac8a47cfcd2984aa99f7ba36b9ceafc95e3af Mon Sep 17 00:00:00 2001 From: laserduor <312182928+laserduor@users.noreply.github.com> Date: Tue, 4 Aug 2026 16:50:28 +0000 Subject: [PATCH 2/4] docs: add authentication guide for --auth-token New dedicated page (config/auth-token.mdx) covering: - How bearer token auth works in DBHub - Setting the token via CLI flag, env var, .env file, Docker - Client configuration (curl, .mcp.json, Claude Code) - Multiple tokens for zero-downtime rotation and per-client tokens - Security considerations (constant-time comparison, defense in depth) - Verification steps to confirm auth is working - Complete reference table Simplified http-server.mdx to reference the new auth page instead of duplicating content. --- docs/config/auth-token.mdx | 168 ++++++++++++++++++++++++++++++++++++ docs/config/http-server.mdx | 22 +---- docs/docs.json | 2 +- 3 files changed, 170 insertions(+), 22 deletions(-) create mode 100644 docs/config/auth-token.mdx diff --git a/docs/config/auth-token.mdx b/docs/config/auth-token.mdx new file mode 100644 index 00000000..0a6be059 --- /dev/null +++ b/docs/config/auth-token.mdx @@ -0,0 +1,168 @@ +--- +title: "Authentication" +description: "Secure your DBHub HTTP server with bearer token authentication" +--- + +When running DBHub with HTTP transport, anybody who can reach the server URL can access your database. To protect it, configure **bearer token authentication** with `--auth-token`. + +## How It Works + +DBHub checks every HTTP request for a valid `Authorization: Bearer ` header. Requests without a valid token are rejected with `401 Unauthorized` and a `WWW-Authenticate: Bearer` header. + +The `/healthz` endpoint is exempt from authentication so uptime monitors and load balancer probes don't need a token. + + +Configuring a token **is** the opt-in — there is no separate "--require-auth" flag to remember. Auth is disabled by default; set `--auth-token` or `DBHUB_AUTH_TOKEN` and it turns on. + + +## Setting the Token + +### CLI Flag + +```bash +npx @bytebase/dbhub@latest --transport http --port 8080 \ + --auth-token "s3cr3t-token" \ + --dsn "postgres://user:***@localhost:5432/dbname" +``` + +### Environment Variable + +```bash +export DBHUB_AUTH_TOKEN="s3cr3t-token" +npx @bytebase/dbhub@latest --transport http --port 8080 --dsn "..." +``` + +### .env File + +```bash +# .env +DBHUB_AUTH_TOKEN="s3cr3t-token" +``` + +```bash +npx @bytebase/dbhub@latest --transport http --port 8080 --dsn "..." +``` + +### Docker + +```bash +docker run --rm --init \ + --name dbhub \ + --publish 8080:8080 \ + -e DBHUB_AUTH_TOKEN="s3cr3t-token" \ + bytebase/dbhub \ + --transport http --port 8080 \ + --dsn "postgres://user:***@localhost:5432/dbname" +``` + +## Client Configuration + +### curl + +```bash +curl -H "Authorization: Bearer s3cr3t-token" http://localhost:8080/api/sources +``` + +### MCP Client (Claude Code, etc.) + +Configure the `Authorization` header in your MCP client's HTTP configuration: + +```json .mcp.json +{ + "mcpServers": { + "dbhub": { + "type": "http", + "url": "http://localhost:8080/mcp", + "headers": { + "Authorization": "Bearer s3cr3t-token" + } + } + } +} +``` + +### Claude Code CLI + +```bash +claude mcp add --transport http dbhub http://localhost:8080/mcp +``` + +Then add the `Authorization` header in your Claude Code settings or `.mcp.json`. + +## Multiple Tokens + +`--auth-token` accepts a comma-separated list. This enables two common scenarios: + +### Zero-Downtime Rotation + +1. Add the new token alongside the old one: + ```bash + --auth-token "old-token,new-token" + ``` +2. Redeploy DBHub. +3. Update all clients to use `new-token`. +4. Remove `old-token` from the list and redeploy again. + +### Per-Client Tokens + +Issue different tokens to different clients so one can be revoked without affecting the others: + +```bash +--auth-token "token-for-ci,token-for-agent,token-for-workbench" +``` + +## Security Considerations + +### Constant-Time Comparison + +DBHub uses Node.js `timingSafeEqual` to compare tokens, preventing timing side-channel attacks that could leak the token character by character. + +### Shared Secret, Not OAuth + +This is a flat shared-secret check, not OAuth 2.1. It answers "does this request have the secret," not "who is this user" — there are no per-user scopes, rate limits, or audit trails. + + +If you need real identity-based authorization (per-user access control, audit logging, integration with your IdP), front DBHub with your own OAuth-aware proxy or IdP-integrated gateway instead of relying on the built-in token check. + + +### Defense in Depth + +- Always use HTTPS in production (put DBHub behind a reverse proxy like nginx or Caddy that terminates TLS). +- The token is sent in the `Authorization` header on every request — without HTTPS, it's visible in plaintext on the network. +- Use a strong, random token (at least 32 characters). `openssl rand -base64 32` is a good way to generate one. + +## Verify It's Working + +When DBHub starts with a token configured, it logs: + +``` +Auth: bearer token required (2 token(s) configured via command line argument) +``` + +Without a token: + +``` +Auth: disabled (set --auth-token or DBHUB_AUTH_TOKEN to require a bearer token) +``` + +Test that a request without a token is rejected: + +```bash +curl -i http://localhost:8080/api/sources +# Expected: 401 Unauthorized +``` + +Test that a request with a valid token succeeds: + +```bash +curl -i -H "Authorization: Bearer s3cr3t-token" http://localhost:8080/api/sources +# Expected: 200 OK +``` + +## Reference + +| Flag | Env | Default | Description | +|------|-----|---------|-------------| +| `--auth-token` | `DBHUB_AUTH_TOKEN` | (disabled) | Comma-separated bearer token(s) | + +See [Command-Line Options](/config/command-line) for all flags. \ No newline at end of file diff --git a/docs/config/http-server.mdx b/docs/config/http-server.mdx index 63ded431..d57e67a8 100644 --- a/docs/config/http-server.mdx +++ b/docs/config/http-server.mdx @@ -96,7 +96,7 @@ Disable the check entirely (only when fronted by your own authentication): ### Bearer Token Authentication -Require a bearer token on every request (except `/healthz`): +Require a bearer token on every request (except `/healthz`). See the [Authentication guide](/config/auth-token) for complete setup, rotation, and client configuration. ```bash npx @bytebase/dbhub@latest --transport http --port 8080 \ @@ -104,26 +104,6 @@ npx @bytebase/dbhub@latest --transport http --port 8080 \ --dsn "postgres://user:***@localhost:5432/dbname" ``` -Multiple tokens for rotation or per-client tokens: - -```bash ---auth-token "token-for-ci,token-for-agent" -``` - -Clients send the token as: - -```bash -curl -H "Authorization: Bearer s3cr3t-token" http://localhost:8080/api/sources -``` - - -Configuring a token is the opt-in — there is no separate "require auth" flag. A comma-separated list lets you rotate tokens without downtime or hand different tokens to different clients for independent revocation. - - - -This is a flat shared-secret check, not OAuth. For real identity-based authorization, front DBHub with your own OAuth-aware proxy or IdP-integrated gateway. - - ### CORS The HTTP transport reflects validated origins in `Access-Control-Allow-Origin` headers and supports preflight (`OPTIONS`). The allowed headers include `Mcp-Method`, `Mcp-Name`, `Mcp-Session-Id`, `MCP-Protocol-Version`, `Authorization`, and `Content-Type`. diff --git a/docs/docs.json b/docs/docs.json index 6464693d..76a1764d 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -37,7 +37,7 @@ }, { "group": "Configuration", - "pages": ["config/command-line", "config/http-server", "config/toml", "config/debug"] + "pages": ["config/command-line", "config/http-server", "config/auth-token", "config/toml", "config/debug"] } ] }, From b997cdf5e0e7114a38f40a934561aced38a3cc4e Mon Sep 17 00:00:00 2001 From: laserduor <312182928+laserduor@users.noreply.github.com> Date: Wed, 5 Aug 2026 08:27:50 +0000 Subject: [PATCH 3/4] docs: systematic fixes across 15 files - SSH: new docs/config/ssh-tunnel.mdx (password, key, ProxyJump, SSH config alias) - API: new docs/config/api-reference.mdx (sources, requests, health check endpoints) - Frontmatter: add description to 12/19 pages (all tools, config, getting started) - Parameters: add parameter table to execute-sql.mdx - See Also: add missing links to explain-sql, health-check, debug - Links: installation.mdx, quickstart.mdx now link to HTTP, auth, SSH pages - --id: expand multi-instance scenario docs - TOML hot reload: expand with behavior, STDIO limitation, troubleshooting - Nav: add ssh-tunnel, api-reference to docs.json - Remove duplicate hot-reload section from toml.mdx --- docs/config/api-reference.mdx | 177 ++++++++++++++++++++++++++++++++++ docs/config/command-line.mdx | 20 ++-- docs/config/debug.mdx | 8 ++ docs/config/ssh-tunnel.mdx | 136 ++++++++++++++++++++++++++ docs/config/toml.mdx | 30 +++--- docs/docs.json | 2 +- docs/index.mdx | 1 + docs/installation.mdx | 3 +- docs/quickstart.mdx | 3 +- docs/tools/custom-tools.mdx | 1 + docs/tools/execute-sql.mdx | 22 ++++- docs/tools/explain-sql.mdx | 9 ++ docs/tools/health-check.mdx | 9 ++ docs/tools/overview.mdx | 1 + docs/tools/search-objects.mdx | 1 + 15 files changed, 396 insertions(+), 27 deletions(-) create mode 100644 docs/config/api-reference.mdx create mode 100644 docs/config/ssh-tunnel.mdx diff --git a/docs/config/api-reference.mdx b/docs/config/api-reference.mdx new file mode 100644 index 00000000..8739a3eb --- /dev/null +++ b/docs/config/api-reference.mdx @@ -0,0 +1,177 @@ +--- +title: "API Reference" +description: "REST API endpoints for querying data sources and request traces" +--- + +DBHub exposes REST API endpoints for integrating with external tools and the Workbench frontend. These are only available when running with HTTP transport. + +## List Sources + +```http +GET /api/sources +``` + +Returns all configured database sources. + +**Example response:** + +```json +[ + { + "id": "local_pg", + "type": "postgres", + "description": "Production PostgreSQL", + "host": "localhost", + "port": 5432, + "database": "mydb", + "user": "myuser", + "tools": [ + { "name": "execute_sql", "readonly": true }, + { "name": "search_objects", "readonly": true } + ] + } +] +``` + +Sensitive fields (passwords, SSH keys) are excluded from the response. + +**Response fields:** + +| Field | Type | Description | +|-------|------|-------------| +| `id` | string | Source identifier | +| `type` | string | Database type: `postgres`, `mysql`, `mariadb`, `sqlserver`, `sqlite` | +| `description` | string? | Optional description from TOML config | +| `host` | string? | Database hostname | +| `port` | number? | Database port | +| `database` | string? | Database name or SQLite file path | +| `user` | string? | Database username | +| `ssh_tunnel` | object? | SSH tunnel configuration (if enabled) | +| `tools` | array | Available MCP tools for this source | + +**Errors:** + +| Status | Meaning | +|--------|---------| +| 200 | Success | +| 500 | Internal server error | + +--- + +## Get Source + +```http +GET /api/sources/:sourceId +``` + +Returns a single source by ID. + +**Example response:** + +```json +{ + "id": "local_pg", + "type": "postgres", + "host": "localhost", + "port": 5432, + "database": "mydb", + "user": "myuser", + "tools": [ + { "name": "execute_sql", "readonly": true }, + { "name": "search_objects", "readonly": true } + ] +} +``` + +**Errors:** + +| Status | Meaning | +|--------|---------| +| 200 | Success | +| 404 | Source not found | +| 500 | Internal server error | + +--- + +## List Requests + +```http +GET /api/requests?source_id=prod_pg +``` + +Returns recent tool execution traces. The `source_id` query parameter is optional — omit it to get requests from all sources. + +**Example response:** + +```json +{ + "requests": [ + { + "id": "req_abc123", + "source_id": "local_pg", + "tool": "execute_sql", + "sql": "SELECT * FROM users LIMIT 5", + "started_at": "2026-08-03T12:00:00Z", + "duration_ms": 12, + "row_count": 5, + "status": "success" + } + ], + "total": 1 +} +``` + +**Query parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `source_id` | string? | Filter by source ID | + +**Response fields:** + +| Field | Type | Description | +|-------|------|-------------| +| `requests` | array | Tool execution traces | +| `total` | number | Total number of requests returned | + +**Errors:** + +| Status | Meaning | +|--------|---------| +| 200 | Success | +| 500 | Internal server error | + + +Request traces are stored in memory and reset on server restart. The latest 100 requests per source are retained. + + +## Health Check + +```http +GET /healthz +``` + +Returns `200 OK` without any authentication. Uptime monitors and load balancer probes can use this endpoint without a token. + +**Example:** + +```bash +curl http://localhost:8080/healthz +# OK +``` + +## Authentication + +All API endpoints (except `/healthz`) require a bearer token if `--auth-token` is configured: + +```bash +curl -H "Authorization: Bearer s3cr3t-token" http://localhost:8080/api/sources +``` + +See [Authentication](/config/auth-token) for complete setup. + +## See Also + +- [HTTP Server](/config/http-server) — Server configuration and endpoints +- [Authentication](/config/auth-token) — Bearer token setup +- [Workbench](/workbench/overview) — Browser-based interface \ No newline at end of file diff --git a/docs/config/command-line.mdx b/docs/config/command-line.mdx index c5226848..a1aaa7fc 100644 --- a/docs/config/command-line.mdx +++ b/docs/config/command-line.mdx @@ -1,5 +1,6 @@ --- title: "Command-Line Options" +description: "Complete reference for all DBHub CLI flags, environment variables, and DSN formats" --- DBHub connects to your database in one of two ways: @@ -289,20 +290,27 @@ This page covers command-line flags and environment variables. For TOML configur ### --id - Instance identifier to suffix tool names. Useful when running multiple DBHub instances (e.g., in Cursor). Env: `ID`. + Instance identifier to suffix tool names. Useful when running multiple DBHub instances (e.g., connecting to different databases from Cursor or Claude Code). Env: `ID`. - Tools will be named `execute_sql_{id}` for each instance. + Tool names will be suffixed with the id: `execute_sql_{id}`, `search_objects_{id}`. ```bash - npx @bytebase/dbhub@latest --id prod --dsn "postgres://user:pass@prod-host:5432/db" - npx @bytebase/dbhub@latest --id staging --dsn "postgres://user:pass@staging-host:5432/db" + # Instance 1: production + npx @bytebase/dbhub@latest --id prod --dsn "postgres://user:***@prod-host:5432/db" + + # Instance 2: staging + npx @bytebase/dbhub@latest --id staging --dsn "postgres://user:***@staging-host:5432/db" ``` - Result: `execute_sql_prod` and `execute_sql_staging` tools + Result: `execute_sql_prod` and `execute_sql_staging` tools. - Cannot be used with `--config` (TOML configuration). TOML config defines source IDs directly in the configuration file. Use command-line DSN configuration instead if you need the `--id` flag. + Cannot be used with `--config` (TOML configuration). TOML config defines source IDs directly in the configuration file (`[[sources]]` with `id` fields). Use command-line DSN configuration instead if you need the `--id` flag. + + + **Multi-instance scenario:** Run two DBHub processes on different ports, each with a different `--id`, then configure your MCP client to connect to both. This gives you separate tool names for each database without needing a TOML file. + ### --demo diff --git a/docs/config/debug.mdx b/docs/config/debug.mdx index 775ed4c3..89575fb0 100644 --- a/docs/config/debug.mdx +++ b/docs/config/debug.mdx @@ -1,5 +1,6 @@ --- title: "Debug" +description: "Troubleshoot DBHub with the MCP Inspector and common connection fixes" --- ## MCP Inspector @@ -48,3 +49,10 @@ If DBHub connects but database queries fail: ### Logs DBHub prints startup and error messages to stderr. There is no adjustable log level — review that output, and the MCP Inspector above, when troubleshooting. + +## See Also + +- [HTTP Server](/config/http-server) — Server configuration and endpoints +- [Authentication](/config/auth-token) — Bearer token setup +- [SSH Tunnel](/config/ssh-tunnel) — Connecting through bastion hosts +- [Installation](/installation) — Client setup guides diff --git a/docs/config/ssh-tunnel.mdx b/docs/config/ssh-tunnel.mdx new file mode 100644 index 00000000..38ad18d9 --- /dev/null +++ b/docs/config/ssh-tunnel.mdx @@ -0,0 +1,136 @@ +--- +title: "SSH Tunnel" +description: "Connect to databases through bastion hosts and private networks with SSH tunneling" +--- + +When your database is behind a firewall or on a private network, you can reach it through an SSH bastion host (jump box). DBHub supports password auth, key-based auth, multi-hop ProxyJump, and `~/.ssh/config` alias resolution. + +## Quick Start + +```bash +npx @bytebase/dbhub@latest --dsn "postgres://user:***@localhost:5432/mydb" \ + --ssh-host bastion.example.com --ssh-user ubuntu --ssh-key ~/.ssh/id_rsa +``` + +DBHub connects to `bastion.example.com` via SSH, then forwards the database connection through the tunnel. + +## Authentication Methods + +### Password + +```bash +npx @bytebase/dbhub@latest --dsn "postgres://..." \ + --ssh-host bastion.example.com --ssh-user ubuntu --ssh-password "my-password" +``` + +### SSH Key + +```bash +npx @bytebase/dbhub@latest --dsn "postgres://..." \ + --ssh-host bastion.example.com --ssh-user ubuntu --ssh-key ~/.ssh/id_rsa +``` + +If the key is encrypted: + +```bash +npx @bytebase/dbhub@latest --dsn "postgres://..." \ + --ssh-host bastion.example.com --ssh-user ubuntu \ + --ssh-key ~/.ssh/id_rsa --ssh-passphrase "my-passphrase" +``` + +### Base64-Encoded Key + +Useful in containerized or cloud environments where you can't mount a key file: + +```bash +export SSH_KEY=$(base64 < ~/.ssh/id_rsa) +npx @bytebase/dbhub@latest --dsn "postgres://..." \ + --ssh-host bastion.example.com --ssh-user ubuntu +``` + + +DBHub auto-detects the format of `--ssh-key` / `SSH_KEY`: it first tries to read the value as a file path, and if that fails, decodes it as base64. + + +## ProxyJump (Multi-Hop) + +For networks that require multiple hops to reach the target database: + +### Single Hop + +```bash +npx @bytebase/dbhub@latest --dsn "postgres://..." \ + --ssh-host target.internal --ssh-proxy-jump bastion.example.com +``` + +### Multi-Hop Chain + +```bash +npx @bytebase/dbhub@latest --dsn "postgres://..." \ + --ssh-host target.internal --ssh-proxy-jump "bastion1.com,admin@bastion2:2222" +``` + +Each hop in the chain is comma-separated. The format per hop is `[user@]host[:port]`. + +## SSH Config Alias + +If you have an entry in `~/.ssh/config`, just pass the alias: + +```bash +npx @bytebase/dbhub@latest --dsn "postgres://..." --ssh-host mybastion +``` + +DBHub automatically resolves the `HostName`, `User`, `IdentityFile`, and `ProxyJump` from your SSH config. Explicit flags always override values from the config file. + + +`ProxyJump` hops that are themselves `~/.ssh/config` aliases are resolved recursively — each hop uses its own `HostName`/`User`/`Port`/`IdentityFile` (and its own nested `ProxyJump`). Cyclic `ProxyJump` chains are rejected with an error. + + +## Environment Variables + +| Variable | Description | +|----------|-------------| +| `SSH_HOST` | SSH server hostname | +| `SSH_PORT` | SSH server port (default: `22`) | +| `SSH_USER` | SSH username | +| `SSH_PASSWORD` | SSH password | +| `SSH_KEY` | Path to SSH private key, or base64-encoded key | +| `SSH_PASSPHRASE` | Passphrase for encrypted SSH key | +| `SSH_PROXY_JUMP` | ProxyJump hosts for multi-hop SSH | + +## TOML Configuration + +For multi-database setups, SSH tunnels can be configured per-source in `dbhub.toml`: + +```toml +[[sources]] +id = "production" +dsn = "postgres://readonly_user:***@private-db.internal:5432/mydb" + +[sources.ssh] +host = "bastion.example.com" +user = "ubuntu" +port = 22 +``` + +See [TOML Configuration](/config/toml) for the complete reference. + +## Limitations + +- **ProxyCommand** is not supported (requires shell execution). Use ProxyJump instead. +- **Integrated security / Kerberos / GSSAPI** is not supported. Use password or key-based authentication. +- Path expansion for `~/` is supported in file paths. + +## Reference + +| Flag | Env | Type | Description | +|------|-----|------|-------------| +| `--ssh-host` | `SSH_HOST` | string | SSH server hostname or alias from `~/.ssh/config` | +| `--ssh-port` | `SSH_PORT` | number | SSH server port (default: `22`) | +| `--ssh-user` | `SSH_USER` | string | SSH username | +| `--ssh-password` | `SSH_PASSWORD` | string | SSH password | +| `--ssh-key` | `SSH_KEY` | string | Path to SSH private key, or base64-encoded key | +| `--ssh-passphrase` | `SSH_PASSPHRASE` | string | Passphrase for encrypted SSH key | +| `--ssh-proxy-jump` | `SSH_PROXY_JUMP` | string | ProxyJump hosts. Format: `[user@]host[:port]` (comma-separated for chains) | + +See [Command-Line Options](/config/command-line) for all flags. \ No newline at end of file diff --git a/docs/config/toml.mdx b/docs/config/toml.mdx index ce6ab012..ca4539ab 100644 --- a/docs/config/toml.mdx +++ b/docs/config/toml.mdx @@ -1,5 +1,6 @@ --- title: "TOML Configuration" +description: "Configure multiple database connections, per-source settings, SSH tunnels, and custom tools with TOML" --- TOML configuration is the recommended way to configure DBHub for multi-database setups and advanced configurations. It provides more flexibility than command-line options or environment variables. @@ -28,23 +29,26 @@ TOML configuration enables: When using TOML configuration, DBHub automatically watches `dbhub.toml` for changes and reloads database connections without requiring a server restart. -**How it works:** +### How It Works -1. DBHub detects file changes and waits 500ms (debounce) to handle editors that write in multiple steps -2. The new configuration is parsed and validated — if invalid, existing connections are preserved -3. All database connections are disconnected and reconnected with the new configuration -4. If reconnection fails, DBHub automatically rolls back to the previous working configuration +DBHub polls the TOML file for changes using `fs.watchFile`. When a change is detected: -``` -# Edit dbhub.toml while DBHub is running — changes apply automatically -# No server restart needed -``` +1. The file is re-parsed and validated. +2. Database connections for **added** or **modified** sources are (re)connected. +3. **Removed** sources are disconnected and their tools are unregistered. +4. Custom tools and tool settings are updated. - -**STDIO transport limitation:** In STDIO mode (the default for Claude Desktop, Cursor, etc.), hot reload updates the underlying database connections and tool settings, but clients won't see newly added or removed tools until a full server restart. This is because STDIO clients discover tools once at startup. +### STDIO Limitation -HTTP transport (`--transport http`) creates a fresh server per request, so all changes — including added/removed tools — take effect immediately. - +When running with STDIO transport (the default for Claude Desktop, Cursor, etc.), hot reload updates the underlying database connections and tool settings, but **clients won't see newly added or removed tools until a full server restart**. This is because STDIO clients discover tools once at startup. + +On HTTP transport, each request creates a fresh server instance, so tool changes apply immediately. 2026-07-28 clients may serve a cached tool list for up to 5 minutes (see [HTTP Server](/config/http-server)). + +### Troubleshooting + +- **File format errors**: If the TOML file contains a syntax error after a change, the reload is **skipped** and the previous configuration remains active. Check stderr for parse error messages. +- **Connection failures**: If a source's database connection fails after a reload, that source is logged as an error and skipped. Other sources continue working normally. +- **No reload on new file**: The watcher only activates after the initial load. If the TOML file doesn't exist at startup, `--config` must be explicitly provided. ## Environment Variable Interpolation diff --git a/docs/docs.json b/docs/docs.json index 76a1764d..f3a8bc61 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -37,7 +37,7 @@ }, { "group": "Configuration", - "pages": ["config/command-line", "config/http-server", "config/auth-token", "config/toml", "config/debug"] + "pages": ["config/command-line", "config/http-server", "config/auth-token", "config/ssh-tunnel", "config/api-reference", "config/toml", "config/debug"] } ] }, diff --git a/docs/index.mdx b/docs/index.mdx index 8a56c39a..15fdfce4 100644 --- a/docs/index.mdx +++ b/docs/index.mdx @@ -1,5 +1,6 @@ --- title: "Introduction" +description: "DBHub is a minimal, token-efficient MCP server for PostgreSQL, MySQL, SQL Server, MariaDB, and SQLite" --- diff --git a/docs/tools/custom-tools.mdx b/docs/tools/custom-tools.mdx index af5e4d9f..beb27c9d 100644 --- a/docs/tools/custom-tools.mdx +++ b/docs/tools/custom-tools.mdx @@ -1,5 +1,6 @@ --- title: "Custom Tools" +description: "Define reusable, parameterized SQL operations in your TOML configuration" --- Custom tools allow you to define reusable, parameterized SQL operations that are automatically registered as MCP tools. They provide type-safe interfaces for common database queries without writing repetitive code. diff --git a/docs/tools/execute-sql.mdx b/docs/tools/execute-sql.mdx index 2ae4f8fc..50bb8d86 100644 --- a/docs/tools/execute-sql.mdx +++ b/docs/tools/execute-sql.mdx @@ -1,16 +1,28 @@ --- title: "execute_sql" +description: "Execute SQL queries with transaction support, read-only mode, and row limiting" --- Execute SQL queries and statements on your database with support for transactions, multiple statements, and safety controls. ## Features -- **Single statements**: Execute a single SQL query or command -- **Multiple statements**: Separate multiple statements with semicolons (`;`) -- **Transactions**: Wrap operations in `BEGIN`/`COMMIT` blocks for atomic execution -- **Read-only mode**: Configure a tool with `readonly = true` to restrict execution to read-only operations, enforced by both a keyword classifier and the database's own read-only mode -- **Row limiting**: Configure `--max-rows` to limit SELECT query results +| Feature | Description | +|---------|-------------| +| Single statements | Execute a single SQL query or command | +| Multiple statements | Separate multiple statements with semicolons (`;`) | +| Transactions | Wrap operations in `BEGIN`/`COMMIT` blocks for atomic execution | +| Read-only mode | Configure a tool with `readonly = true` to restrict execution to read-only operations, enforced by both a keyword classifier and the database's own read-only mode | +| Row limiting | Configure `--max-rows` to limit SELECT query results | + +## Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `sql` | string | ✅ | — | The SQL statement to execute | +| `source_id` | string | ❌ | first source | Database source identifier for multi-database setups | +| `transaction` | boolean | ❌ | `false` | Enable transaction mode for atomic execution | +| `max_rows` | integer | ❌ | `--max-rows` setting | Override the row limit for this query | ## Single Query diff --git a/docs/tools/explain-sql.mdx b/docs/tools/explain-sql.mdx index 152f2c14..bbb364aa 100644 --- a/docs/tools/explain-sql.mdx +++ b/docs/tools/explain-sql.mdx @@ -1,5 +1,6 @@ --- title: "explain_sql" +description: "Show a query's execution plan without executing it (opt-in)" --- Show the execution plan for a SQL statement without running it. @@ -58,3 +59,11 @@ source = "production" ``` See [Tool Configuration](/tools/overview#tool-configuration) for how `[[tools]]` entries work across multiple sources. + +## See Also + +- [execute_sql](/tools/execute-sql) — SQL execution with safety controls +- [search_objects](/tools/search-objects) — Schema and object exploration +- [Custom Tools](/tools/custom-tools) — Parameterized SQL operations +- [TOML Configuration](/config/toml) — Tool configuration reference +- [HTTP Server](/config/http-server) — Running DBHub with HTTP transport diff --git a/docs/tools/health-check.mdx b/docs/tools/health-check.mdx index 22623403..2b2650ac 100644 --- a/docs/tools/health-check.mdx +++ b/docs/tools/health-check.mdx @@ -1,5 +1,6 @@ --- title: "health_check" +description: "Monitor connection pool state and buffer cache hit ratio (opt-in)" --- Report operational health metrics for a database source: connection pool state and buffer cache hit ratio. @@ -94,3 +95,11 @@ source = "production" ``` See [Tool Configuration](/tools/overview#tool-configuration) for how `[[tools]]` entries work across multiple sources. + +## See Also + +- [execute_sql](/tools/execute-sql) — SQL execution with safety controls +- [search_objects](/tools/search-objects) — Schema and object exploration +- [Custom Tools](/tools/custom-tools) — Parameterized SQL operations +- [TOML Configuration](/config/toml) — Tool configuration reference +- [HTTP Server](/config/http-server) — Running DBHub with HTTP transport diff --git a/docs/tools/overview.mdx b/docs/tools/overview.mdx index 0d22ee9b..1b725a02 100644 --- a/docs/tools/overview.mdx +++ b/docs/tools/overview.mdx @@ -1,5 +1,6 @@ --- title: "Overview" +description: "DBHub's MCP tools — execute_sql, search_objects, explain_sql, health_check, and custom tools" --- ## Available Tools diff --git a/docs/tools/search-objects.mdx b/docs/tools/search-objects.mdx index 7cb77962..2818ac93 100644 --- a/docs/tools/search-objects.mdx +++ b/docs/tools/search-objects.mdx @@ -1,5 +1,6 @@ --- title: "search_objects" +description: "Search and explore database schemas, tables, columns, indexes, and procedures with progressive disclosure" --- Search and list database objects (schemas, tables, columns, procedures, functions, indexes) with pattern matching. This unified tool supports both targeted searches and browsing all objects, implementing progressive disclosure to minimize token usage. From 4c1fddb03bfa061b2bddda6b9767a305ef7512bb Mon Sep 17 00:00:00 2001 From: laserduor <312182928+laserduor@users.noreply.github.com> Date: Sat, 8 Aug 2026 06:09:39 +0000 Subject: [PATCH 4/4] docs: fix execute_sql parameter table and remove deprecated --max-rows flag reference - execute_sql schema only has a single 'sql' parameter; remove the fabricated source_id / transaction / max_rows entries - readonly and max_rows are per-tool TOML config, not query parameters; multi-source routing is via tool name suffix (execute_sql_{source_id}) - replace deprecated --max-rows CLI flag mention with the TOML [[tools]] max_rows configuration --- docs/tools/execute-sql.mdx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/tools/execute-sql.mdx b/docs/tools/execute-sql.mdx index 50bb8d86..e252c9d5 100644 --- a/docs/tools/execute-sql.mdx +++ b/docs/tools/execute-sql.mdx @@ -13,16 +13,15 @@ Execute SQL queries and statements on your database with support for transaction | Multiple statements | Separate multiple statements with semicolons (`;`) | | Transactions | Wrap operations in `BEGIN`/`COMMIT` blocks for atomic execution | | Read-only mode | Configure a tool with `readonly = true` to restrict execution to read-only operations, enforced by both a keyword classifier and the database's own read-only mode | -| Row limiting | Configure `--max-rows` to limit SELECT query results | +| Row limiting | Configure `max_rows` per tool in TOML (`[[tools]]`) to limit SELECT query results | ## Parameters | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | `sql` | string | ✅ | — | The SQL statement to execute | -| `source_id` | string | ❌ | first source | Database source identifier for multi-database setups | -| `transaction` | boolean | ❌ | `false` | Enable transaction mode for atomic execution | -| `max_rows` | integer | ❌ | `--max-rows` setting | Override the row limit for this query | + +`readonly` and `max_rows` are not query parameters — they are configured per tool via TOML `[[tools]]` entries. In multi-database setups, each source registers its own tool named `execute_sql_{source_id}`; no `source_id` parameter is needed. ## Single Query