n2n-nexus 0.4.2 → 0.6.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/CHANGELOG.md +87 -0
- package/README.md +74 -117
- package/assets/n2n-nexus-banner.jpg +0 -0
- package/assets/n2n-nexus-icon.png +0 -0
- package/assets/n2n-nexus-logo.png +0 -0
- package/build/client/nexus-client.js +30 -14
- package/build/config/cli.js +0 -3
- package/build/config/index.js +0 -10
- package/build/constants.js +7 -11
- package/build/daemon/index.js +35 -19
- package/build/daemon/rate-limit.js +62 -0
- package/build/daemon/server.js +349 -542
- package/build/daemon/tool-outputs.js +155 -0
- package/build/daemon/tools.js +271 -0
- package/build/index.js +1 -1
- package/build/server/instance-id.js +19 -0
- package/build/server/nexus.js +152 -43
- package/build/storage/docs.js +14 -7
- package/build/storage/events.js +31 -0
- package/build/storage/fs-utils.js +42 -0
- package/build/storage/global-messages.js +44 -0
- package/build/storage/index.js +44 -41
- package/build/storage/migrations.js +79 -0
- package/build/storage/paths.js +0 -3
- package/build/storage/projects.js +4 -5
- package/build/storage/registry.js +67 -25
- package/build/storage/sqlite-meeting.js +35 -23
- package/build/storage/sqlite.js +41 -24
- package/build/storage/tasks.js +29 -103
- package/build/types.js +1 -1
- package/docs/ARCHITECTURE.md +29 -20
- package/docs/ARCHITECTURE_zh.md +29 -20
- package/docs/ASSISTANT_GUIDE.md +70 -67
- package/docs/README_zh.md +25 -15
- package/llms.txt +11 -1
- package/package.json +24 -14
- package/build/storage/logs.js +0 -60
- package/build/storage/meetings.js +0 -276
- package/build/storage/store.js +0 -153
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -28,7 +28,7 @@ Stateless protocol adapter, one per IDE
|
|
|
28
28
|
1. **Daemon is the single source of truth** — all reads/writes, business logic, and tool definitions live in the daemon.
|
|
29
29
|
2. **MCP is a stateless protocol adapter** — no tool definitions, no hardcoded names, no local data.
|
|
30
30
|
3. **Daemon decides tool capability** — MCP fetches `GET /api/tools` at startup; any daemon upgrade is immediately visible to all connected MCPs.
|
|
31
|
-
4. **No local fallback** — if the daemon is unreachable, the MCP reports an error and retries every 3 s. No split-brain degradation.
|
|
31
|
+
4. **No local fallback** — if the daemon is unreachable, the MCP reports an error and retries every 3 s. No split-brain degradation. A tool call the daemon rejects (validation, not found, permission) is returned to the IDE as an error result (`isError: true`) and does not affect the connection; an unknown tool name is a JSON-RPC `-32602` error.
|
|
32
32
|
5. **Plain HTTP between MCP and daemon** — no SSE; AI is request-driven and doesn't need push.
|
|
33
33
|
|
|
34
34
|
### MCP Startup Flow
|
|
@@ -36,20 +36,21 @@ Stateless protocol adapter, one per IDE
|
|
|
36
36
|
```
|
|
37
37
|
Read NEXUS_ENDPOINT (default: http://127.0.0.1:5688)
|
|
38
38
|
│
|
|
39
|
-
├─
|
|
39
|
+
├─ Serve stdio (MCP TypeScript SDK v2, serveStdio) and GET /api/tools once;
|
|
40
|
+
│ the first tools/list waits up to 1 s for that fetch
|
|
41
|
+
│ ├─ 2026-07-28 clients: server/discover, per-request _meta envelope,
|
|
42
|
+
│ │ list_changed delivered on subscriptions/listen
|
|
43
|
+
│ └─ 2025-era clients: initialize handshake, unsolicited list_changed
|
|
40
44
|
│
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
│
|
|
47
|
-
└─ GET /api/tools succeeds
|
|
48
|
-
→ cache tool list
|
|
49
|
-
→ send notifications/tools/list_changed
|
|
50
|
-
→ IDE re-fetches: tools appear
|
|
45
|
+
├─ If the daemon was down: retry loop (every 3 s)
|
|
46
|
+
│ └─ GET /api/tools succeeds → cache tool list
|
|
47
|
+
│ → notifications/tools/list_changed → IDE re-fetches
|
|
48
|
+
│
|
|
49
|
+
└─ stdin closes → stop retrying, close, exit
|
|
51
50
|
```
|
|
52
51
|
|
|
52
|
+
The adapter's instance ID (read cursors, meeting permissions) uses the first client name seen on the connection, from the request's `io.modelcontextprotocol/clientInfo` (2026-07-28) or from `initialize` (2025 era), unless `NEXUS_INSTANCE_ID` / `--id` pins it.
|
|
53
|
+
|
|
53
54
|
---
|
|
54
55
|
|
|
55
56
|
## 💾 Data Persistence
|
|
@@ -60,7 +61,6 @@ All data lives under the daemon's storage root (default `~/.n2n-nexus`):
|
|
|
60
61
|
~/.n2n-nexus/
|
|
61
62
|
├── global/
|
|
62
63
|
│ ├── blueprint.md # Master strategy document
|
|
63
|
-
│ ├── discussion.json # Global chat (JSON fallback)
|
|
64
64
|
│ ├── docs_index.json # Global docs index
|
|
65
65
|
│ └── docs/ # Shared markdown documents
|
|
66
66
|
├── projects/
|
|
@@ -68,14 +68,17 @@ All data lives under the daemon's storage root (default `~/.n2n-nexus`):
|
|
|
68
68
|
│ ├── manifest.json # Project metadata
|
|
69
69
|
│ ├── internal_blueprint.md # Internal technical docs
|
|
70
70
|
│ └── assets/ # Binary assets (images, PDFs)
|
|
71
|
-
├── meetings/ # Meeting files (JSON fallback mode)
|
|
72
71
|
├── registry.json # Global project index
|
|
73
|
-
└── nexus.db # SQLite database (meetings, tasks, cursors)
|
|
72
|
+
└── nexus.db # SQLite database (meetings, global chat, events, tasks, cursors)
|
|
74
73
|
```
|
|
75
74
|
|
|
76
|
-
**SQLite WAL mode**: Only the daemon process
|
|
75
|
+
**SQLite WAL mode**: Only the daemon process opens the database. MCP adapters never touch it — they go through HTTP.
|
|
76
|
+
|
|
77
|
+
**File-store writes**: HTTP requests are handled concurrently, so every mutation of `registry.json`, manifests and the docs index is queued behind one daemon-wide lock and written atomically (temp file + rename).
|
|
77
78
|
|
|
78
|
-
**
|
|
79
|
+
**Activity log**: state changes made through the daemon (project sync/rename/delete, meeting start/end, doc sync, ...) are recorded as structured events in SQLite and read with `list_events` / `GET /api/events`; they are not mixed into chat streams.
|
|
80
|
+
|
|
81
|
+
**Self-healing**: `registry.json` is auto-repaired if corrupted or missing.
|
|
79
82
|
|
|
80
83
|
---
|
|
81
84
|
|
|
@@ -148,32 +151,34 @@ POST /api/tools/call Execute tool call { tool, args, instanceId }
|
|
|
148
151
|
### System
|
|
149
152
|
```
|
|
150
153
|
GET /health Health status + version
|
|
151
|
-
GET /api/storage/info Storage mode and stats
|
|
152
154
|
```
|
|
153
155
|
|
|
154
|
-
###
|
|
156
|
+
### Projects
|
|
155
157
|
```
|
|
156
|
-
POST /api/session/register
|
|
157
158
|
POST /api/projects/sync
|
|
158
159
|
POST /api/projects/update
|
|
159
160
|
POST /api/projects/rename
|
|
160
161
|
POST /api/projects/delete
|
|
161
162
|
GET /api/projects/search
|
|
162
163
|
GET /api/projects/topology
|
|
164
|
+
GET /api/projects/:projectId
|
|
163
165
|
```
|
|
164
166
|
|
|
165
167
|
### Messages & Global
|
|
166
168
|
```
|
|
167
169
|
POST /api/messages/send
|
|
168
170
|
GET /api/messages/unread
|
|
171
|
+
GET /api/events
|
|
169
172
|
GET /api/global/docs
|
|
170
173
|
GET /api/global/docs/:docId
|
|
171
174
|
POST /api/global/docs/:docId
|
|
175
|
+
GET /api/global/strategy
|
|
172
176
|
POST /api/global/strategy
|
|
173
177
|
```
|
|
174
178
|
|
|
175
179
|
### Meetings
|
|
176
180
|
```
|
|
181
|
+
GET /api/meetings
|
|
177
182
|
POST /api/meetings/start
|
|
178
183
|
POST /api/meetings/end
|
|
179
184
|
POST /api/meetings/archive
|
|
@@ -197,6 +202,10 @@ POST /api/maintenance/logs
|
|
|
197
202
|
|
|
198
203
|
---
|
|
199
204
|
|
|
205
|
+
### Request guards
|
|
206
|
+
|
|
207
|
+
The daemon rejects browser-originated requests (`Origin` header or cross-site `Sec-Fetch-Site`: 403), `Host` names that are neither IP literals nor local/allow-listed names (403, prevents DNS rebinding), non-JSON POST bodies (415) and bodies above 16 MB (413). Tool calls are rate limited per instance and per client address (429 with `Retry-After`). See `SECURITY.md`.
|
|
208
|
+
|
|
200
209
|
## Scope Boundaries
|
|
201
210
|
|
|
202
211
|
- No cloud bridge by default.
|
package/docs/ARCHITECTURE_zh.md
CHANGED
|
@@ -28,7 +28,7 @@ MCP-A MCP-B MCP-C
|
|
|
28
28
|
1. **Daemon 是唯一的真相来源** — 所有读写、业务逻辑和工具定义都在 daemon 侧。
|
|
29
29
|
2. **MCP 是无状态协议适配器** — 不含工具定义、不含 hardcode 工具名、不存本地数据。
|
|
30
30
|
3. **Daemon 决定工具能力** — MCP 启动时拉取 `GET /api/tools`;daemon 升级新工具后,所有已连接 MCP 立即获得新能力,无需更新。
|
|
31
|
-
4. **无本地降级** — daemon 不可达时,MCP 每 3 秒重试并报告错误,不做本地 fallback(避免数据分裂)。
|
|
31
|
+
4. **无本地降级** — daemon 不可达时,MCP 每 3 秒重试并报告错误,不做本地 fallback(避免数据分裂)。daemon 拒绝的工具调用(校验失败、不存在、无权限)作为错误结果(`isError: true`)返回给 IDE,不影响连接;未知工具名返回 JSON-RPC `-32602` 错误。
|
|
32
32
|
5. **MCP ↔ Daemon 全部走普通 HTTP** — 不使用 SSE;AI 是请求驱动模型,不需要推送。
|
|
33
33
|
|
|
34
34
|
### MCP 启动流程
|
|
@@ -36,20 +36,21 @@ MCP-A MCP-B MCP-C
|
|
|
36
36
|
```
|
|
37
37
|
读取 NEXUS_ENDPOINT(默认 http://127.0.0.1:5688)
|
|
38
38
|
│
|
|
39
|
-
├─
|
|
39
|
+
├─ 开始 stdio 服务(MCP TypeScript SDK v2,serveStdio),同时拉一次 GET /api/tools;
|
|
40
|
+
│ 第一次 tools/list 最多等这次拉取 1 秒
|
|
41
|
+
│ ├─ 2026-07-28 客户端:server/discover、每请求 _meta 信封,
|
|
42
|
+
│ │ list_changed 经 subscriptions/listen 下发
|
|
43
|
+
│ └─ 2025 代客户端:initialize 握手,主动下发 list_changed
|
|
40
44
|
│
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
│
|
|
47
|
-
└─ GET /api/tools 成功
|
|
48
|
-
→ 缓存工具列表
|
|
49
|
-
→ 发送 notifications/tools/list_changed
|
|
50
|
-
→ IDE 重新拉取,工具出现
|
|
45
|
+
├─ 若 daemon 不在线:重试循环(每 3 秒)
|
|
46
|
+
│ └─ GET /api/tools 成功 → 缓存工具列表
|
|
47
|
+
│ → notifications/tools/list_changed → IDE 重新拉取
|
|
48
|
+
│
|
|
49
|
+
└─ stdin 关闭 → 停止重试、关闭、退出
|
|
51
50
|
```
|
|
52
51
|
|
|
52
|
+
适配器的实例 ID(未读游标、会议权限以它为键)取自该连接上第一次见到的客户端名,来源是请求 `_meta` 中的 `io.modelcontextprotocol/clientInfo`(2026-07-28)或 `initialize`(2025 代),`NEXUS_INSTANCE_ID` / `--id` 可固定。
|
|
53
|
+
|
|
53
54
|
---
|
|
54
55
|
|
|
55
56
|
## 💾 数据持久化
|
|
@@ -60,7 +61,6 @@ MCP-A MCP-B MCP-C
|
|
|
60
61
|
~/.n2n-nexus/
|
|
61
62
|
├── global/
|
|
62
63
|
│ ├── blueprint.md # 主战略文档
|
|
63
|
-
│ ├── discussion.json # 全局聊天(JSON 回退)
|
|
64
64
|
│ ├── docs_index.json # 全局文档索引
|
|
65
65
|
│ └── docs/ # 共享 Markdown 文档
|
|
66
66
|
├── projects/
|
|
@@ -68,14 +68,17 @@ MCP-A MCP-B MCP-C
|
|
|
68
68
|
│ ├── manifest.json # 项目元数据
|
|
69
69
|
│ ├── internal_blueprint.md # 内部技术文档
|
|
70
70
|
│ └── assets/ # 二进制资产(图片、PDF)
|
|
71
|
-
├── meetings/ # 会议文件(JSON 回退模式)
|
|
72
71
|
├── registry.json # 全局项目索引
|
|
73
|
-
└── nexus.db # SQLite
|
|
72
|
+
└── nexus.db # SQLite 数据库(会议、全局聊天、事件、任务、游标)
|
|
74
73
|
```
|
|
75
74
|
|
|
76
|
-
**SQLite WAL 模式**:只有 daemon
|
|
75
|
+
**SQLite WAL 模式**:只有 daemon 进程打开数据库。MCP 适配器不直接访问,全部经由 HTTP。
|
|
76
|
+
|
|
77
|
+
**文件存储写入**:HTTP 请求是并发处理的,因此对 `registry.json`、manifest 和文档索引的每次修改都排在一把 daemon 级写锁后面,并以原子方式写入(临时文件 + rename)。
|
|
77
78
|
|
|
78
|
-
|
|
79
|
+
**活动日志**:经由 daemon 发生的状态变更(项目同步/重命名/删除、会议开始/结束、文档同步等)以结构化事件记录在 SQLite 中,通过 `list_events` / `GET /api/events` 读取,不混入聊天流。
|
|
80
|
+
|
|
81
|
+
**自我修复**:`registry.json` 在损坏或丢失时自动重建初始状态。
|
|
79
82
|
|
|
80
83
|
---
|
|
81
84
|
|
|
@@ -148,32 +151,34 @@ POST /api/tools/call 执行工具调用 { tool, args, instanceId }
|
|
|
148
151
|
### 系统
|
|
149
152
|
```
|
|
150
153
|
GET /health 健康状态 + 版本信息
|
|
151
|
-
GET /api/storage/info 存储模式和统计
|
|
152
154
|
```
|
|
153
155
|
|
|
154
|
-
###
|
|
156
|
+
### 项目
|
|
155
157
|
```
|
|
156
|
-
POST /api/session/register
|
|
157
158
|
POST /api/projects/sync
|
|
158
159
|
POST /api/projects/update
|
|
159
160
|
POST /api/projects/rename
|
|
160
161
|
POST /api/projects/delete
|
|
161
162
|
GET /api/projects/search
|
|
162
163
|
GET /api/projects/topology
|
|
164
|
+
GET /api/projects/:projectId
|
|
163
165
|
```
|
|
164
166
|
|
|
165
167
|
### 消息与全局协作
|
|
166
168
|
```
|
|
167
169
|
POST /api/messages/send
|
|
168
170
|
GET /api/messages/unread
|
|
171
|
+
GET /api/events
|
|
169
172
|
GET /api/global/docs
|
|
170
173
|
GET /api/global/docs/:docId
|
|
171
174
|
POST /api/global/docs/:docId
|
|
175
|
+
GET /api/global/strategy
|
|
172
176
|
POST /api/global/strategy
|
|
173
177
|
```
|
|
174
178
|
|
|
175
179
|
### 会议
|
|
176
180
|
```
|
|
181
|
+
GET /api/meetings
|
|
177
182
|
POST /api/meetings/start
|
|
178
183
|
POST /api/meetings/end
|
|
179
184
|
POST /api/meetings/archive
|
|
@@ -197,6 +202,10 @@ POST /api/maintenance/logs
|
|
|
197
202
|
|
|
198
203
|
---
|
|
199
204
|
|
|
205
|
+
### 请求防护
|
|
206
|
+
|
|
207
|
+
daemon 拒绝来自浏览器的请求(带 `Origin` 头或跨站 `Sec-Fetch-Site`:403)、既非 IP 也不在本地/允许列表中的 `Host`(403,防 DNS rebinding)、非 JSON 的 POST 请求体(415)以及超过 16 MB 的请求体(413)。工具调用按实例和客户端地址限流(429,带 `Retry-After`)。详见 `SECURITY.md`。
|
|
208
|
+
|
|
200
209
|
## 边界说明
|
|
201
210
|
|
|
202
211
|
- 不默认提供云端桥接。
|
package/docs/ASSISTANT_GUIDE.md
CHANGED
|
@@ -1,120 +1,123 @@
|
|
|
1
1
|
# Nexus Assistant Guide
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
You are now part of the **n2ns Nexus** coordination network. All capabilities are provided by a standalone **daemon** — every tool you use is defined and executed by the daemon. The MCP adapter is a transparent forwarding layer only.
|
|
4
4
|
|
|
5
|
-
>
|
|
5
|
+
> **Prerequisite**: Before calling any tool, confirm that the daemon is running (`n2n-nexus daemon --port 5688`) and that your MCP is connected (a non-empty tool list means you are connected).
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Core principle: discover first, then act
|
|
10
10
|
|
|
11
|
-
### 1.
|
|
11
|
+
### 1. Understand the global system state
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Before starting any task, use these tools to orient yourself:
|
|
14
14
|
|
|
15
15
|
```
|
|
16
|
-
get_global_topology() →
|
|
17
|
-
get_global_topology(projectId) →
|
|
18
|
-
search_projects(query) →
|
|
19
|
-
|
|
16
|
+
get_global_topology() → summary list of all projects + dependency stats
|
|
17
|
+
get_global_topology(projectId) → detailed dependency sub-graph for one project
|
|
18
|
+
search_projects(query) → search projects by name or description
|
|
19
|
+
get_project(projectId) → full manifest + internal docs of one project
|
|
20
|
+
read_messages(count) → fetch messages you have not yet read (incremental, auto-cursor)
|
|
20
21
|
```
|
|
21
22
|
|
|
22
|
-
### 2.
|
|
23
|
+
### 2. Project IDs
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
There is no session to set up: every project tool takes the `projectId` it acts on.
|
|
26
|
+
Project IDs must follow `[prefix]_[name]` format, for example: `web_my-site`, `api_user-auth`, `mcp_nexus`.
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
register_session_context(projectId) → 绑定当前会话到指定项目
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
项目 ID 格式必须为 `[prefix]_[name]`,例如:`web_datafrog.io`、`api_user-auth`、`mcp_nexus`。
|
|
31
|
-
|
|
32
|
-
### 3. 项目数据写入
|
|
28
|
+
### 3. Write project data
|
|
33
29
|
|
|
34
30
|
```
|
|
35
|
-
sync_project_assets(manifest, internalDocs) →
|
|
36
|
-
update_project(projectId, patch) →
|
|
37
|
-
rename_project(oldId, newId) →
|
|
38
|
-
upload_project_asset(fileName, base64Content) →
|
|
31
|
+
sync_project_assets(manifest, internalDocs) → sync full project data
|
|
32
|
+
update_project(projectId, patch) → partial update of manifest fields
|
|
33
|
+
rename_project(oldId, newId) → rename and cascade-update all references
|
|
34
|
+
upload_project_asset(projectId, fileName, base64Content) → upload a binary file to the project store
|
|
39
35
|
```
|
|
40
36
|
|
|
41
|
-
|
|
37
|
+
All write tools run synchronously and return their result directly.
|
|
42
38
|
|
|
43
|
-
### 4.
|
|
39
|
+
### 4. Messages and collaboration
|
|
44
40
|
|
|
45
41
|
```
|
|
46
|
-
send_message(message, category?)
|
|
47
|
-
read_messages(count?, meetingId?) →
|
|
48
|
-
|
|
49
|
-
|
|
42
|
+
send_message(message, category?, meetingId?) → post to meetingId, else the active meeting, else global chat
|
|
43
|
+
read_messages(count?, meetingId?) → read your unread messages (incremental)
|
|
44
|
+
list_events(limit?, action?) → structured activity log (project.sync, meeting.end, ...)
|
|
45
|
+
get_global_strategy() → read the master strategy document
|
|
46
|
+
update_global_strategy(content) → overwrite the master strategy document
|
|
47
|
+
list_global_docs() → list cross-project shared documents
|
|
48
|
+
get_global_doc(docId) → read a shared document
|
|
49
|
+
sync_global_doc(docId, title, content) → create or update a cross-project shared document
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
- `CHAT` — 普通讨论(默认)
|
|
54
|
-
- `PROPOSAL` — 提案
|
|
55
|
-
- `DECISION` — 决策/共识
|
|
56
|
-
- `UPDATE` — 进度更新
|
|
57
|
-
- `MEETING_START` — 系统用,无需手动设置
|
|
52
|
+
Message categories (`category`):
|
|
58
53
|
|
|
59
|
-
|
|
54
|
+
- `CHAT` — general discussion (default)
|
|
55
|
+
- `PROPOSAL` — a proposal for others to review
|
|
56
|
+
- `DECISION` — a locked consensus or decision
|
|
57
|
+
- `UPDATE` — a progress update
|
|
58
|
+
- `MEETING_START` — set by the system; do not set manually
|
|
59
|
+
|
|
60
|
+
### 5. Tactical meetings
|
|
60
61
|
|
|
61
62
|
```
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
send_message("...", "
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
list_meetings(status?, limit?) → list meetings with status, participants, counts, summary
|
|
64
|
+
start_meeting(topic) → open a meeting, returns meetingId
|
|
65
|
+
send_message("...", "PROPOSAL") → post a proposal inside the meeting
|
|
66
|
+
send_message("...", "DECISION") → record a decision
|
|
67
|
+
end_meeting(meetingId?, summary?) → close and lock the meeting
|
|
68
|
+
archive_meeting(meetingId) → move to archive (read-only)
|
|
69
|
+
reopen_meeting(meetingId) → reactivate a closed or archived meeting
|
|
68
70
|
```
|
|
69
71
|
|
|
70
|
-
### 6.
|
|
72
|
+
### 6. Task tracking
|
|
71
73
|
|
|
72
74
|
```
|
|
73
|
-
create_task(source_meeting_id?, metadata?) →
|
|
74
|
-
get_task(taskId) →
|
|
75
|
-
list_tasks(status?) →
|
|
76
|
-
cancel_task(taskId) →
|
|
75
|
+
create_task(source_meeting_id?, metadata?) → create a task you manage yourself, returns taskId
|
|
76
|
+
get_task(taskId) → query status and progress
|
|
77
|
+
list_tasks(status?) → list all tasks
|
|
78
|
+
cancel_task(taskId) → cancel a pending or running task
|
|
77
79
|
```
|
|
78
80
|
|
|
79
|
-
### 7.
|
|
81
|
+
### 7. Maintenance
|
|
80
82
|
|
|
81
83
|
```
|
|
82
|
-
host_maintenance(action, count) → prune
|
|
83
|
-
host_delete_project(projectId) →
|
|
84
|
+
host_maintenance(action, count) → prune the oldest N global messages / clear all
|
|
85
|
+
host_delete_project(projectId) → permanently delete a project (irreversible)
|
|
84
86
|
```
|
|
85
87
|
|
|
86
88
|
---
|
|
87
89
|
|
|
88
|
-
##
|
|
90
|
+
## Typical workflows
|
|
91
|
+
|
|
92
|
+
### First connection to the system
|
|
89
93
|
|
|
90
|
-
### 首次接入系统
|
|
91
94
|
```
|
|
92
|
-
1. get_global_topology() ←
|
|
93
|
-
2. read_messages(20) ←
|
|
94
|
-
3.
|
|
95
|
+
1. get_global_topology() ← learn what projects exist
|
|
96
|
+
2. read_messages(20) ← catch up on recent discussion
|
|
97
|
+
3. get_project(projectId) ← read the manifest and docs of the project you work on
|
|
95
98
|
```
|
|
96
99
|
|
|
97
|
-
###
|
|
100
|
+
### Sync project data
|
|
101
|
+
|
|
98
102
|
```
|
|
99
|
-
1.
|
|
100
|
-
2. sync_project_assets(manifest, internalDocs) ← 返回 taskId
|
|
101
|
-
3. get_task(taskId) ← 轮询直到 completed
|
|
103
|
+
1. sync_project_assets(manifest, internalDocs) ← returns { ok, projectId }
|
|
102
104
|
```
|
|
103
105
|
|
|
104
|
-
###
|
|
106
|
+
### Start a collaborative discussion
|
|
107
|
+
|
|
105
108
|
```
|
|
106
109
|
1. start_meeting("Topic")
|
|
107
|
-
2. send_message("
|
|
108
|
-
3. read_messages() ←
|
|
109
|
-
4. send_message("
|
|
110
|
+
2. send_message("My proposal...", "PROPOSAL")
|
|
111
|
+
3. read_messages() ← read replies from other instances
|
|
112
|
+
4. send_message("Consensus reached", "DECISION")
|
|
110
113
|
5. end_meeting(meetingId, "summary")
|
|
111
114
|
```
|
|
112
115
|
|
|
113
116
|
---
|
|
114
117
|
|
|
115
|
-
##
|
|
118
|
+
## Notes
|
|
116
119
|
|
|
117
|
-
- `read_messages`
|
|
118
|
-
-
|
|
119
|
-
-
|
|
120
|
-
- daemon
|
|
120
|
+
- `read_messages` is **incremental**: each call returns only messages received since the last read. The cursor is managed automatically by the daemon — do not pass `afterId`.
|
|
121
|
+
- Write tools (`sync_project_assets`, `update_project`, `rename_project`, `host_delete_project`) complete before they return; there is nothing to poll.
|
|
122
|
+
- When a project ID is referenced by other projects via `relations`, renaming it automatically cascades to all references — no manual cleanup needed.
|
|
123
|
+
- After a daemon restart, your MCP reconnects automatically and restores the tool list. You do not need to restart the IDE.
|
package/docs/README_zh.md
CHANGED
|
@@ -37,12 +37,12 @@ n2n-nexus 面向这些场景设计:共享 daemon 状态、无状态 MCP 适配
|
|
|
37
37
|
|
|
38
38
|
n2n-nexus 为 AI 助手提供共享协作空间。不同助手不再只依赖自己的聊天上下文,而是可以通过 MCP 读取和更新同一个本地 daemon 中的项目状态。
|
|
39
39
|
|
|
40
|
-
**
|
|
40
|
+
**Quick summary**
|
|
41
41
|
|
|
42
42
|
- **安装**:`npx n2n-nexus daemon --port 5688`
|
|
43
43
|
- **协议**:Model Context Protocol (MCP),适配器通过 HTTP 连接 daemon
|
|
44
44
|
- **存储**:默认在 `~/.n2n-nexus` 下使用本地文件和 SQLite
|
|
45
|
-
-
|
|
45
|
+
- **适合**:多助手编码会话、项目交接、共享决策、会议记录、任务跟踪、项目 Manifest
|
|
46
46
|
- **不适合**:云端团队聊天、公开项目管理 SaaS、源码索引、向量搜索或远程数据库托管
|
|
47
47
|
|
|
48
48
|
## 为什么使用它?
|
|
@@ -75,6 +75,8 @@ n2n-nexus 为 AI 助手提供共享协作空间。不同助手不再只依赖自
|
|
|
75
75
|
|
|
76
76
|
## 快速开始
|
|
77
77
|
|
|
78
|
+
运行环境要求 Node.js 22.x 中的 22.14.0 或更高版本,或 Node.js 23.6.0 及以上版本。
|
|
79
|
+
|
|
78
80
|
### 1. 启动 daemon
|
|
79
81
|
|
|
80
82
|
```bash
|
|
@@ -110,43 +112,45 @@ npx n2n-nexus daemon --port 5688
|
|
|
110
112
|
|
|
111
113
|
## 工具集
|
|
112
114
|
|
|
113
|
-
### 会话和上下文
|
|
114
|
-
|
|
115
|
-
- `register_session_context`:声明当前活跃项目 ID。
|
|
116
|
-
|
|
117
115
|
### 项目资产管理
|
|
118
116
|
|
|
119
117
|
- `sync_project_assets`:提交项目 Manifest 和内部文档。
|
|
120
118
|
- `update_project`:局部更新项目 Manifest。
|
|
121
119
|
- `rename_project`:重命名项目 ID 并更新关联关系。
|
|
122
|
-
- `upload_project_asset
|
|
120
|
+
- `upload_project_asset`:向指定项目上传二进制或文本资产。
|
|
123
121
|
- `search_projects`:搜索项目注册表。
|
|
124
122
|
- `get_global_topology`:查看项目拓扑和依赖关系。
|
|
123
|
+
- `get_project`:读取项目完整 Manifest 和内部文档。
|
|
125
124
|
|
|
126
125
|
### 消息和协作
|
|
127
126
|
|
|
128
127
|
- `send_message`:发送会议消息或全局消息。
|
|
129
|
-
- `read_messages
|
|
128
|
+
- `read_messages`:增量读取未读消息(全局或指定会议)。
|
|
129
|
+
- `list_events`:读取结构化活动日志(项目同步、重命名、会议结束等)。
|
|
130
|
+
- `get_global_strategy`:读取主策略文档。
|
|
130
131
|
- `update_global_strategy`:更新主策略文档。
|
|
132
|
+
- `list_global_docs`:列出共享文档。
|
|
133
|
+
- `get_global_doc`:读取共享文档。
|
|
131
134
|
- `sync_global_doc`:创建或更新共享文档。
|
|
132
135
|
|
|
133
136
|
### 会议管理
|
|
134
137
|
|
|
138
|
+
- `list_meetings`:列出会议(状态、参与者、消息与决策数、摘要)。
|
|
135
139
|
- `start_meeting`:开启会议会话。
|
|
136
140
|
- `end_meeting`:关闭并锁定会议。
|
|
137
141
|
- `archive_meeting`:归档已关闭会议。
|
|
138
142
|
- `reopen_meeting`:重新打开已关闭或已归档会议。
|
|
139
143
|
|
|
140
|
-
###
|
|
144
|
+
### 任务管理
|
|
141
145
|
|
|
142
|
-
- `create_task
|
|
146
|
+
- `create_task`:创建由助手自行管理的任务。
|
|
143
147
|
- `get_task`:查询任务状态和结果。
|
|
144
148
|
- `list_tasks`:按状态列出任务。
|
|
145
149
|
- `cancel_task`:取消等待中或运行中的任务。
|
|
146
150
|
|
|
147
151
|
### 维护
|
|
148
152
|
|
|
149
|
-
- `host_maintenance
|
|
153
|
+
- `host_maintenance`:清理或清空全局聊天流。
|
|
150
154
|
- `host_delete_project`:删除项目和资产。
|
|
151
155
|
|
|
152
156
|
## 数据存储
|
|
@@ -209,7 +213,11 @@ NEXUS_ENDPOINT=http://127.0.0.1:5688 n2n-nexus mcp
|
|
|
209
213
|
| `NEXUS_ENDPOINT` | MCP 适配器连接的 daemon 地址 | `http://127.0.0.1:5688` |
|
|
210
214
|
| `NEXUS_ROOT` | daemon 存储根目录 | `~/.n2n-nexus` |
|
|
211
215
|
| `NEXUS_HOST` | daemon 监听地址 | `127.0.0.1` |
|
|
212
|
-
| `
|
|
216
|
+
| `NEXUS_DAEMON_PORT` | daemon 端口(`--port` 优先) | `5688` |
|
|
217
|
+
| `NEXUS_RATE_LIMIT` | 每个实例每秒工具调用数,每个客户端地址为其 5 倍;`0` 关闭限流 | `20` |
|
|
218
|
+
| `NEXUS_RATE_BURST` | 每个实例可一次性突发的调用数(最小为 1) | `60` |
|
|
219
|
+
| `NEXUS_ALLOWED_HOSTS` | `Host` 头额外允许的域名,逗号分隔(IP、`localhost`、`host.docker.internal` 始终允许) | 空 |
|
|
220
|
+
| `NEXUS_INSTANCE_ID` | 覆盖 MCP 实例 ID(未读游标、会议权限都以它为键) | `mcp-<主机名>-<工作目录哈希>-<IDE 名>` |
|
|
213
221
|
|
|
214
222
|
## 安全和治理说明
|
|
215
223
|
|
|
@@ -226,10 +234,12 @@ NEXUS_ENDPOINT=http://127.0.0.1:5688 n2n-nexus mcp
|
|
|
226
234
|
| 文件 | 说明 |
|
|
227
235
|
| --- | --- |
|
|
228
236
|
| [会议纪要](./MEETING_MINUTES_2025-12-29.md) | 结构化决策和测试记录 |
|
|
229
|
-
| [讨论日志](./discussion_2025-12-
|
|
237
|
+
| [讨论日志](./discussion_2025-12-29.md) | 可读的讨论记录 |
|
|
230
238
|
|
|
231
239
|
## 本地开发
|
|
232
240
|
|
|
241
|
+
开发请使用 Node.js 24,与 CI 和 lint 工具链保持一致。
|
|
242
|
+
|
|
233
243
|
```bash
|
|
234
244
|
git clone https://github.com/n2ns/n2n-nexus.git
|
|
235
245
|
cd n2n-nexus
|
|
@@ -272,7 +282,7 @@ NEXUS_ENDPOINT=http://127.0.0.1:5688 node build/index.js mcp
|
|
|
272
282
|
## 相关文档
|
|
273
283
|
|
|
274
284
|
- [架构文档](./ARCHITECTURE_zh.md)
|
|
275
|
-
- [AI 助手指南](./
|
|
285
|
+
- [AI 助手指南](./ASSISTANT_GUIDE_zh.md)
|
|
276
286
|
- [英文 README](../README.md)
|
|
277
287
|
- [llms.txt](../llms.txt)
|
|
278
288
|
|
|
@@ -282,4 +292,4 @@ NEXUS_ENDPOINT=http://127.0.0.1:5688 node build/index.js mcp
|
|
|
282
292
|
|
|
283
293
|
---
|
|
284
294
|
|
|
285
|
-
Built by N2NS Lab,
|
|
295
|
+
Built by N2NS Lab, Datafrog's open-source lab for practical AI developer tools.
|
package/llms.txt
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
n2n-nexus is a local-first Model Context Protocol (MCP) coordination hub from N2NS Lab for multi-AI assistant collaboration. It uses a long-running local daemon as the source of truth and stateless MCP adapters for IDEs and AI coding assistants.
|
|
4
4
|
|
|
5
|
+
## Search intent coverage
|
|
6
|
+
|
|
7
|
+
- multi-agent MCP coordination
|
|
8
|
+
- multi-AI assistant collaboration
|
|
9
|
+
- local MCP coordination hub
|
|
10
|
+
- shared project context for AI coding agents
|
|
11
|
+
- cross-IDE MCP collaboration server
|
|
12
|
+
- local-first project registry for AI assistants
|
|
13
|
+
- meeting and task coordination for coding agents
|
|
14
|
+
|
|
5
15
|
## Core positioning
|
|
6
16
|
|
|
7
17
|
- Local MCP coordination hub for multi-AI assistant collaboration.
|
|
@@ -43,4 +53,4 @@ Default storage root is `~/.n2n-nexus`, containing global docs, project manifest
|
|
|
43
53
|
|
|
44
54
|
## Brand
|
|
45
55
|
|
|
46
|
-
Built by N2NS Lab,
|
|
56
|
+
Built by N2NS Lab, Datafrog's open-source lab for practical AI developer tools.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n2n-nexus",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Local-first MCP coordination hub from N2NS Lab for multi-AI assistant collaboration.",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
"build",
|
|
12
|
+
"assets",
|
|
12
13
|
"README.md",
|
|
13
14
|
"llms.txt",
|
|
14
15
|
"CHANGELOG.md",
|
|
@@ -49,6 +50,10 @@
|
|
|
49
50
|
"ai-developer-tools"
|
|
50
51
|
],
|
|
51
52
|
"author": "N2NS Lab",
|
|
53
|
+
"funding": {
|
|
54
|
+
"type": "github",
|
|
55
|
+
"url": "https://github.com/sponsors/n2ns"
|
|
56
|
+
},
|
|
52
57
|
"license": "Apache-2.0",
|
|
53
58
|
"repository": {
|
|
54
59
|
"type": "git",
|
|
@@ -59,32 +64,37 @@
|
|
|
59
64
|
"url": "https://github.com/n2ns/n2n-nexus/issues"
|
|
60
65
|
},
|
|
61
66
|
"engines": {
|
|
62
|
-
"node": "
|
|
67
|
+
"node": "^22.14.0 || >=23.6.0"
|
|
63
68
|
},
|
|
64
69
|
"scripts": {
|
|
65
|
-
"build": "tsc",
|
|
70
|
+
"build": "node -e \"fs.rmSync('build', { recursive: true, force: true })\" && tsc",
|
|
66
71
|
"start": "node build/index.js",
|
|
67
72
|
"daemon": "node build/index.js daemon",
|
|
68
73
|
"dev": "tsc -w",
|
|
69
74
|
"test": "vitest run",
|
|
75
|
+
"audit": "npm audit",
|
|
76
|
+
"audit:prod": "npm audit --omit=dev",
|
|
77
|
+
"pack:dry-run": "npm pack --dry-run",
|
|
78
|
+
"check": "npm run lint && npm test && npm run build && npm run audit && npm run pack:dry-run",
|
|
70
79
|
"test:publish": "npm run build && npm test && npm pack --dry-run",
|
|
71
80
|
"test:integration": "vitest run tests/daemon_projects.test.ts tests/daemon_messages.test.ts tests/message_cursor.test.ts",
|
|
72
|
-
"lint": "eslint src
|
|
73
|
-
"prepublishOnly": "npm run
|
|
81
|
+
"lint": "eslint src tests",
|
|
82
|
+
"prepublishOnly": "npm run check"
|
|
74
83
|
},
|
|
75
84
|
"dependencies": {
|
|
76
|
-
"@modelcontextprotocol/
|
|
77
|
-
"better-sqlite3": "^
|
|
78
|
-
"zod": "^4.
|
|
85
|
+
"@modelcontextprotocol/server": "^2.3.1",
|
|
86
|
+
"better-sqlite3": "^13.0.3",
|
|
87
|
+
"zod": "^4.6.6"
|
|
79
88
|
},
|
|
80
89
|
"devDependencies": {
|
|
81
90
|
"@eslint/js": "^10.0.1",
|
|
82
|
-
"@
|
|
83
|
-
"@types/
|
|
84
|
-
"
|
|
85
|
-
"
|
|
91
|
+
"@modelcontextprotocol/client": "^2.3.1",
|
|
92
|
+
"@types/better-sqlite3": "^9.6.0",
|
|
93
|
+
"@types/node": "^26.6.5",
|
|
94
|
+
"eslint": "^10.12.0",
|
|
95
|
+
"lefthook": "^2.2.1",
|
|
86
96
|
"typescript": "^6.0.3",
|
|
87
|
-
"typescript-eslint": "^8.
|
|
88
|
-
"vitest": "^
|
|
97
|
+
"typescript-eslint": "^8.71.1",
|
|
98
|
+
"vitest": "^5.0.3"
|
|
89
99
|
}
|
|
90
100
|
}
|