npm package: @harneon-ai/db
Description: MCP Server for database metadata and read-only data queries with ShardingSphere topology support
Author: lyuzb
Latest version: 0.0.5

# Harneon DB MCP Server

一个 MCP (Model Context Protocol) Server，为 AI 助手提供只读的 PostgreSQL 数据库元数据查询能力，支持 ShardingSphere 风格的多数据源分片拓扑解析。

## 功能概览

- 查看多数据源配置信息
- 查询任意数据源的表列表、表结构、索引信息
- 解析 ShardingSphere 分片拓扑（逻辑表 → 实际数据节点映射）
- 执行自定义元数据查询（仅允许 information_schema / pg_catalog）
- 多层安全防护，严禁任何数据写入和业务数据读取

## 快速开始

### 1. 全局安装

```bash
npm install -g @harneon-ai/db
```

### 2. 在 Claude Desktop 中使用

编辑 Claude Desktop 配置文件（`claude_desktop_config.json`）：

```json
{
  "mcpServers": {
    "harneon-db": {
      "command": "harneon-db"
    }
  }
}
```

### 3. 在 Claude Code 中使用

```bash
claude mcp add harneon-db -- harneon-db
```

### 4. 配置数据源

配置文件默认保存在 `~/.harneon-ai/db/datasource.yaml`。

你可以手动创建该文件，也可以启动后通过 `save_datasource_config` 工具添加数据源（目录会自动创建）。

如需使用自定义配置路径：

```bash
harneon-db /path/to/datasource.yaml
```

或通过环境变量：

```bash
DB_CONFIG_PATH=/path/to/datasource.yaml harneon-db
```

### 5. 开发模式运行

```bash
npm run dev
```

## 配置文件格式

配置文件采用 YAML 格式，兼容 ShardingSphere 配置：

```yaml
dataSources:
  ds_0:
    dataSourceClassName: com.zaxxer.hikari.HikariDataSource
    driverClassName: org.postgresql.Driver
    jdbcUrl: jdbc:postgresql://localhost:5432/shop_db_0
    username: postgres
    password: your_password
  ds_1:
    jdbcUrl: jdbc:postgresql://localhost:5432/shop_db_1
    username: postgres
    password: your_password

rules:
  - !SHARDING
    tables:
      tbl_order:
        actualDataNodes: ds_$->{0..1}.tbl_order_$->{0..3}
        tableStrategy:
          standard:
            shardingColumn: order_id
            shardingAlgorithmName: tbl_order_inline
    defaultShardingColumn: corporation_id
    defaultDatabaseStrategy:
      standard:
        shardingColumn: corporation_id
        shardingAlgorithmName: database_inline
    shardingAlgorithms:
      database_inline:
        type: INLINE
        props:
          algorithm-expression: ds_$->{corporation_id % 2}
      tbl_order_inline:
        type: INLINE
        props:
          algorithm-expression: tbl_order_$->{order_id % 4}
```

配置路径优先级：命令行参数 > `DB_CONFIG_PATH` 环境变量 > `~/.harneon-ai/db/datasource.yaml`

## MCP Tools 说明

### list_datasources

列出所有已配置的数据源信息。密码字段显示为 `***`。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| （无参数） | | | |

返回示例：

```json
[
  {
    "name": "ds_0",
    "host": "localhost",
    "port": 5432,
    "database": "shop_db_0",
    "username": "postgres",
    "password": "***"
  }
]
```

### list_tables

列出指定数据源中的所有用户表和视图。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| datasource | string | 是 | 数据源名称，如 `ds_0` |
| schema | string | 否 | Schema 名称，默认 `public` |

返回示例：

```json
[
  { "table_name": "tbl_order_0", "table_type": "BASE TABLE" },
  { "table_name": "tbl_order_1", "table_type": "BASE TABLE" }
]
```

### describe_table

查询指定表的详细结构，包含列信息、约束和统计数据。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| datasource | string | 是 | 数据源名称 |
| table | string | 是 | 表名 |
| schema | string | 否 | Schema 名称，默认 `public` |

返回示例：

```json
{
  "columns": [
    {
      "column_name": "id",
      "data_type": "bigint",
      "is_nullable": "NO",
      "column_default": "nextval('tbl_order_0_id_seq'::regclass)",
      "character_maximum_length": null,
      "ordinal_position": 1,
      "comment": "主键ID"
    }
  ],
  "constraints": [
    {
      "constraint_name": "tbl_order_0_pkey",
      "constraint_type": "PRIMARY KEY",
      "columns": "id"
    }
  ],
  "stats": {
    "estimated_rows": 15000,
    "total_size": "2048 kB",
    "table_size": "1536 kB",
    "index_size": "512 kB"
  }
}
```

### describe_indexes

查询指定表的所有索引信息。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| datasource | string | 是 | 数据源名称 |
| table | string | 是 | 表名 |
| schema | string | 否 | Schema 名称，默认 `public` |

返回示例：

```json
[
  {
    "index_name": "tbl_order_0_pkey",
    "index_columns": "id",
    "is_unique": true,
    "index_method": "btree",
    "index_definition": "CREATE UNIQUE INDEX tbl_order_0_pkey ON public.tbl_order_0 USING btree (id)"
  },
  {
    "index_name": "idx_order_corporation",
    "index_columns": "corporation_id",
    "is_unique": false,
    "index_method": "btree",
    "index_definition": "CREATE INDEX idx_order_corporation ON public.tbl_order_0 USING btree (corporation_id)"
  }
]
```

### sharding_topology

查看分片拓扑信息。这是纯配置解析操作，不连接数据库。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| table | string | 否 | 逻辑表名（不传则返回所有表的拓扑） |

返回示例：

```json
[
  {
    "logicalTable": "tbl_order",
    "actualDataNodes": [
      "ds_0.tbl_order_0",
      "ds_0.tbl_order_1",
      "ds_1.tbl_order_0",
      "ds_1.tbl_order_1"
    ],
    "nodeCount": 4,
    "tableStrategy": "standard",
    "shardingColumn": "order_id",
    "algorithmName": "tbl_order_inline",
    "algorithmType": "INLINE",
    "algorithmExpression": "tbl_order_$->{order_id % 2}",
    "databaseStrategy": "standard",
    "databaseShardingColumn": "corporation_id"
  }
]
```

### query_metadata

执行自定义的元数据查询。仅允许查询 `information_schema` 或 `pg_catalog` 的 SELECT 语句。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| datasource | string | 是 | 数据源名称 |
| sql | string | 是 | SQL 查询语句 |

安全限制：
- 必须以 `SELECT` 开头
- 不允许包含分号（禁止多语句）
- 不允许包含写操作关键字（INSERT/UPDATE/DELETE/DROP/ALTER 等）
- `FROM` 子句必须直接引用 `information_schema` 或 `pg_catalog`

合法查询示例：

```sql
SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'tbl_order_0'
```

```sql
SELECT relname, reltuples FROM pg_catalog.pg_class WHERE relkind = 'r'
```

## 安全机制

本工具采用多层防御策略确保数据安全：

| 层级 | 措施 | 说明 |
|------|------|------|
| 连接层 | `default_transaction_read_only=on` | pg.Pool 级别强制只读，即使 SQL 注入也无法写入 |
| SQL 层 | 白名单过滤 | query_metadata 仅允许 SELECT + information_schema/pg_catalog |
| Tool 层 | 固定查询 | 预定义 tool 只执行硬编码的参数化查询 |
| 输出层 | 密码遮蔽 | 所有输出中密码显示为 `***` |

## 项目结构

```
src/
├── index.ts                    # MCP Server 入口，组装所有组件
├── config/
│   ├── types.ts                # Zod 配置 schema 和 TypeScript 类型定义
│   └── parser.ts               # YAML 解析、DataNodes 展开、JDBC URL 解析
├── db/
│   ├── connection-manager.ts   # 多数据源连接池管理（懒初始化、并发安全）
│   └── metadata-queries.ts     # PostgreSQL 元数据查询 SQL 封装
└── tools/
    ├── list-datasources.ts     # Tool: 列出数据源
    ├── list-tables.ts          # Tool: 列出表
    ├── describe-table.ts       # Tool: 表结构详情
    ├── describe-indexes.ts     # Tool: 索引详情
    ├── sharding-topology.ts    # Tool: 分片拓扑
    └── query-metadata.ts       # Tool: 通用元数据查询（带安全过滤）
config/
├── datasource.yaml             # 实际配置文件（.gitignore 忽略，含密码）
└── datasource.example.yaml     # 示例配置文件
```

## 常用场景

### 了解数据库全貌

1. 调用 `list_datasources` 查看有哪些数据源
2. 调用 `sharding_topology` 了解分片规则和数据分布
3. 对感兴趣的数据源调用 `list_tables` 查看有哪些表

### 了解某张表的结构

1. 调用 `describe_table` 查看列定义、约束和统计信息
2. 调用 `describe_indexes` 查看索引设计

### 跨分片对比表结构

1. 调用 `sharding_topology` 获取逻辑表对应的所有物理节点
2. 对不同数据源的分片表分别调用 `describe_table` 对比结构差异

### 自定义元数据查询

使用 `query_metadata` 执行灵活的 information_schema / pg_catalog 查询，例如：
- 查找所有包含某列名的表
- 统计各 schema 下的表数量
- 查看表的存储参数