database/README.md
2025-12-28 15:54:35 +08:00

12 KiB
Raw Blame History

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

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 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

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

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 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
# 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