cq-mcp-server 0.1.0 → 0.2.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 +17 -2
- package/dist/index.js +41 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,15 +5,30 @@
|
|
|
5
5
|
## 工具调用顺序
|
|
6
6
|
|
|
7
7
|
```
|
|
8
|
-
list_databases → list_tables → get_table_columns → execute_sql
|
|
8
|
+
connect(可选)→ list_databases → list_tables → get_table_columns → execute_sql
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
- **`connect`**:动态传入连接参数时需要先调用(如 Dify 等场景)。若已通过环境变量 `CQ_BASE_URL` / `CQ_USERNAME` / `CQ_PASSWORD` 配置,可跳过。
|
|
12
|
+
- 后续工具所需的 `connection_id`、`connection_type`、`database`、`schema` 参数,都只能从前面的工具返回结果中获取,不能凭空猜测。
|
|
12
13
|
|
|
13
14
|
---
|
|
14
15
|
|
|
15
16
|
## 工具详解
|
|
16
17
|
|
|
18
|
+
### 0. `connect` — 设置连接参数(动态场景必须首先调用)
|
|
19
|
+
|
|
20
|
+
| 参数 | 说明 |
|
|
21
|
+
|------|------|
|
|
22
|
+
| `base_url` | CloudQuery 平台地址,如 `http://10.10.2.73` |
|
|
23
|
+
| `username` | 登录账号 |
|
|
24
|
+
| `password` | 登录密码(明文,服务端自动加密) |
|
|
25
|
+
|
|
26
|
+
返回:连接配置成功确认。调用后原 Session 失效,下次请求自动重新登录。
|
|
27
|
+
|
|
28
|
+
**Dify 配置示例**:在 workflow 开始节点调用 `connect`,将用户输入的 `base_url` / `username` / `password` 传入,后续工具调用无需再传。
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
17
32
|
### 1. `list_databases` — 查询数据库清单
|
|
18
33
|
|
|
19
34
|
**无需任何参数。**
|
package/dist/index.js
CHANGED
|
@@ -3,15 +3,18 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import forge from "node-forge";
|
|
6
|
-
const BASE_URL = process.env.CQ_BASE_URL ?? "http://10.10.2.73";
|
|
7
|
-
const USERNAME = process.env.CQ_USERNAME ?? "admin001";
|
|
8
|
-
const PASSWORD = process.env.CQ_PASSWORD ?? "Hello123$";
|
|
9
6
|
// MCP 协议通过 stdio 通信,日志必须输出到 stderr 避免污染 stdout
|
|
10
7
|
const log = {
|
|
11
8
|
info: (...args) => process.stderr.write(`[INFO] ${args.join(" ")}\n`),
|
|
12
9
|
warn: (...args) => process.stderr.write(`[WARN] ${args.join(" ")}\n`),
|
|
13
10
|
error: (...args) => process.stderr.write(`[ERROR] ${args.join(" ")}\n`),
|
|
14
11
|
};
|
|
12
|
+
// 运行时连接配置(可由 connect 工具覆盖,也可由环境变量提供默认值)
|
|
13
|
+
let config = {
|
|
14
|
+
baseUrl: process.env.CQ_BASE_URL ?? "",
|
|
15
|
+
username: process.env.CQ_USERNAME ?? "",
|
|
16
|
+
password: process.env.CQ_PASSWORD ?? "",
|
|
17
|
+
};
|
|
15
18
|
let sessionCookie = null;
|
|
16
19
|
// ── 认证 ──────────────────────────────────────────────────────────
|
|
17
20
|
/** 用 RSA 公钥加密密码(与前端 JSEncrypt 行为一致) */
|
|
@@ -23,18 +26,24 @@ function encryptPassword(publicKeyB64, password) {
|
|
|
23
26
|
return forge.util.encode64(encrypted);
|
|
24
27
|
}
|
|
25
28
|
async function login() {
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
if (!config.baseUrl)
|
|
30
|
+
throw new Error("未配置 baseUrl,请先调用 connect 工具或设置 CQ_BASE_URL 环境变量");
|
|
31
|
+
if (!config.username)
|
|
32
|
+
throw new Error("未配置 username,请先调用 connect 工具或设置 CQ_USERNAME 环境变量");
|
|
33
|
+
if (!config.password)
|
|
34
|
+
throw new Error("未配置 password,请先调用 connect 工具或设置 CQ_PASSWORD 环境变量");
|
|
35
|
+
log.info(`登录 ${config.baseUrl},用户: ${config.username}`);
|
|
36
|
+
const keyResp = await fetch(`${config.baseUrl}/user/sys/transmission/publicKey`);
|
|
28
37
|
if (!keyResp.ok)
|
|
29
38
|
throw new Error(`获取公钥失败: HTTP ${keyResp.status}`);
|
|
30
39
|
const keyData = (await keyResp.json());
|
|
31
40
|
if (keyData.resCode !== 10000)
|
|
32
41
|
throw new Error(`获取公钥异常: ${keyData.resCode}`);
|
|
33
|
-
const encryptedPassword = encryptPassword(keyData.data.publicKey,
|
|
34
|
-
const resp = await fetch(`${
|
|
42
|
+
const encryptedPassword = encryptPassword(keyData.data.publicKey, config.password);
|
|
43
|
+
const resp = await fetch(`${config.baseUrl}/user/login`, {
|
|
35
44
|
method: "POST",
|
|
36
45
|
headers: { "Content-Type": "application/json" },
|
|
37
|
-
body: JSON.stringify({ userId:
|
|
46
|
+
body: JSON.stringify({ userId: config.username, password: encryptedPassword }),
|
|
38
47
|
});
|
|
39
48
|
if (!resp.ok)
|
|
40
49
|
throw new Error(`登录请求失败: HTTP ${resp.status}`);
|
|
@@ -62,7 +71,7 @@ async function login() {
|
|
|
62
71
|
async function post(path, body) {
|
|
63
72
|
if (!sessionCookie)
|
|
64
73
|
await login();
|
|
65
|
-
const resp = await fetch(`${
|
|
74
|
+
const resp = await fetch(`${config.baseUrl}${path}`, {
|
|
66
75
|
method: "POST",
|
|
67
76
|
headers: {
|
|
68
77
|
"Content-Type": "application/json",
|
|
@@ -93,7 +102,28 @@ async function metaNode(payload) {
|
|
|
93
102
|
// ── MCP Server ────────────────────────────────────────────────────
|
|
94
103
|
const server = new McpServer({
|
|
95
104
|
name: "cq-mcp-server",
|
|
96
|
-
version: "0.
|
|
105
|
+
version: "0.2.0",
|
|
106
|
+
});
|
|
107
|
+
// ── 工具零:连接配置 ──────────────────────────────────────────────
|
|
108
|
+
server.tool("connect", `配置 CloudQuery 平台的连接信息(地址、账号、密码)。
|
|
109
|
+
|
|
110
|
+
用途:在调用其他工具前,先通过此工具设置连接参数。适用于未配置环境变量的场景(如 Dify、动态多租户等)。
|
|
111
|
+
参数说明:
|
|
112
|
+
- base_url:CloudQuery 平台地址,如 http://10.10.2.73
|
|
113
|
+
- username:登录账号
|
|
114
|
+
- password:登录密码(明文,服务端自动加密)
|
|
115
|
+
返回:连接配置成功的确认信息。
|
|
116
|
+
注意:每次调用会重置连接配置并清除已有 Session,强制重新登录。`, {
|
|
117
|
+
base_url: z.string().describe("CloudQuery 平台地址,如 http://10.10.2.73"),
|
|
118
|
+
username: z.string().describe("登录账号"),
|
|
119
|
+
password: z.string().describe("登录密码"),
|
|
120
|
+
}, async ({ base_url, username, password }) => {
|
|
121
|
+
config = { baseUrl: base_url.replace(/\/$/, ""), username, password };
|
|
122
|
+
sessionCookie = null;
|
|
123
|
+
log.info(`connect: 配置已更新 baseUrl=${config.baseUrl} user=${username}`);
|
|
124
|
+
return {
|
|
125
|
+
content: [{ type: "text", text: `连接配置已设置:${config.baseUrl},用户:${username}` }],
|
|
126
|
+
};
|
|
97
127
|
});
|
|
98
128
|
// ── 工具一:查询数据库清单 ─────────────────────────────────────────
|
|
99
129
|
server.tool("list_databases", `查询所有数据库连接及其下的数据库实例列表。
|
|
@@ -274,6 +304,6 @@ server.tool("execute_sql", `在指定数据库上执行 SQL 语句,返回查
|
|
|
274
304
|
return { content: [{ type: "text", text: lines.join("\n") || "无输出" }] };
|
|
275
305
|
});
|
|
276
306
|
// ── 启动 ──────────────────────────────────────────────────────────
|
|
277
|
-
log.info(`CloudQuery MCP Server 启动 BASE_URL=${
|
|
307
|
+
log.info(`CloudQuery MCP Server 启动 BASE_URL=${config.baseUrl || "(未配置)"} USER=${config.username || "(未配置)"}`);
|
|
278
308
|
const transport = new StdioServerTransport();
|
|
279
309
|
await server.connect(transport);
|
package/package.json
CHANGED