microgrids-mysql2pg-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +175 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +564 -0
- package/dist/index.js.map +1 -0
- package/package.json +48 -0
package/README.md
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# microgrids-mysql2pg-mcp
|
|
2
|
+
|
|
3
|
+
MySQL → PostgreSQL 全量数据库迁移 MCP 服务。
|
|
4
|
+
|
|
5
|
+
支持 AI 助手(Claude、Cursor 等)通过 MCP 工具调用触发数据库迁移,自动完成结构转换、数据迁移、报告生成。
|
|
6
|
+
|
|
7
|
+
Powered by Bangdao Inc.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 快速使用(无需安装)
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"mcpServers": {
|
|
16
|
+
"microgrids-mysql2pg-mcp": {
|
|
17
|
+
"type": "stdio",
|
|
18
|
+
"command": "npx",
|
|
19
|
+
"args": ["-y", "microgrids-mysql2pg-mcp@latest"]
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 注册到 Cursor
|
|
28
|
+
|
|
29
|
+
在 Cursor 设置中打开 MCP 配置,添加如下内容:
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"mcpServers": {
|
|
34
|
+
"microgrids-mysql2pg-mcp": {
|
|
35
|
+
"type": "stdio",
|
|
36
|
+
"command": "npx",
|
|
37
|
+
"args": ["-y", "microgrids-mysql2pg-mcp@latest"]
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## 工具说明
|
|
46
|
+
|
|
47
|
+
### `migrate_mysql_to_postgres`
|
|
48
|
+
|
|
49
|
+
执行 MySQL → PostgreSQL 全量数据库迁移。
|
|
50
|
+
|
|
51
|
+
#### 必填参数
|
|
52
|
+
|
|
53
|
+
| 参数 | 类型 | 说明 |
|
|
54
|
+
|------|------|------|
|
|
55
|
+
| `mysql_host` | string | MySQL 服务器地址 |
|
|
56
|
+
| `mysql_username` | string | MySQL 用户名 |
|
|
57
|
+
| `mysql_password` | string | MySQL 密码 |
|
|
58
|
+
| `pg_host` | string | PostgreSQL 服务器地址 |
|
|
59
|
+
| `pg_username` | string | PostgreSQL 用户名 |
|
|
60
|
+
| `pg_password` | string | PostgreSQL 密码 |
|
|
61
|
+
|
|
62
|
+
#### 可选参数
|
|
63
|
+
|
|
64
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
65
|
+
|------|------|--------|------|
|
|
66
|
+
| `mysql_port` | number | `3306` | MySQL 端口号 |
|
|
67
|
+
| `pg_port` | number | `5432` | PostgreSQL 端口号 |
|
|
68
|
+
| `batch_size` | number | `3000` | 每批次写入行数 |
|
|
69
|
+
| `large_table_threshold` | number | `100000` | 大表阈值(超过此行数只迁移结构) |
|
|
70
|
+
| `target_databases` | string[] | `[]` | 指定同步的库列表,为空时同步全部非系统库 |
|
|
71
|
+
| `report_output_dir` | string | `"doc"` | 报告文件输出目录 |
|
|
72
|
+
| `sql_output_dir` | string | `"doc/sql"` | DDL/DML 脚本输出目录 |
|
|
73
|
+
| `enable_timescaledb` | boolean | `false` | 是否启用 timescaledb 插件自动检测 |
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 迁移流程
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
MySQL 实例 PostgreSQL 实例
|
|
81
|
+
│ │
|
|
82
|
+
├─ 查询所有非系统数据库 ├─ 查询已有数据库
|
|
83
|
+
└──────────── 计算差集 ───────────────┘
|
|
84
|
+
│
|
|
85
|
+
┌────────────▼────────────┐
|
|
86
|
+
│ 待迁移数据库列表 │
|
|
87
|
+
└────────────┬────────────┘
|
|
88
|
+
│ 遍历每个数据库
|
|
89
|
+
▼
|
|
90
|
+
┌────────────────────────────┐
|
|
91
|
+
│ 1. 检测 PG 扩展需求 │
|
|
92
|
+
│ 2. 创建 PG 数据库 │
|
|
93
|
+
│ 3. 安装扩展 │
|
|
94
|
+
│ 4. 逐表 DDL 转换 + 执行 │ → {db}_ddl.sql
|
|
95
|
+
│ 5. 分批迁移表数据 │ → {db}_dml.sql
|
|
96
|
+
└────────────┬───────────────┘
|
|
97
|
+
▼
|
|
98
|
+
生成 migration_report_{ts}.json
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 输出文件
|
|
104
|
+
|
|
105
|
+
| 文件 | 说明 |
|
|
106
|
+
|------|------|
|
|
107
|
+
| `{report_output_dir}/migration_report_{timestamp}.json` | 完整迁移报告(每库每表状态) |
|
|
108
|
+
| `{report_output_dir}/table_failures_{timestamp}.json` | 实时写入的失败记录 |
|
|
109
|
+
| `{sql_output_dir}/{database}_ddl.sql` | 建表、索引、注释语句 |
|
|
110
|
+
| `{sql_output_dir}/{database}_dml.sql` | 已成功迁移表的 INSERT 语句 |
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## 类型映射
|
|
115
|
+
|
|
116
|
+
| MySQL | PostgreSQL |
|
|
117
|
+
|-------|-----------|
|
|
118
|
+
| `tinyint(1)` | `BOOLEAN` |
|
|
119
|
+
| `tinyint` | `SMALLINT` |
|
|
120
|
+
| `smallint` | `INTEGER` |
|
|
121
|
+
| `mediumint` / `bigint` | `BIGINT` |
|
|
122
|
+
| `int` / `integer` | `INTEGER` |
|
|
123
|
+
| `float` / `double` | `NUMERIC` |
|
|
124
|
+
| `decimal(p,s)` | `DECIMAL(p,s)` |
|
|
125
|
+
| `varchar(n)` | `VARCHAR(n)` |
|
|
126
|
+
| `char(n)` | `CHAR(n)` |
|
|
127
|
+
| `*text` / `*blob` | `TEXT` |
|
|
128
|
+
| `datetime` / `timestamp` | `TIMESTAMP` |
|
|
129
|
+
| `date` | `DATE` |
|
|
130
|
+
| `time` | `TIME` |
|
|
131
|
+
| `year` | `VARCHAR(4)` |
|
|
132
|
+
| `json` | `JSONB` |
|
|
133
|
+
| `enum` / `set` | `TEXT` |
|
|
134
|
+
| `AUTO_INCREMENT` (int) | `SERIAL` |
|
|
135
|
+
| `AUTO_INCREMENT` (bigint) | `BIGSERIAL` |
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 本地开发
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# 安装依赖
|
|
143
|
+
npm install
|
|
144
|
+
|
|
145
|
+
# 编译
|
|
146
|
+
npm run build
|
|
147
|
+
|
|
148
|
+
# 本地运行
|
|
149
|
+
npm start
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 发布到 NPM
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# 登录 NPM
|
|
158
|
+
npm login
|
|
159
|
+
|
|
160
|
+
# 构建并发布
|
|
161
|
+
npm publish
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
发布后其他人可通过以下方式使用:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
npx -y microgrids-mysql2pg-mcp@latest
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 环境要求
|
|
173
|
+
|
|
174
|
+
- Node.js >= 18.0.0
|
|
175
|
+
- npm >= 8.0.0
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* MySQL → PostgreSQL 全量迁移 MCP 服务
|
|
4
|
+
*
|
|
5
|
+
* 功能说明:
|
|
6
|
+
* 1. 获取 MySQL 实例所有非系统数据库列表(支持指定同步哪些库)
|
|
7
|
+
* 2. 与 PostgreSQL 已有库计算差集(跳过已存在的库)
|
|
8
|
+
* 3. 自动检测所需 PG 扩展(如 timescaledb)
|
|
9
|
+
* 4. 创建 PG 数据库,安装扩展,执行转换后的 DDL
|
|
10
|
+
* 5. 分批迁移表数据,超过大表阈值的表只同步结构
|
|
11
|
+
* 6. 生成汇总报告 JSON 及 DDL/DML SQL 脚本
|
|
12
|
+
*
|
|
13
|
+
* Powered by Bangdao Inc.
|
|
14
|
+
*
|
|
15
|
+
* @author acw
|
|
16
|
+
* @date 2026/05/19, 周二
|
|
17
|
+
*/
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;GAeG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* MySQL → PostgreSQL 全量迁移 MCP 服务
|
|
4
|
+
*
|
|
5
|
+
* 功能说明:
|
|
6
|
+
* 1. 获取 MySQL 实例所有非系统数据库列表(支持指定同步哪些库)
|
|
7
|
+
* 2. 与 PostgreSQL 已有库计算差集(跳过已存在的库)
|
|
8
|
+
* 3. 自动检测所需 PG 扩展(如 timescaledb)
|
|
9
|
+
* 4. 创建 PG 数据库,安装扩展,执行转换后的 DDL
|
|
10
|
+
* 5. 分批迁移表数据,超过大表阈值的表只同步结构
|
|
11
|
+
* 6. 生成汇总报告 JSON 及 DDL/DML SQL 脚本
|
|
12
|
+
*
|
|
13
|
+
* Powered by Bangdao Inc.
|
|
14
|
+
*
|
|
15
|
+
* @author acw
|
|
16
|
+
* @date 2026/05/19, 周二
|
|
17
|
+
*/
|
|
18
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
19
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
20
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
21
|
+
import mysql from "mysql2/promise";
|
|
22
|
+
import pg from "pg";
|
|
23
|
+
import fs from "fs";
|
|
24
|
+
import path from "path";
|
|
25
|
+
const { Client: PgClient } = pg;
|
|
26
|
+
// ==================== 常量 ====================
|
|
27
|
+
const MYSQL_SYSTEM_DBS = new Set(["information_schema", "mysql", "performance_schema", "sys"]);
|
|
28
|
+
const PG_SYSTEM_DBS = new Set(["postgres", "template0", "template1"]);
|
|
29
|
+
const TIMESCALE_TABLE_KEYWORDS = ["data", "metrics", "log", "record", "history", "monitor", "sensor", "telemetry", "point", "measure"];
|
|
30
|
+
const TIMESCALE_COLUMN_KEYWORDS = ["time", "date", "ts", "at", "moment"];
|
|
31
|
+
// ==================== DDL 类型转换 ====================
|
|
32
|
+
function convertColumnType(mysqlType, extra) {
|
|
33
|
+
const t = mysqlType.trim().toLowerCase();
|
|
34
|
+
const isAutoInc = extra.toLowerCase().includes("auto_increment");
|
|
35
|
+
let pgType;
|
|
36
|
+
if (/^tinyint\s*\(1\)$/.test(t)) {
|
|
37
|
+
pgType = "BOOLEAN";
|
|
38
|
+
}
|
|
39
|
+
else if (/^tinyint/.test(t)) {
|
|
40
|
+
pgType = "SMALLINT";
|
|
41
|
+
}
|
|
42
|
+
else if (/^smallint/.test(t)) {
|
|
43
|
+
pgType = "INTEGER";
|
|
44
|
+
}
|
|
45
|
+
else if (/^mediumint/.test(t)) {
|
|
46
|
+
pgType = "BIGINT";
|
|
47
|
+
}
|
|
48
|
+
else if (/^bigint/.test(t)) {
|
|
49
|
+
pgType = "BIGINT";
|
|
50
|
+
}
|
|
51
|
+
else if (/^int(eger)?(\s*\(\d+\))?$/.test(t)) {
|
|
52
|
+
pgType = "INTEGER";
|
|
53
|
+
}
|
|
54
|
+
else if (/^float/.test(t)) {
|
|
55
|
+
pgType = "NUMERIC";
|
|
56
|
+
}
|
|
57
|
+
else if (/^double/.test(t)) {
|
|
58
|
+
pgType = "NUMERIC";
|
|
59
|
+
}
|
|
60
|
+
else if (/^decimal\s*\((\d+)\s*,\s*(\d+)\)$/.test(t)) {
|
|
61
|
+
const m = t.match(/^decimal\s*\((\d+)\s*,\s*(\d+)\)$/);
|
|
62
|
+
pgType = `DECIMAL(${m[1]},${m[2]})`;
|
|
63
|
+
}
|
|
64
|
+
else if (/^numeric\s*\((\d+)\s*,\s*(\d+)\)$/.test(t)) {
|
|
65
|
+
const m = t.match(/^numeric\s*\((\d+)\s*,\s*(\d+)\)$/);
|
|
66
|
+
pgType = `NUMERIC(${m[1]},${m[2]})`;
|
|
67
|
+
}
|
|
68
|
+
else if (/^varchar\s*\((\d+)\)$/.test(t)) {
|
|
69
|
+
const m = t.match(/^varchar\s*\((\d+)\)$/);
|
|
70
|
+
pgType = `VARCHAR(${m[1]})`;
|
|
71
|
+
}
|
|
72
|
+
else if (/^char\s*\((\d+)\)$/.test(t)) {
|
|
73
|
+
const m = t.match(/^char\s*\((\d+)\)$/);
|
|
74
|
+
pgType = `CHAR(${m[1]})`;
|
|
75
|
+
}
|
|
76
|
+
else if (/text$/.test(t)) {
|
|
77
|
+
pgType = "TEXT";
|
|
78
|
+
}
|
|
79
|
+
else if (/blob$/.test(t)) {
|
|
80
|
+
pgType = "TEXT";
|
|
81
|
+
}
|
|
82
|
+
else if (/^datetime/.test(t)) {
|
|
83
|
+
pgType = "TIMESTAMP";
|
|
84
|
+
}
|
|
85
|
+
else if (/^timestamp/.test(t)) {
|
|
86
|
+
pgType = "TIMESTAMP";
|
|
87
|
+
}
|
|
88
|
+
else if (/^date$/.test(t)) {
|
|
89
|
+
pgType = "DATE";
|
|
90
|
+
}
|
|
91
|
+
else if (/^time/.test(t)) {
|
|
92
|
+
pgType = "TIME";
|
|
93
|
+
}
|
|
94
|
+
else if (/^year/.test(t)) {
|
|
95
|
+
pgType = "VARCHAR(4)";
|
|
96
|
+
}
|
|
97
|
+
else if (/^json$/.test(t)) {
|
|
98
|
+
pgType = "JSONB";
|
|
99
|
+
}
|
|
100
|
+
else if (/^enum/.test(t) || /^set/.test(t)) {
|
|
101
|
+
pgType = "TEXT";
|
|
102
|
+
}
|
|
103
|
+
else if (/^bit/.test(t)) {
|
|
104
|
+
pgType = "BOOLEAN";
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
pgType = mysqlType.toUpperCase();
|
|
108
|
+
}
|
|
109
|
+
if (isAutoInc) {
|
|
110
|
+
return pgType === "BIGINT" ? "BIGSERIAL" : "SERIAL";
|
|
111
|
+
}
|
|
112
|
+
return pgType;
|
|
113
|
+
}
|
|
114
|
+
function buildCreateTableSql(table, columns, pks) {
|
|
115
|
+
const colDefs = [];
|
|
116
|
+
for (const col of columns) {
|
|
117
|
+
const pgType = convertColumnType(col.COLUMN_TYPE, col.EXTRA);
|
|
118
|
+
let line = ` "${col.COLUMN_NAME}" ${pgType}`;
|
|
119
|
+
const def = col.COLUMN_DEFAULT;
|
|
120
|
+
if (def !== null && !col.EXTRA.toLowerCase().includes("auto_increment")) {
|
|
121
|
+
if (def.toUpperCase() === "CURRENT_TIMESTAMP") {
|
|
122
|
+
line += " DEFAULT CURRENT_TIMESTAMP";
|
|
123
|
+
}
|
|
124
|
+
else if (def.toUpperCase() !== "NULL") {
|
|
125
|
+
line += ` DEFAULT '${def.replace(/'/g, "''")}'`;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (col.IS_NULLABLE === "NO" && !pgType.includes("SERIAL")) {
|
|
129
|
+
line += " NOT NULL";
|
|
130
|
+
}
|
|
131
|
+
colDefs.push(line);
|
|
132
|
+
}
|
|
133
|
+
if (pks.length > 0) {
|
|
134
|
+
colDefs.push(` PRIMARY KEY (${pks.map((p) => `"${p}"`).join(", ")})`);
|
|
135
|
+
}
|
|
136
|
+
return `CREATE TABLE IF NOT EXISTS "${table}" (\n${colDefs.join(",\n")}\n);`;
|
|
137
|
+
}
|
|
138
|
+
function buildIndexSqls(table, indexes) {
|
|
139
|
+
const indexMap = new Map();
|
|
140
|
+
for (const row of indexes) {
|
|
141
|
+
if (!indexMap.has(row.INDEX_NAME)) {
|
|
142
|
+
indexMap.set(row.INDEX_NAME, { unique: row.NON_UNIQUE === 0, columns: [] });
|
|
143
|
+
}
|
|
144
|
+
indexMap.get(row.INDEX_NAME).columns.push(row.COLUMN_NAME);
|
|
145
|
+
}
|
|
146
|
+
const sqls = [];
|
|
147
|
+
for (const [idxName, info] of indexMap) {
|
|
148
|
+
const pgIdxName = `${table}_${idxName}`.substring(0, 63);
|
|
149
|
+
const cols = info.columns.map((c) => `"${c}"`).join(", ");
|
|
150
|
+
const unique = info.unique ? "UNIQUE " : "";
|
|
151
|
+
sqls.push(`CREATE ${unique}INDEX IF NOT EXISTS "${pgIdxName}" ON "${table}" (${cols});`);
|
|
152
|
+
}
|
|
153
|
+
return sqls;
|
|
154
|
+
}
|
|
155
|
+
function buildCommentSqls(table, tableComment, columns) {
|
|
156
|
+
const sqls = [];
|
|
157
|
+
if (tableComment) {
|
|
158
|
+
sqls.push(`COMMENT ON TABLE "${table}" IS '${tableComment.replace(/'/g, "''")}';`);
|
|
159
|
+
}
|
|
160
|
+
for (const col of columns) {
|
|
161
|
+
if (col.COLUMN_COMMENT) {
|
|
162
|
+
sqls.push(`COMMENT ON COLUMN "${table}"."${col.COLUMN_NAME}" IS '${col.COLUMN_COMMENT.replace(/'/g, "''")}';`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return sqls;
|
|
166
|
+
}
|
|
167
|
+
// ==================== 失败记录 ====================
|
|
168
|
+
function recordFailure(reportOutputDir, timestamp, database, table, stage, reason) {
|
|
169
|
+
const failurePath = path.join(reportOutputDir, `table_failures_${timestamp}.json`);
|
|
170
|
+
let records = [];
|
|
171
|
+
if (fs.existsSync(failurePath)) {
|
|
172
|
+
try {
|
|
173
|
+
records = JSON.parse(fs.readFileSync(failurePath, "utf-8"));
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
records = [];
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
records.push({
|
|
180
|
+
database,
|
|
181
|
+
table,
|
|
182
|
+
stage,
|
|
183
|
+
reason,
|
|
184
|
+
time: new Date().toISOString(),
|
|
185
|
+
});
|
|
186
|
+
fs.writeFileSync(failurePath, JSON.stringify(records, null, 2), "utf-8");
|
|
187
|
+
}
|
|
188
|
+
// ==================== TimescaleDB 检测 ====================
|
|
189
|
+
async function detectExtensions(mysqlConn, database, enableTimescaledb) {
|
|
190
|
+
if (!enableTimescaledb)
|
|
191
|
+
return [];
|
|
192
|
+
const [rows] = await mysqlConn.query(`SELECT TABLE_NAME, COLUMN_NAME FROM information_schema.COLUMNS
|
|
193
|
+
WHERE TABLE_SCHEMA = ? AND DATA_TYPE IN ('timestamp', 'datetime')`, [database]);
|
|
194
|
+
for (const row of rows) {
|
|
195
|
+
const tableName = String(row.TABLE_NAME).toLowerCase();
|
|
196
|
+
const colName = String(row.COLUMN_NAME).toLowerCase();
|
|
197
|
+
const matchTable = TIMESCALE_TABLE_KEYWORDS.some((kw) => tableName.includes(kw));
|
|
198
|
+
const matchCol = TIMESCALE_COLUMN_KEYWORDS.some((kw) => colName.includes(kw));
|
|
199
|
+
if (matchTable && matchCol)
|
|
200
|
+
return ["timescaledb"];
|
|
201
|
+
}
|
|
202
|
+
return [];
|
|
203
|
+
}
|
|
204
|
+
// ==================== 数据迁移 ====================
|
|
205
|
+
async function migrateTableData(mysqlConn, pgClient, database, table, columns, batchSize, largeTableThreshold, sqlOutputDir) {
|
|
206
|
+
const [countRows] = await mysqlConn.query(`SELECT COUNT(*) AS cnt FROM \`${table}\``);
|
|
207
|
+
const rowCount = Number(countRows[0].cnt);
|
|
208
|
+
if (rowCount > largeTableThreshold) {
|
|
209
|
+
return { rowCount, dataStatus: "SKIPPED_LARGE_TABLE", migratedRows: 0 };
|
|
210
|
+
}
|
|
211
|
+
const boolCols = new Set(columns.filter((c) => /^tinyint\s*\(1\)$/i.test(c.COLUMN_TYPE)).map((c) => c.COLUMN_NAME));
|
|
212
|
+
const dateCols = new Set(columns
|
|
213
|
+
.filter((c) => /^(date|datetime|timestamp)/i.test(c.COLUMN_TYPE))
|
|
214
|
+
.map((c) => c.COLUMN_NAME));
|
|
215
|
+
const colNames = columns.map((c) => c.COLUMN_NAME);
|
|
216
|
+
const colList = colNames.map((c) => `"${c}"`).join(", ");
|
|
217
|
+
const placeholders = colNames.map((_, i) => `$${i + 1}`).join(", ");
|
|
218
|
+
const insertSql = `INSERT INTO "${table}" (${colList}) VALUES (${placeholders})`;
|
|
219
|
+
const dmlLines = [];
|
|
220
|
+
let offset = 0;
|
|
221
|
+
let migratedRows = 0;
|
|
222
|
+
try {
|
|
223
|
+
await pgClient.query("BEGIN");
|
|
224
|
+
while (true) {
|
|
225
|
+
const [rows] = await mysqlConn.query(`SELECT * FROM \`${table}\` LIMIT ? OFFSET ?`, [batchSize, offset]);
|
|
226
|
+
if (rows.length === 0)
|
|
227
|
+
break;
|
|
228
|
+
for (const row of rows) {
|
|
229
|
+
const values = colNames.map((colName) => {
|
|
230
|
+
const val = row[colName];
|
|
231
|
+
if (val === null || val === undefined)
|
|
232
|
+
return null;
|
|
233
|
+
if (boolCols.has(colName))
|
|
234
|
+
return Boolean(Number(val));
|
|
235
|
+
if (dateCols.has(colName) && typeof val === "string" && val.startsWith("0000-00-00"))
|
|
236
|
+
return null;
|
|
237
|
+
return val;
|
|
238
|
+
});
|
|
239
|
+
await pgClient.query(insertSql, values);
|
|
240
|
+
const dmlVals = values
|
|
241
|
+
.map((v) => {
|
|
242
|
+
if (v === null)
|
|
243
|
+
return "NULL";
|
|
244
|
+
if (v === true)
|
|
245
|
+
return "TRUE";
|
|
246
|
+
if (v === false)
|
|
247
|
+
return "FALSE";
|
|
248
|
+
return `'${String(v).replace(/'/g, "''")}'`;
|
|
249
|
+
})
|
|
250
|
+
.join(", ");
|
|
251
|
+
dmlLines.push(`INSERT INTO "${table}" (${colList}) VALUES (${dmlVals});`);
|
|
252
|
+
}
|
|
253
|
+
await pgClient.query("COMMIT");
|
|
254
|
+
await pgClient.query("BEGIN");
|
|
255
|
+
migratedRows += rows.length;
|
|
256
|
+
offset += batchSize;
|
|
257
|
+
if (rows.length < batchSize)
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
await pgClient.query("COMMIT");
|
|
261
|
+
}
|
|
262
|
+
catch (err) {
|
|
263
|
+
await pgClient.query("ROLLBACK");
|
|
264
|
+
return {
|
|
265
|
+
rowCount,
|
|
266
|
+
dataStatus: "FAILED",
|
|
267
|
+
dataFailReason: `数据写入失败(offset=${offset}):${err}`,
|
|
268
|
+
migratedRows,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
if (dmlLines.length > 0) {
|
|
272
|
+
const dmlPath = path.join(sqlOutputDir, `${database}_dml.sql`);
|
|
273
|
+
fs.appendFileSync(dmlPath, `\n-- Table: ${table}\n${dmlLines.join("\n")}\n`, "utf-8");
|
|
274
|
+
}
|
|
275
|
+
return { rowCount, dataStatus: "SUCCESS", migratedRows };
|
|
276
|
+
}
|
|
277
|
+
// ==================== 单表迁移 ====================
|
|
278
|
+
async function migrateOneTable(mysqlConn, pgClient, database, table, batchSize, largeTableThreshold, sqlOutputDir, reportOutputDir, timestamp) {
|
|
279
|
+
const result = {
|
|
280
|
+
tableName: table,
|
|
281
|
+
rowCount: -1,
|
|
282
|
+
ddlStatus: "FAILED",
|
|
283
|
+
dataStatus: "SKIPPED_DDL_FAILED",
|
|
284
|
+
migratedRows: 0,
|
|
285
|
+
};
|
|
286
|
+
let columns;
|
|
287
|
+
let pks;
|
|
288
|
+
let indexes;
|
|
289
|
+
let tableComment = "";
|
|
290
|
+
let ddlSqls;
|
|
291
|
+
try {
|
|
292
|
+
[columns] = await mysqlConn.query(`SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT, EXTRA, COLUMN_COMMENT, COLUMN_KEY
|
|
293
|
+
FROM information_schema.COLUMNS
|
|
294
|
+
WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? ORDER BY ORDINAL_POSITION`, [database, table]);
|
|
295
|
+
const [pkRows] = await mysqlConn.query(`SELECT COLUMN_NAME FROM information_schema.KEY_COLUMN_USAGE
|
|
296
|
+
WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? AND CONSTRAINT_NAME = 'PRIMARY'
|
|
297
|
+
ORDER BY ORDINAL_POSITION`, [database, table]);
|
|
298
|
+
pks = pkRows.map((r) => String(r.COLUMN_NAME));
|
|
299
|
+
[indexes] = await mysqlConn.query(`SELECT INDEX_NAME, COLUMN_NAME, NON_UNIQUE, SEQ_IN_INDEX
|
|
300
|
+
FROM information_schema.STATISTICS
|
|
301
|
+
WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? AND INDEX_NAME != 'PRIMARY'
|
|
302
|
+
ORDER BY INDEX_NAME, SEQ_IN_INDEX`, [database, table]);
|
|
303
|
+
const [tcRows] = await mysqlConn.query(`SELECT TABLE_COMMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?`, [database, table]);
|
|
304
|
+
if (tcRows.length > 0)
|
|
305
|
+
tableComment = String(tcRows[0].TABLE_COMMENT ?? "");
|
|
306
|
+
ddlSqls = [
|
|
307
|
+
buildCreateTableSql(table, columns, pks),
|
|
308
|
+
...buildIndexSqls(table, indexes),
|
|
309
|
+
...buildCommentSqls(table, tableComment, columns),
|
|
310
|
+
];
|
|
311
|
+
}
|
|
312
|
+
catch (err) {
|
|
313
|
+
const reason = `DDL 转换失败:${err}`;
|
|
314
|
+
result.ddlFailReason = reason;
|
|
315
|
+
recordFailure(reportOutputDir, timestamp, database, table, "DDL_CONVERT", reason);
|
|
316
|
+
return result;
|
|
317
|
+
}
|
|
318
|
+
// 写入 DDL SQL 文件
|
|
319
|
+
const ddlPath = path.join(sqlOutputDir, `${database}_ddl.sql`);
|
|
320
|
+
fs.appendFileSync(ddlPath, `\n-- Table: ${table}\n${ddlSqls.join("\n")}\n`, "utf-8");
|
|
321
|
+
// 执行 DDL
|
|
322
|
+
try {
|
|
323
|
+
for (const stmt of ddlSqls) {
|
|
324
|
+
if (stmt.trim())
|
|
325
|
+
await pgClient.query(stmt);
|
|
326
|
+
}
|
|
327
|
+
result.ddlStatus = "SUCCESS";
|
|
328
|
+
}
|
|
329
|
+
catch (err) {
|
|
330
|
+
const reason = `DDL 执行失败:${err}`;
|
|
331
|
+
result.ddlFailReason = reason;
|
|
332
|
+
recordFailure(reportOutputDir, timestamp, database, table, "DDL_EXECUTE", reason);
|
|
333
|
+
return result;
|
|
334
|
+
}
|
|
335
|
+
// 数据迁移
|
|
336
|
+
const dataResult = await migrateTableData(mysqlConn, pgClient, database, table, columns, batchSize, largeTableThreshold, sqlOutputDir);
|
|
337
|
+
result.rowCount = dataResult.rowCount ?? -1;
|
|
338
|
+
result.dataStatus = dataResult.dataStatus ?? "FAILED";
|
|
339
|
+
result.dataFailReason = dataResult.dataFailReason;
|
|
340
|
+
result.migratedRows = dataResult.migratedRows ?? 0;
|
|
341
|
+
if (result.dataStatus === "FAILED") {
|
|
342
|
+
recordFailure(reportOutputDir, timestamp, database, table, "DATA_SYNC", result.dataFailReason ?? "");
|
|
343
|
+
}
|
|
344
|
+
return result;
|
|
345
|
+
}
|
|
346
|
+
// ==================== 单库迁移 ====================
|
|
347
|
+
async function migrateOneDatabase(database, mysqlHost, mysqlPort, mysqlUser, mysqlPassword, pgHost, pgPort, pgUser, pgPassword, batchSize, largeTableThreshold, enableTimescaledb, sqlOutputDir, reportOutputDir, timestamp) {
|
|
348
|
+
const dbResult = {
|
|
349
|
+
databaseName: database,
|
|
350
|
+
status: "FAILED",
|
|
351
|
+
requiredExtensions: [],
|
|
352
|
+
tables: [],
|
|
353
|
+
};
|
|
354
|
+
let mysqlConn = null;
|
|
355
|
+
let pgAdmin = null;
|
|
356
|
+
let pgConn = null;
|
|
357
|
+
try {
|
|
358
|
+
mysqlConn = await mysql.createConnection({
|
|
359
|
+
host: mysqlHost,
|
|
360
|
+
port: mysqlPort,
|
|
361
|
+
user: mysqlUser,
|
|
362
|
+
password: mysqlPassword,
|
|
363
|
+
database,
|
|
364
|
+
dateStrings: true,
|
|
365
|
+
connectTimeout: 30000,
|
|
366
|
+
});
|
|
367
|
+
pgAdmin = new PgClient({ host: pgHost, port: pgPort, user: pgUser, password: pgPassword, database: "postgres" });
|
|
368
|
+
await pgAdmin.connect();
|
|
369
|
+
// 检测扩展
|
|
370
|
+
dbResult.requiredExtensions = await detectExtensions(mysqlConn, database, enableTimescaledb);
|
|
371
|
+
// 创建 PG 数据库(需在 autocommit 模式下执行,pg 默认 autocommit)
|
|
372
|
+
await pgAdmin.query(`CREATE DATABASE "${database.replace(/"/g, '""')}" ENCODING 'UTF8'`);
|
|
373
|
+
await pgAdmin.end();
|
|
374
|
+
pgAdmin = null;
|
|
375
|
+
// 连接到目标库
|
|
376
|
+
pgConn = new PgClient({ host: pgHost, port: pgPort, user: pgUser, password: pgPassword, database });
|
|
377
|
+
await pgConn.connect();
|
|
378
|
+
// 安装扩展
|
|
379
|
+
for (const ext of dbResult.requiredExtensions) {
|
|
380
|
+
await pgConn.query(`CREATE EXTENSION IF NOT EXISTS ${ext}`);
|
|
381
|
+
}
|
|
382
|
+
// 初始化 SQL 输出文件
|
|
383
|
+
const ddlPath = path.join(sqlOutputDir, `${database}_ddl.sql`);
|
|
384
|
+
const dmlPath = path.join(sqlOutputDir, `${database}_dml.sql`);
|
|
385
|
+
fs.writeFileSync(ddlPath, `-- DDL for database: ${database}\n-- Generated at: ${timestamp}\n\n`, "utf-8");
|
|
386
|
+
fs.writeFileSync(dmlPath, `-- DML for database: ${database}\n-- Generated at: ${timestamp}\n\n`, "utf-8");
|
|
387
|
+
// 获取表列表
|
|
388
|
+
const [tableRows] = await mysqlConn.query(`SELECT TABLE_NAME FROM information_schema.TABLES
|
|
389
|
+
WHERE TABLE_SCHEMA = ? AND TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, [database]);
|
|
390
|
+
const tables = tableRows.map((r) => String(r.TABLE_NAME));
|
|
391
|
+
for (const table of tables) {
|
|
392
|
+
const tableResult = await migrateOneTable(mysqlConn, pgConn, database, table, batchSize, largeTableThreshold, sqlOutputDir, reportOutputDir, timestamp);
|
|
393
|
+
dbResult.tables.push(tableResult);
|
|
394
|
+
}
|
|
395
|
+
dbResult.status = "SUCCESS";
|
|
396
|
+
}
|
|
397
|
+
catch (err) {
|
|
398
|
+
dbResult.failReason = String(err);
|
|
399
|
+
}
|
|
400
|
+
finally {
|
|
401
|
+
if (pgConn)
|
|
402
|
+
await pgConn.end().catch(() => { });
|
|
403
|
+
if (pgAdmin)
|
|
404
|
+
await pgAdmin.end().catch(() => { });
|
|
405
|
+
if (mysqlConn)
|
|
406
|
+
await mysqlConn.end().catch(() => { });
|
|
407
|
+
}
|
|
408
|
+
return dbResult;
|
|
409
|
+
}
|
|
410
|
+
// ==================== MCP 工具实现 ====================
|
|
411
|
+
async function migrateMysqlToPostgres(params) {
|
|
412
|
+
const { mysql_host, mysql_username, mysql_password, pg_host, pg_username, pg_password, mysql_port = 3306, pg_port = 5432, batch_size = 3000, large_table_threshold = 100000, target_databases = [], report_output_dir = "doc", sql_output_dir = "doc/sql", enable_timescaledb = false, } = params;
|
|
413
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19).replace("T", "_");
|
|
414
|
+
const report = {
|
|
415
|
+
startTime: new Date().toISOString(),
|
|
416
|
+
mysqlHost: `${mysql_host}:${mysql_port}`,
|
|
417
|
+
postgresHost: `${pg_host}:${pg_port}`,
|
|
418
|
+
largeTableThreshold: large_table_threshold,
|
|
419
|
+
batchSize: batch_size,
|
|
420
|
+
totalDatabases: 0,
|
|
421
|
+
successDatabases: 0,
|
|
422
|
+
failedDatabases: 0,
|
|
423
|
+
databases: [],
|
|
424
|
+
};
|
|
425
|
+
fs.mkdirSync(report_output_dir, { recursive: true });
|
|
426
|
+
fs.mkdirSync(sql_output_dir, { recursive: true });
|
|
427
|
+
let mysqlAdmin = null;
|
|
428
|
+
let pgAdmin = null;
|
|
429
|
+
try {
|
|
430
|
+
mysqlAdmin = await mysql.createConnection({
|
|
431
|
+
host: mysql_host,
|
|
432
|
+
port: mysql_port,
|
|
433
|
+
user: mysql_username,
|
|
434
|
+
password: mysql_password,
|
|
435
|
+
database: "information_schema",
|
|
436
|
+
connectTimeout: 30000,
|
|
437
|
+
});
|
|
438
|
+
pgAdmin = new PgClient({ host: pg_host, port: pg_port, user: pg_username, password: pg_password, database: "postgres" });
|
|
439
|
+
await pgAdmin.connect();
|
|
440
|
+
// 获取 MySQL 数据库列表
|
|
441
|
+
const [dbRows] = await mysqlAdmin.query("SHOW DATABASES");
|
|
442
|
+
let mysqlDbs = dbRows
|
|
443
|
+
.map((r) => String(r.Database))
|
|
444
|
+
.filter((db) => !MYSQL_SYSTEM_DBS.has(db.toLowerCase()));
|
|
445
|
+
if (target_databases.length > 0) {
|
|
446
|
+
const targetSet = new Set(target_databases.map((d) => d.toLowerCase()));
|
|
447
|
+
mysqlDbs = mysqlDbs.filter((db) => targetSet.has(db.toLowerCase()));
|
|
448
|
+
}
|
|
449
|
+
// 获取 PG 已有数据库
|
|
450
|
+
const pgRes = await pgAdmin.query("SELECT datname FROM pg_database");
|
|
451
|
+
const existingPgDbs = new Set(pgRes.rows.map((r) => r.datname.toLowerCase()).filter((d) => !PG_SYSTEM_DBS.has(d)));
|
|
452
|
+
await mysqlAdmin.end();
|
|
453
|
+
mysqlAdmin = null;
|
|
454
|
+
await pgAdmin.end();
|
|
455
|
+
pgAdmin = null;
|
|
456
|
+
const pendingDbs = mysqlDbs.filter((db) => !existingPgDbs.has(db.toLowerCase()));
|
|
457
|
+
report.totalDatabases = pendingDbs.length;
|
|
458
|
+
for (const database of pendingDbs) {
|
|
459
|
+
const dbResult = await migrateOneDatabase(database, mysql_host, mysql_port, mysql_username, mysql_password, pg_host, pg_port, pg_username, pg_password, batch_size, large_table_threshold, enable_timescaledb, sql_output_dir, report_output_dir, timestamp);
|
|
460
|
+
report.databases.push(dbResult);
|
|
461
|
+
if (dbResult.status === "SUCCESS") {
|
|
462
|
+
report.successDatabases++;
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
report.failedDatabases++;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
catch (err) {
|
|
470
|
+
report.error = String(err);
|
|
471
|
+
}
|
|
472
|
+
finally {
|
|
473
|
+
if (mysqlAdmin)
|
|
474
|
+
await mysqlAdmin.end().catch(() => { });
|
|
475
|
+
if (pgAdmin)
|
|
476
|
+
await pgAdmin.end().catch(() => { });
|
|
477
|
+
}
|
|
478
|
+
report.endTime = new Date().toISOString();
|
|
479
|
+
const reportPath = path.join(report_output_dir, `migration_report_${timestamp}.json`);
|
|
480
|
+
fs.writeFileSync(reportPath, JSON.stringify(report, null, 2), "utf-8");
|
|
481
|
+
return JSON.stringify({
|
|
482
|
+
status: "completed",
|
|
483
|
+
reportPath,
|
|
484
|
+
totalDatabases: report.totalDatabases,
|
|
485
|
+
successDatabases: report.successDatabases,
|
|
486
|
+
failedDatabases: report.failedDatabases,
|
|
487
|
+
startTime: report.startTime,
|
|
488
|
+
endTime: report.endTime,
|
|
489
|
+
...(report.error ? { error: report.error } : {}),
|
|
490
|
+
}, null, 2);
|
|
491
|
+
}
|
|
492
|
+
// ==================== MCP 服务定义 ====================
|
|
493
|
+
const TOOL_DEFINITION = {
|
|
494
|
+
name: "migrate_mysql_to_postgres",
|
|
495
|
+
description: "MySQL → PostgreSQL 全量数据库迁移工具。支持批量迁移数据库结构与数据,自动检测 timescaledb 扩展,大表保护,生成迁移报告及 DDL/DML SQL 脚本。",
|
|
496
|
+
inputSchema: {
|
|
497
|
+
type: "object",
|
|
498
|
+
properties: {
|
|
499
|
+
mysql_host: { type: "string", description: "MySQL 服务器地址" },
|
|
500
|
+
mysql_port: { type: "number", description: "MySQL 端口号,默认 3306", default: 3306 },
|
|
501
|
+
mysql_username: { type: "string", description: "MySQL 用户名" },
|
|
502
|
+
mysql_password: { type: "string", description: "MySQL 密码" },
|
|
503
|
+
pg_host: { type: "string", description: "PostgreSQL 服务器地址" },
|
|
504
|
+
pg_port: { type: "number", description: "PostgreSQL 端口号,默认 5432", default: 5432 },
|
|
505
|
+
pg_username: { type: "string", description: "PostgreSQL 用户名" },
|
|
506
|
+
pg_password: { type: "string", description: "PostgreSQL 密码" },
|
|
507
|
+
batch_size: {
|
|
508
|
+
type: "number",
|
|
509
|
+
description: "每批次写入行数,默认 3000",
|
|
510
|
+
default: 3000,
|
|
511
|
+
},
|
|
512
|
+
large_table_threshold: {
|
|
513
|
+
type: "number",
|
|
514
|
+
description: "大表阈值(超过此行数只迁移结构,不迁移数据),默认 100000",
|
|
515
|
+
default: 100000,
|
|
516
|
+
},
|
|
517
|
+
target_databases: {
|
|
518
|
+
type: "array",
|
|
519
|
+
items: { type: "string" },
|
|
520
|
+
description: "指定同步的数据库列表,为空时同步 MySQL 实例中所有非系统库",
|
|
521
|
+
},
|
|
522
|
+
report_output_dir: {
|
|
523
|
+
type: "string",
|
|
524
|
+
description: "报告文件输出目录,默认 doc",
|
|
525
|
+
default: "doc",
|
|
526
|
+
},
|
|
527
|
+
sql_output_dir: {
|
|
528
|
+
type: "string",
|
|
529
|
+
description: "DDL/DML SQL 脚本输出目录,默认 doc/sql",
|
|
530
|
+
default: "doc/sql",
|
|
531
|
+
},
|
|
532
|
+
enable_timescaledb: {
|
|
533
|
+
type: "boolean",
|
|
534
|
+
description: "是否启用 timescaledb 插件自动检测,默认 false",
|
|
535
|
+
default: false,
|
|
536
|
+
},
|
|
537
|
+
},
|
|
538
|
+
required: ["mysql_host", "mysql_username", "mysql_password", "pg_host", "pg_username", "pg_password"],
|
|
539
|
+
},
|
|
540
|
+
};
|
|
541
|
+
// ==================== 启动 MCP 服务 ====================
|
|
542
|
+
const server = new Server({ name: "microgrids-mysql2pg-mcp", version: "1.0.0" }, { capabilities: { tools: {} } });
|
|
543
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
544
|
+
tools: [TOOL_DEFINITION],
|
|
545
|
+
}));
|
|
546
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
547
|
+
const { name, arguments: args } = request.params;
|
|
548
|
+
if (name !== "migrate_mysql_to_postgres") {
|
|
549
|
+
throw new Error(`未知工具:${name}`);
|
|
550
|
+
}
|
|
551
|
+
try {
|
|
552
|
+
const result = await migrateMysqlToPostgres(args);
|
|
553
|
+
return { content: [{ type: "text", text: result }] };
|
|
554
|
+
}
|
|
555
|
+
catch (err) {
|
|
556
|
+
return {
|
|
557
|
+
content: [{ type: "text", text: JSON.stringify({ error: String(err) }, null, 2) }],
|
|
558
|
+
isError: true,
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
const transport = new StdioServerTransport();
|
|
563
|
+
await server.connect(transport);
|
|
564
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "microgrids-mysql2pg-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MySQL → PostgreSQL 全量数据库迁移 MCP 服务 | Powered by Bangdao Inc.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"mcp",
|
|
7
|
+
"mysql",
|
|
8
|
+
"postgresql",
|
|
9
|
+
"migration",
|
|
10
|
+
"database",
|
|
11
|
+
"microgrids"
|
|
12
|
+
],
|
|
13
|
+
"author": "acw",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "dist/index.js",
|
|
17
|
+
"bin": {
|
|
18
|
+
"microgrids-mysql2pg-mcp": "dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc",
|
|
26
|
+
"start": "node dist/index.js",
|
|
27
|
+
"dev": "tsx src/index.ts",
|
|
28
|
+
"prepublishOnly": "npm run build"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
32
|
+
"mysql2": "^3.9.0",
|
|
33
|
+
"pg": "^8.11.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/node": "^20.0.0",
|
|
37
|
+
"@types/pg": "^8.11.0",
|
|
38
|
+
"tsx": "^4.0.0",
|
|
39
|
+
"typescript": "^5.0.0"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=18.0.0"
|
|
43
|
+
},
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "https://github.com/bangdao-tech/microgrids-mysql2pg-mcp.git"
|
|
47
|
+
}
|
|
48
|
+
}
|