| .claude | ||
| config | ||
| dist | ||
| docs | ||
| scripts | ||
| src | ||
| .gitignore | ||
| changelog.json | ||
| CLAUDE.md | ||
| docker-compose.example.yml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
| vitest.config.ts | ||
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
/healthendpoint for monitoring - Docker Ready: Multi-stage build with minimal image size
Quick Start
1. Install Dependencies
npm install
2. Build
npm run build
3. Generate Auth Token
node scripts/generate-token.js
4. Create Configuration
cp config/database.example.json config/database.json
# Edit config/database.json with your database connections
5. Start Server
export MCP_AUTH_TOKEN="your-generated-token"
export MCP_DRWORKS_PASSWORD="your-db-password"
node dist/server.js --config config/database.json
6. Verify
curl http://localhost:7700/health
Configuration
Configuration File Format
{
"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:
{
"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
node dist/server.js [options]
Options:
--config <path> Configuration file path (default: ./config/database.json)
--listen <host:port> Listen address (overrides config)
--auth-token <token> Auth token (overrides config)
--log-level <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:
GET / HTTP/1.1
Upgrade: websocket
Authorization: Bearer your-token-here
Generate a secure token:
node scripts/generate-token.js
# Output: 64-character hex string
Client Configuration (Claude Code)
{
"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 environmentspg_list_schemas- List schemas in an environmentpg_list_tables- List tables in a schemapg_describe_table- Get table structurepg_list_views- List viewspg_list_functions- List functionspg_list_indexes- List indexespg_list_constraints- List constraintspg_list_triggers- List triggers
Query Tools
pg_query- Execute read-only SQL querypg_explain- Get query execution plan
Data Tools
pg_insert- Insert rowspg_update- Update rowspg_delete- Delete rowspg_upsert- Insert or update rowspg_bulk_insert- Insert multiple rows
Transaction Tools
pg_begin_transaction- Start transactionpg_commit_transaction- Commit transactionpg_rollback_transaction- Rollback transaction
Diagnostic Tools
pg_analyze_query- Analyze query performancepg_check_connection- Check database connectivity
Docker Deployment
Build Image
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 compose build --no-cache && docker compose up -d
Run Container
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
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:
curl http://localhost:7700/health
Response:
{
"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 connecteddegraded- Some environments disconnectederror- Critical failures
Security Recommendations
- Use Strong Tokens: Generate 64-character random tokens
- Enable SSL: Use
wss://in production with TLS termination - Restrict Network: Use firewall rules to limit access
- Read-Only Mode: Use
mode: "readonly"for read-only access - Audit Logging: Enable audit logging for compliance
- Rotate Tokens: Periodically rotate authentication tokens
- Non-Root User: Docker image runs as non-root user (UID 1001)
Graceful Shutdown
The server handles SIGTERM and SIGINT signals:
- Stops accepting new connections
- Rolls back active transactions
- Closes all sessions
- Closes database connection pools
- Exits cleanly
# 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):
{"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