# MCP Database Server WebSocket-based PostgreSQL tooling service for AI clients using the Model Context Protocol (MCP). ## Features - **WebSocket Transport**: Long-running daemon accessible by multiple AI clients - **Multi-Environment Support**: Connect to multiple PostgreSQL databases with different schemas - **Token Authentication**: Secure Bearer token authentication - **Session Isolation**: Per-client session management with transaction binding - **Audit Logging**: JSON Lines format with SQL sanitization - **Health Check**: Built-in `/health` endpoint for monitoring - **Docker Ready**: Multi-stage build with minimal image size ## Quick Start ### 1. Install Dependencies ```bash npm install ``` ### 2. Build ```bash npm run build ``` ### 3. Generate Auth Token ```bash node scripts/generate-token.js ``` ### 4. Create Configuration ```bash cp config/database.example.json config/database.json # Edit config/database.json with your database connections ``` ### 5. Start Server ```bash export MCP_AUTH_TOKEN="your-generated-token" export MCP_DRWORKS_PASSWORD="your-db-password" node dist/server.js --config config/database.json ``` ### 6. Verify ```bash curl http://localhost:7700/health ``` ## Configuration ### Configuration File Format ```json { "server": { "listen": { "host": "0.0.0.0", "port": 7700 }, "auth": { "type": "token", "token": "ENV:MCP_AUTH_TOKEN" }, "maxConcurrentClients": 50, "logLevel": "info" }, "environments": { "mydb": { "type": "postgres", "connection": { "host": "localhost", "port": 5432, "database": "mydb", "user": "postgres", "password": "ENV:MCP_MYDB_PASSWORD" }, "defaultSchema": "public", "searchPath": ["public", "app"], "pool": { "max": 10, "idleTimeoutMs": 30000 }, "statementTimeoutMs": 60000, "mode": "readonly" } }, "audit": { "enabled": true, "output": "stdout", "redactParams": true, "maxSqlLength": 200 } } ``` 配置结构总览 { "server": { ... }, // 服务器配置 "environments": { ... }, // 数据库环境配置(可多个) "audit": { ... } // 审计日志配置 } --- 一、server - 服务器配置 "server": { "listen": { "host": "0.0.0.0", // 监听地址 // "0.0.0.0" = 所有网卡(外部可访问) // "127.0.0.1" = 仅本机 "port": 7700 // WebSocket 端口 }, "auth": { "type": "token", // 鉴权类型:token / mtls / none "token": "ENV:MCP_AUTH_TOKEN" // Token 值,从环境变量读取 }, "maxConcurrentClients": 50, // 最大同时连接的客户端数 "logLevel": "info" // 日志级别:debug / info / warn / error } --- 二、environments - 数据库环境 每个环境是一个独立的连接池,可配置多个: "environments": { "drworks": { // 环境名(调用工具时指定) "type": "postgres", // 数据库类型(目前仅支持 postgres) "connection": { // ═══ 连接参数 ═══ "host": "47.99.124.43", // 数据库服务器 IP/域名 "port": 5432, // PostgreSQL 端口 "database": "shcis_drworks_cpoe_pg", // 数据库名 "user": "postgres", // 用户名 "password": "passw0rd!", // 密码(建议用 ENV:) "ssl": { "require": false // SSL 连接:true=强制,false=不使用 } }, "defaultSchema": "dbo", // ═══ 模式配置 ═══ // 默认模式,工具调用不传 schema 时使用 "searchPath": ["dbo", "api", "nurse"], // 搜索路径,查询时按顺序在这些模式中查找表 // 例:SELECT * FROM patient 会先找 dbo.patient "pool": { // ═══ 连接池配置 ═══ "max": 10, // 最大连接数(并发查询上限) "idleTimeoutMs": 30000, // 空闲连接 30 秒后释放 "connectionTimeoutMs": 10000 // 获取连接超时 10 秒 }, "statementTimeoutMs": 60000, // SQL 执行超时 60 秒(防止卡死) "slowQueryMs": 2000, // 超过 2 秒记录慢查询告警 "mode": "ddl" // ═══ 权限模式 ═══ // readonly = 只能 SELECT // readwrite = 可 INSERT/UPDATE/DELETE // ddl = 可 CREATE/ALTER/DROP(最高权限) }, "ipworkstation": { ... } // 第二个环境,配置类似 } --- 三、audit - 审计日志 "audit": { "enabled": true, // 是否启用审计日志 "output": "stdout", // 输出位置: // "stdout" = 标准输出(容器推荐) // "/var/log/mcp/audit.log" = 文件 "format": "json", // 格式:json(便于日志系统解析) "redactParams": true, // 脱敏:SQL 参数值替换为 [REDACTED] "maxSqlLength": 200 // SQL 预览最大长度(超出截断) } --- ### Environment Variable Resolution Use `ENV:VAR_NAME` syntax to reference environment variables: ```json { "password": "ENV:MCP_MYDB_PASSWORD" } ``` ### Configuration Fields #### server | Field | Type | Default | Description | |-------|------|---------|-------------| | listen.host | string | "0.0.0.0" | Listen address | | listen.port | number | 7700 | Listen port | | auth.type | string | "token" | Authentication type: token, mtls, none | | auth.token | string | - | Bearer token (required if type=token) | | maxConcurrentClients | number | 50 | Maximum WebSocket connections | | logLevel | string | "info" | Log level: debug, info, warn, error | #### environments | Field | Type | Default | Description | |-------|------|---------|-------------| | type | string | "postgres" | Database type (only postgres supported) | | connection.host | string | - | PostgreSQL host | | connection.port | number | 5432 | PostgreSQL port | | connection.database | string | - | Database name | | connection.user | string | - | Username | | connection.password | string | - | Password | | connection.ssl | object | - | SSL configuration | | defaultSchema | string | "public" | Default schema | | searchPath | string[] | - | Schema search path | | pool.max | number | 10 | Max pool connections | | pool.idleTimeoutMs | number | 30000 | Idle connection timeout | | statementTimeoutMs | number | 60000 | Query timeout | | mode | string | "readonly" | Permission mode: readonly, readwrite, ddl | #### audit | Field | Type | Default | Description | |-------|------|---------|-------------| | enabled | boolean | true | Enable audit logging | | output | string | "stdout" | Output: stdout or file path | | redactParams | boolean | true | Redact SQL parameters | | maxSqlLength | number | 200 | Max SQL preview length | ## Command Line Options ```bash node dist/server.js [options] Options: --config Configuration file path (default: ./config/database.json) --listen Listen address (overrides config) --auth-token Auth token (overrides config) --log-level Log level (overrides config) ``` Environment variables override configuration file: | Variable | Description | |----------|-------------| | MCP_CONFIG | Configuration file path | | MCP_LISTEN | Listen address (host:port) | | MCP_AUTH_TOKEN | Authentication token | | MCP_LOG_LEVEL | Log level | | MCP__PASSWORD | Database password for environment | ## Authentication ### Token Authentication Clients must provide a Bearer token in the WebSocket handshake: ```http GET / HTTP/1.1 Upgrade: websocket Authorization: Bearer your-token-here ``` Generate a secure token: ```bash node scripts/generate-token.js # Output: 64-character hex string ``` ### Client Configuration (Claude Code) ```json { "mcpServers": { "database": { "transport": "websocket", "endpoint": "ws://localhost:7700", "headers": { "Authorization": "Bearer your-token-here" } } } } ``` ## Available Tools The server exposes 30+ MCP tools for PostgreSQL operations: ### Metadata Tools - `pg_list_environments` - List configured database environments - `pg_list_schemas` - List schemas in an environment - `pg_list_tables` - List tables in a schema - `pg_describe_table` - Get table structure - `pg_list_views` - List views - `pg_list_functions` - List functions - `pg_list_indexes` - List indexes - `pg_list_constraints` - List constraints - `pg_list_triggers` - List triggers ### Query Tools - `pg_query` - Execute read-only SQL query - `pg_explain` - Get query execution plan ### Data Tools - `pg_insert` - Insert rows - `pg_update` - Update rows - `pg_delete` - Delete rows - `pg_upsert` - Insert or update rows - `pg_bulk_insert` - Insert multiple rows ### Transaction Tools - `pg_begin_transaction` - Start transaction - `pg_commit_transaction` - Commit transaction - `pg_rollback_transaction` - Rollback transaction ### Diagnostic Tools - `pg_analyze_query` - Analyze query performance - `pg_check_connection` - Check database connectivity ## Docker Deployment ### Build Image ```bash docker build -t mcp-database-server:1.0.0 . docker build -t mcp-database-server:1.0.1.02 . docker build -t mcp-database-server:1.0.1.03 . docker build -t mcp-database-server:1.0.2 . docker compose build --no-cache && docker compose up -d ``` ### Run Container ```bash docker run -d \ --name mcp-database-server \ -p 7700:7700 \ -v $(pwd)/config/database.json:/app/config/database.json:ro \ -e MCP_AUTH_TOKEN=your-token \ -e MCP_DRWORKS_PASSWORD=your-password \ mcp-database-server:1.0.0 ``` ### Docker Compose ```bash cp docker-compose.example.yml docker-compose.yml cp config/database.example.json config/database.json # Edit configuration files # Create .env file echo "MCP_AUTH_TOKEN=$(node scripts/generate-token.js | head -2 | tail -1)" > .env echo "MCP_DRWORKS_PASSWORD=your-password" >> .env # Start docker compose up -d ``` ## Health Check The server exposes a health check endpoint: ```bash curl http://localhost:7700/health ``` Response: ```json { "status": "ok", "uptime": 3600, "version": "1.0.0", "clients": 5, "environments": [ { "name": "drworks", "status": "connected", "poolSize": 10, "activeConnections": 2 } ], "timestamp": "2025-12-23T10:30:00.000Z" } ``` Status values: - `ok` - All environments connected - `degraded` - Some environments disconnected - `error` - Critical failures ## Security Recommendations 1. **Use Strong Tokens**: Generate 64-character random tokens 2. **Enable SSL**: Use `wss://` in production with TLS termination 3. **Restrict Network**: Use firewall rules to limit access 4. **Read-Only Mode**: Use `mode: "readonly"` for read-only access 5. **Audit Logging**: Enable audit logging for compliance 6. **Rotate Tokens**: Periodically rotate authentication tokens 7. **Non-Root User**: Docker image runs as non-root user (UID 1001) ## Graceful Shutdown The server handles SIGTERM and SIGINT signals: 1. Stops accepting new connections 2. Rolls back active transactions 3. Closes all sessions 4. Closes database connection pools 5. Exits cleanly ```bash # Graceful stop docker stop mcp-database-server # Or send signal directly kill -TERM $(pgrep -f "node dist/server.js") ``` ## Logging Logs are output in JSON format (pino): ```json {"level":"info","time":"2025-12-23T10:30:00.000Z","msg":"WebSocket server started","host":"0.0.0.0","port":7700} ``` Log levels: `debug`, `info`, `warn`, `error`, `fatal` ## License MIT