This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
DBHub is a zero-dependency, token efficient database MCP server implementing the Model Context Protocol (MCP) server interface. This lightweight server bridges MCP-compatible clients (Claude Desktop, Claude Code, Cursor) with various database systems.
- Build:
pnpm run build- Compiles TypeScript to JavaScript using tsup - Start:
pnpm run start- Runs the compiled server - Dev:
pnpm run dev- Runs server with tsx (no compilation needed) - Test:
pnpm test- Run all tests - Test Watch:
pnpm test:watch- Run tests in watch mode - Integration Tests:
pnpm test:integration- Run database integration tests (requires Docker)
The codebase follows a modular architecture centered around the MCP protocol:
src/
├── connectors/ # Database-specific implementations
│ ├── postgres/ # PostgreSQL connector
│ ├── mysql/ # MySQL connector
│ ├── mariadb/ # MariaDB connector
│ ├── sqlserver/ # SQL Server connector
│ └── sqlite/ # SQLite connector
├── tools/ # MCP tool handlers
│ ├── execute-sql.ts # SQL execution handler
│ └── search-objects.ts # Unified search/list with progressive disclosure
├── utils/ # Shared utilities
│ ├── dsn-obfuscator.ts# DSN security
│ ├── response-formatter.ts # Output formatting
│ └── allowed-keywords.ts # Read-only SQL validation
└── index.ts # Entry point with transport handling
Key architectural patterns:
- Connector Registry: Dynamic registration system for database connectors
- Connector Manager: Manages database connections (single or multiple)
- Supports multi-database configuration via TOML
- Maintains
Map<id, Connector>for named connections getConnector(sourceId?)returns connector by ID or default (first)getCurrentConnector(sourceId?)static method for tool handlers- Backward compatible with single-connection mode
- Location:
src/connectors/manager.ts
- Transport Abstraction: Support for both stdio (desktop tools) and HTTP (network clients)
- HTTP transport endpoint:
/mcp(aligns with official MCP SDK standard) - Implemented in
src/server.tsusingStreamableHTTPServerTransportwith JSON responses - Runs in stateless mode (no SSE support) - GET requests to
/mcpreturn 405 Method Not Allowed - Tests in
src/__tests__/json-rpc-integration.test.ts
- HTTP transport endpoint:
- Tool Handlers: Clean separation of MCP protocol concerns
- Tools accept optional
source_idparameter for multi-database routing
- Tools accept optional
- Token-Efficient Schema Exploration: Unified search/list tool with progressive disclosure
search_objects: Single tool for both pattern-based search and listing all objects- Pattern parameter defaults to
%(match all) - optional for listing use cases - Detail levels:
names(minimal),summary(with metadata),full(complete structure) - Supports: schemas, tables, columns, procedures, indexes
- Inspired by Anthropic's MCP code execution patterns for reducing token usage
- Integration Test Base: Shared test utilities for consistent connector testing
DBHub supports three configuration methods (in priority order):
Recommended for projects requiring multiple database connections
- Create
dbhub.tomlin your project directory or use--config=path/to/config.toml - Configuration structure:
[[sources]]- Database connection definitions with uniqueidfields[[tools]]- Tool configuration (execution settings, custom tools)
- Example:
[[sources]] id = "prod_pg" dsn = "postgres://user:pass@localhost:5432/production" connection_timeout = 60 query_timeout = 30 [[sources]] id = "staging_mysql" type = "mysql" host = "localhost" database = "staging" user = "root" password = "secret" # Tool configuration (readonly, max_rows are tool-level settings) [[tools]] name = "execute_sql" source = "prod_pg" readonly = true max_rows = 1000
- Key files:
src/types/config.ts: TypeScript interfaces for TOML structuresrc/config/toml-loader.ts: TOML parsing and validationsrc/config/__tests__/toml-loader.test.ts: Comprehensive test suite
- Features:
- Per-source settings: SSH tunnels, timeouts, SSL configuration
- Per-tool settings:
readonly,max_rows(configured in[[tools]]section, not[[sources]]) - Custom tools: Define reusable, parameterized SQL operations
- Path expansion for
~/in file paths - Automatic password redaction in logs
- First source is the default database
- Usage in MCP tools: Add optional
source_idparameter (e.g.,execute_sql(sql, source_id="prod_pg")) - See
dbhub.toml.examplefor complete configuration reference - Documentation: https://dbhub.ai/config/toml
- Copy
.env.exampleto.envand configure for your database connection - Two ways to configure:
- Set
DSNto a full connection string (recommended) - Set individual parameters:
DB_TYPE,DB_HOST,DB_PORT,DB_USER,DB_PASSWORD,DB_NAME
- Set
- SSH tunnel via environment:
SSH_HOST,SSH_PORT,SSH_USER,SSH_PASSWORD,SSH_KEY,SSH_PASSPHRASE
--dsn: Database connection string--transport:stdio(default) orhttpfor streamable HTTP transport (endpoint:/mcp)--port: HTTP server port (default: 8080)--config: Path to TOML configuration file--demo: Use bundled SQLite employee database--readonly: Restrict to read-only SQL operations (deprecated - use TOML configuration instead)--max-rows: Limit rows returned from SELECT queries (deprecated - use TOML configuration instead)- SSH tunnel options:
--ssh-host,--ssh-port,--ssh-user,--ssh-password,--ssh-key,--ssh-passphrase - Documentation: https://dbhub.ai/config/command-line
- Command-line arguments (highest)
- TOML config file (if present)
- Environment variables
.envfiles (.env.localin development,.envin production)
- Add new connectors in
src/connectors/{db-type}/index.ts - Implement the
ConnectorandDSNParserinterfaces fromsrc/interfaces/connector.ts - Register connector with
ConnectorRegistry.register(connector) - DSN Examples:
- PostgreSQL:
postgres://user:password@localhost:5432/dbname?sslmode=disable - MySQL:
mysql://user:password@localhost:3306/dbname?sslmode=disable - MariaDB:
mariadb://user:password@localhost:3306/dbname?sslmode=disable - SQL Server:
sqlserver://user:password@localhost:1433/dbname?sslmode=disable - SQL Server (named instance):
sqlserver://user:password@localhost:1433/dbname?instanceName=ENV1 - SQL Server (NTLM):
sqlserver://user:password@localhost:1433/dbname?authentication=ntlm&domain=MYDOMAIN - SQLite:
sqlite:///path/to/database.dborsqlite:///:memory:
- PostgreSQL:
- SSL modes:
sslmode=disable(no SSL),sslmode=require(SSL without cert verification),sslmode=verify-ca(PostgreSQL only, CA verification),sslmode=verify-full(PostgreSQL only, CA + hostname verification). Usesslrootcertto specify CA certificate path for verify modes.
See TESTING.md for comprehensive testing documentation.
For detailed guidance on running and troubleshooting tests, refer to the testing skill. This skill is automatically activated when working with tests, test failures, or Docker/database container issues.
Key points:
- Unit tests for individual components and utilities
- Integration tests using Testcontainers for real database testing
- All connectors have comprehensive integration test coverage
- Pre-commit hooks run related tests automatically
- Test specific databases:
pnpm test src/connectors/__tests__/{db-type}.integration.test.ts - SSH tunnel tests:
pnpm test postgres-ssh-simple.integration.test.ts
DBHub supports SSH tunnels for secure database connections through bastion hosts:
- Configuration via command-line options:
--ssh-host,--ssh-port,--ssh-user,--ssh-password,--ssh-key,--ssh-passphrase - Configuration via environment variables:
SSH_HOST,SSH_PORT,SSH_USER,SSH_PASSWORD,SSH_KEY,SSH_PASSPHRASE - SSH config file support: Automatically reads from
~/.ssh/configwhen using host aliases - Implementation in
src/utils/ssh-tunnel.tsusing thessh2library - SSH config parsing in
src/utils/ssh-config-parser.tsusing thessh-configlibrary - Automatic tunnel establishment when SSH config is detected
- Support for both password and key-based authentication
- Default SSH key detection (tries
~/.ssh/id_rsa,~/.ssh/id_ed25519, etc.) - Tunnel lifecycle managed by
ConnectorManager
- TypeScript with strict mode enabled
- ES modules with
.jsextension in imports - Group imports: Node.js core modules → third-party → local modules
- Use camelCase for variables/functions, PascalCase for classes/types
- Include explicit type annotations for function parameters/returns
- Use try/finally blocks with DB connections (always release clients)
- Prefer async/await over callbacks and Promise chains
- Format error messages consistently
- Use parameterized queries for DB operations
- Validate inputs with zod schemas
- Include fallbacks for environment variables
- Use descriptive variable/function names
- Keep functions focused and single-purpose