@datafrog-io/n2n-memory 1.2.0 → 1.2.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logging.js","sourceRoot":"","sources":["../../src/utils/logging.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,UAAU,cAAc;IAC1B,OAAO,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,WAAW,EAAE,KAAK,OAAO,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,WAAmB;IACjD,IAAI,cAAc,EAAE,EAAE,CAAC;QACnB,OAAO,WAAW,CAAC;IACvB,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC5C,OAAO,QAAQ,IAAI,WAAW,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,OAAe;IACnC,IAAI,cAAc,EAAE,EAAE,CAAC;QACnB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;AACL,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAe;IACtC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,OAAe,EAAE,KAAe;IACrD,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;QAC3C,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACvB,OAAO;IACX,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AAClC,CAAC"}
@@ -1,9 +1,9 @@
1
1
  import path from "path";
2
2
  import fs from "fs-extra";
3
3
  /**
4
- * Common markers that define a project root.
4
+ * Strong markers that define a project root.
5
5
  */
6
- const ROOT_MARKERS = [
6
+ const STRONG_ROOT_MARKERS = [
7
7
  ".git",
8
8
  ".mcp",
9
9
  "package.json",
@@ -12,11 +12,13 @@ const ROOT_MARKERS = [
12
12
  "requirements.txt",
13
13
  "pom.xml",
14
14
  "composer.json",
15
- "README.md",
16
15
  ".vscode",
17
16
  "tsconfig.json",
18
17
  ".gitignore"
19
18
  ];
19
+ const WEAK_ROOT_MARKERS = [
20
+ "README.md"
21
+ ];
20
22
  /**
21
23
  * Recursively finds the project root.
22
24
  * NOTE: For N2N-Memory, we now strictly only check the provided path or its immediate markers
@@ -24,12 +26,12 @@ const ROOT_MARKERS = [
24
26
  * @param startPath The path to start searching from.
25
27
  */
26
28
  export async function findProjectRoot(startPath) {
27
- const absoluteStart = path.resolve(startPath);
29
+ const absoluteStart = validateAbsolutePath(startPath);
28
30
  const current = absoluteStart;
29
31
  const foundMarkers = [];
30
32
  let hasMcp = false;
31
- // Check current directory for markers
32
- for (const marker of ROOT_MARKERS) {
33
+ // Check current directory for strong markers.
34
+ for (const marker of STRONG_ROOT_MARKERS) {
33
35
  const markerPath = path.join(current, marker);
34
36
  if (await fs.pathExists(markerPath)) {
35
37
  foundMarkers.push(marker);
@@ -40,7 +42,15 @@ export async function findProjectRoot(startPath) {
40
42
  if (foundMarkers.length > 0) {
41
43
  return { rootPath: current, hasMcp, markersFound: foundMarkers };
42
44
  }
43
- throw new Error(`Directory Not Recognized as a Project Root: No project markers (.git, package.json, README.md, etc.) found in "${absoluteStart}". ` +
45
+ const weakMarkersFound = [];
46
+ for (const marker of WEAK_ROOT_MARKERS) {
47
+ const markerPath = path.join(current, marker);
48
+ if (await fs.pathExists(markerPath)) {
49
+ weakMarkersFound.push(marker);
50
+ }
51
+ }
52
+ throw new Error(`Directory Not Recognized as a Project Root: No strong project markers (.git, package.json, tsconfig.json, etc.) found in "${absoluteStart}". ` +
53
+ `${weakMarkersFound.length > 0 ? `Weak markers found (${weakMarkersFound.join(", ")}), but they are not sufficient for initialization. ` : ""}` +
44
54
  `N2N-Memory strictly requires you to open the IDE at the project root or use a workspace top-level directory. ` +
45
55
  `Memory initialization is refused for generic or sub-directories to prevent context pollution.`);
46
56
  }
@@ -50,9 +60,11 @@ export async function findProjectRoot(startPath) {
50
60
  export function validateAbsolutePath(projectPath) {
51
61
  if (!projectPath)
52
62
  throw new Error("Project path is required.");
53
- const resolved = path.resolve(projectPath);
54
- if (!path.isAbsolute(resolved))
63
+ if (projectPath.includes('\0'))
64
+ throw new Error("Invalid path detected.");
65
+ if (!path.isAbsolute(projectPath))
55
66
  throw new Error(`Path must be absolute: ${projectPath}`);
67
+ const resolved = path.resolve(projectPath);
56
68
  if (resolved.includes('\0'))
57
69
  throw new Error("Invalid path detected.");
58
70
  return resolved;
@@ -1 +1 @@
1
- {"version":3,"file":"path-utils.js","sourceRoot":"","sources":["../../src/utils/path-utils.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,UAAU,CAAC;AAE1B;;GAEG;AACH,MAAM,YAAY,GAAG;IACjB,MAAM;IACN,MAAM;IACN,cAAc;IACd,QAAQ;IACR,YAAY;IACZ,kBAAkB;IAClB,SAAS;IACT,eAAe;IACf,WAAW;IACX,SAAS;IACT,eAAe;IACf,YAAY;CACf,CAAC;AAcF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,SAAiB;IACnD,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,aAAa,CAAC;IAE9B,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,sCAAsC;IACtC,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;QAChC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC9C,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAClC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1B,IAAI,MAAM,KAAK,MAAM;gBAAE,MAAM,GAAG,IAAI,CAAC;QACzC,CAAC;IACL,CAAC;IAED,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;IACrE,CAAC;IAED,MAAM,IAAI,KAAK,CACX,kHAAkH,aAAa,KAAK;QACpI,+GAA+G;QAC/G,+FAA+F,CAClG,CAAC;AACN,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,WAAmB;IACpD,IAAI,CAAC,WAAW;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC/D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC3C,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,WAAW,EAAE,CAAC,CAAC;IACzF,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IACvE,OAAO,QAAQ,CAAC;AACpB,CAAC"}
1
+ {"version":3,"file":"path-utils.js","sourceRoot":"","sources":["../../src/utils/path-utils.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,UAAU,CAAC;AAE1B;;GAEG;AACH,MAAM,mBAAmB,GAAG;IACxB,MAAM;IACN,MAAM;IACN,cAAc;IACd,QAAQ;IACR,YAAY;IACZ,kBAAkB;IAClB,SAAS;IACT,eAAe;IACf,SAAS;IACT,eAAe;IACf,YAAY;CACf,CAAC;AAEF,MAAM,iBAAiB,GAAG;IACtB,WAAW;CACd,CAAC;AAcF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,SAAiB;IACnD,MAAM,aAAa,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,aAAa,CAAC;IAE9B,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,8CAA8C;IAC9C,KAAK,MAAM,MAAM,IAAI,mBAAmB,EAAE,CAAC;QACvC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC9C,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAClC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1B,IAAI,MAAM,KAAK,MAAM;gBAAE,MAAM,GAAG,IAAI,CAAC;QACzC,CAAC;IACL,CAAC;IAED,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;IACrE,CAAC;IAED,MAAM,gBAAgB,GAAa,EAAE,CAAC;IACtC,KAAK,MAAM,MAAM,IAAI,iBAAiB,EAAE,CAAC;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC9C,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAClC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClC,CAAC;IACL,CAAC;IAED,MAAM,IAAI,KAAK,CACX,6HAA6H,aAAa,KAAK;QAC/I,GAAG,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,uBAAuB,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC,CAAC,EAAE,EAAE;QAC/I,+GAA+G;QAC/G,+FAA+F,CAClG,CAAC;AACN,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,WAAmB;IACpD,IAAI,CAAC,WAAW;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC/D,IAAI,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC1E,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,WAAW,EAAE,CAAC,CAAC;IAC5F,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC3C,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IACvE,OAAO,QAAQ,CAAC;AACpB,CAAC"}
@@ -0,0 +1,283 @@
1
+ # n2n-memory API Reference
2
+
3
+ [中文版](./API_REFERENCE_zh.md)
4
+
5
+ ---
6
+
7
+ N2N-Memory provides project-local knowledge graph tools over MCP. Every tool requires `projectPath`, the absolute path of the project root or workspace top-level directory. The server does not recursively search parent directories; this is intentional to prevent cross-project memory pollution.
8
+
9
+ Project recognition requires a strong marker such as `.git`, `.mcp`, `package.json`, `tsconfig.json`, or a language-specific build file. README-only directories are treated as weak roots and rejected.
10
+
11
+ ## SEO and discoverability notes
12
+
13
+ - Recommended labels: **project-local MCP memory**, **AI coding memory graph**, **local-first AI context storage**.
14
+ - Primary user intent: repository context recovery, deterministic project memory, and safe AI coding assistant handoff.
15
+ - This API is designed for local-first agents and does not depend on cloud infrastructure.
16
+
17
+ ## Shared Parameters
18
+
19
+ All tools include:
20
+
21
+ - `projectPath` (`string`, required): Absolute project root or workspace top-level path.
22
+ - `confirmNewProjectRoot` (`string`, optional): Required only when initializing a project that does not yet have `.mcp`. Use the `detectedRoot` value returned by the handshake response.
23
+
24
+ If the server recognizes a project root but `.mcp` is missing, it returns an `AWAITING_CONFIRMATION` error response. Call the same tool again with `confirmNewProjectRoot` set to the detected root.
25
+
26
+ ## Data Storage
27
+
28
+ - Cold graph: `.mcp/memory.json`
29
+ - Hot context: `.mcp/context.json`
30
+ - Atomic writes: JSON is written to a temporary file and then moved into place.
31
+ - Stable diffs: entities, observations, and relations are sorted before graph writes.
32
+ - Data integrity: existing but unreadable JSON files raise an error instead of being treated as empty memory.
33
+ - Path containment: exported files must stay inside the project root.
34
+ - Logging: full local paths are hidden from server logs by default. Set `N2N_LOG_LEVEL=debug` to include complete paths while troubleshooting.
35
+
36
+ ## Data Model
37
+
38
+ ### Entity
39
+ ```json
40
+ {
41
+ "name": "MemoryService",
42
+ "entityType": "CLASS",
43
+ "observations": ["Coordinates graph and context reads"]
44
+ }
45
+ ```
46
+
47
+ ### Relation
48
+ ```json
49
+ {
50
+ "from": "MemoryService",
51
+ "to": "MemoryManager",
52
+ "relationType": "USES"
53
+ }
54
+ ```
55
+
56
+ Relations must reference existing entities. Orphan relations are rejected.
57
+
58
+ ### Project Context
59
+ ```json
60
+ {
61
+ "activeTask": "Refactor storage layer",
62
+ "status": "IN_PROGRESS",
63
+ "reason": "Optional status reason",
64
+ "nextSteps": ["Run tests"],
65
+ "lastCommit": "abc123 or message",
66
+ "updatedAt": "2026-06-14T00:00:00.000Z"
67
+ }
68
+ ```
69
+
70
+ `updatedAt` is managed by the server when context is written.
71
+
72
+ ## Resources & Templates
73
+
74
+ ### Static Resource
75
+ - **URI**: `mcp://memory/graph`
76
+ - **Note**: Requires the client to manage project path context or use the template below.
77
+
78
+ ### Resource Template
79
+ - **Template**: `mcp://memory/graph?path={path}`
80
+ - **Example**: `mcp://memory/graph?path=/home/deploy/projects/n2n-memory`
81
+ - **Behavior**: Returns the complete graph and active context for established projects. New projects must be initialized through tools because resources cannot perform the confirmation handshake.
82
+
83
+ ## Tool Responses & Metadata
84
+
85
+ Most mutating tools return structured JSON:
86
+
87
+ ```json
88
+ {
89
+ "status": "success",
90
+ "message": "Human-readable description of the operation.",
91
+ "_protocol": {
92
+ "action": "MEMORY_UPDATED",
93
+ "reminder": "Remember to call n2n_update_context before 'git commit'."
94
+ }
95
+ }
96
+ ```
97
+
98
+ The `_protocol` field guides AI assistants during development cycles:
99
+
100
+ - `action`: Logical state change, such as `MEMORY_LOADED`, `MEMORY_UPDATED`, or `CONTEXT_SYNCED`.
101
+ - `reminder`: Synchronization hint for AI assistants.
102
+ - `policy` / `tip`: Context-specific behavior guidance when present.
103
+
104
+ ## Common usage patterns
105
+
106
+ 1. Start each session by calling `n2n_read_graph` with `summaryMode: true` to inspect the project index.
107
+ 2. Add durable facts with `n2n_add_entities` and `n2n_add_observations`.
108
+ 3. Link facts with `n2n_create_relations`.
109
+ 4. Track daily work in `n2n_update_context` before major refactors.
110
+ 5. Before commit, call `n2n_read_graph` again so the context reminder is refreshed.
111
+
112
+ Example `n2n_update_context` payload:
113
+
114
+ ```json
115
+ {
116
+ "projectPath": "/absolute/path/to/repo",
117
+ "activeTask": "Refactor MCP error handling",
118
+ "status": "IN_PROGRESS",
119
+ "nextSteps": ["Run tests", "Update docs"],
120
+ "reason": "Refactor without changing public API"
121
+ }
122
+ ```
123
+
124
+ ## Tools
125
+
126
+ ### `n2n_add_entities`
127
+
128
+ Create new entities or merge observations into existing entities with the same name.
129
+
130
+ Additional input:
131
+
132
+ - `entities` (`Entity[]`, required)
133
+
134
+ Notes:
135
+
136
+ - Existing entity type is preserved.
137
+ - Observations are deduplicated with lightweight similarity checks.
138
+
139
+ ### `n2n_add_observations`
140
+
141
+ Append observations to existing entities.
142
+
143
+ Additional input:
144
+
145
+ - `observations` (`Array<{ entityName: string; contents: string[] }>`, required)
146
+
147
+ Notes:
148
+
149
+ - Observations for missing entities are skipped.
150
+ - The response reports how many observation fragments were actually added after deduplication.
151
+
152
+ ### `n2n_create_relations`
153
+
154
+ Create directed relations between existing entities.
155
+
156
+ Additional input:
157
+
158
+ - `relations` (`Relation[]`, required)
159
+
160
+ Notes:
161
+
162
+ - Duplicate relations are ignored.
163
+ - Relations pointing to missing entities are rejected.
164
+
165
+ ### `n2n_read_graph`
166
+
167
+ Read project graph and active context together.
168
+
169
+ Additional input:
170
+
171
+ - `summaryMode` (`boolean`, optional): Return entity names and types without observations.
172
+ - `limit` (`number`, optional): Maximum entities to return.
173
+ - `offset` (`number`, optional): Number of entities to skip.
174
+
175
+ Output includes:
176
+
177
+ - `graph`
178
+ - `context`
179
+ - `totalEntityCount`
180
+ - `isTruncated`
181
+ - `_protocol`
182
+
183
+ When paginated, relations are included only when both endpoints are present in the current page.
184
+
185
+ ### `n2n_get_graph_summary`
186
+
187
+ Return a lightweight entity index plus total relation count.
188
+
189
+ Additional input:
190
+
191
+ - `limit` (`number`, optional)
192
+ - `offset` (`number`, optional)
193
+
194
+ Output includes:
195
+
196
+ - `entities`: `{ name, type }[]`
197
+ - `relationCount`
198
+ - `totalEntityCount`
199
+ - `isTruncated`
200
+
201
+ ### `n2n_update_context`
202
+
203
+ Update hot project context.
204
+
205
+ Additional input:
206
+
207
+ - `activeTask` (`string`, optional)
208
+ - `status` (`"IN_PROGRESS" | "COMPLETED" | "BLOCKED" | "PLANNING"`, optional)
209
+ - `reason` (`string`, optional)
210
+ - `nextSteps` (`string[]`, optional)
211
+ - `lastCommit` (`string`, optional)
212
+
213
+ Notes:
214
+
215
+ - Updates are merged with the current context.
216
+ - `updatedAt` is set automatically.
217
+
218
+ ### `n2n_search`
219
+
220
+ Search entities by name, type, and observations. Fuzzy matching is enabled by default.
221
+
222
+ Additional input:
223
+
224
+ - `query` (`string`, required)
225
+ - `limit` (`number`, optional)
226
+ - `offset` (`number`, optional)
227
+ - `fuzzy` (`boolean`, optional, default `true`)
228
+ - `minScore` (`number`, optional, default `0.3`)
229
+
230
+ Output includes matching entities, related relations, `totalResults`, and `isTruncated`.
231
+
232
+ ### `n2n_delete_entities`
233
+
234
+ Delete entities and all relations attached to them.
235
+
236
+ Additional input:
237
+
238
+ - `entityNames` (`string[]`, required)
239
+
240
+ Output reports the number of deleted entities.
241
+
242
+ ### `n2n_delete_observations`
243
+
244
+ Delete exact observation strings from entities.
245
+
246
+ Additional input:
247
+
248
+ - `deletions` (`Array<{ entityName: string; observations: string[] }>`, required)
249
+
250
+ Output reports the number of deleted observations.
251
+
252
+ ### `n2n_delete_relations`
253
+
254
+ Delete exact relation triples.
255
+
256
+ Additional input:
257
+
258
+ - `relations` (`Relation[]`, required)
259
+
260
+ Output reports the number of deleted relations.
261
+
262
+ ### `n2n_open_nodes`
263
+
264
+ Retrieve specific entities by name.
265
+
266
+ Additional input:
267
+
268
+ - `names` (`string[]`, required)
269
+
270
+ Output includes matching entities and relations where both endpoints are among the returned entities.
271
+
272
+ ### `n2n_export_markdown`
273
+
274
+ Export the graph to Markdown for review or documentation.
275
+
276
+ Additional input:
277
+
278
+ - `outputPath` (`string`, optional): Relative output path inside the project root. Defaults to `KNOWLEDGE_GRAPH.md`.
279
+
280
+ Notes:
281
+
282
+ - Absolute paths are rejected.
283
+ - Relative paths that escape the project root are rejected.
@@ -0,0 +1,283 @@
1
+ # n2n-memory API 参考手册
2
+
3
+ [English](./API_REFERENCE.md)
4
+
5
+ ---
6
+
7
+ N2N-Memory 通过 MCP 提供项目本地知识图谱工具。所有工具都要求传入 `projectPath`,即项目根目录或工作区顶级目录的绝对路径。服务不会递归向上搜索父目录,这是为了避免跨项目记忆污染。
8
+
9
+ 项目识别要求存在 `.git`、`.mcp`、`package.json`、`tsconfig.json` 或语言构建文件等强标记。只有 README 的目录会被视为弱根目录并被拒绝。
10
+
11
+ ## SEO 与可发现性说明
12
+
13
+ - 推荐检索词:**项目级 MCP memory**、**AI 编码记忆图谱**、**本地优先 AI 上下文存储**。
14
+ - 主要使用意图:仓库上下文恢复、确定性的项目记忆、与 AI 编码助手的安全交接。
15
+ - 本 API 采用本地优先设计,不依赖云端服务。
16
+
17
+ ## 共享参数
18
+
19
+ 所有工具都包含:
20
+
21
+ - `projectPath`(`string`,必填):项目根目录或工作区顶级目录的绝对路径。
22
+ - `confirmNewProjectRoot`(`string`,可选):仅在初始化尚未创建 `.mcp` 的项目时使用。取值应为握手响应中的 `detectedRoot`。
23
+
24
+ 如果服务识别到项目根目录,但 `.mcp` 尚不存在,会返回 `AWAITING_CONFIRMATION` 错误响应。此时使用同一个工具再次调用,并将 `confirmNewProjectRoot` 设置为返回的 `detectedRoot`。
25
+
26
+ ## 数据存储
27
+
28
+ - 冷知识图谱:`.mcp/memory.json`
29
+ - 热任务上下文:`.mcp/context.json`
30
+ - 原子写入:JSON 先写入临时文件,再移动到目标位置。
31
+ - 稳定 diff:写入图谱前会对实体、观测事实、关系执行排序。
32
+ - 数据完整性:已存在但无法读取的 JSON 文件会抛错,不会被当成空记忆。
33
+ - 路径边界:导出文件必须保留在项目根目录内部。
34
+ - 日志:服务日志默认隐藏完整本地路径。排查问题时可设置 `N2N_LOG_LEVEL=debug` 输出完整路径。
35
+
36
+ ## 数据模型
37
+
38
+ ### Entity
39
+ ```json
40
+ {
41
+ "name": "MemoryService",
42
+ "entityType": "CLASS",
43
+ "observations": ["Coordinates graph and context reads"]
44
+ }
45
+ ```
46
+
47
+ ### Relation
48
+ ```json
49
+ {
50
+ "from": "MemoryService",
51
+ "to": "MemoryManager",
52
+ "relationType": "USES"
53
+ }
54
+ ```
55
+
56
+ 关系必须指向已存在实体。指向不存在实体的孤儿关系会被拒绝。
57
+
58
+ ### Project Context
59
+ ```json
60
+ {
61
+ "activeTask": "Refactor storage layer",
62
+ "status": "IN_PROGRESS",
63
+ "reason": "Optional status reason",
64
+ "nextSteps": ["Run tests"],
65
+ "lastCommit": "abc123 or message",
66
+ "updatedAt": "2026-06-14T00:00:00.000Z"
67
+ }
68
+ ```
69
+
70
+ `updatedAt` 由服务在写入上下文时自动维护。
71
+
72
+ ## 资源与模板
73
+
74
+ ### 静态资源
75
+ - **URI**: `mcp://memory/graph`
76
+ - **注意**: 要求客户端手动管理项目路径上下文,或使用下方的资源模板。
77
+
78
+ ### 资源模板
79
+ - **模板**: `mcp://memory/graph?path={path}`
80
+ - **示例**: `mcp://memory/graph?path=/home/deploy/projects/n2n-memory`
81
+ - **行为**: 对已初始化项目返回完整图谱与活跃上下文。新项目必须通过工具完成确认握手,因为资源读取无法携带初始化确认参数。
82
+
83
+ ## 工具响应与元数据
84
+
85
+ 多数写入工具返回结构化 JSON:
86
+
87
+ ```json
88
+ {
89
+ "status": "success",
90
+ "message": "操作的人类可读描述。",
91
+ "_protocol": {
92
+ "action": "MEMORY_UPDATED",
93
+ "reminder": "Remember to call n2n_update_context before 'git commit'."
94
+ }
95
+ }
96
+ ```
97
+
98
+ `_protocol` 字段用于在开发周期内引导 AI 助手:
99
+
100
+ - `action`:逻辑状态变更,例如 `MEMORY_LOADED`、`MEMORY_UPDATED` 或 `CONTEXT_SYNCED`。
101
+ - `reminder`:给 AI 助手的同步提醒。
102
+ - `policy` / `tip`:存在时表示特定上下文下的行为提示。
103
+
104
+ ## 常见使用流程
105
+
106
+ 1. 会话开始时先调用 `n2n_read_graph`,可用 `summaryMode: true` 获取项目实体索引。
107
+ 2. 用 `n2n_add_entities`、`n2n_add_observations` 写入长期事实。
108
+ 3. 用 `n2n_create_relations` 建立关系。
109
+ 4. 在关键阶段用 `n2n_update_context` 记录任务进展。
110
+ 5. 提交前再次调用 `n2n_read_graph`,让上下文同步提醒保持最新。
111
+
112
+ `n2n_update_context` 示例:
113
+
114
+ ```json
115
+ {
116
+ "projectPath": "/absolute/path/to/repo",
117
+ "activeTask": "重构 MCP 错误处理",
118
+ "status": "IN_PROGRESS",
119
+ "nextSteps": ["运行测试", "更新文档"],
120
+ "reason": "在不改动外部行为的前提下优化上下文"
121
+ }
122
+ ```
123
+
124
+ ## 工具
125
+
126
+ ### `n2n_add_entities`
127
+
128
+ 创建新实体,或将观测事实合并到同名实体。
129
+
130
+ 额外输入:
131
+
132
+ - `entities`(`Entity[]`,必填)
133
+
134
+ 说明:
135
+
136
+ - 已存在实体的 `entityType` 会保留。
137
+ - 观测事实会通过轻量相似度规则去重。
138
+
139
+ ### `n2n_add_observations`
140
+
141
+ 向已存在实体追加观测事实。
142
+
143
+ 额外输入:
144
+
145
+ - `observations`(`Array<{ entityName: string; contents: string[] }>`,必填)
146
+
147
+ 说明:
148
+
149
+ - 指向不存在实体的观测事实会被跳过。
150
+ - 响应会报告去重后实际新增的观测事实数量。
151
+
152
+ ### `n2n_create_relations`
153
+
154
+ 在已存在实体之间创建有向关系。
155
+
156
+ 额外输入:
157
+
158
+ - `relations`(`Relation[]`,必填)
159
+
160
+ 说明:
161
+
162
+ - 重复关系会被忽略。
163
+ - 指向不存在实体的关系会被拒绝。
164
+
165
+ ### `n2n_read_graph`
166
+
167
+ 同时读取项目知识图谱和活跃上下文。
168
+
169
+ 额外输入:
170
+
171
+ - `summaryMode`(`boolean`,可选):只返回实体名称和类型,不返回观测事实。
172
+ - `limit`(`number`,可选):最多返回多少个实体。
173
+ - `offset`(`number`,可选):跳过多少个实体。
174
+
175
+ 输出包含:
176
+
177
+ - `graph`
178
+ - `context`
179
+ - `totalEntityCount`
180
+ - `isTruncated`
181
+ - `_protocol`
182
+
183
+ 分页读取时,只有当关系两端实体都在当前页中,该关系才会返回。
184
+
185
+ ### `n2n_get_graph_summary`
186
+
187
+ 返回轻量实体索引和关系总数。
188
+
189
+ 额外输入:
190
+
191
+ - `limit`(`number`,可选)
192
+ - `offset`(`number`,可选)
193
+
194
+ 输出包含:
195
+
196
+ - `entities`:`{ name, type }[]`
197
+ - `relationCount`
198
+ - `totalEntityCount`
199
+ - `isTruncated`
200
+
201
+ ### `n2n_update_context`
202
+
203
+ 更新热任务上下文。
204
+
205
+ 额外输入:
206
+
207
+ - `activeTask`(`string`,可选)
208
+ - `status`(`"IN_PROGRESS" | "COMPLETED" | "BLOCKED" | "PLANNING"`,可选)
209
+ - `reason`(`string`,可选)
210
+ - `nextSteps`(`string[]`,可选)
211
+ - `lastCommit`(`string`,可选)
212
+
213
+ 说明:
214
+
215
+ - 更新会与当前上下文合并。
216
+ - `updatedAt` 会自动写入。
217
+
218
+ ### `n2n_search`
219
+
220
+ 按实体名称、类型、观测事实搜索图谱。默认启用模糊匹配。
221
+
222
+ 额外输入:
223
+
224
+ - `query`(`string`,必填)
225
+ - `limit`(`number`,可选)
226
+ - `offset`(`number`,可选)
227
+ - `fuzzy`(`boolean`,可选,默认 `true`)
228
+ - `minScore`(`number`,可选,默认 `0.3`)
229
+
230
+ 输出包含匹配实体、相关关系、`totalResults` 与 `isTruncated`。
231
+
232
+ ### `n2n_delete_entities`
233
+
234
+ 删除实体及其关联关系。
235
+
236
+ 额外输入:
237
+
238
+ - `entityNames`(`string[]`,必填)
239
+
240
+ 输出会报告删除的实体数量。
241
+
242
+ ### `n2n_delete_observations`
243
+
244
+ 从实体中删除精确匹配的观测事实字符串。
245
+
246
+ 额外输入:
247
+
248
+ - `deletions`(`Array<{ entityName: string; observations: string[] }>`,必填)
249
+
250
+ 输出会报告删除的观测事实数量。
251
+
252
+ ### `n2n_delete_relations`
253
+
254
+ 删除精确匹配的关系三元组。
255
+
256
+ 额外输入:
257
+
258
+ - `relations`(`Relation[]`,必填)
259
+
260
+ 输出会报告删除的关系数量。
261
+
262
+ ### `n2n_open_nodes`
263
+
264
+ 按名称读取指定实体。
265
+
266
+ 额外输入:
267
+
268
+ - `names`(`string[]`,必填)
269
+
270
+ 输出包含匹配实体,以及两端都在返回实体集合内的关系。
271
+
272
+ ### `n2n_export_markdown`
273
+
274
+ 将图谱导出为 Markdown,便于审阅或生成文档。
275
+
276
+ 额外输入:
277
+
278
+ - `outputPath`(`string`,可选):项目根目录内的相对输出路径,默认 `KNOWLEDGE_GRAPH.md`。
279
+
280
+ 说明:
281
+
282
+ - 绝对路径会被拒绝。
283
+ - 试图逃逸项目根目录的相对路径会被拒绝。