harmonyos-guides-mcp 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 +25 -0
- package/dist/data.js +30 -1
- package/dist/search.js +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -37,6 +37,31 @@
|
|
|
37
37
|
|------|------|------|
|
|
38
38
|
| `BP_DOCS_DIR` | 包内 `data/docs` | 文档目录(一般无需改) |
|
|
39
39
|
|
|
40
|
+
## 更新
|
|
41
|
+
|
|
42
|
+
指南文档和服务器会持续更新(版本号见 `package.json`)。
|
|
43
|
+
|
|
44
|
+
**更新服务器**:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# npx -y 方式:无需手动操作,每次启动自动拉最新版
|
|
48
|
+
# 全局安装方式:手动更新
|
|
49
|
+
npm update -g harmonyos-guides-mcp
|
|
50
|
+
# 或锁定最新版
|
|
51
|
+
npm install -g harmonyos-guides-mcp@latest
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
更新后**重启 AI 客户端**(Claude Code / opencode / Cursor 等),让新进程加载新版 MCP。
|
|
55
|
+
|
|
56
|
+
**更新文档**:5489 篇指南随包内置(`data/docs/`),更新 npm 包即同步更新,无需单独操作。guides 为纯文档,无代码包。
|
|
57
|
+
|
|
58
|
+
**查看版本**:
|
|
59
|
+
```bash
|
|
60
|
+
npm view harmonyos-guides-mcp version # 最新发布版
|
|
61
|
+
npm ls -g harmonyos-guides-mcp # 本地已装版本
|
|
62
|
+
```
|
|
63
|
+
或看客户端 MCP 面板里服务器的 `version` 字段。
|
|
64
|
+
|
|
40
65
|
## 与 best-practices 并列使用(opencode 示例)
|
|
41
66
|
|
|
42
67
|
```json
|
package/dist/data.js
CHANGED
|
@@ -32,7 +32,7 @@ function parseCrawlLog(docsDir) {
|
|
|
32
32
|
const segs = fullPath.split(SEP).map((s) => s.trim()).filter(Boolean);
|
|
33
33
|
const topic = segs[0] || "未分类";
|
|
34
34
|
const title = segs.length ? segs[segs.length - 1] : docId;
|
|
35
|
-
docs.set(docId, { docId, title, path: fullPath, topic });
|
|
35
|
+
docs.set(docId, { docId, title, path: fullPath, topic, headings: "" });
|
|
36
36
|
}
|
|
37
37
|
return docs;
|
|
38
38
|
}
|
|
@@ -53,9 +53,38 @@ export function getStore() {
|
|
|
53
53
|
arr.push(meta.docId);
|
|
54
54
|
topics.set(meta.topic, arr);
|
|
55
55
|
}
|
|
56
|
+
// Preload all markdown headings — section-level signal for search (covers full doc).
|
|
57
|
+
for (const meta of docs.values()) {
|
|
58
|
+
meta.headings = extractHeadings(docsDir, meta.docId);
|
|
59
|
+
}
|
|
56
60
|
_store = { docs, topics, docsDir };
|
|
57
61
|
return _store;
|
|
58
62
|
}
|
|
63
|
+
/** Extract all markdown heading texts from a doc, joined by space. Light & full-text. */
|
|
64
|
+
export function extractHeadings(docsDir, docId) {
|
|
65
|
+
const file = path.join(docsDir, `${docId}.md`);
|
|
66
|
+
let text;
|
|
67
|
+
try {
|
|
68
|
+
text = fs.readFileSync(file, "utf8");
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return "";
|
|
72
|
+
}
|
|
73
|
+
const heads = [];
|
|
74
|
+
for (const line of text.split(/\r?\n/)) {
|
|
75
|
+
const m = line.match(/^#{1,6}\s+(.+?)\s*#*\s*$/);
|
|
76
|
+
if (m) {
|
|
77
|
+
const clean = m[1]
|
|
78
|
+
.replace(/\*\*/g, "")
|
|
79
|
+
.replace(/`([^`]+)`/g, "$1")
|
|
80
|
+
.replace(/\[([^\]]+)\]\([^)]*\)/g, "$1")
|
|
81
|
+
.trim();
|
|
82
|
+
if (clean)
|
|
83
|
+
heads.push(clean);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return heads.join(" ");
|
|
87
|
+
}
|
|
59
88
|
/** Read a guide's full markdown body. Returns null if missing. */
|
|
60
89
|
export function readDoc(docsDir, docId) {
|
|
61
90
|
const file = path.join(docsDir, `${docId}.md`);
|
package/dist/search.js
CHANGED
|
@@ -56,6 +56,8 @@ export function search(store, query, limit = 8) {
|
|
|
56
56
|
let score = 0;
|
|
57
57
|
score += scoreAgainst(qTf, tokenize(meta.title), 5);
|
|
58
58
|
score += scoreAgainst(qTf, tokenize(meta.path), 3);
|
|
59
|
+
// All markdown headings — section-level signal, covers full doc (not just first 200 lines).
|
|
60
|
+
score += scoreAgainst(qTf, tokenize(meta.headings), 3);
|
|
59
61
|
score += scanBody(store.docsDir, meta.docId, qTf, 200);
|
|
60
62
|
if (score <= 0)
|
|
61
63
|
continue;
|
package/package.json
CHANGED