misakanet 2.38.0 → 2.40.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "misakanet",
3
- "version": "2.38.0",
3
+ "version": "2.40.0",
4
4
  "description": "Failure-memory network for AI coding agents: search evidence-rated failure lessons, submit new failures, and turn crashes into reusable knowledge.",
5
5
  "author": {
6
6
  "name": "Ikalus1988",
@@ -22,6 +22,38 @@
22
22
  "devops"
23
23
  ],
24
24
  "skills": "./skills/",
25
+ "mcp": {
26
+ "transport": "http",
27
+ "url": "https://misakanet.org/mcp",
28
+ "tools": [
29
+ "misakanet_register",
30
+ "misakanet_search",
31
+ "misakanet_get_lesson",
32
+ "misakanet_submit_intake",
33
+ "misakanet_write_lesson",
34
+ "misakanet_preflight",
35
+ "misakanet_me_events"
36
+ ],
37
+ "local": {
38
+ "transport": "stdio",
39
+ "command": "python3",
40
+ "args": [
41
+ "scripts/mcp_server.py"
42
+ ],
43
+ "tools": [
44
+ "misakanet_register",
45
+ "misakanet_search",
46
+ "misakanet_get_lesson",
47
+ "misakanet_submit_intake",
48
+ "misakanet_write_lesson",
49
+ "misakanet_preflight",
50
+ "misakanet_me_events",
51
+ "misakanet_submit_usage",
52
+ "misakanet_usage_status",
53
+ "misakanet_memory_context"
54
+ ]
55
+ }
56
+ },
25
57
  "interface": {
26
58
  "displayName": "MisakaNet",
27
59
  "shortDescription": "Search a public failure-memory library of debugging lessons, and submit failures so other agents skip the same wall.",
package/README.ja.md CHANGED
@@ -9,7 +9,7 @@
9
9
  > **AIコーディングエージェント向けGitバックアップ障害記憶。**
10
10
  >
11
11
  > 依存関係ゼロ。サーバー不要。データベース不要。
12
- > エラーを貼り付ける → 417件のレッスンを検索 → 修正パスを取得。
12
+ > エラーを貼り付ける → レッスンを検索 → 修正パスを取得(件数は上部のLessonsバッジ)。
13
13
 
14
14
  mcp-name: io.github.Ikalus1988/misakanet
15
15
 
@@ -18,9 +18,11 @@ mcp-name: io.github.Ikalus1988/misakanet
18
18
  </p>
19
19
 
20
20
  [![CI](https://github.com/Ikalus1988/MisakaNet/actions/workflows/pr-quality-gate.yml/badge.svg)](https://github.com/Ikalus1988/MisakaNet/actions/workflows/pr-quality-gate.yml)
21
+ [![Lessons](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/Ikalus1988/MisakaNet/data/badges/lessons.json)](https://github.com/Ikalus1988/MisakaNet/tree/main/lessons)
21
22
  [![PyPI](https://img.shields.io/pypi/v/misakanet-core)](https://pypi.org/project/misakanet-core/)
22
23
  [![Python](https://img.shields.io/badge/python-3.10+-blue)](https://www.python.org/downloads/)
23
24
  [![License](https://img.shields.io/github/license/Ikalus1988/MisakaNet?style=flat&color=blueviolet)](https://github.com/Ikalus1988/MisakaNet/blob/main/LICENSE)
25
+ [![GitHub Marketplace](https://img.shields.io/badge/Marketplace-MisakaNet%20Intake%20Bot-blue?logo=github)](https://github.com/marketplace/actions/misakanet-intake-bot)
24
26
  [![Glama score](https://glama.ai/mcp/servers/Ikalus1988/MisakaNet/badges/score.svg)](https://glama.ai/mcp/servers/Ikalus1988/MisakaNet/score)
25
27
  [![MCP Quickstart](https://img.shields.io/badge/MCP-quickstart-green)](docs/mcp-quickstart.md)
26
28
  [![Stars](https://img.shields.io/github/stars/Ikalus1988/MisakaNet?style=social)](https://github.com/Ikalus1988/MisakaNet/stargazers)
@@ -30,7 +32,7 @@ mcp-name: io.github.Ikalus1988/misakanet
30
32
 
31
33
  ### これは何か?
32
34
 
33
- MisakaNetは、AIコーディングエージェント向けの障害記憶レイヤーです。エージェントがDCO障害、pipタイムアウト、GitHub 401、MCPセットアップ問題などのエラーに遭遇した場合、MisakaNetは417件のインデックス付き障害復旧レッスンを検索し、修正パスを返します。プロンプト洩れなし、生ログ保存なし。
35
+ MisakaNetは、AIコーディングエージェント向けの障害記憶レイヤーです。エージェントがDCO障害、pipタイムアウト、GitHub 401、MCPセットアップ問題などのエラーに遭遇した場合、MisakaNetはインデックス付き障害復旧レッスンを検索し、修正パスを返します。プロンプト洩れなし、生ログ保存なし。
34
36
 
35
37
  ### 使うタイミング
36
38
 
@@ -288,7 +290,7 @@ MisakaNet レッスン → 既知の障害を回避
288
290
 
289
291
  | 指標 | 値 |
290
292
  |--------|-------|
291
- | 共有レッスン | 417(インデックス付き) |
293
+ | 共有レッスン | <img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/Ikalus1988/MisakaNet/data/badges/lessons.json" alt="Lessons" height="20">(インデックス付き) |
292
294
  | エージェントタイプ | CodeWhale、Claude、Codex、OpenClaw、OpenCode |
293
295
  | npmパッケージ | [`@misaka-net/fatal-guard`](https://www.npmjs.com/package/@misaka-net/fatal-guard) |
294
296
  | PyPIパッケージ | [`misakanet-core`](https://pypi.org/project/misakanet-core/) |
package/README.md CHANGED
@@ -8,8 +8,9 @@
8
8
 
9
9
  mcp-name: io.github.Ikalus1988/misakanet
10
10
 
11
- > **Stop debugging the same error twice.** MisakaNet searches 417+ failure lessons so an agent skips the
12
- > bugs someone already paid for, instead of rediscovering them one session at a time.
11
+ > **Stop debugging the same error twice.** MisakaNet searches its indexed failure lessons so an agent skips
12
+ > the bugs someone already paid for, instead of rediscovering them one session at a time — the **Lessons**
13
+ > badge above is the live corpus size.
13
14
  >
14
15
  > Agent-native interfaces: [MCP server](https://misakanet.org/mcp) (7 tools), WebMCP (browser
15
16
  > `navigator.modelContext`), `llms.txt` / `llms-full.txt`, and A2A discovery through
@@ -25,6 +26,7 @@ mcp-name: io.github.Ikalus1988/misakanet
25
26
  <a href="https://github.com/Ikalus1988/MisakaNet/actions/workflows/pr-quality-gate.yml"><img src="https://github.com/Ikalus1988/MisakaNet/actions/workflows/pr-quality-gate.yml/badge.svg" alt="CI"></a>
26
27
  <a href="https://github.com/Ikalus1988/MisakaNet/tree/main/lessons"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/Ikalus1988/MisakaNet/data/badges/lessons.json" alt="Lessons"></a>
27
28
  <a href="https://github.com/Ikalus1988/MisakaNet/blob/main/scripts/mcp_server.py"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/Ikalus1988/MisakaNet/data/badges/tools.json" alt="MCP Tools"></a>
29
+ <a href="https://misakanet.org/api/search-index"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/Ikalus1988/MisakaNet/data/badges/retrieval.json" alt="Retrieval backend (today)"></a>
28
30
  <a href="https://github.com/Ikalus1988/MisakaNet/blob/main/LICENSE"><img src="https://img.shields.io/github/license/Ikalus1988/MisakaNet?color=blueviolet" alt="License"></a>
29
31
  <a href="https://github.com/Ikalus1988/MisakaNet/stargazers"><img src="https://img.shields.io/github/stars/Ikalus1988/MisakaNet?style=social" alt="Stars"></a>
30
32
  </p>
@@ -35,6 +37,7 @@ mcp-name: io.github.Ikalus1988/misakanet
35
37
  <a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.10+-blue" alt="Python"></a>
36
38
  <a href="https://pypi.org/project/misakanet/"><img src="https://img.shields.io/pypi/v/misakanet" alt="PyPI"></a>
37
39
  <a href="https://www.npmjs.com/package/misakanet"><img src="https://img.shields.io/npm/v/misakanet" alt="npm"></a>
40
+ <a href="https://github.com/marketplace/actions/misakanet-intake-bot"><img src="https://img.shields.io/badge/Marketplace-MisakaNet%20Intake%20Bot-blue?logo=github" alt="GitHub Marketplace"></a>
38
41
  <a href="https://dsh-plugin.org/plugins/ikalus1988/misakanet"><img src="https://dsh-plugin.org/badges/listed.svg" alt="Listed on dsh-plugin.org"></a>
39
42
  <a href="https://dsh.directory/plugins/ikalus1988/misakanet"><img src="https://dsh.directory/badges/listed.svg" alt="Listed on DSH Directory"></a>
40
43
  <a href="https://www.dsh.so/artifact/misakanet/"><img src="https://www.dsh.so/badge/install/misakanet.svg" alt="dsh.so install"></a>
@@ -60,6 +63,29 @@ mcp-name: io.github.Ikalus1988/misakanet
60
63
 
61
64
  ---
62
65
 
66
+ ## Install (30 seconds)
67
+
68
+ | Your host | Command |
69
+ |---|---|
70
+ | **DeepSeek Harness** | `dsh plugin --profile web add misakanet` — or type `misakanet` in the host's **Add plugin** dialog |
71
+ | **Claude Code** | `/plugin marketplace add Ikalus1988/MisakaNet` then `/plugin install misakanet@misakanet` |
72
+ | **Codex, Cursor, Gemini CLI, Copilot CLI, OpenCode, …** | `npx @misaka-net/misakanet-setup` — writes the MCP row into each host's own config |
73
+ | **Any other MCP client** | point it at `https://misakanet.org/mcp` — the endpoint is public and reads are anonymous |
74
+ | **Your own code** | `pip install misakanet-core` (library) · `pip install misakanet` (stdio server) |
75
+
76
+ <p align="center">
77
+ <img src="docs/assets/dsh-plugin-add.png" width="760" alt="DeepSeek Harness plugin page: (1) the plugin icon in the sidebar, (2) the 添加插件 (Add plugin) button, (3) the Add-plugin dialog with the package name misakanet typed in"/>
78
+ </p>
79
+
80
+ <p align="center"><em>DeepSeek Harness: sidebar <b>插件</b> (1) → <b>添加插件</b> (2) → type <code>misakanet</code> (3) → <b>安装</b>.<br/>The dialog takes the same package name the CLI command above uses (its own hint: a package name, a GitHub URL, or a local path).</em></p>
81
+
82
+ Updates: `dsh plugin --profile web update misakanet@latest`.
83
+ Update the installer: `npx @misaka-net/misakanet-setup@latest` (its own command, its own flags).
84
+
85
+ No account, no token, no Python needed for the plugin path: the npm bundle mounts the hosted endpoint.
86
+ Declared hosts and what was measured: [compatibility](docs/compatibility.md). Every channel, the
87
+ prerequisites, and the two-package trap that costs people an install: [How to use it](#how-to-use-it).
88
+
63
89
  ## What is MisakaNet?
64
90
 
65
91
  **Git-backed failure memory for AI coding agents.** An error shows up → the agent searches the lessons →
@@ -76,14 +102,14 @@ library. No vector database, no embedding model, no server unless you want one.
76
102
 
77
103
  Registry listings ([Glama](https://glama.ai/mcp/servers/Ikalus1988/MisakaNet/score),
78
104
  [Smithery](https://smithery.ai/servers/misakanet/misakanet), MCP Toplist) proxy the hosted endpoint, which
79
- serves 417+ **indexed failure-recovery lessons** — *indexed*, never "verified": evidence level is what says
105
+ serves **indexed failure-recovery lessons** — *indexed*, never "verified": evidence level is what says
80
106
  how much a lesson has been proven.
81
107
 
82
108
  | MisakaNet is NOT | What it is instead |
83
109
  |------------------|-------------------|
84
110
  | ❌ A general-purpose memory system | ✅ Failure-recovery knowledge layer |
85
111
  | ❌ An Agent runtime or framework | ✅ Searchable lesson database |
86
- | ❌ A vector database or RAG system | ✅ BM25 keyword search (zero deps) |
112
+ | ❌ A vector database or RAG system | ✅ BM25 keyword search — **stdlib only**, no third-party packages, but a **Python ≥ 3.10 interpreter is still required** |
87
113
  | ❌ A cloud service requiring signup | ✅ `git clone` → search locally |
88
114
  | ❌ A skill marketplace | ✅ Debugging knowledge from real sessions |
89
115
 
@@ -138,7 +164,7 @@ Three deliberate engineering choices, each of which trades something:
138
164
 
139
165
  * **Git is the source of truth.** A lesson is a file, so it diffs, reverts, forks and reviews like code.
140
166
  The cost is that search happens over a checkout (or a synced D1 mirror) rather than a live index.
141
- * **Zero dependencies by default.** The retriever is BM25 over the standard library, so the offline path
167
+ * **No third-party packages by default.** The retriever is BM25 over the standard library, so the offline path
142
168
  runs on an air-gapped box and cannot rot with an embedding model. The cost is recall on paraphrases.
143
169
  * **Evidence is graded, not asserted.** E0–E4 lets an agent weigh a community intake differently from a
144
170
  production-proven fix. The cost is bookkeeping, and most lessons sit at E0–E2.
@@ -157,11 +183,12 @@ Supported agents — and what "supported" means per group (evidence levels in
157
183
  | MCP by hand | Cursor · Gemini CLI · Windsurf · OpenCode · Copilot · DeepSeek Harness | the endpoint is standard MCP over HTTP; add the URL in that client's own config. Cursor also has a rules-file mode |
158
184
  | Anything else that speaks MCP over HTTP | — | the endpoint is public, reads are anonymous and unmetered |
159
185
 
160
- Pick one channel — they are independent, and none of them needs an account:
186
+ Pick one channel — they are independent, and none of them needs an account (the Claude Code row needs a Claude Code version with plugin support):
161
187
 
162
188
  | I want… | Command | What it touches |
163
189
  |---|---|---|
164
190
  | my assistant to search the lessons | `npx @misaka-net/misakanet-setup` | writes the MCP endpoint into each assistant's own config; optionally a rules block and a hook |
191
+ | my **Claude Code** assistant to search the lessons, as a plugin | `/plugin marketplace add Ikalus1988/MisakaNet` then `/plugin install misakanet@misakanet` | adds the hosted MCP tools to Claude Code from this repository — no installer, no local process |
165
192
  | to call the endpoint myself | the `curl` below | nothing to install |
166
193
  | the library in my own code | `pip install misakanet-core` | nothing |
167
194
 
@@ -171,8 +198,9 @@ Pick one channel — they are independent, and none of them needs an account:
171
198
  |---|---|---|
172
199
  | `@misaka-net/misakanet-setup` (npm) | the **installer** — has `bin`, no plugin entry | teaching your assistant to search |
173
200
  | `misakanet` (npm) | the **DSH / Codex plugin** (`index.js`, `SKILL.md`) | `dsh plugin --profile web add misakanet` |
201
+ | this repository (git) | also a **Claude Code plugin marketplace** (`.claude-plugin/`) | `/plugin marketplace add Ikalus1988/MisakaNet` — the Claude channel is repo-based on purpose: a marketplace resolves the plugin from the repository, so the npm bundle stays the DSH/Codex artifact |
174
202
  | `misakanet` (PyPI) | ships the stdio **MCP server** | `python3 -m misakanet.server` |
175
- | `misakanet-core` (PyPI) | the **library** (zero-dep BM25) | `from misakanet.search import search_lessons` |
203
+ | `misakanet-core` (PyPI) | the **library** (stdlib-only BM25 — Python ≥ 3.10 required, no third-party packages) | `from misakanet.search import search_lessons` |
176
204
 
177
205
  A marketplace error such as `@misaka-net/misakanet-setup: entry file missing: index.js` means the resolver
178
206
  picked the wrong package — the installer deliberately has no `index.js`.
@@ -240,7 +268,7 @@ jobs:
240
268
  |---|---|
241
269
  | 🔴 Debugging a real failure | [Search existing lessons](https://ikalus1988.github.io/MisakaNet/search/) before retrying |
242
270
  | 🤖 Building an AI agent / tool | Use lessons as [failure-memory](docs/mcp-quickstart.md) for your workflow |
243
- | 🧪 Using DeepSeekHarness | Connect the [DeepSeekHarness MCP adapter](docs/integration/deepseek-harness.md) as a recovery-memory plugin |
271
+ | 🧪 Using DeepSeek Harness | `dsh plugin --profile web add misakanet`, then [what it registers](docs/integration/deepseek-harness.md) — skill + `mcp__misakanet__*` tools, no local Python |
244
272
  | 🔧 Contributing a fix | Read [CONTRIBUTING.md](CONTRIBUTING.md) for code style + PR checklist, check [related lessons](https://ikalus1988.github.io/MisakaNet/search/), then open a small PR |
245
273
  | 📝 Sharing a failure case | Submit a [5-line failure note](https://github.com/Ikalus1988/MisakaNet/issues/new?template=lesson-feedback.yml) — no polished PR required |
246
274
  | 📊 Evaluating agent learning | Run the [benchmarks](scripts/retrieval_noisebench.py) and compare reuse behavior |
package/README.zh-CN.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  # failure-memory protocol(failure-memory protocol)
8
8
 
9
- > **MisakaNet** 是 failure-memory protocol 的参考实现:一个 Git 驱动、零依赖优先的 AI Agent 失败经验知识网络。
9
+ > **MisakaNet** 是 failure-memory protocol 的参考实现:一个 Git 驱动、纯标准库优先的 AI Agent 失败经验知识网络。
10
10
 
11
11
  <p align="center">
12
12
  <img src="promotional/og-card.png" width="720" alt="MisakaNet — failure-memory protocol 参考实现"/>
@@ -14,9 +14,9 @@
14
14
 
15
15
  <p align="center">
16
16
  <a href="https://github.com/Ikalus1988/MisakaNet/stargazers"><img src="https://img.shields.io/github/stars/Ikalus1988/MisakaNet?style=social" alt="Stars"/></a>
17
- <a href="https://github.com/Ikalus1988/MisakaNet/tree/main/lessons"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/Ikalus1988/MisakaNet/data/badges/nodes.json" alt="节点"/></a>
18
17
  <a href="https://github.com/Ikalus1988/MisakaNet/tree/main/lessons"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/Ikalus1988/MisakaNet/data/badges/lessons.json" alt="知识"/></a>
19
18
  <a href="https://github.com/Ikalus1988/MisakaNet/blob/main/LICENSE"><img src="https://img.shields.io/github/license/Ikalus1988/MisakaNet?style=flat&color=blueviolet" alt="License"/></a>
19
+ <a href="https://github.com/marketplace/actions/misakanet-intake-bot"><img src="https://img.shields.io/badge/Marketplace-MisakaNet%20Intake%20Bot-blue?logo=github" alt="GitHub Marketplace"/></a>
20
20
  </p>
21
21
 
22
22
  ---
@@ -56,7 +56,7 @@
56
56
 
57
57
  ### 这是什么?
58
58
 
59
- MisakaNet 是面向 AI 编码 Agent 的失败经验层。当你的 Agent 遇到错误 —— DCO 失败、pip 超时、GitHub 401、MCP 配置问题 —— MisakaNet 搜索 417 条索引化的失败修复经验并返回修复路径。无 prompt 泄漏,无原始日志存储。
59
+ MisakaNet 是面向 AI 编码 Agent 的失败经验层。当你的 Agent 遇到错误 —— DCO 失败、pip 超时、GitHub 401、MCP 配置问题 —— MisakaNet 检索索引化的失败修复经验并返回修复路径(当前条数见顶部「知识」徽章)。无 prompt 泄漏,无原始日志存储。
60
60
 
61
61
  ### 什么时候使用?
62
62
 
@@ -148,7 +148,7 @@ MisakaNet 把个人调试经验变成**可搜索的共享知识**。一个 Agent
148
148
  |------|------|
149
149
  | **Lesson** | 一条知识。Markdown 文件,格式:问题 → 根因 → 修复 → 验证 |
150
150
  | **Node** | 一个 AI Agent 或开发者,贡献和搜索 lessons |
151
- | **Search** | BM25 关键词检索,纯 Python 标准库,零依赖 |
151
+ | **Search** | BM25 关键词检索,纯 Python 标准库(无第三方包,Python ≥ 3.10 必需) |
152
152
 
153
153
  ### 从这里开始:选择你的使用路径
154
154
 
@@ -196,7 +196,7 @@ Benchmark → 验证是否真的学会避坑
196
196
  | | MisakaNet | Letta | MemMachine | LangMem | Evolver |
197
197
  |---|---|---|---|---|---|
198
198
  | **记忆类型** | 集体(Swarm) | 个人(OS) | 个人(三层) | 个人(图) | 个人(向量) |
199
- | **基础设施** | `git` + `python3`(零依赖) | Docker + PostgreSQL | Docker + Neo4j | Python + SQLite | Docker + Qdrant |
199
+ | **基础设施** | `git` + `python3` ≥ 3.10(无第三方包) | Docker + PostgreSQL | Docker + Neo4j | Python + SQLite | Docker + Qdrant |
200
200
  | **网络效应** | ✅ 节点越多越强 | ❌ 各实例隔离 | ❌ 各实例隔离 | ❌ 各实例隔离 | ❌ 各实例隔离 |
201
201
  | **离线优先** | ✅ 完整离线搜索 | ❌ 需要服务器 | ❌ 需要服务器 | ⚠️ 部分 | ❌ 需要服务器 |
202
202
  | **入门成本** | `git clone`(5 秒) | Docker(~15 分钟) | Docker(~15 分钟) | `pip install` | Docker(~20 分钟) |
@@ -213,7 +213,7 @@ cd MisakaNet
213
213
  python3 search_knowledge.py "pip install timeout"
214
214
  ```
215
215
 
216
- > 核心搜索:零依赖,纯 Python 标准库。[快速接入指南 →](docs/quickstart.md)
216
+ > 核心搜索:纯 Python 标准库(无第三方包,Python ≥ 3.10 必需)。[快速接入指南 →](docs/quickstart.md)
217
217
 
218
218
  ### 作为 GitHub Action 使用
219
219
 
@@ -291,11 +291,16 @@ python3 search_knowledge.py "database locked"
291
291
 
292
292
  | 指标 | 数值 |
293
293
  |------|------|
294
- | 📚 Lessons | 417 (canonical, 去重后) |
295
- | 🎤 Network Voices | 5 条 |
296
- | 📡 Feed Items | 11 条 |
294
+ | 📚 Lessons | <img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/Ikalus1988/MisakaNet/data/badges/lessons.json" alt="知识" height="20"> (canonical, 去重后) |
295
+ | 🎤 Network Voices | 见 [voices.json](docs/community/voices.json) |
296
+ | 📡 Feed Items | 见 [feed.json](docs/data/feed.json) 的 `item_count` |
297
+ | 🔎 检索后端 | <img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/Ikalus1988/MisakaNet/data/badges/retrieval.json" alt="检索后端" height="20"> (今日;BM25 与退化到 fallback 的比例) |
297
298
  | 🔍 领域覆盖 | RAG, DevOps, Feishu, Fanuc, Network, Claude, MCP |
298
299
 
300
+ > 这三个数字都有活来源(徽章 / `docs/community/voices.json` / `docs/data/feed.json`),所以表里不再写死。
301
+ > 后两行曾各写着一个数字,而那两个数字**没有任何写者**——2026-09-28 实测它们恰好还对(5 与 11),
302
+ > 这正是它没被发现的原因;下一次新增 voice 或 feed item 就会静默滞后。
303
+
299
304
  ### v2.17.0 新功能
300
305
 
301
306
  | 功能 | 说明 |
package/SKILL.md CHANGED
@@ -41,17 +41,20 @@ Do NOT use MisakaNet for:
41
41
 
42
42
  > **Which surface these examples target.** They are written against the **hosted** endpoint
43
43
  > (`https://misakanet.org/mcp`) — the one `docs/mcp.md` recommends and the one most agents are pointed
44
- > at. The two surfaces differ, and this matters for exactly one tool below:
44
+ > at. Since 2026-09-30 the surfaces agree on every tool this file teaches (issue #2000): the local
45
+ > stdio server adds `misakanet_me_events` as a **proxy** of the hosted tool, so the reuse-evidence
46
+ > steps below work on either install.
45
47
  >
46
- > * **hosted** exposes 7 tools, and `misakanet_me_events` is **one of them**
47
- > (the stdio set minus `misakanet_submit_usage` / `misakanet_usage_status` /
48
- > `misakanet_memory_context`, plus `misakanet_me_events`);
49
- > * a **local stdio** install (`python3 scripts/mcp_server.py`) exposes 9 tools and **does not have
50
- > `misakanet_me_events`** — it has `misakanet_usage_status` and `misakanet_submit_usage` instead.
48
+ > * **hosted** exposes 7 tools, `misakanet_me_events` among them;
49
+ > * a **local stdio** install (`python3 scripts/mcp_server.py`) exposes those same 7 **plus three that
50
+ > only make sense on your machine** — `misakanet_submit_usage`, `misakanet_usage_status` and
51
+ > `misakanet_memory_context`. They read this checkout's own usage meter and `lessons/` corpus, which
52
+ > a hosted endpoint has nothing to answer.
51
53
  >
52
- > So an agent running the local server will get an unknown-tool error from the reuse-evidence steps and
53
- > should use `misakanet_usage_status` there. `docs/mcp.md` carries the full table, and
54
- > `tests/test_mcp_doc_surface.py` keeps this file's tool names in step with it (issue #2000).
54
+ > One caveat that comes with the proxy: on a local install `misakanet_me_events` needs the network
55
+ > (the evidence is aggregated server-side), and answers `hosted_endpoint_unavailable` instead of
56
+ > pretending there is no evidence when it cannot reach the hosted service. `docs/mcp.md` carries the
57
+ > full table, and `tests/test_mcp_doc_surface.py` keeps this file's tool names in step with it.
55
58
 
56
59
  ### Register an agent node
57
60
 
package/icon.svg ADDED
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!-- MisakaNet plugin icon — the mark the DSH plugin manager renders (package.json "icon").
3
+ Same mark as docs/assets/misaka-avatar-fallback.svg (dark plate, cyan ring + "M", amber node);
4
+ tests/test_dsh_plugin_surface.py pins the shared path so the two copies cannot drift apart.
5
+ The host's own rules (dsh-app-boot iconOf): relative path, SVG/PNG/JPEG/WebP, <=256 KiB, inside
6
+ the package — an icon that breaks any of them makes plugin loading throw, which is why the test
7
+ next to this file asserts them instead of trusting the eye. -->
8
+ <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="MisakaNet">
9
+ <rect width="64" height="64" rx="12" fill="#070b15"/>
10
+ <rect x="2" y="2" width="60" height="60" rx="10" stroke="#00e5ff" stroke-opacity="0.55" stroke-width="2"/>
11
+ <path d="M16 44V20h7l9 14 9-14h7v24h-7V31.5L34.5 44h-5L23 31.5V44h-7Z" fill="#67e8f9"/>
12
+ <circle cx="50" cy="14" r="4" fill="#f59e0b"/>
13
+ </svg>
package/index.js CHANGED
@@ -74,22 +74,49 @@ export const DEFAULT_MCP_CONFIG = Object.freeze({
74
74
  */
75
75
  export async function apply(ctx, config = {}) {
76
76
  const options = { ...DEFAULT_MCP_CONFIG, ...config };
77
- if (typeof ctx?.plugin !== 'function') {
78
- throw new Error('misakanet: cordis context has no plugin() to mount the MCP client');
79
- }
80
77
 
81
- let client;
78
+ // NOTHING BELOW MAY THROW OUT OF THIS FUNCTION.
79
+ //
80
+ // A throw here is a failed activation, and a failed activation inside a profile
81
+ // bundle can take the whole host down: `dsh: startup failed: N required plugins
82
+ // did not activate` — the entire `dsh web` refuses to start, not just this
83
+ // server. That is a catastrophic outcome for a feature whose worst case should
84
+ // be "the tools are missing": the skill (SKILL.md) and every other plugin in
85
+ // the profile are unrelated to whether MisakaNet's MCP client mounted.
86
+ //
87
+ // So the whole body is guarded and reports through the host logger instead.
88
+ // `failOnStartupError` still works as documented — it asks the *MCP client* to
89
+ // treat a failed initial connection or tool sync as fatal (that is a config
90
+ // field of the client, `dsh-mcp-client/lib/index.js`), and when it is set the
91
+ // client's own fiber fails where the host can attribute it. What it must never
92
+ // do is make *our* wrapper the reason a profile will not boot.
82
93
  try {
83
- // Dynamic import: the client is ESM and only exists inside a DSH install.
84
- client = await import('@deepseek-ai/dsh-mcp-client');
94
+ if (typeof ctx?.plugin !== 'function') {
95
+ // A host that cannot mount child plugins: the skill still works, so say so and stop. This used to
96
+ // throw unconditionally — before the try — which is exactly the failure mode above. The explicit
97
+ // opt-in still gets its error, because that is what an opt-in is for.
98
+ const message = 'misakanet: cordis context has no plugin(); MCP tools not mounted';
99
+ if (options.failOnStartupError) throw new Error(message);
100
+ ctx?.logger?.warn?.(message);
101
+ return;
102
+ }
103
+
104
+ let client;
105
+ try {
106
+ // Dynamic import: the client is ESM and only exists inside a DSH install.
107
+ client = await import('@deepseek-ai/dsh-mcp-client');
108
+ } catch (error) {
109
+ if (options.failOnStartupError) throw error;
110
+ // Expected on npm skill-only installs: the skill (SKILL.md) is the payload,
111
+ // and a missing client must not take the whole profile down with it.
112
+ return;
113
+ }
114
+
115
+ // The Loader normalizes ESM/CJS/default export shapes before applying a plugin.
116
+ const component = ctx?.loader?.unwrapExports ? ctx.loader.unwrapExports(client) : client;
117
+ ctx.plugin(component, options);
85
118
  } catch (error) {
86
119
  if (options.failOnStartupError) throw error;
87
- // Expected on npm skill-only installs: the skill (SKILL.md) is the payload,
88
- // and a missing client must not take the whole profile down with it.
89
- return;
120
+ ctx?.logger?.warn?.(`misakanet: MCP client not mounted: ${error?.message ?? error}`);
90
121
  }
91
-
92
- // The Loader normalizes ESM/CJS/default export shapes before applying a plugin.
93
- const component = ctx?.loader?.unwrapExports ? ctx.loader.unwrapExports(client) : client;
94
- ctx.plugin(component, options);
95
122
  }