basedoc-dameng-mcp 0.1.0 → 0.1.2

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 CHANGED
@@ -1,113 +1,201 @@
1
- # dameng-mcp
1
+ # basedoc-dameng-mcp
2
2
 
3
- Read-only MCP server for Dameng (DM8). Built after rejecting `zqeast/dameng-mcp-server` for stdout-leaking the password and offering an unguarded `execute_sql`.
3
+ 面向达梦数据库 (DM8) 的只读 MCP 服务,附带**本地 Markdown 手册**的离线全文检索能力。把"运维问答"和"翻手册"这两件事做成 LLM 直接可调用的工具,让 Claude / 其它 MCP 客户端在一次会话里既能问数据库当前状态,也能查官方文档。
4
4
 
5
- ## Guarantees
5
+ 整套搜索能力**完全离线**——内网部署的达梦客户也能用。
6
6
 
7
- - **Read-only at the application layer.** Only `SELECT` / `WITH` / `EXPLAIN` are accepted. Multi-statement input is rejected. Leading line/block comments are stripped before classification, so `-- foo\nDROP TABLE t` is also rejected.
8
- - **No password fallback.** `DAMENG_PASSWORD` must be set; missing → exit 2. Nothing defaults to `SYSDBA`.
9
- - **stderr-only logging.** stdio's stdout is the JSON-RPC channel — every log line goes through `console.error`.
10
- - **Timeout + row cap.** Every query is bounded by `DAMENG_QUERY_TIMEOUT_MS` (default 10s) and capped at `DAMENG_MAX_ROWS` (default 1000). On timeout the underlying connection is closed.
11
- - **Pinned dependencies.** `dmdb`, `@modelcontextprotocol/sdk`, and `zod` are all locked to exact versions.
7
+ ---
12
8
 
13
- The first line of defense is still **using a low-privilege Dameng account**. The app-layer guard is belt-and-braces; the database account should not have DML/DDL grants in the first place.
9
+ ## 快速开始
14
10
 
15
- ## Provision a read-only DB user
11
+ 接入这个 MCP 需要先准备一个 markdown 手册目录(用作搜索语料)。两条路:
16
12
 
17
- ```sql
18
- CREATE USER MCP_RO IDENTIFIED BY "<strong-password>";
19
- GRANT CONNECT TO MCP_RO;
20
- GRANT SELECT ON <schema>.<table> TO MCP_RO;
21
- -- or grant on a whole schema you trust:
22
- -- GRANT SELECT ANY TABLE TO MCP_RO;
23
- GRANT SELECT ON V$INSTANCE TO MCP_RO;
24
- GRANT SELECT ON V$DATABASE TO MCP_RO;
25
- ```
13
+ ### 路径 A:你已经有 markdown 手册目录
26
14
 
27
- ## Build
15
+ 直接跳到下面的 [接入 Claude Code](#接入-claude-code),把 `DAMENG_DOCS_ROOT` 指过去。
16
+
17
+ ### 路径 B:你还没有,从达梦官方文档站抓一份
18
+
19
+ 包内置了一个抓取转换工具(`basedoc-dameng-fetch-docs`),从 https://eco.dameng.com 拉所有手册并自动转 markdown,写到本地目录:
28
20
 
29
21
  ```bash
30
- npm install
31
- npm run build
22
+ npx -y basedoc-dameng-mcp basedoc-dameng-fetch-docs ~/.dameng-docs
23
+ # 或者直接调 bin:
24
+ npx -y -p basedoc-dameng-mcp basedoc-dameng-fetch-docs ~/.dameng-docs
32
25
  ```
33
26
 
34
- ## Configuration (env vars)
35
-
36
- | Variable | Required | Default | Notes |
37
- |---|---|---|---|
38
- | `DAMENG_HOST` | yes | — | e.g. `dameng.example.com` |
39
- | `DAMENG_PORT` | yes | — | e.g. `5236` |
40
- | `DAMENG_USER` | yes | — | low-privilege account |
41
- | `DAMENG_PASSWORD` | yes | — | no fallback |
42
- | `DAMENG_SCHEMA` | no | — | default schema for `list_tables` / `describe_table` |
43
- | `DAMENG_QUERY_TIMEOUT_MS` | no | `10000` | per-query timeout |
44
- | `DAMENG_MAX_ROWS` | no | `1000` | hard cap on returned rows |
45
- | `DAMENG_POOL_MIN` | no | `1` | |
46
- | `DAMENG_POOL_MAX` | no | `4` | |
47
- | `DAMENG_DOCS_ROOT` | no | — | absolute path to a directory of Markdown manuals. Enables the docs tools. |
48
- | `DAMENG_DOCS_INCLUDE` | no | — | comma-separated top-level dir patterns to include (glob `*` supported). Recommended: `DM8-*` to scope to official manuals only. |
49
- | `DAMENG_DOCS_EXCLUDE` | no | — | comma-separated top-level dir patterns to exclude. `node_modules` is always excluded. |
50
-
51
- ## Tools
52
-
53
- ### Database (require DB connection)
54
- - `query(sql)` run a single read-only statement.
55
- - `list_tables(schema?)` — tables in a schema (defaults to `DAMENG_SCHEMA` or current user).
56
- - `describe_table(table, schema?)` — columns + types for one table.
57
- - `instance_status()` — `V$INSTANCE` + `V$DATABASE` snapshot.
58
-
59
- ### Docs (require `DAMENG_DOCS_ROOT`)
60
- - `list_manuals()` — discover what manuals exist; each entry has `fileCount` and a short index summary (from `00-目录索引.md` or `README.md`).
61
- - `list_sections(manual)` — list `.md` chapters in one manual with their H1/H2 headings (with line numbers).
62
- - `read_section(file, heading?, maxBytes?)` — read a chapter or a single heading-bounded section. Use this to pull full context after a `lookup_docs` hit.
63
- - `lookup_docs(query, manual?, regex?, maxMatches?)` — keyword/regex search. Results are **grouped by section** (file + nearest heading), each match has line ± 1 line of context, sections sorted by match count descending.
64
-
65
- **Recommended workflow** for the LLM client:
66
- 1. `list_manuals()` → know what's available
67
- 2. `lookup_docs("keyword", manual: "DM8-...")` → find candidate sections
68
- 3. `read_section(file, heading)` → pull the full passage
69
- 4. Synthesize the answer for the user
70
-
71
- ### Safety
72
- - `list_tables` / `describe_table` build their SQL internally and only accept identifier-shaped input (`[A-Za-z_][A-Za-z0-9_]*`).
73
- - All docs tools only read `.md` files under `DAMENG_DOCS_ROOT`. `manual` and `file` parameters reject `..`, leading `.`, leading `/`, and other unsafe segments — no path traversal. `node_modules` directories are never walked.
74
-
75
- ## Register with Claude Code
27
+ 完成后会得到 22 本手册、~250 个章节、~9 MB 的 markdown 目录,下面像这样:
28
+
29
+ ```
30
+ ~/.dameng-docs/
31
+ ├── README.md
32
+ ├── DM8-系统管理员手册/
33
+ │ ├── system-administrator.md
34
+ │ ├── physical-storage-structure.md
35
+ │ └── ...
36
+ ├── DM8-SQL 语言使用手册/
37
+ ├── DM8-安全管理/
38
+ └── ...
39
+ ```
40
+
41
+ 抓取过程默认 5 并发、约 2-3 秒结束。需要联通 `eco.dameng.com`——内网/隔离环境跑不了,请走路径 A 或者在能联网的机器上抓完后再 rsync 进内网。
42
+
43
+ > **关于版权**:抓取下来的内容版权属于**达梦数据库股份有限公司**,仅供个人/团队内部参考使用,**不要公开发布**。
44
+
45
+ ---
46
+
47
+ ## 接入 Claude Code
76
48
 
77
49
  ```bash
78
- claude mcp add dameng-prod \
79
- -e DAMENG_HOST=<your-dameng-host> \
50
+ claude mcp add dameng \
51
+ --scope user \
52
+ -e DAMENG_DOCS_ROOT="$HOME/.dameng-docs" \
53
+ -e DAMENG_DOCS_INCLUDE='DM8-*' \
54
+ -e DAMENG_HOST=<达梦主机> \
80
55
  -e DAMENG_PORT=5236 \
81
56
  -e DAMENG_USER=MCP_RO \
82
- -e DAMENG_PASSWORD=<password> \
83
- -e DAMENG_SCHEMA=<your-schema> \
84
- -e DAMENG_DOCS_ROOT=/path/to/dameng-docs \
85
- -e DAMENG_DOCS_INCLUDE='DM8-*' \
57
+ -e DAMENG_PASSWORD=<密码> \
86
58
  -- npx -y basedoc-dameng-mcp
87
59
  ```
88
60
 
89
- Or, if you cloned the repo and want to run from source:
61
+ 不需要数据库工具的话,所有 `DAMENG_HOST` / `PORT` / `USER` / `PASSWORD` 都可以省略——只剩文档检索能力(**仅文档模式**)。
90
62
 
91
- ```bash
92
- -- node /path/to/basedoc-dameng-mcp/dist/server.js
63
+ ---
64
+
65
+ ## 启动模式
66
+
67
+ 按环境变量自动判定:
68
+
69
+ | 给的环境变量 | 启动什么 |
70
+ | --- | --- |
71
+ | 完整 DB 凭据 + `DAMENG_DOCS_ROOT` | 全部 8 个工具 |
72
+ | 只有 DB 凭据 | 只 4 个 DB 工具 |
73
+ | 只有 `DAMENG_DOCS_ROOT` | 只 4 个文档工具——适合"只让 LLM 看手册、不暴露数据库" |
74
+ | 都没有 | exit 2 |
75
+
76
+ ---
77
+
78
+ ## 工具
79
+
80
+ ### 数据库(需要 DB 凭据)
81
+
82
+ | 工具 | 说明 |
83
+ | --- | --- |
84
+ | `query(sql)` | 执行单条只读 SQL |
85
+ | `list_tables(schema?)` | 列某 schema 下的表 |
86
+ | `describe_table(table, schema?)` | 列字段名 / 类型 / 是否可空 / 默认值 |
87
+ | `instance_status()` | `V$INSTANCE` + `V$DATABASE` 当前快照 |
88
+
89
+ ### 文档(需要 `DAMENG_DOCS_ROOT`)
90
+
91
+ | 工具 | 说明 |
92
+ | --- | --- |
93
+ | `list_manuals()` | 根目录下都有哪些手册(用 `00-目录索引.md` / `README.md` 当摘要) |
94
+ | `list_sections(manual)` | 某本手册里有哪些 .md 章节,每个带 H1 / H2 标题 + 行号 |
95
+ | `read_section(file, heading?, maxBytes?)` | 读整个章节文件;带 heading 则只切出对应小节 |
96
+ | `lookup_docs(query, manual?, regex?, maxMatches?)` | 全文检索;按 (文件 + 最近 heading) 分组,每条带 ±1 行上下文,按命中数倒序 |
97
+
98
+ ### 给 LLM 客户端的推荐工作流
99
+
100
+ ```
101
+ list_manuals()
102
+
103
+ lookup_docs(query, manual="DM8-...")
104
+
105
+ read_section(file, heading="...")
106
+
107
+ (合成回答)
93
108
  ```
94
109
 
95
- Register one MCP server per Dameng instance. If the same box hosts multiple instances on different ports, use distinct names like `dameng-prod-a` / `dameng-prod-b`.
110
+ `list_tables` `describe_table` 内部生成 SQL,对入参做严格的标识符正则校验(`[A-Za-z_][A-Za-z0-9_]*`),不会拼接出注入。
96
111
 
97
- ## Tests
112
+ ---
98
113
 
99
- ```bash
114
+ ## 取舍清单
115
+
116
+ 不该让 LLM 做的事,挡在工具调用之前:
117
+
118
+ - SQL 入参只放 `SELECT` / `WITH` / `EXPLAIN`,多语句 / 注释绕过 / `DROP` 之类的关键字一律拒绝
119
+ - `DAMENG_PASSWORD` 不写也不补——缺失就直接退出 (exit 2),不存在 SYSDBA 兜底
120
+ - stdout 留给 JSON-RPC,所有日志都走 stderr
121
+ - 每个查询带超时 + 行数硬上限
122
+ - 文档相关的工具不能跨出 `DAMENG_DOCS_ROOT` 边界——`..`、绝对路径、`node_modules` 全部拦截
123
+ - 关键依赖(`@modelcontextprotocol/sdk`、`dmdb`、`zod`、`turndown`)锁死精确版本
124
+
125
+ ---
126
+
127
+ ## 环境变量
128
+
129
+ | 变量 | 何时必填 | 默认 | 说明 |
130
+ | --- | --- | --- | --- |
131
+ | `DAMENG_HOST` | DB 模式 | — | 达梦服务器地址 |
132
+ | `DAMENG_PORT` | DB 模式 | — | 比如 `5236` |
133
+ | `DAMENG_USER` | DB 模式 | — | 推荐建低权账号 |
134
+ | `DAMENG_PASSWORD` | DB 模式 | — | 没有任何兜底 |
135
+ | `DAMENG_SCHEMA` | 否 | — | `list_tables` / `describe_table` 默认查的 schema |
136
+ | `DAMENG_QUERY_TIMEOUT_MS` | 否 | `10000` | 单次查询超时 |
137
+ | `DAMENG_MAX_ROWS` | 否 | `1000` | 单次返回行数硬上限 |
138
+ | `DAMENG_POOL_MIN` / `DAMENG_POOL_MAX` | 否 | `1` / `4` | 连接池上下限 |
139
+ | `DAMENG_DOCS_ROOT` | 文档模式 | — | 含 markdown 的目录的**绝对路径** |
140
+ | `DAMENG_DOCS_INCLUDE` | 否 | — | 顶层目录白名单,逗号分隔,支持 `*` 通配,例如 `DM8-*` |
141
+ | `DAMENG_DOCS_EXCLUDE` | 否 | — | 顶层目录黑名单。`node_modules` 永远硬排,无需手动加 |
142
+ | `DAMENG_NO_LEGACY_OPENSSL` | 否 | 不设 | 设 `1` 跳过下文那个自重启 |
143
+
144
+ ---
145
+
146
+ ## 准备一个低权数据库账号
147
+
148
+ 直接给 SYSDBA 跑也能用——SQL 守卫已经限死只读——但纵深防御原则下建议:
149
+
150
+ ```sql
151
+ CREATE USER MCP_RO IDENTIFIED BY "<强密码>";
152
+ GRANT SELECT ANY TABLE TO MCP_RO;
153
+ GRANT SELECT ON V$INSTANCE TO MCP_RO;
154
+ GRANT SELECT ON V$DATABASE TO MCP_RO;
155
+ ```
156
+
157
+ 注:达梦中 `CREATE USER` 后默认就有 session 权限,无需 `GRANT CONNECT`(这条会报语法错)。
158
+
159
+ ---
160
+
161
+ ## 二进制为什么会自重启
162
+
163
+ `dmdb` 驱动握手阶段使用了 OpenSSL 3 在 Node 17+ 默认禁用的算法。不带 `--openssl-legacy-provider` 启动 Node 时会报 `[6071] 消息加密失败` / `error:0308010C`。本包的 bin 入口检测到没带这个 flag 就自己 spawn 一次新进程加上,对调用者透明。代价是约 50ms 的额外启动。如果你的 dmdb 版本不需要,设 `DAMENG_NO_LEGACY_OPENSSL=1` 跳过。
164
+
165
+ ---
166
+
167
+ ## 测试
168
+
169
+ ```
100
170
  npm test
101
171
  ```
102
172
 
103
- Tests cover the SQL guard (rejection rules, comment stripping, multi-statement detection), the config loader (required vars, no password fallback, type validation, docs-root + include/exclude validation), the timeout helper, and the docs layer (`searchDocs` grouping/ranking/context, `listManuals`, `listSections`, `readSection` heading extraction + path-traversal safety). The dmdb integration is not unit-tested; verify it by pointing at a real instance.
173
+ 117 个用例,覆盖:
174
+
175
+ - SQL 守卫的关键字白名单 / 注释剥离 / 多语句检测
176
+ - 配置加载,包括无 SYSDBA 兜底的明确断言、include/exclude 解析
177
+ - 超时 helper
178
+ - 4 个文档函数:搜索分组与排名、目录列出、章节按 heading 切片读取、路径越权防护
179
+ - HTML→MD 抓取链路:sidebar 解析、article 抽取、turndown 包装
180
+
181
+ dmdb 与 MCP 协议握手部分没有单元测试,需要指向真实达梦实例验证。
182
+
183
+ ---
184
+
185
+ ## 故意不做的能力
186
+
187
+ - 不暴露 DML / DDL / 系统过程调用——写入操作请直接走 dmctl 或 JDBC
188
+ - 不开 HTTP transport——只 stdio,没有可被外部访问的网络面
189
+ - 启动时不做 schema 自检——按需查系统视图,避免不必要的握手成本
190
+
191
+ ---
192
+
193
+ ## 已知传递依赖告警
104
194
 
105
- ## What is NOT here, by design
195
+ `npm audit` 会标记 `@modelcontextprotocol/sdk` HTTP transport 链(`express-rate-limit` → `ip-address`)以及开发环境 Vitest / Vite 链上的几个中等漏洞。本服务只跑 stdio transport,HTTP 那条链不会被加载;Vitest 是开发依赖不进入运行时。等上游升级后会自动消失,不会用 `npm audit fix --force` 强行覆盖。
106
196
 
107
- - No `execute_sql` / no DML / no DDL. If you need writes, write them directly with `dmctl`/JDBC, not through an LLM.
108
- - No HTTP transport. stdio only — no inbound network surface.
109
- - No automatic schema introspection on startup. Tools query system views on demand.
197
+ ---
110
198
 
111
- ## Known transitive vulnerabilities
199
+ ## 许可证
112
200
 
113
- `npm audit` flags issues in `@modelcontextprotocol/sdk`'s HTTP transport chain (`express-rate-limit` → `ip-address`) and in the dev-only Vitest/Vite chain. The stdio server we ship doesn't load the HTTP transport, and Vitest isn't part of the runtime. These will clear when upstream bumps; we don't paper over them with `npm audit fix --force`.
201
+ MIT。详见 [LICENSE](./LICENSE)
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env node
2
+ import { resolve } from "node:path";
3
+ import { fetchAndConvertAll } from "./fetch-docs.js";
4
+ const DEFAULT_SOURCE = "https://eco.dameng.com/document/dm/zh-cn/pm/";
5
+ function usage() {
6
+ process.stderr.write([
7
+ "用法: basedoc-dameng-fetch-docs <目标目录> [--source <URL>] [--concurrency <N>]",
8
+ "",
9
+ " 从达梦官方在线文档抓取所有手册并转换为 Markdown,写入指定目录。",
10
+ " 目标目录可以直接当作 DAMENG_DOCS_ROOT 给 basedoc-dameng-mcp 使用。",
11
+ "",
12
+ "选项:",
13
+ " --source <URL> 达梦文档站点的索引页 URL",
14
+ ` 默认: ${DEFAULT_SOURCE}`,
15
+ " --concurrency <N> 并发下载数 (默认 5)",
16
+ " -h, --help 显示帮助",
17
+ "",
18
+ "示例:",
19
+ " basedoc-dameng-fetch-docs ~/.dameng-docs",
20
+ " npx -y basedoc-dameng-mcp/dist/bin-fetch.js ~/.dameng-docs",
21
+ "",
22
+ "注意: 抓取到的内容版权属于达梦数据库股份有限公司。仅供个人或团队",
23
+ " 内部使用,不要公开再发布。",
24
+ "",
25
+ ].join("\n"));
26
+ process.exit(2);
27
+ }
28
+ function parseArgs(argv) {
29
+ let target;
30
+ let source = DEFAULT_SOURCE;
31
+ let concurrency = 5;
32
+ for (let i = 0; i < argv.length; i++) {
33
+ const a = argv[i];
34
+ if (a === "-h" || a === "--help")
35
+ usage();
36
+ else if (a === "--source")
37
+ source = argv[++i] ?? usage();
38
+ else if (a === "--concurrency")
39
+ concurrency = parseInt(argv[++i] ?? "", 10) || usage();
40
+ else if (a.startsWith("-")) {
41
+ process.stderr.write(`未知选项: ${a}\n`);
42
+ usage();
43
+ }
44
+ else if (!target)
45
+ target = a;
46
+ else {
47
+ process.stderr.write(`只支持一个目标目录参数,已经是 ${target}\n`);
48
+ usage();
49
+ }
50
+ }
51
+ if (!target)
52
+ usage();
53
+ if (concurrency < 1 || concurrency > 20) {
54
+ process.stderr.write(`concurrency 取值必须在 1–20 之间,得到 ${concurrency}\n`);
55
+ process.exit(2);
56
+ }
57
+ return { target: resolve(target), source, concurrency };
58
+ }
59
+ async function main() {
60
+ const args = parseArgs(process.argv.slice(2));
61
+ process.stderr.write(`目标目录: ${args.target}\n`);
62
+ process.stderr.write(`源站点: ${args.source}\n`);
63
+ process.stderr.write(`并发: ${args.concurrency}\n\n`);
64
+ const t0 = Date.now();
65
+ const result = await fetchAndConvertAll({
66
+ source: args.source,
67
+ targetDir: args.target,
68
+ concurrency: args.concurrency,
69
+ onProgress: (m) => process.stderr.write(m + "\n"),
70
+ });
71
+ const elapsed = ((Date.now() - t0) / 1000).toFixed(1);
72
+ process.stderr.write(`\n完成: ${result.manualCount} 本手册, ${result.chapterCount} 个章节, ${elapsed}s\n`);
73
+ if (result.failures.length > 0) {
74
+ process.stderr.write(`\n失败 ${result.failures.length} 个章节:\n`);
75
+ for (const f of result.failures) {
76
+ process.stderr.write(` ${f.url}: ${f.error}\n`);
77
+ }
78
+ process.stderr.write(`\n可以重新运行同一条命令来重试 (已成功的章节会被覆盖)。\n`);
79
+ process.exit(1);
80
+ }
81
+ process.stderr.write(`\n下一步: 把 ${args.target} 当 DAMENG_DOCS_ROOT 用,例如:\n` +
82
+ ` claude mcp add dameng \\\n` +
83
+ ` --scope user \\\n` +
84
+ ` -e DAMENG_DOCS_ROOT="${args.target}" \\\n` +
85
+ ` -e DAMENG_DOCS_INCLUDE='DM8-*' \\\n` +
86
+ ` -- npx -y basedoc-dameng-mcp\n`);
87
+ }
88
+ main().catch((e) => {
89
+ process.stderr.write(`[fetch-docs] 错误: ${e instanceof Error ? e.message : String(e)}\n`);
90
+ process.exit(1);
91
+ });
92
+ //# sourceMappingURL=bin-fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin-fetch.js","sourceRoot":"","sources":["../src/bin-fetch.ts"],"names":[],"mappings":"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"}
package/dist/config.js CHANGED
@@ -4,14 +4,23 @@ export class ConfigError extends Error {
4
4
  this.name = "ConfigError";
5
5
  }
6
6
  }
7
- const REQUIRED = ["DAMENG_HOST", "DAMENG_PORT", "DAMENG_USER", "DAMENG_PASSWORD"];
8
7
  export function loadConfig(env) {
9
- for (const key of REQUIRED) {
10
- if (!env[key] || env[key].length === 0) {
11
- throw new ConfigError(`Missing required env var: ${key}`);
8
+ // Parse docs config first (always optional, but useful independently)
9
+ let docsRoot;
10
+ if (env.DAMENG_DOCS_ROOT) {
11
+ if (!env.DAMENG_DOCS_ROOT.startsWith("/")) {
12
+ throw new ConfigError(`DAMENG_DOCS_ROOT must be an absolute path, got "${env.DAMENG_DOCS_ROOT}"`);
12
13
  }
14
+ docsRoot = env.DAMENG_DOCS_ROOT.replace(/\/+$/, "");
15
+ }
16
+ const docsInclude = parsePatternList(env.DAMENG_DOCS_INCLUDE);
17
+ const docsExclude = parsePatternList(env.DAMENG_DOCS_EXCLUDE);
18
+ // Check if DB credentials are provided
19
+ const DB_KEYS = ["DAMENG_HOST", "DAMENG_PORT", "DAMENG_USER", "DAMENG_PASSWORD"];
20
+ const hasDbConfig = DB_KEYS.every((k) => env[k] && env[k].length > 0);
21
+ if (!hasDbConfig && !docsRoot) {
22
+ throw new ConfigError("Either DB credentials (DAMENG_HOST/PORT/USER/PASSWORD) or DAMENG_DOCS_ROOT must be set.");
13
23
  }
14
- const port = parsePositiveInt(env.DAMENG_PORT, "DAMENG_PORT");
15
24
  const queryTimeoutMs = env.DAMENG_QUERY_TIMEOUT_MS
16
25
  ? parsePositiveInt(env.DAMENG_QUERY_TIMEOUT_MS, "DAMENG_QUERY_TIMEOUT_MS")
17
26
  : 10_000;
@@ -24,20 +33,11 @@ export function loadConfig(env) {
24
33
  const poolMax = env.DAMENG_POOL_MAX
25
34
  ? parsePositiveInt(env.DAMENG_POOL_MAX, "DAMENG_POOL_MAX")
26
35
  : 4;
27
- let docsRoot;
28
- if (env.DAMENG_DOCS_ROOT) {
29
- if (!env.DAMENG_DOCS_ROOT.startsWith("/")) {
30
- throw new ConfigError(`DAMENG_DOCS_ROOT must be an absolute path, got "${env.DAMENG_DOCS_ROOT}"`);
31
- }
32
- docsRoot = env.DAMENG_DOCS_ROOT.replace(/\/+$/, "");
33
- }
34
- const docsInclude = parsePatternList(env.DAMENG_DOCS_INCLUDE);
35
- const docsExclude = parsePatternList(env.DAMENG_DOCS_EXCLUDE);
36
36
  return {
37
- host: env.DAMENG_HOST,
38
- port,
39
- user: env.DAMENG_USER,
40
- password: env.DAMENG_PASSWORD,
37
+ host: env.DAMENG_HOST ?? "",
38
+ port: hasDbConfig ? parsePositiveInt(env.DAMENG_PORT, "DAMENG_PORT") : 0,
39
+ user: env.DAMENG_USER ?? "",
40
+ password: env.DAMENG_PASSWORD ?? "",
41
41
  schema: env.DAMENG_SCHEMA,
42
42
  queryTimeoutMs,
43
43
  maxRows,
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,175 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import TurndownService from "turndown";
4
+ const ICONFONT_RANGE = /[-]/g;
5
+ const HTML_ICONFONT_ENTITY = /&#x[eE][0-9a-fA-F]{3};/g;
6
+ export function normalizeManualName(raw) {
7
+ return raw
8
+ .replace(HTML_ICONFONT_ENTITY, "")
9
+ .replace(ICONFONT_RANGE, "")
10
+ .replace(/\s+/g, " ")
11
+ .trim()
12
+ .replace(/^DM8\s+/, "DM8-");
13
+ }
14
+ export function parseManualsFromSidebar(html) {
15
+ // Each manual is rendered as `<div class="left-sidebar-link-group top" ...>`
16
+ // The literal string `left-sidebar-link-group` also appears inside <script>
17
+ // blocks for the toggle animation; we anchor to the `top` modifier so we
18
+ // only match the actual HTML wrappers.
19
+ const blockRe = /<div\s+class="left-sidebar-link-group top"[^>]*>/g;
20
+ const positions = [];
21
+ let mm;
22
+ while ((mm = blockRe.exec(html)) !== null)
23
+ positions.push(mm.index);
24
+ const out = [];
25
+ for (let i = 0; i < positions.length; i++) {
26
+ const start = positions[i];
27
+ const end = i + 1 < positions.length ? positions[i + 1] : html.length;
28
+ let block = html.slice(start, end);
29
+ // Bound to the closing of this group's container — the `bar-border`
30
+ // separator that always follows a finished group.
31
+ const closeAt = block.search(/<div\s+class="bar-border"/);
32
+ if (closeAt > 0)
33
+ block = block.slice(0, closeAt);
34
+ // Manual name is the first font-weight:800 anchor in the block.
35
+ const titleMatch = block.match(/<a[^>]*font-weight:\s*800;?[^>]*>([\s\S]*?)<\/a>/);
36
+ if (!titleMatch)
37
+ continue;
38
+ const rawTitle = titleMatch[1].replace(/<[^>]+>/g, "");
39
+ const manual = normalizeManualName(rawTitle);
40
+ if (!manual.startsWith("DM8-"))
41
+ continue;
42
+ const chapters = [];
43
+ const chapterRe = /<a[^>]*href="([^"]+\.html)"[^>]*>([\s\S]*?)<\/a>/g;
44
+ let m;
45
+ while ((m = chapterRe.exec(block)) !== null) {
46
+ const href = m[1];
47
+ if (!href.endsWith(".html") || href.includes("/") || href.includes(":"))
48
+ continue;
49
+ const title = m[2].replace(/<[^>]+>/g, "").replace(ICONFONT_RANGE, "").trim();
50
+ if (!title)
51
+ continue;
52
+ chapters.push({ href, title });
53
+ }
54
+ if (chapters.length > 0)
55
+ out.push({ manual, chapters });
56
+ }
57
+ return out;
58
+ }
59
+ export function extractArticleHtml(html) {
60
+ // The eco.dameng.com pages wrap the actual chapter content in
61
+ // <div class="article-content vditor-reset" ...> ... </div>
62
+ // followed by a <footer class="article-footer"> we want to drop.
63
+ const m = html.match(/<div\s+class="article-content[^"]*"[^>]*>([\s\S]*?)<(?:footer|div|aside)[^>]*\sclass="article-footer/);
64
+ return m ? m[1].trim() : "";
65
+ }
66
+ let _turndown = null;
67
+ function turndown() {
68
+ if (_turndown)
69
+ return _turndown;
70
+ const t = new TurndownService({
71
+ headingStyle: "atx",
72
+ codeBlockStyle: "fenced",
73
+ bulletListMarker: "-",
74
+ emDelimiter: "*",
75
+ });
76
+ // Drop the inline anchor links Hexo adds after every heading.
77
+ t.addRule("strip-article-anchor", {
78
+ filter: (node) => node.nodeName === "A" &&
79
+ (node.getAttribute("class") || "").includes("article-anchor"),
80
+ replacement: () => "",
81
+ });
82
+ // Drop "copy code" buttons commonly added by docs sites.
83
+ t.addRule("strip-copy-button", {
84
+ filter: (node) => node.nodeName === "BUTTON" ||
85
+ (node.getAttribute("class") || "").includes("copy"),
86
+ replacement: () => "",
87
+ });
88
+ _turndown = t;
89
+ return t;
90
+ }
91
+ export function htmlToMarkdown(html) {
92
+ return turndown().turndown(html).trim() + "\n";
93
+ }
94
+ export async function fetchAndConvertAll(opts) {
95
+ const concurrency = opts.concurrency ?? 5;
96
+ const log = opts.onProgress ?? (() => { });
97
+ const baseUrl = opts.source.endsWith("/") ? opts.source : opts.source + "/";
98
+ log(`fetching index: ${baseUrl}`);
99
+ const indexHtml = await fetchText(baseUrl);
100
+ const manuals = parseManualsFromSidebar(indexHtml);
101
+ if (manuals.length === 0) {
102
+ throw new Error(`No manuals found in sidebar at ${baseUrl}. Did the site structure change?`);
103
+ }
104
+ log(`found ${manuals.length} manuals, ${manuals.reduce((n, m) => n + m.chapters.length, 0)} chapters total`);
105
+ await mkdir(opts.targetDir, { recursive: true });
106
+ await writeFile(join(opts.targetDir, "README.md"), `# Dameng manuals (auto-fetched)\n\nGenerated from ${baseUrl} at ${new Date().toISOString()}.\n\nCopyright belongs to 达梦数据库股份有限公司. Kept locally for personal/team reference.\n`, "utf8");
107
+ const tasks = [];
108
+ for (const group of manuals) {
109
+ const dir = join(opts.targetDir, group.manual);
110
+ await mkdir(dir, { recursive: true });
111
+ for (const ch of group.chapters) {
112
+ tasks.push({
113
+ manual: group.manual,
114
+ chapter: ch,
115
+ url: baseUrl + ch.href,
116
+ outPath: join(dir, ch.href.replace(/\.html$/, ".md")),
117
+ });
118
+ }
119
+ }
120
+ const failures = [];
121
+ let completed = 0;
122
+ const total = tasks.length;
123
+ async function worker(slice) {
124
+ for (const t of slice) {
125
+ try {
126
+ const html = await fetchText(t.url);
127
+ const article = extractArticleHtml(html);
128
+ if (!article)
129
+ throw new Error("no article body in HTML");
130
+ const md = `# ${t.chapter.title}\n\n` + htmlToMarkdown(article);
131
+ await writeFile(t.outPath, md, "utf8");
132
+ }
133
+ catch (e) {
134
+ failures.push({ url: t.url, error: e instanceof Error ? e.message : String(e) });
135
+ }
136
+ completed++;
137
+ if (completed % 10 === 0 || completed === total) {
138
+ log(` [${completed}/${total}] ${t.manual} :: ${t.chapter.title}`);
139
+ }
140
+ }
141
+ }
142
+ // Slice tasks evenly across workers.
143
+ const slices = Array.from({ length: concurrency }, () => []);
144
+ tasks.forEach((t, i) => slices[i % concurrency].push(t));
145
+ await Promise.all(slices.map((s) => worker(s)));
146
+ return {
147
+ manualCount: manuals.length,
148
+ chapterCount: tasks.length,
149
+ failures,
150
+ };
151
+ }
152
+ async function fetchText(url, retries = 2) {
153
+ let lastErr;
154
+ for (let attempt = 0; attempt <= retries; attempt++) {
155
+ try {
156
+ const res = await fetch(url, {
157
+ headers: {
158
+ "User-Agent": "basedoc-dameng-mcp/0.1.2 (+https://github.com/bravejack/basedoc-dameng-mcp)",
159
+ "Accept": "text/html",
160
+ },
161
+ });
162
+ if (!res.ok)
163
+ throw new Error(`HTTP ${res.status} for ${url}`);
164
+ return await res.text();
165
+ }
166
+ catch (e) {
167
+ lastErr = e;
168
+ if (attempt < retries) {
169
+ await new Promise((r) => setTimeout(r, 500 * (attempt + 1)));
170
+ }
171
+ }
172
+ }
173
+ throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));
174
+ }
175
+ //# sourceMappingURL=fetch-docs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-docs.js","sourceRoot":"","sources":["../src/fetch-docs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,eAAe,MAAM,UAAU,CAAC;AAYvC,MAAM,cAAc,GAAG,QAAQ,CAAC;AAEhC,MAAM,oBAAoB,GAAG,yBAAyB,CAAC;AAEvD,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC7C,OAAO,GAAG;SACP,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC;SACjC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC;SAC3B,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE;SACN,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,6EAA6E;IAC7E,4EAA4E;IAC5E,yEAAyE;IACzE,uCAAuC;IACvC,MAAM,OAAO,GAAG,mDAAmD,CAAC;IACpE,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,IAAI,EAA0B,CAAC;IAC/B,OAAO,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI;QAAE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IAEpE,MAAM,GAAG,GAAkB,EAAE,CAAC;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QACvE,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACnC,oEAAoE;QACpE,kDAAkD;QAClD,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC;QAC1D,IAAI,OAAO,GAAG,CAAC;YAAE,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QAEjD,gEAAgE;QAChE,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAC5B,kDAAkD,CACnD,CAAC;QACF,IAAI,CAAC,UAAU;YAAE,SAAS;QAC1B,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QACxD,MAAM,MAAM,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QAC7C,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC;YAAE,SAAS;QAEzC,MAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,MAAM,SAAS,GAAG,mDAAmD,CAAC;QACtE,IAAI,CAAyB,CAAC;QAC9B,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC5C,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;YACnB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,SAAS;YAClF,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAC/E,IAAI,CAAC,KAAK;gBAAE,SAAS;YACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACjC,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,8DAA8D;IAC9D,8DAA8D;IAC9D,iEAAiE;IACjE,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAClB,sGAAsG,CACvG,CAAC;IACF,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAC/B,CAAC;AAED,IAAI,SAAS,GAA2B,IAAI,CAAC;AAC7C,SAAS,QAAQ;IACf,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC;IAChC,MAAM,CAAC,GAAG,IAAI,eAAe,CAAC;QAC5B,YAAY,EAAE,KAAK;QACnB,cAAc,EAAE,QAAQ;QACxB,gBAAgB,EAAE,GAAG;QACrB,WAAW,EAAE,GAAG;KACjB,CAAC,CAAC;IACH,8DAA8D;IAC9D,CAAC,CAAC,OAAO,CAAC,sBAAsB,EAAE;QAChC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CACf,IAAI,CAAC,QAAQ,KAAK,GAAG;YACrB,CAAE,IAAoB,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAChF,WAAW,EAAE,GAAG,EAAE,CAAC,EAAE;KACtB,CAAC,CAAC;IACH,yDAAyD;IACzD,CAAC,CAAC,OAAO,CAAC,mBAAmB,EAAE;QAC7B,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CACf,IAAI,CAAC,QAAQ,KAAK,QAAQ;YAC1B,CAAE,IAAoB,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QACtE,WAAW,EAAE,GAAG,EAAE,CAAC,EAAE;KACtB,CAAC,CAAC;IACH,SAAS,GAAG,CAAC,CAAC;IACd,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,QAAQ,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC;AACjD,CAAC;AAeD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAAe;IACtD,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC;IAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC;IAE5E,GAAG,CAAC,mBAAmB,OAAO,EAAE,CAAC,CAAC;IAClC,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,uBAAuB,CAAC,SAAS,CAAC,CAAC;IACnD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,kCAAkC,OAAO,kCAAkC,CAAC,CAAC;IAC/F,CAAC;IACD,GAAG,CAAC,SAAS,OAAO,CAAC,MAAM,aAAa,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,iBAAiB,CAAC,CAAC;IAE7G,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,MAAM,SAAS,CACb,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,EACjC,qDAAqD,OAAO,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,oFAAoF,EAC/K,MAAM,CACP,CAAC;IAEF,MAAM,KAAK,GAAyE,EAAE,CAAC;IACvF,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC;gBACT,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,OAAO,EAAE,EAAE;gBACX,GAAG,EAAE,OAAO,GAAG,EAAE,CAAC,IAAI;gBACtB,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;aACtD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAA4B,EAAE,CAAC;IAC7C,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;IAE3B,KAAK,UAAU,MAAM,CAAC,KAAmB;QACvC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBACpC,MAAM,OAAO,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;gBACzC,IAAI,CAAC,OAAO;oBAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;gBACzD,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,MAAM,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;gBAChE,MAAM,SAAS,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;YACzC,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACnF,CAAC;YACD,SAAS,EAAE,CAAC;YACZ,IAAI,SAAS,GAAG,EAAE,KAAK,CAAC,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;gBAChD,GAAG,CAAC,MAAM,SAAS,IAAI,KAAK,KAAK,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;IACH,CAAC;IAED,qCAAqC;IACrC,MAAM,MAAM,GAAmB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IAC7E,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,WAAW,CAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1D,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEhD,OAAO;QACL,WAAW,EAAE,OAAO,CAAC,MAAM;QAC3B,YAAY,EAAE,KAAK,CAAC,MAAM;QAC1B,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,GAAW,EAAE,OAAO,GAAG,CAAC;IAC/C,IAAI,OAAgB,CAAC;IACrB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;QACpD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAC3B,OAAO,EAAE;oBACP,YAAY,EAAE,6EAA6E;oBAC3F,QAAQ,EAAE,WAAW;iBACtB;aACF,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,GAAG,CAAC,MAAM,QAAQ,GAAG,EAAE,CAAC,CAAC;YAC9D,OAAO,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC1B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,GAAG,CAAC,CAAC;YACZ,IAAI,OAAO,GAAG,OAAO,EAAE,CAAC;gBACtB,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,OAAO,YAAY,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;AACxE,CAAC"}
package/dist/server.js CHANGED
@@ -1,4 +1,20 @@
1
1
  #!/usr/bin/env node
2
+ // Self-relaunch with --openssl-legacy-provider so dmdb's login handshake works
3
+ // on Node >= 17 (OpenSSL 3 disabled the algos dmdb relies on by default).
4
+ // Set DAMENG_NO_LEGACY_OPENSSL=1 to skip this, or invoke node directly with
5
+ // the flag already set.
6
+ import { spawnSync } from "node:child_process";
7
+ import { fileURLToPath } from "node:url";
8
+ const haveLegacyFlag = process.execArgv.some((a) => a.includes("openssl-legacy-provider")) ||
9
+ (process.env.NODE_OPTIONS ?? "").includes("openssl-legacy-provider");
10
+ if (!haveLegacyFlag && !process.env.DAMENG_NO_LEGACY_OPENSSL) {
11
+ const r = spawnSync(process.execPath, [
12
+ "--openssl-legacy-provider",
13
+ fileURLToPath(import.meta.url),
14
+ ...process.argv.slice(2),
15
+ ], { stdio: "inherit" });
16
+ process.exit(r.status ?? 1);
17
+ }
2
18
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
19
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
20
  import { z } from "zod";
@@ -51,197 +67,207 @@ async function main() {
51
67
  }
52
68
  throw e;
53
69
  }
54
- const db = new Database(config);
55
- await db.connect();
70
+ const hasDb = config.host.length > 0 && config.port > 0;
71
+ const db = hasDb ? new Database(config) : null;
72
+ if (db) {
73
+ await db.connect();
74
+ }
75
+ else {
76
+ console.error("[dameng-mcp] no DB credentials — docs-only mode");
77
+ }
56
78
  const server = new McpServer({
57
79
  name: "dameng-mcp",
58
80
  version: "0.1.0",
59
81
  });
60
- server.registerTool("query", {
61
- description: "Execute a read-only SQL statement against Dameng. Only SELECT/WITH/EXPLAIN are accepted; multi-statement input is rejected. Results are capped by DAMENG_MAX_ROWS.",
62
- inputSchema: {
63
- sql: z.string().describe("Single SELECT, WITH, or EXPLAIN statement."),
64
- },
65
- annotations: { readOnlyHint: true, destructiveHint: false },
66
- }, async ({ sql }) => {
67
- try {
68
- const result = await db.runReadOnly(sql);
69
- return toolText(formatResult(result));
70
- }
71
- catch (e) {
72
- return toolError(formatToolError(e));
73
- }
74
- });
75
- server.registerTool("list_tables", {
76
- description: "List tables in a schema. Defaults to DAMENG_SCHEMA (or the connected user's schema if unset).",
77
- inputSchema: {
78
- schema: z
79
- .string()
80
- .optional()
81
- .describe("Schema/owner name. Identifier characters only."),
82
- },
83
- annotations: { readOnlyHint: true, destructiveHint: false },
84
- }, async ({ schema }) => {
85
- try {
86
- const owner = schema ?? config.schema;
87
- const sql = owner
88
- ? `SELECT OWNER, TABLE_NAME FROM ALL_TABLES WHERE OWNER = '${quoteIdent(owner).slice(1, -1)}' ORDER BY TABLE_NAME`
89
- : `SELECT TABLE_NAME FROM USER_TABLES ORDER BY TABLE_NAME`;
90
- const result = await db.runRaw(sql);
91
- return toolText(formatResult(result));
92
- }
93
- catch (e) {
94
- return toolError(formatToolError(e));
95
- }
96
- });
97
- server.registerTool("describe_table", {
98
- description: "Show columns and data types for a table.",
99
- inputSchema: {
100
- table: z.string().describe("Table name."),
101
- schema: z.string().optional().describe("Schema/owner name (optional)."),
102
- },
103
- annotations: { readOnlyHint: true, destructiveHint: false },
104
- }, async ({ table, schema }) => {
105
- try {
106
- const tableQ = quoteIdent(table).slice(1, -1);
107
- const owner = schema ?? config.schema;
108
- const sql = owner
109
- ? `SELECT COLUMN_NAME, DATA_TYPE, DATA_LENGTH, NULLABLE, DATA_DEFAULT
82
+ // --- DB tools (only when connected) ---
83
+ if (db) {
84
+ server.registerTool("query", {
85
+ description: "Execute a read-only SQL statement against Dameng. Only SELECT/WITH/EXPLAIN are accepted; multi-statement input is rejected. Results are capped by DAMENG_MAX_ROWS.",
86
+ inputSchema: {
87
+ sql: z.string().describe("Single SELECT, WITH, or EXPLAIN statement."),
88
+ },
89
+ annotations: { readOnlyHint: true, destructiveHint: false },
90
+ }, async ({ sql }) => {
91
+ try {
92
+ const result = await db.runReadOnly(sql);
93
+ return toolText(formatResult(result));
94
+ }
95
+ catch (e) {
96
+ return toolError(formatToolError(e));
97
+ }
98
+ });
99
+ server.registerTool("list_tables", {
100
+ description: "List tables in a schema. Defaults to DAMENG_SCHEMA (or the connected user's schema if unset).",
101
+ inputSchema: {
102
+ schema: z
103
+ .string()
104
+ .optional()
105
+ .describe("Schema/owner name. Identifier characters only."),
106
+ },
107
+ annotations: { readOnlyHint: true, destructiveHint: false },
108
+ }, async ({ schema }) => {
109
+ try {
110
+ const owner = schema ?? config.schema;
111
+ const sql = owner
112
+ ? `SELECT OWNER, TABLE_NAME FROM ALL_TABLES WHERE OWNER = '${quoteIdent(owner).slice(1, -1)}' ORDER BY TABLE_NAME`
113
+ : `SELECT TABLE_NAME FROM USER_TABLES ORDER BY TABLE_NAME`;
114
+ const result = await db.runRaw(sql);
115
+ return toolText(formatResult(result));
116
+ }
117
+ catch (e) {
118
+ return toolError(formatToolError(e));
119
+ }
120
+ });
121
+ server.registerTool("describe_table", {
122
+ description: "Show columns and data types for a table.",
123
+ inputSchema: {
124
+ table: z.string().describe("Table name."),
125
+ schema: z.string().optional().describe("Schema/owner name (optional)."),
126
+ },
127
+ annotations: { readOnlyHint: true, destructiveHint: false },
128
+ }, async ({ table, schema }) => {
129
+ try {
130
+ const tableQ = quoteIdent(table).slice(1, -1);
131
+ const owner = schema ?? config.schema;
132
+ const sql = owner
133
+ ? `SELECT COLUMN_NAME, DATA_TYPE, DATA_LENGTH, NULLABLE, DATA_DEFAULT
110
134
  FROM ALL_TAB_COLUMNS
111
135
  WHERE OWNER = '${quoteIdent(owner).slice(1, -1)}' AND TABLE_NAME = '${tableQ}'
112
136
  ORDER BY COLUMN_ID`
113
- : `SELECT COLUMN_NAME, DATA_TYPE, DATA_LENGTH, NULLABLE, DATA_DEFAULT
137
+ : `SELECT COLUMN_NAME, DATA_TYPE, DATA_LENGTH, NULLABLE, DATA_DEFAULT
114
138
  FROM USER_TAB_COLUMNS
115
139
  WHERE TABLE_NAME = '${tableQ}'
116
140
  ORDER BY COLUMN_ID`;
117
- const result = await db.runRaw(sql);
118
- return toolText(formatResult(result));
119
- }
120
- catch (e) {
121
- return toolError(formatToolError(e));
122
- }
123
- });
124
- server.registerTool("lookup_docs", {
125
- description: "Search the local Dameng knowledge base (Markdown manuals) for a phrase or pattern. Returns matches grouped by file with the nearest preceding heading. Requires DAMENG_DOCS_ROOT to be set.",
126
- inputSchema: {
127
- query: z.string().describe("Phrase to search for (literal, case-insensitive by default)."),
128
- manual: z
129
- .string()
130
- .optional()
131
- .describe("Optional top-level subdirectory under DAMENG_DOCS_ROOT to restrict the search (e.g. DM8-SQL语言使用手册)."),
132
- regex: z
133
- .boolean()
134
- .optional()
135
- .describe("Treat query as a JavaScript regex (case-insensitive). Default false."),
136
- maxMatches: z
137
- .number()
138
- .int()
139
- .positive()
140
- .optional()
141
- .describe("Cap on returned matches. Default 30."),
142
- },
143
- annotations: { readOnlyHint: true, destructiveHint: false },
144
- }, async ({ query, manual, regex, maxMatches }) => {
145
- if (!config.docsRoot)
146
- return docsRootMissingError();
147
- try {
148
- const sections = await searchDocs({
149
- root: config.docsRoot,
150
- query,
151
- manual,
152
- regex,
153
- maxMatches,
154
- include: config.docsInclude,
155
- exclude: config.docsExclude,
156
- });
157
- return toolText(formatSections(sections, maxMatches ?? 30));
158
- }
159
- catch (e) {
160
- return toolError(formatToolError(e));
161
- }
162
- });
163
- server.registerTool("list_manuals", {
164
- description: "List the Dameng manuals available under DAMENG_DOCS_ROOT, with file counts and a short index summary per manual. Use this to discover what to pass to list_sections / lookup_docs(manual=...).",
165
- inputSchema: {},
166
- annotations: { readOnlyHint: true, destructiveHint: false },
167
- }, async () => {
168
- if (!config.docsRoot)
169
- return docsRootMissingError();
170
- try {
171
- const manuals = await listManuals({
172
- root: config.docsRoot,
173
- include: config.docsInclude,
174
- exclude: config.docsExclude,
175
- });
176
- return toolText(formatManuals(manuals));
177
- }
178
- catch (e) {
179
- return toolError(formatToolError(e));
180
- }
181
- });
182
- server.registerTool("list_sections", {
183
- description: "List the .md files (chapters) inside one manual along with their H1/H2 headings. Use the (file, heading) pair to call read_section.",
184
- inputSchema: {
185
- manual: z.string().describe("Manual name (top-level dir under DAMENG_DOCS_ROOT)."),
186
- },
187
- annotations: { readOnlyHint: true, destructiveHint: false },
188
- }, async ({ manual }) => {
189
- if (!config.docsRoot)
190
- return docsRootMissingError();
191
- try {
192
- const files = await listSections({ root: config.docsRoot, manual });
193
- return toolText(formatSectionList(files));
194
- }
195
- catch (e) {
196
- return toolError(formatToolError(e));
197
- }
198
- });
199
- server.registerTool("read_section", {
200
- description: "Read a Markdown chapter under DAMENG_DOCS_ROOT. With heading omitted, returns the whole file. With heading set, returns text from that heading until the next same-or-higher heading. Use after lookup_docs / list_sections to pull full context.",
201
- inputSchema: {
202
- file: z
203
- .string()
204
- .describe("Relative path under DAMENG_DOCS_ROOT, e.g. DM8-数据守护与读写分离集群/data-watch-version-upgrade.md"),
205
- heading: z
206
- .string()
207
- .optional()
208
- .describe("Heading text (without # markers) to extract a single section."),
209
- maxBytes: z
210
- .number()
211
- .int()
212
- .positive()
213
- .optional()
214
- .describe("Cap on returned content size. Default 64000."),
215
- },
216
- annotations: { readOnlyHint: true, destructiveHint: false },
217
- }, async ({ file, heading, maxBytes }) => {
218
- if (!config.docsRoot)
219
- return docsRootMissingError();
220
- try {
221
- const r = await readSection({ root: config.docsRoot, file, heading, maxBytes });
222
- const header = r.heading
223
- ? `# ${r.file} — ${r.heading}${r.truncated ? " (truncated)" : ""}\n\n`
224
- : `# ${r.file}${r.truncated ? " (truncated)" : ""}\n\n`;
225
- return toolText(header + r.content);
226
- }
227
- catch (e) {
228
- return toolError(formatToolError(e));
229
- }
230
- });
231
- server.registerTool("instance_status", {
232
- description: "Report Dameng instance and database status from V$INSTANCE / V$DATABASE.",
233
- inputSchema: {},
234
- annotations: { readOnlyHint: true, destructiveHint: false },
235
- }, async () => {
236
- try {
237
- const inst = await db.runRaw(`SELECT NAME, INSTANCE_NAME, HOST_NAME, SVR_VERSION, STATUS$, MODE$, START_TIME FROM V$INSTANCE`);
238
- const dbi = await db.runRaw(`SELECT NAME, STATUS$, ARCH_MODE, DSC_ROLE FROM V$DATABASE`);
239
- return toolText(`# V$INSTANCE\n${formatResult(inst)}\n\n# V$DATABASE\n${formatResult(dbi)}`);
240
- }
241
- catch (e) {
242
- return toolError(formatToolError(e));
243
- }
244
- });
141
+ const result = await db.runRaw(sql);
142
+ return toolText(formatResult(result));
143
+ }
144
+ catch (e) {
145
+ return toolError(formatToolError(e));
146
+ }
147
+ });
148
+ server.registerTool("lookup_docs", {
149
+ description: "Search the local Dameng knowledge base (Markdown manuals) for a phrase or pattern. Returns matches grouped by file with the nearest preceding heading. Requires DAMENG_DOCS_ROOT to be set.",
150
+ inputSchema: {
151
+ query: z.string().describe("Phrase to search for (literal, case-insensitive by default)."),
152
+ manual: z
153
+ .string()
154
+ .optional()
155
+ .describe("Optional top-level subdirectory under DAMENG_DOCS_ROOT to restrict the search (e.g. DM8-SQL语言使用手册)."),
156
+ regex: z
157
+ .boolean()
158
+ .optional()
159
+ .describe("Treat query as a JavaScript regex (case-insensitive). Default false."),
160
+ maxMatches: z
161
+ .number()
162
+ .int()
163
+ .positive()
164
+ .optional()
165
+ .describe("Cap on returned matches. Default 30."),
166
+ },
167
+ annotations: { readOnlyHint: true, destructiveHint: false },
168
+ }, async ({ query, manual, regex, maxMatches }) => {
169
+ if (!config.docsRoot)
170
+ return docsRootMissingError();
171
+ try {
172
+ const sections = await searchDocs({
173
+ root: config.docsRoot,
174
+ query,
175
+ manual,
176
+ regex,
177
+ maxMatches,
178
+ include: config.docsInclude,
179
+ exclude: config.docsExclude,
180
+ });
181
+ return toolText(formatSections(sections, maxMatches ?? 30));
182
+ }
183
+ catch (e) {
184
+ return toolError(formatToolError(e));
185
+ }
186
+ });
187
+ server.registerTool("list_manuals", {
188
+ description: "List the Dameng manuals available under DAMENG_DOCS_ROOT, with file counts and a short index summary per manual. Use this to discover what to pass to list_sections / lookup_docs(manual=...).",
189
+ inputSchema: {},
190
+ annotations: { readOnlyHint: true, destructiveHint: false },
191
+ }, async () => {
192
+ if (!config.docsRoot)
193
+ return docsRootMissingError();
194
+ try {
195
+ const manuals = await listManuals({
196
+ root: config.docsRoot,
197
+ include: config.docsInclude,
198
+ exclude: config.docsExclude,
199
+ });
200
+ return toolText(formatManuals(manuals));
201
+ }
202
+ catch (e) {
203
+ return toolError(formatToolError(e));
204
+ }
205
+ });
206
+ server.registerTool("list_sections", {
207
+ description: "List the .md files (chapters) inside one manual along with their H1/H2 headings. Use the (file, heading) pair to call read_section.",
208
+ inputSchema: {
209
+ manual: z.string().describe("Manual name (top-level dir under DAMENG_DOCS_ROOT)."),
210
+ },
211
+ annotations: { readOnlyHint: true, destructiveHint: false },
212
+ }, async ({ manual }) => {
213
+ if (!config.docsRoot)
214
+ return docsRootMissingError();
215
+ try {
216
+ const files = await listSections({ root: config.docsRoot, manual });
217
+ return toolText(formatSectionList(files));
218
+ }
219
+ catch (e) {
220
+ return toolError(formatToolError(e));
221
+ }
222
+ });
223
+ server.registerTool("read_section", {
224
+ description: "Read a Markdown chapter under DAMENG_DOCS_ROOT. With heading omitted, returns the whole file. With heading set, returns text from that heading until the next same-or-higher heading. Use after lookup_docs / list_sections to pull full context.",
225
+ inputSchema: {
226
+ file: z
227
+ .string()
228
+ .describe("Relative path under DAMENG_DOCS_ROOT, e.g. DM8-数据守护与读写分离集群/data-watch-version-upgrade.md"),
229
+ heading: z
230
+ .string()
231
+ .optional()
232
+ .describe("Heading text (without # markers) to extract a single section."),
233
+ maxBytes: z
234
+ .number()
235
+ .int()
236
+ .positive()
237
+ .optional()
238
+ .describe("Cap on returned content size. Default 64000."),
239
+ },
240
+ annotations: { readOnlyHint: true, destructiveHint: false },
241
+ }, async ({ file, heading, maxBytes }) => {
242
+ if (!config.docsRoot)
243
+ return docsRootMissingError();
244
+ try {
245
+ const r = await readSection({ root: config.docsRoot, file, heading, maxBytes });
246
+ const header = r.heading
247
+ ? `# ${r.file} — ${r.heading}${r.truncated ? " (truncated)" : ""}\n\n`
248
+ : `# ${r.file}${r.truncated ? " (truncated)" : ""}\n\n`;
249
+ return toolText(header + r.content);
250
+ }
251
+ catch (e) {
252
+ return toolError(formatToolError(e));
253
+ }
254
+ });
255
+ server.registerTool("instance_status", {
256
+ description: "Report Dameng instance and database status from V$INSTANCE / V$DATABASE.",
257
+ inputSchema: {},
258
+ annotations: { readOnlyHint: true, destructiveHint: false },
259
+ }, async () => {
260
+ try {
261
+ const inst = await db.runRaw(`SELECT NAME, INSTANCE_NAME, HOST_NAME, SVR_VERSION, STATUS$, MODE$, START_TIME FROM V$INSTANCE`);
262
+ const dbi = await db.runRaw(`SELECT NAME, STATUS$, ARCH_MODE, DSC_ROLE FROM V$DATABASE`);
263
+ return toolText(`# V$INSTANCE\n${formatResult(inst)}\n\n# V$DATABASE\n${formatResult(dbi)}`);
264
+ }
265
+ catch (e) {
266
+ return toolError(formatToolError(e));
267
+ }
268
+ });
269
+ } // end if (db) block for DB tools
270
+ // --- Docs tools (always available when DOCS_ROOT is set) ---
245
271
  const shutdown = async (signal) => {
246
272
  console.error(`[dameng-mcp] received ${signal}, shutting down`);
247
273
  try {
@@ -249,7 +275,8 @@ async function main() {
249
275
  }
250
276
  catch { }
251
277
  try {
252
- await db.close();
278
+ if (db)
279
+ await db.close();
253
280
  }
254
281
  catch { }
255
282
  process.exit(0);
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "basedoc-dameng-mcp",
3
- "version": "0.1.0",
4
- "description": "Read-only MCP server for Dameng (DM8): SQL whitelist + local Markdown manual search (list_manuals / list_sections / read_section / lookup_docs).",
3
+ "version": "0.1.2",
4
+ "description": "面向达梦数据库 (DM8) 的只读 MCP 服务:受限 SQL 查询 + 本地 Markdown 手册离线全文检索(list_manuals / list_sections / read_section / lookup_docs)。",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": "bravejack",
@@ -24,7 +24,8 @@
24
24
  "documentation"
25
25
  ],
26
26
  "bin": {
27
- "basedoc-dameng-mcp": "dist/server.js"
27
+ "basedoc-dameng-mcp": "dist/server.js",
28
+ "basedoc-dameng-fetch-docs": "dist/bin-fetch.js"
28
29
  },
29
30
  "main": "dist/server.js",
30
31
  "files": [
@@ -33,7 +34,7 @@
33
34
  "LICENSE"
34
35
  ],
35
36
  "scripts": {
36
- "build": "tsc -p tsconfig.json && chmod +x dist/server.js",
37
+ "build": "tsc -p tsconfig.json && chmod +x dist/server.js dist/bin-fetch.js",
37
38
  "test": "vitest run",
38
39
  "test:watch": "vitest",
39
40
  "start": "node dist/server.js",
@@ -42,10 +43,12 @@
42
43
  "dependencies": {
43
44
  "@modelcontextprotocol/sdk": "1.29.0",
44
45
  "dmdb": "1.0.48286",
46
+ "turndown": "7.2.4",
45
47
  "zod": "4.4.3"
46
48
  },
47
49
  "devDependencies": {
48
50
  "@types/node": "22.10.2",
51
+ "@types/turndown": "5.0.6",
49
52
  "typescript": "5.7.2",
50
53
  "vitest": "2.1.8"
51
54
  },