oh-memos-mcp 2.0.1 → 3.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.
Files changed (94) hide show
  1. package/.env.example +44 -27
  2. package/CHANGELOG.md +266 -95
  3. package/README.md +73 -28
  4. package/dist/api-client.d.ts +0 -0
  5. package/dist/api-client.js +0 -0
  6. package/dist/canvas-format.d.ts +101 -0
  7. package/dist/canvas-format.js +259 -0
  8. package/dist/canvas-store.d.ts +62 -0
  9. package/dist/canvas-store.js +187 -0
  10. package/dist/config.d.ts +3 -0
  11. package/dist/config.js +44 -9
  12. package/dist/cube-manager.d.ts +0 -0
  13. package/dist/cube-manager.js +11 -0
  14. package/dist/formatters.d.ts +0 -0
  15. package/dist/formatters.js +0 -0
  16. package/dist/graph-provenance.d.ts +34 -0
  17. package/dist/graph-provenance.js +175 -0
  18. package/dist/graphify-import.d.ts +72 -0
  19. package/dist/graphify-import.js +221 -0
  20. package/dist/handlers/admin.d.ts +1 -0
  21. package/dist/handlers/admin.js +18 -0
  22. package/dist/handlers/arg-contract.d.ts +0 -0
  23. package/dist/handlers/arg-contract.js +0 -0
  24. package/dist/handlers/calendar.d.ts +0 -0
  25. package/dist/handlers/calendar.js +0 -0
  26. package/dist/handlers/canvas.d.ts +40 -0
  27. package/dist/handlers/canvas.js +334 -0
  28. package/dist/handlers/graph.d.ts +8 -0
  29. package/dist/handlers/graph.js +66 -14
  30. package/dist/handlers/index.d.ts +0 -0
  31. package/dist/handlers/index.js +30 -5
  32. package/dist/handlers/memory.d.ts +0 -0
  33. package/dist/handlers/memory.js +33 -2
  34. package/dist/handlers/search.d.ts +0 -0
  35. package/dist/handlers/search.js +56 -15
  36. package/dist/handlers/skill.d.ts +6 -0
  37. package/dist/handlers/skill.js +123 -0
  38. package/dist/handlers/think.d.ts +0 -0
  39. package/dist/handlers/think.js +0 -0
  40. package/dist/handlers/utils.d.ts +0 -0
  41. package/dist/handlers/utils.js +0 -0
  42. package/dist/handlers/wiki-export.d.ts +0 -0
  43. package/dist/handlers/wiki-export.js +7 -9
  44. package/dist/handlers/wiki-import-relations.d.ts +11 -0
  45. package/dist/handlers/wiki-import-relations.js +32 -0
  46. package/dist/handlers/wiki-import.d.ts +19 -0
  47. package/dist/handlers/wiki-import.js +382 -0
  48. package/dist/index.d.ts +0 -0
  49. package/dist/index.js +27 -6
  50. package/dist/keyword-enhancer.d.ts +0 -0
  51. package/dist/keyword-enhancer.js +0 -0
  52. package/dist/memory-analysis.d.ts +0 -0
  53. package/dist/memory-analysis.js +0 -0
  54. package/dist/memory-quality.d.ts +10 -0
  55. package/dist/memory-quality.js +57 -0
  56. package/dist/memory-write-response.d.ts +8 -0
  57. package/dist/memory-write-response.js +15 -0
  58. package/dist/models.d.ts +0 -0
  59. package/dist/models.js +0 -0
  60. package/dist/policy.d.ts +8 -0
  61. package/dist/policy.js +9 -0
  62. package/dist/providers/lite-embedding.d.ts +31 -0
  63. package/dist/providers/lite-embedding.js +60 -0
  64. package/dist/providers/local-jsonl-provider.d.ts +28 -0
  65. package/dist/providers/local-jsonl-provider.js +225 -0
  66. package/dist/providers/memory-provider.d.ts +21 -0
  67. package/dist/providers/memory-provider.js +2 -0
  68. package/dist/providers/provider-factory.d.ts +11 -0
  69. package/dist/providers/provider-factory.js +27 -0
  70. package/dist/query-processing.d.ts +0 -0
  71. package/dist/query-processing.js +0 -0
  72. package/dist/runtime-version.d.ts +2 -0
  73. package/dist/runtime-version.js +10 -0
  74. package/dist/server-lifecycle.d.ts +10 -0
  75. package/dist/server-lifecycle.js +30 -0
  76. package/dist/server.d.ts +5 -2
  77. package/dist/server.js +42 -48
  78. package/dist/skill-candidate.d.ts +11 -0
  79. package/dist/skill-candidate.js +56 -0
  80. package/dist/skill-lifecycle.d.ts +15 -0
  81. package/dist/skill-lifecycle.js +51 -0
  82. package/dist/stdio-compat-transport.d.ts +24 -0
  83. package/dist/stdio-compat-transport.js +75 -0
  84. package/dist/tools-registry.d.ts +140 -169
  85. package/dist/tools-registry.js +93 -31
  86. package/dist/types.d.ts +0 -0
  87. package/dist/types.js +0 -0
  88. package/dist/wiki-import-format.d.ts +47 -0
  89. package/dist/wiki-import-format.js +113 -0
  90. package/dist/wiki-import-safety.d.ts +25 -0
  91. package/dist/wiki-import-safety.js +31 -0
  92. package/dist/wiki-relations.d.ts +44 -0
  93. package/dist/wiki-relations.js +88 -0
  94. package/package.json +18 -6
package/.env.example CHANGED
@@ -1,27 +1,44 @@
1
- # ============================================================================
2
- # oh-memos-mcp Environment Configuration
3
- # ============================================================================
4
- # Copy this file to .env in your project root and adjust values.
5
- # Priority: CLI args > environment variables > defaults
6
- # ============================================================================
7
-
8
- # --- Required ---
9
- MEMOS_URL=http://localhost:18000 # oh-memos API address
10
- MEMOS_USER=dev_user # Default user ID
11
- MEMOS_DEFAULT_CUBE=dev_cube # Default memory cube ID
12
- MEMOS_CUBES_DIR=/path/to/cubes # Absolute path to cubes directory
13
-
14
- # --- Timeouts (seconds) ---
15
- # MEMOS_TIMEOUT_TOOL=300 # Tool call timeout (default: 300)
16
- # MEMOS_TIMEOUT_STARTUP=30 # Startup timeout (default: 30)
17
- # MEMOS_TIMEOUT_HEALTH=5 # Health check timeout (default: 5)
18
- # MEMOS_API_WAIT_MAX=60 # Max API wait time (default: 60)
19
-
20
- # --- Feature Flags ---
21
- # MEMOS_ENABLE_DELETE=false # Enable memory deletion (default: false)
22
- # MEMOS_LOG_LEVEL=WARNING # DEBUG | INFO | WARNING | ERROR
23
-
24
- # --- Neo4j (optional, for direct graph queries) ---
25
- # NEO4J_HTTP_URL=http://localhost:7474
26
- # NEO4J_USER=neo4j
27
- # NEO4J_PASSWORD=your_password
1
+ # ============================================================================
2
+ # oh-memos-mcp Environment Configuration
3
+ # ============================================================================
4
+ # Copy this file to .env in your project root and adjust values.
5
+ # Priority: CLI flags > explicit env file > inherited environment > discovered .env > defaults
6
+ # A discovered .env only fills gaps; it never overrides MCP client env values.
7
+ # Set MEMOS_ENV_FILE when a specific file must be authoritative (recommended for npx).
8
+ # ============================================================================
9
+
10
+ # --- Required (Full/API mode) ---
11
+ MEMOS_URL=http://localhost:18000 # oh-memos API address (may be empty in local mode)
12
+ MEMOS_USER=dev_user # Default user ID
13
+ MEMOS_DEFAULT_CUBE=dev_cube # Default memory cube ID
14
+ MEMOS_CUBES_DIR=/path/to/cubes # Absolute path to cubes directory
15
+
16
+ # --- Provider selection ---
17
+ # MEMOS_PROVIDER=api # api = Full backend via Python API (default)
18
+ # MEMOS_PROVIDER=local # local = Lite JSONL store, no Python API needed
19
+ # MEMOS_MODE=lite # Shorthand: implies MEMOS_PROVIDER=local
20
+
21
+ # --- Lite local embeddings (optional, only for MEMOS_PROVIDER=local) ---
22
+ # Semantic ranking for the Lite store talks to an Ollama-compatible endpoint.
23
+ # It expects the Ollama /api/embeddings protocol, so point it at an Ollama
24
+ # host (local or self-hosted remote) — cloud OpenAI-compatible embedding
25
+ # endpoints belong to the Full backend instead (see docker/.env.docker.example,
26
+ # MOS_EMBEDDER_*). Defaults below need no configuration at all.
27
+ # MEMOS_LITE_EMBED_URL=http://127.0.0.1:11434 # Ollama endpoint
28
+ # MEMOS_LITE_EMBED_MODEL=bge-m3 # any embedding model you pulled
29
+ # MEMOS_LITE_EMBED=off # pin lexical-only ranking explicitly
30
+
31
+ # --- Timeouts (seconds) ---
32
+ # MEMOS_TIMEOUT_TOOL=300 # Tool call timeout (default: 300)
33
+ # MEMOS_TIMEOUT_STARTUP=30 # Startup timeout (default: 30)
34
+ # MEMOS_TIMEOUT_HEALTH=5 # Health check timeout (default: 5)
35
+ # MEMOS_API_WAIT_MAX=60 # Max API wait time (default: 60)
36
+
37
+ # --- Feature Flags ---
38
+ # MEMOS_ENABLE_DELETE=false # Enable memory deletion (default: false)
39
+ # MEMOS_LOG_LEVEL=WARNING # DEBUG | INFO | WARNING | ERROR
40
+
41
+ # --- Neo4j (optional, for direct graph queries) ---
42
+ # NEO4J_HTTP_URL=http://localhost:7474
43
+ # NEO4J_USER=neo4j
44
+ # NEO4J_PASSWORD=your_password
package/CHANGELOG.md CHANGED
@@ -1,95 +1,266 @@
1
- # Changelog
2
-
3
- All notable changes to `oh-memos-mcp` are documented here.
4
-
5
- This project follows [Semantic Versioning](https://semver.org/).
6
-
7
- ---
8
-
9
- ## [2.0.1] — 2026-08-02
10
-
11
- ### Fixed
12
-
13
- - MCP `serverInfo` was hardcoded in `server.ts` and reported
14
- `{name: "memos-memory", version: "1.0.1"}` — a name matching neither the
15
- package (`oh-memos-mcp`) nor the conventional server key (`oh-memos`), and a
16
- version that 2.0.0 shipped stale. Clients display this during the handshake.
17
- It is now read from `package.json` at startup, so it cannot drift again.
18
-
19
- ---
20
-
21
- ## [2.0.0] — 2026-08-02
22
-
23
- ### ⚠️ Breaking — tool surface consolidated from 18 to 10
24
-
25
- Eleven tools were merged into three dispatching tools. **There is no compatibility
26
- shim**: the MCP SDK only dispatches registered tools, so calling a removed name now
27
- returns `Unknown tool`.
28
-
29
- If your MCP client config pins tool names (e.g. Claude Code's `alwaysAllow` list),
30
- you must update it before upgrading.
31
-
32
- #### Migration
33
-
34
- | 1.x tool | 2.0 replacement |
35
- |----------|-----------------|
36
- | `memos_search_context` | `memos_search` — pass the `context` array (recent turns) |
37
- | `memos_get_graph` | `memos_graph(mode="related")` |
38
- | `memos_trace_path` | `memos_graph(mode="path")` |
39
- | `memos_impact` | `memos_graph(mode="impact")` |
40
- | `memos_export_schema` | `memos_graph(mode="schema")` |
41
- | `memos_list_cubes` | `memos_admin(action="list_cubes")` |
42
- | `memos_register_cube` | `memos_admin(action="register_cube")` |
43
- | `memos_create_user` | `memos_admin(action="create_user")` |
44
- | `memos_validate_cubes` | `memos_admin(action="validate_cubes")` |
45
- | `memos_get_stats` | `memos_admin(action="stats")` |
46
- | `memos_calendar` | `memos_admin(action="calendar")` |
47
-
48
- Unchanged: `memos_context_resume`, `memos_search`, `memos_save`, `memos_list_v2`,
49
- `memos_get`, `memos_suggest`, `memos_delete`.
50
-
51
- `alwaysAllow` for 2.0:
52
-
53
- ```json
54
- "alwaysAllow": [
55
- "memos_context_resume", "memos_search", "memos_save",
56
- "memos_list_v2", "memos_get", "memos_suggest",
57
- "memos_think", "memos_graph", "memos_admin", "memos_export_wiki"
58
- ]
59
- ```
60
-
61
- ### Added
62
-
63
- - **`memos_think`** — evidence pack for a question. Runs semantic retrieval plus a
64
- recent-72h temporal pass, deduplicates, and returns numbered evidence with graph
65
- relationships between items, contradiction/evolution candidates, staleness
66
- candidates, and gap analysis. Synthesis is deliberately left to the calling model;
67
- the server emits no prose. Results can be persisted back as `SYNTHESIS`.
68
- - **`memos_export_wiki`** — export a cube as an interlinked markdown wiki: one page
69
- per memory (YAML frontmatter, `[[wikilink]]` relations), plus `index.md` and a
70
- mermaid `graph.md`. Only files carrying the generator marker are ever replaced;
71
- foreign files in the output directory are preserved. Defaults to
72
- `<project_path>/docs/memory-wiki`.
73
- - **`SYNTHESIS`** memory type, for answers synthesized from retrieved evidence.
74
-
75
- ### Changed
76
-
77
- - Tool-surface cost dropped ~51%: `tools/list` payload 22.9 KB → 11.2 KB
78
- (≈5850 → ≈2856 tokens). Shared `project_path` / `cube_id` parameter descriptions
79
- were deduplicated; the full cube-routing rules are now stated once, on
80
- `memos_save` and `memos_search`.
81
- - Runtime error `suggestions` now name the 2.0 call forms, so a model reading a
82
- failure message is no longer told to call a tool that does not exist.
83
-
84
- ### Fixed
85
-
86
- - `memos_admin`'s `cube_id` no longer carries a `MEMOS_DEFAULT_CUBE` default.
87
- Previously, calling `register_cube` without `cube_id` would silently register the
88
- default cube instead of failing.
89
-
90
- ---
91
-
92
- ## [1.0.0] — 2026-03-04
93
-
94
- Initial npm release. 18 tools, Node-only MCP server for oh-memos — no Python
95
- required, runs via `npx`.
1
+ # Changelog
2
+
3
+ All notable changes to `oh-memos-mcp` are documented here.
4
+
5
+ This project follows [Semantic Versioning](https://semver.org/).
6
+
7
+ ---
8
+
9
+ ## [3.0.0] - 2026-08-19
10
+
11
+ ### Breaking
12
+
13
+ - **Node.js 20 is now the minimum runtime.** Node 18 users must stay on
14
+ `oh-memos-mcp@2` (`npx -y oh-memos-mcp@2`) until they can upgrade their
15
+ runtime. The entry point exits with an actionable message on Node 18 instead
16
+ of failing with an opaque module error.
17
+ - The MCP runtime now uses the role-split `@modelcontextprotocol/server@2` and
18
+ Zod 4 instead of the monolithic v1 SDK and Zod 3.
19
+
20
+ ### Added
21
+
22
+ - **Dual-era stdio serving.** The same package accepts legacy 2025-era
23
+ initialize clients and clients pinned to MCP `2026-07-28` through
24
+ `serveStdio(..., { legacy: "serve" })`.
25
+ - Stringified `tools/call` arguments are normalized before era classification
26
+ and schema validation, preserving the existing client compatibility path.
27
+ - Protocol, lifecycle, semantic-schema and package-boundary release gates now
28
+ cover legacy/auto/modern clients, Full/Lite providers, 16/17 tools, large
29
+ requests, probe fallback and graceful process shutdown.
30
+
31
+ ### Migration
32
+
33
+ - Install with `npx -y oh-memos-mcp` (npm `latest`) or pin `oh-memos-mcp@3.0.0`.
34
+ - No memory, cube or Lite JSONL migration is required. Existing Full and Lite
35
+ data formats, tool names and input schemas remain unchanged, so Agent
36
+ configurations only need the package reference updated.
37
+ - Clients that still negotiate the 2025-era wire keep working unchanged; no
38
+ client-side protocol migration is required to adopt 3.0.
39
+
40
+ ### Rollback
41
+
42
+ - Pin Agent configurations to `npx -y oh-memos-mcp@2.1.0`. No data rollback is
43
+ necessary because this release does not change persisted formats.
44
+ - `2.x` remains installable from npm; this release does not unpublish or
45
+ deprecate it.
46
+
47
+ ## [2.1.0] - 2026-08-16
48
+
49
+ ### Fixed
50
+
51
+ - **Auto-discovered `.env` no longer overrides launcher environment.** A `.env`
52
+ found in the working directory or package root now only fills missing values,
53
+ so MCP client `env` blocks and shell exports such as `MEMOS_PROVIDER=local`
54
+ stay in effect. A file selected explicitly through `MEMOS_ENV_FILE` or
55
+ `--memos-env-file` remains authoritative.
56
+
57
+ ### Added
58
+
59
+ - **Local Lite provider.** `MEMOS_PROVIDER=local` (implied by `MEMOS_MODE=lite`)
60
+ serves `memos_save`, `memos_get`, `memos_list_v2`, `memos_search`, and
61
+ `memos_context_resume` from a per-cube `memories.jsonl` with deterministic
62
+ lexical ranking, durable appends, and a cross-process lock. Graph, Think,
63
+ Wiki, and admin tools report `LOCAL_PROVIDER_UNSUPPORTED` rather than
64
+ pretending a graph backend exists.
65
+
66
+ - **Skill candidate lifecycle.** `memos_review_skill_candidate` records
67
+ approve/reject with reviewer audit metadata, and
68
+ `memos_install_skill_candidate` installs only approved candidates into
69
+ `.claude/skills/<slug>/SKILL.md` without overwriting, following symlinks, or
70
+ executing anything.
71
+
72
+ - **Explainable graph provenance.** `memos_graph(mode="related"|"path"|"impact")`
73
+ now reports normalized evidence categories (`EXTRACTED`, `INFERRED`,
74
+ `AMBIGUOUS`, or `UNKNOWN`) and includes confidence, evidence references,
75
+ source file/location, extractor version and verification time when those
76
+ fields exist. Legacy graph data without provenance remains readable and is
77
+ reported as `UNKNOWN` rather than assigned invented evidence.
78
+
79
+ - **`memos_graph(mode="import")` Graphify boundary.** Accepts up to 5 MB of
80
+ Graphify/NetworkX node-link JSON through `graph_json`, validates `nodes` plus
81
+ `links` (or the `edges` alias), and produces a deterministic import plan with
82
+ portable stable Code Graph ids. Duplicate ids, dangling edges, unsafe source
83
+ paths, invalid confidence values and oversized graphs are rejected before
84
+ any persistence boundary. This mode is intentionally **dry-run only**: it
85
+ never writes to Neo4j, Qdrant or a memory cube.
86
+
87
+ - **`memos_canvas`** — a symbolic task canvas: short-term task state that survives
88
+ context compaction. One Mermaid file per task under
89
+ `{MEMOS_CUBES_DIR}/{cube_id}/canvas/`, whose nodes carry a greppable id
90
+ (`000-N1`) and an optional `ref` anchoring them to evidence:
91
+ `mem:<memory_id>` (a memory in the graph), `file:<path>` (any file, including
92
+ the large tool results the harness already offloads), or `note:<text>`.
93
+
94
+ `action`: `open` (needs `goal`) · `update` (appends a node; `node_id` edits one
95
+ in place) · `show` · `list`.
96
+
97
+ Canvases are deliberately **not** written to Neo4j or Qdrant. A canvas changes
98
+ several times an hour, and paying an embedding round trip for a `doing→done`
99
+ flip would be absurd. Durable facts still go through `memos_save`; the canvas
100
+ points at them with a `mem:` ref.
101
+
102
+ This is **not** a token-saving feature. The design it borrows from
103
+ ([TencentDB-Agent-Memory](https://github.com/TencentCloud/TencentDB-Agent-Memory))
104
+ achieves its reduction by intercepting and replacing tool output before the
105
+ model sees it, which a Claude Code hook cannot do — `PreToolUse` can rewrite a
106
+ tool's *input* via `updatedInput`, but no hook can rewrite its *output*. What
107
+ this offers instead is task state that survives compaction, and a path from a
108
+ summary back to the evidence behind it.
109
+
110
+ Node ids and canvas prefixes are allocated as max+1 and **never reuse a gap**:
111
+ a deleted `000-N2` may still be cited from a commit message, a memory body or
112
+ another node's ref, and handing that id to a new node would silently repoint
113
+ every one of those citations.
114
+
115
+ - `memos_context_resume` now lists **unfinished** canvases first — headlines and
116
+ counts only, a few dozen tokens — so the first thing visible after a compaction
117
+ is the open work rather than a memory feed. Injecting canvas bodies here would
118
+ rebuild the very context bloat the canvas exists to avoid; the model opens what
119
+ it needs with `show`.
120
+
121
+ - **Test infrastructure.** This package previously had none: no test script, no
122
+ `*.test.ts`. Adds vitest and `npm test`, with 65 unit tests covering the
123
+ parse/render round trip, node-id allocation, Mermaid label injection, path
124
+ traversal refusal and atomic writes. `scripts/canvas-e2e.mjs` adds 18 checks
125
+ driven over real MCP stdio rather than mocks.
126
+
127
+ - `MEMOS_ENV_FILE` env var and `--memos-env-file` flag, to point the server at an
128
+ explicit `.env`. Previously the file was located only by guessing from position
129
+ (cwd, two levels above the package, dotenv's upward search) — which works from
130
+ a checkout and never works under `npx`, where the package root sits in the npm
131
+ cache and every candidate misses, loading not one variable. A path that does
132
+ not exist now warns on stderr rather than falling through silently.
133
+
134
+ ### Fixed
135
+
136
+ - `toLocalPath()` rewrote Windows cube paths to `/mnt/...` unconditionally. That
137
+ mapping only resolves inside WSL; under native Windows Node the result is not
138
+ absolute, so it resolved against the current drive and every cube write landed
139
+ in a phantom tree while the API kept reading the real path. Registration
140
+ reported success, then `/search` and `/memories` failed 400 — the loaded cube
141
+ had no memory backend.
142
+
143
+ ### Security
144
+
145
+ - `canvasPath` is the one place caller text becomes a filesystem path. It uses a
146
+ **whitelist** (`[a-z0-9-]`) rather than a blacklist of dangerous characters,
147
+ because a blacklist is always missing an entry. `.` is outside the whitelist,
148
+ so `..` cannot survive it — traversal is structurally impossible rather than
149
+ merely checked for — and a post-resolve containment check backs that up
150
+ independently. `cube_id` is treated as untrusted too, since it is derived from
151
+ a caller-supplied `project_path`.
152
+
153
+ ### Documentation
154
+
155
+ - The `alwaysAllow` example carried two defects. `memos_search` appeared twice,
156
+ and several entries were **call forms** — `memos_admin(action=list_cubes)` and
157
+ the like. `alwaysAllow` matches tool names, so those entries matched nothing:
158
+ a reader would believe those calls were pre-approved and still be prompted for
159
+ every one. Replaced with bare tool names, which auto-approve every action of
160
+ the tool.
161
+ - `memos_delete` was dropped from that example, which also set
162
+ `MEMOS_ENABLE_DELETE: "true"` — together they auto-approve deleting memories
163
+ with no prompt. Enabling that is a decision worth making deliberately.
164
+ - The `.env` note claimed the working directory's file loads "automatically with
165
+ highest priority". Under `npx` no file loads at all. Documented `MEMOS_ENV_FILE`
166
+ and what actually happens.
167
+
168
+ ### Notes
169
+
170
+ - Tool surface grew 12488 B → 13680 B (+9.5%), past the +5% drift budget, and the
171
+ baseline was re-frozen. This is the cost of a new tool rather than description
172
+ drift; the description was trimmed from 1333 B to 1192 B first, moving detail
173
+ into `show`'s output (the same move `memos_suggest` made with the memory-type
174
+ decision tree).
175
+ - `tsconfig.json` now excludes `src/**/*.test.ts`. Without it the test files
176
+ compile into `dist` and ship with `npm publish`.
177
+
178
+ ---
179
+
180
+ ## [2.0.1] — 2026-08-02
181
+
182
+ ### Fixed
183
+
184
+ - MCP `serverInfo` was hardcoded in `server.ts` and reported
185
+ `{name: "memos-memory", version: "1.0.1"}` — a name matching neither the
186
+ package (`oh-memos-mcp`) nor the conventional server key (`oh-memos`), and a
187
+ version that 2.0.0 shipped stale. Clients display this during the handshake.
188
+ It is now read from `package.json` at startup, so it cannot drift again.
189
+
190
+ ---
191
+
192
+ ## [2.0.0] — 2026-08-02
193
+
194
+ ### ⚠️ Breaking — tool surface consolidated from 18 to 10
195
+
196
+ Eleven tools were merged into three dispatching tools. **There is no compatibility
197
+ shim**: the MCP SDK only dispatches registered tools, so calling a removed name now
198
+ returns `Unknown tool`.
199
+
200
+ If your MCP client config pins tool names (e.g. Claude Code's `alwaysAllow` list),
201
+ you must update it before upgrading.
202
+
203
+ #### Migration
204
+
205
+ | 1.x tool | 2.0 replacement |
206
+ |----------|-----------------|
207
+ | `memos_search_context` | `memos_search` — pass the `context` array (recent turns) |
208
+ | `memos_get_graph` | `memos_graph(mode="related")` |
209
+ | `memos_trace_path` | `memos_graph(mode="path")` |
210
+ | `memos_impact` | `memos_graph(mode="impact")` |
211
+ | `memos_export_schema` | `memos_graph(mode="schema")` |
212
+ | `memos_list_cubes` | `memos_admin(action="list_cubes")` |
213
+ | `memos_register_cube` | `memos_admin(action="register_cube")` |
214
+ | `memos_create_user` | `memos_admin(action="create_user")` |
215
+ | `memos_validate_cubes` | `memos_admin(action="validate_cubes")` |
216
+ | `memos_get_stats` | `memos_admin(action="stats")` |
217
+ | `memos_calendar` | `memos_admin(action="calendar")` |
218
+
219
+ Unchanged: `memos_context_resume`, `memos_search`, `memos_save`, `memos_list_v2`,
220
+ `memos_get`, `memos_suggest`, `memos_delete`.
221
+
222
+ `alwaysAllow` for 2.0:
223
+
224
+ ```json
225
+ "alwaysAllow": [
226
+ "memos_context_resume", "memos_search", "memos_save",
227
+ "memos_list_v2", "memos_get", "memos_suggest",
228
+ "memos_think", "memos_graph", "memos_admin", "memos_export_wiki"
229
+ ]
230
+ ```
231
+
232
+ ### Added
233
+
234
+ - **`memos_think`** — evidence pack for a question. Runs semantic retrieval plus a
235
+ recent-72h temporal pass, deduplicates, and returns numbered evidence with graph
236
+ relationships between items, contradiction/evolution candidates, staleness
237
+ candidates, and gap analysis. Synthesis is deliberately left to the calling model;
238
+ the server emits no prose. Results can be persisted back as `SYNTHESIS`.
239
+ - **`memos_export_wiki`** — export a cube as an interlinked markdown wiki: one page
240
+ per memory (YAML frontmatter, `[[wikilink]]` relations), plus `index.md` and a
241
+ mermaid `graph.md`. Only files carrying the generator marker are ever replaced;
242
+ foreign files in the output directory are preserved. Defaults to
243
+ `<project_path>/docs/memory-wiki`.
244
+ - **`SYNTHESIS`** memory type, for answers synthesized from retrieved evidence.
245
+
246
+ ### Changed
247
+
248
+ - Tool-surface cost dropped ~51%: `tools/list` payload 22.9 KB → 11.2 KB
249
+ (≈5850 → ≈2856 tokens). Shared `project_path` / `cube_id` parameter descriptions
250
+ were deduplicated; the full cube-routing rules are now stated once, on
251
+ `memos_save` and `memos_search`.
252
+ - Runtime error `suggestions` now name the 2.0 call forms, so a model reading a
253
+ failure message is no longer told to call a tool that does not exist.
254
+
255
+ ### Fixed
256
+
257
+ - `memos_admin`'s `cube_id` no longer carries a `MEMOS_DEFAULT_CUBE` default.
258
+ Previously, calling `register_cube` without `cube_id` would silently register the
259
+ default cube instead of failing.
260
+
261
+ ---
262
+
263
+ ## [1.0.0] — 2026-03-04
264
+
265
+ Initial npm release. 18 tools, Node-only MCP server for oh-memos — no Python
266
+ required, runs via `npx`.
package/README.md CHANGED
@@ -1,17 +1,28 @@
1
1
  # oh-memos-mcp
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/oh-memos-mcp.svg)](https://www.npmjs.com/package/oh-memos-mcp)
4
- [![Node.js >= 18](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://nodejs.org)
4
+ [![Node.js >= 20](https://img.shields.io/badge/node-%3E%3D20-brightgreen)](https://nodejs.org)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
6
 
7
7
  MCP Server for **oh-memos** — Intelligent Persistent Memory for AI Assistants.
8
8
 
9
9
  Pure Node.js. No Python required. Works with `npx` out of the box.
10
10
 
11
+ > **3.0:** requires Node.js 20+, serves legacy 2025-era and MCP `2026-07-28`
12
+ > clients from the same stdio package, and requires no data migration. Still on
13
+ > Node 18? Pin `oh-memos-mcp@2` until you can upgrade the runtime.
14
+
11
15
  ---
12
16
 
13
17
  ## Prerequisites
14
18
 
19
+ - **Node.js 20 or newer**
20
+
21
+ ```bash
22
+ npx -y oh-memos-mcp # 3.x, npm latest — needs Node.js 20+
23
+ npx -y oh-memos-mcp@2 # 2.x maintenance line — still runs on Node.js 18
24
+ ```
25
+
15
26
  oh-memos backend API must be running before connecting this MCP server:
16
27
 
17
28
  - **oh-memos API** on `http://localhost:18000`
@@ -48,7 +59,7 @@ Or use a `.env` file in your working directory (the server auto-discovers it):
48
59
  ```bash
49
60
  cp node_modules/oh-memos-mcp/.env.example .env
50
61
  # Edit .env with your paths
51
- npx oh-memos-mcp
62
+ npx -y oh-memos-mcp
52
63
  ```
53
64
 
54
65
  ---
@@ -114,6 +125,13 @@ npx oh-memos-mcp
114
125
 
115
126
  ### With `alwaysAllow` (skip per-tool confirmation)
116
127
 
128
+ `alwaysAllow` matches **tool names**, so a call form like
129
+ `memos_admin(action=list_cubes)` matches nothing — list the bare name and every
130
+ action of that tool is auto-approved.
131
+
132
+ `memos_delete` is deliberately absent below. Auto-approving it means memories can
133
+ be deleted without a prompt; add it only if you have decided you want that.
134
+
117
135
  ```json
118
136
  {
119
137
  "mcpServers": {
@@ -125,28 +143,20 @@ npx oh-memos-mcp
125
143
  "MEMOS_URL": "http://localhost:18000",
126
144
  "MEMOS_USER": "dev_user",
127
145
  "MEMOS_DEFAULT_CUBE": "dev_cube",
128
- "MEMOS_CUBES_DIR": "/path/to/oh-memos/data/oh-memos_cubes",
129
- "MEMOS_ENABLE_DELETE": "true"
146
+ "MEMOS_CUBES_DIR": "/path/to/oh-memos/data/oh-memos_cubes"
130
147
  },
131
148
  "alwaysAllow": [
132
149
  "memos_context_resume",
133
150
  "memos_search",
134
- "memos_search",
135
151
  "memos_save",
136
152
  "memos_list_v2",
137
153
  "memos_get",
138
154
  "memos_suggest",
139
- "memos_admin(action=list_cubes)",
140
- "memos_admin(action=stats)",
141
- "memos_graph(mode=related)",
142
- "memos_graph(mode=path)",
143
- "memos_graph(mode=schema)",
144
- "memos_admin(action=register_cube)",
145
- "memos_admin(action=create_user)",
146
- "memos_admin(action=validate_cubes)",
147
- "memos_graph(mode=impact)",
148
- "memos_admin(action=calendar)",
149
- "memos_delete"
155
+ "memos_think",
156
+ "memos_graph",
157
+ "memos_admin",
158
+ "memos_export_wiki",
159
+ "memos_canvas"
150
160
  ]
151
161
  }
152
162
  }
@@ -171,14 +181,26 @@ npx oh-memos-mcp
171
181
  | `NEO4J_HTTP_URL` | No | — | Neo4j HTTP endpoint (for direct graph queries) |
172
182
  | `NEO4J_USER` | No | — | Neo4j username |
173
183
  | `NEO4J_PASSWORD` | No | — | Neo4j password |
174
-
175
- > **Tip**: `.env` file in your working directory is loaded automatically with highest priority.
184
+ | `MEMOS_ENV_FILE` | No | — | Explicit path to a `.env` file. Highest priority — see below |
185
+
186
+ > **On locating `.env`**: without `MEMOS_ENV_FILE`, the file is found by guessing
187
+ > from position (working directory, two levels above the package, then dotenv's
188
+ > upward search). That works from a checkout and **never works under `npx`**,
189
+ > where the package root sits in the npm cache and every candidate misses — so no
190
+ > variable loads at all. Set `MEMOS_ENV_FILE` (or pass `--memos-env-file`) when the
191
+ > client's working directory and the install location are both outside the project.
192
+ > A path that does not exist warns on stderr rather than failing silently.
193
+ >
176
194
  > Copy `.env.example` to get started.
177
195
 
178
196
  ---
179
197
 
180
- ## Tools (10)
198
+ ## Tools (17)
181
199
 
200
+ The package defines 17 tool schemas. `memos_delete` is exposed by `tools/list`
201
+ only when `MEMOS_ENABLE_DELETE=true`; the other 16 are available by default.
202
+
203
+ <!-- mcp-tool-inventory:start -->
182
204
  | Tool | Description |
183
205
  |------|-------------|
184
206
  | `memos_context_resume` | Recover project context after compaction (recent 24h + project state) |
@@ -188,23 +210,46 @@ npx oh-memos-mcp
188
210
  | `memos_get` | Get full memory details by ID |
189
211
  | `memos_suggest` | Smart search query suggestions + `memory_type` decision tree |
190
212
  | `memos_think` | Evidence pack for a question: retrieval + contradiction/staleness flags + gap analysis. The caller synthesizes the answer and may persist it as `SYNTHESIS` |
191
- | `memos_graph` | Knowledge graph queries — `mode`: `related` / `path` / `impact` / `schema` |
213
+ | `memos_graph` | Explainable graph queries plus strict Graphify node-link validation — `mode`: `related` / `path` / `impact` / `schema` / `import` |
192
214
  | `memos_admin` | Maintenance — `action`: `list_cubes` / `register_cube` / `create_user` / `validate_cubes` / `stats` / `calendar` |
193
215
  | `memos_export_wiki` | Export a cube as an interlinked markdown wiki (page per memory + index + mermaid graph) |
194
-
195
- Plus `memos_delete`, hidden from `tools/list` unless `MEMOS_ENABLE_DELETE=true`.
216
+ | `memos_import_wiki` | Import an exported wiki back into a cube; supports dry-run and versioning edited pages, never deletes memories |
217
+ | `memos_canvas` | Symbolic task canvas — short-term task state that survives context compaction. `action`: `open` / `update` / `show` / `list`. Nodes carry greppable ids (`000-N1`) and a `ref` anchoring them to evidence: `mem:<memory_id>` / `file:<path>` / `note:<text>` |
218
+ | `memos_distill_skill` | Create an inert, reviewable Skill candidate under `<project_path>/skill-candidates`; it never installs the candidate automatically |
219
+ | `memos_list_skill_candidates` | List generated Skill candidates without modifying or installing them |
220
+ | `memos_review_skill_candidate` | Approve or reject a candidate with reviewer audit metadata; approval does not install |
221
+ | `memos_install_skill_candidate` | Install an approved candidate only into `.claude/skills/<slug>/SKILL.md`, without overwrite or script execution |
222
+ | `memos_delete` | Delete selected or all memories. Disabled by default and requires explicit user confirmation when enabled |
223
+ <!-- mcp-tool-inventory:end -->
224
+
225
+ ### `memos_graph` modes
226
+
227
+ | Mode | Main input | Result |
228
+ |------|------------|--------|
229
+ | `related` | `query` | Related memories and edges, with provenance explanations when available |
230
+ | `path` | `source_id`, `target_id` | A bounded path between two graph nodes, including relationship evidence |
231
+ | `impact` | `memory_id`, optional `max_depth` | Forward blast radius from one memory |
232
+ | `schema` | Optional `sample_size` | Graph structure and statistics |
233
+ | `import` | `graph_json`, optional `project_key` | Deterministic validation and dry-run plan for Graphify NetworkX node-link JSON |
234
+
235
+ `import` accepts at most 5 MB of JSON and rejects duplicate node ids, dangling
236
+ edges, unsafe source paths, invalid confidence values, and oversized graphs. It
237
+ does **not** write Code Graph nodes to Neo4j, Qdrant, or a memory cube.
196
238
 
197
239
  ---
198
240
 
199
241
  ## How .env Loading Works
200
242
 
201
- Priority order (highest first):
243
+ Priority order for configuration values (highest first):
202
244
 
203
- 1. **`process.cwd()/.env`** — your project working directory
204
- 2. **Package root `.env`** — where oh-memos-mcp is installed
205
- 3. **dotenv default search** — walks up from cwd
245
+ 1. **CLI configuration flags** such as `--memos-url`
246
+ 2. **Explicit env file** selected by `--memos-env-file` or inherited `MEMOS_ENV_FILE`
247
+ 3. **Inherited process environment** — this is where MCP client `env` values belong
248
+ 4. **Auto-discovered `process.cwd()/.env`** — provides only missing defaults
249
+ 5. **Auto-discovered package-root `.env`** — provides only missing defaults
250
+ 6. **dotenv upward fallback**, then built-in defaults
206
251
 
207
- This means you can place a `.env` in your project root and `npx oh-memos-mcp` will pick it up automatically — no need to repeat env vars in every MCP config.
252
+ The automatic file search never overrides explicit MCP/launcher environment values. Use `MEMOS_ENV_FILE` only when the selected file should deliberately be authoritative; this is also the reliable option for `npx` installs.
208
253
 
209
254
  ---
210
255
 
@@ -222,5 +267,5 @@ npm run build # Compile to dist/
222
267
 
223
268
  ## Requirements
224
269
 
225
- - Node.js >= 18.0.0
270
+ - Node.js >= 20.0.0
226
271
  - oh-memos backend API running (`scripts\local\start.bat`)
File without changes
File without changes