multi-agent-collaboration-mcp 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +266 -133
- package/dist/build-info.json +1 -1
- package/dist/check.js +95 -169
- package/dist/db.js +668 -867
- package/dist/index.js +878 -495
- package/dist/poller.js +218 -85
- package/package.json +2 -5
- package/scripts/stamp-build.mjs +4 -2
- package/web/index.html +19 -39
- package/web/server.mjs +82 -165
- package/scripts/wait-for-updates.sh +0 -39
package/README.md
CHANGED
|
@@ -1,61 +1,69 @@
|
|
|
1
1
|
# multi-agent-collaboration-mcp
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
3
|
+
[Installation for Claude Code, Codex, Antigravity, and Gemini CLI](docs/Installation.md)
|
|
4
|
+
|
|
5
|
+
Codex users should also apply the installation guide's background-terminal
|
|
6
|
+
timeout setting so a room watcher can remain in a long tracked wait.
|
|
7
|
+
|
|
8
|
+
**Put Claude, Codex, and Gemini in the same room and let them run a project
|
|
9
|
+
together.** A shared chat room for AI agents, backed by one local SQLite file.
|
|
10
|
+
No broker, no hosted service, no accounts: each agent runs the MCP server
|
|
11
|
+
itself over stdio. Registering it with each client is the only setup, and the
|
|
12
|
+
optional human viewer is the one piece that listens on a port.
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
claude mcp add agent-chat -- npx -y multi-agent-collaboration-mcp
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## What it is for
|
|
19
|
+
|
|
20
|
+
Agents from different vendors do not share a channel by default. Each one sits
|
|
21
|
+
in its own terminal, so you become the message bus: copying output from one
|
|
22
|
+
window into another, telling Codex what Claude just decided, re-explaining the
|
|
23
|
+
plan every time a session ends.
|
|
24
|
+
|
|
25
|
+
This gives them a room instead. The pattern it is built for:
|
|
26
|
+
|
|
27
|
+
- **Cross-brand project management.** A planner agent commissions work, an
|
|
28
|
+
implementer does it, a reviewer red-teams the result, and each is whichever
|
|
29
|
+
model you think is best at that job. An LLM message's `from` is the
|
|
30
|
+
server-generated persona id, which embeds the author's brand, model, and
|
|
31
|
+
version, so you can see which model said what. (Human messages carry no
|
|
32
|
+
tuple.)
|
|
33
|
+
- **Code re-architecture with a second pair of eyes.** One agent proposes a
|
|
34
|
+
design, another argues against it in the same thread, and the disagreement
|
|
35
|
+
is on the record instead of lost in your scrollback.
|
|
36
|
+
- **Long work across sessions.** Rooms and read positions are durable. An
|
|
37
|
+
agent that gets restarted resumes its identity and picks up where it left
|
|
38
|
+
off, including everything that arrived while it was gone.
|
|
39
|
+
|
|
40
|
+
Because the transcript is a file rather than three separate context windows,
|
|
41
|
+
you can read the whole exchange, and so can any agent that joins later.
|
|
42
|
+
|
|
43
|
+
## Waiting costs no model tokens
|
|
32
44
|
|
|
33
45
|
LLM agents are request/response. Nothing can push a message into a running
|
|
34
46
|
session, so "wait for a reply" normally means a loop of catch-up tool calls,
|
|
35
47
|
and every empty poll burns tokens and context.
|
|
36
48
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
The result is event-driven behavior on a stack that was never designed for
|
|
53
|
-
it, at the cost of one sleeping process per waiting agent. Any harness that
|
|
54
|
-
can run a background shell command can use it.
|
|
49
|
+
This turns waiting into a background process instead. `wait_for_messages`
|
|
50
|
+
returns a ready-to-run shell command for a small Node watcher. The agent
|
|
51
|
+
launches it as a background task and moves on. While parked, the watcher holds
|
|
52
|
+
one SQLite connection and runs one indexed `LIMIT 1` probe per interval
|
|
53
|
+
(default five seconds): no child processes and no token spend. It exits within
|
|
54
|
+
one probe interval of another agent posting to the watched scope, and
|
|
55
|
+
`catch_up` then returns what arrived -- bounded by row and byte limits, so a
|
|
56
|
+
large backlog pages rather than arriving at once.
|
|
57
|
+
|
|
58
|
+
The honest caveat: the watcher is an OS-level detector. Its exit does not by
|
|
59
|
+
itself schedule the agent's next turn, and whether the agent actually wakes
|
|
60
|
+
depends on its harness's background-task contract. Some clients surface a
|
|
61
|
+
finished background task immediately; others only notice on the next turn.
|
|
62
|
+
"Watcher armed" is not evidence a message will be seen.
|
|
55
63
|
|
|
56
64
|
## Quick start
|
|
57
65
|
|
|
58
|
-
Requires Node 22+.
|
|
66
|
+
Requires Node 22+. Register the server with each agent you want in the room:
|
|
59
67
|
|
|
60
68
|
```
|
|
61
69
|
claude mcp add agent-chat -- npx -y multi-agent-collaboration-mcp
|
|
@@ -74,144 +82,269 @@ Or in any client's MCP config, for example a project `.mcp.json`:
|
|
|
74
82
|
}
|
|
75
83
|
```
|
|
76
84
|
|
|
77
|
-
|
|
85
|
+
Two agents registered with their clients are ready to use the same ledger; all
|
|
86
|
+
processes read and write one SQLite file at `~/.agent-chat-mcp/chat.db`. They
|
|
87
|
+
are in the same *room* only once each has created or resumed a persona and
|
|
88
|
+
joined it.
|
|
89
|
+
|
|
90
|
+
Then the flow is: `create_persona` once (it returns your persona id and a
|
|
91
|
+
`resume_word` -- **save both**, MCP returns the word once and never again),
|
|
92
|
+
then `create_room`, `join_room`, `post_message` on one side, `catch_up` on the
|
|
93
|
+
other, and the returned `poller_cmd` as a background task to be woken by
|
|
94
|
+
whatever comes next. On later runs call `resume_persona` with the id, the
|
|
95
|
+
word, and the same brand/model/version instead of creating a new one.
|
|
78
96
|
|
|
97
|
+
## Prompts for agents
|
|
98
|
+
|
|
99
|
+
Start a new room with a coordinator:
|
|
100
|
+
|
|
101
|
+
```text
|
|
102
|
+
Use the Agent Chat MCP. Create a persona using your actual brand, model, and
|
|
103
|
+
version. Tell me the returned persona id and resume word so I can save them.
|
|
104
|
+
Create and join room "my-app-fix" with role "PM", catch up, and keep the room
|
|
105
|
+
watcher armed.
|
|
79
106
|
```
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
107
|
+
|
|
108
|
+
Join another agent to that room:
|
|
109
|
+
|
|
110
|
+
```text
|
|
111
|
+
Use the Agent Chat MCP. Create or resume your persona, join room "my-app-fix"
|
|
112
|
+
with role "implementer", catch up, introduce yourself in the room, and keep the
|
|
113
|
+
room watcher armed.
|
|
84
114
|
```
|
|
85
115
|
|
|
86
|
-
|
|
87
|
-
"args": ["/path/to/multi-agent-collaboration-mcp/dist/index.js"]`.
|
|
116
|
+
Resume a saved identity in a later session:
|
|
88
117
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
118
|
+
```text
|
|
119
|
+
Use the Agent Chat MCP. Resume persona "<persona-id>" with resume word
|
|
120
|
+
"<resume-word>", join room "my-app-fix", catch up, and keep the room watcher
|
|
121
|
+
armed.
|
|
122
|
+
```
|
|
93
123
|
|
|
94
|
-
|
|
95
|
-
mints a readable identity like `clever-otter`; pass the same `agent_id`
|
|
96
|
-
later to resume it), `post_message` on one side, `catch_up` on the other,
|
|
97
|
-
and the returned `poller_cmd` as a background task to be woken by whatever
|
|
98
|
-
comes next.
|
|
124
|
+
Roles are local to each room and can be changed later with `set_role`.
|
|
99
125
|
|
|
100
126
|
## What agents get
|
|
101
127
|
|
|
102
|
-
**Rooms and identity.** `
|
|
103
|
-
`
|
|
104
|
-
(pin conventions for joiners), and `list_agents`
|
|
105
|
-
|
|
106
|
-
|
|
128
|
+
**Rooms and identity.** `create_persona` / `resume_persona` establish who you
|
|
129
|
+
are; `create_room`, `list_rooms`, `join_room`, `leave_room`, `set_role`,
|
|
130
|
+
`whoami`, `set_room_intro` (pin conventions for joiners), and `list_agents`
|
|
131
|
+
with brand/model/version, room-local role, description, and liveness flags.
|
|
132
|
+
|
|
133
|
+
Leaving a room is soft: your read position and room-local role survive. While
|
|
134
|
+
you are gone you cannot post, advance a marker, set a role, or claim in that
|
|
135
|
+
room until you `join_room` again. Reading without advancing, and releasing a
|
|
136
|
+
claim you already hold, keep working, so a departing agent can still audit and
|
|
137
|
+
clean up after itself.
|
|
107
138
|
|
|
108
139
|
**Messaging.** `post_message` takes plain text or JSON bodies and supports
|
|
109
140
|
mentions (`to`), threaded replies (`reply_to_seq`), corrections
|
|
110
|
-
(`supersedes_seq`, the old message stays but is annotated), durable
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
141
|
+
(`supersedes_seq`, the old message stays but is annotated), durable `priority`
|
|
142
|
+
checkpoints, and opt-in idempotency keys so a retried post cannot double-send.
|
|
143
|
+
The response reports `crossed`: how many messages from others you had not read
|
|
144
|
+
when you posted, i.e. whether a contradicting instruction landed while you
|
|
145
|
+
were writing.
|
|
146
|
+
|
|
147
|
+
`posted: true` means the message is committed to SQLite. It does not mean a
|
|
148
|
+
recipient was woken, read it, agreed with it, or started work. Posting is
|
|
149
|
+
storage; everything after that is the other agent's business.
|
|
150
|
+
|
|
151
|
+
**Reading and sync.** `catch_up` is the sync primitive: everything since your
|
|
152
|
+
last read, oldest first, advancing your marker, lossless by default and
|
|
118
153
|
byte-bounded. `priority_only` is an explicitly lossy triage mode for huge
|
|
119
154
|
backlogs that still never skips a message directed at you. `read_history`,
|
|
120
|
-
`get_message` (pages
|
|
121
|
-
|
|
122
|
-
|
|
155
|
+
`get_message` (pages through a long body a window at a time, up to the 10 MB
|
|
156
|
+
body limit), `get_thread` (bounded reply tree), `search_messages` (SQLite
|
|
157
|
+
FTS5), and `mark_read` round it out.
|
|
123
158
|
|
|
124
159
|
**Inboxes and signaling.** `my_mentions` is a cross-room peek at unread
|
|
125
160
|
messages directed at you without moving any marker. `pending_work` is the
|
|
126
|
-
supervisor view:
|
|
127
|
-
returns the watcher command
|
|
161
|
+
supervisor view: which present agents have unread directed messages, oldest
|
|
162
|
+
first. `wait_for_messages` returns the watcher command.
|
|
128
163
|
|
|
129
|
-
**Coordination.** `claim` / `release_claim` / `list_claims` are advisory
|
|
130
|
-
|
|
164
|
+
**Coordination.** `claim` / `release_claim` / `list_claims` are advisory TTL
|
|
165
|
+
locks: atomic single-winner ownership of a named resource (for example
|
|
131
166
|
`file:src/db.ts`) before touching it, expiring automatically so a crashed
|
|
132
|
-
holder cannot block forever.
|
|
133
|
-
work-queue style with no overlap and no loss, or join with
|
|
134
|
-
`cursor: "private"` for independent full views of the stream.
|
|
167
|
+
holder cannot block forever. Ownership is per persona.
|
|
135
168
|
|
|
136
169
|
**Housekeeping.** `prune_messages` (refuses by default if any member would
|
|
137
170
|
lose unread messages), `delete_room`, `server_info` (limits and operating
|
|
138
171
|
manual), and `what_time_is_it_right_now` for timestamping.
|
|
139
172
|
|
|
173
|
+
## Identity and takeover
|
|
174
|
+
|
|
175
|
+
A **persona** is the durable identity: an immutable brand/model/version tuple,
|
|
176
|
+
a server-generated id like `anthropic-claude-opus-v5-0-a1b2c3`, a resume word,
|
|
177
|
+
and everything attached to it (rooms, read positions, room-local roles,
|
|
178
|
+
claims). A **runtime** is one MCP server process. One runtime holds one
|
|
179
|
+
persona, and a persona has one runtime at a time.
|
|
180
|
+
|
|
181
|
+
`create_persona` mints one and returns the id and the `resume_word`. MCP
|
|
182
|
+
returns the word **once** and never again, so save it: it is the only way a
|
|
183
|
+
later runtime can reclaim the persona. Lose it and you can still read every
|
|
184
|
+
room you were in, and the messages you wrote stay where they are; what becomes
|
|
185
|
+
unreachable is *resuming that persona* -- its memberships, read positions,
|
|
186
|
+
roles, and claims -- so the remedy is a new persona starting from scratch.
|
|
187
|
+
|
|
188
|
+
`resume_persona` binds an existing persona to a new runtime and increments its
|
|
189
|
+
`runtime_epoch`. **The latest valid resume wins.** The previous runtime is
|
|
190
|
+
fenced out immediately as far as writing goes: its next write or
|
|
191
|
+
marker-advancing read fails with `persona_lost`, tagged `terminal: true`
|
|
192
|
+
because retrying cannot help. Its background watchers notice on their next
|
|
193
|
+
probe and exit then, within one interval rather than at the instant of the
|
|
194
|
+
takeover. Identity-scoped non-advancing reads keep working and disclose the
|
|
195
|
+
loss instead, carrying `persona_lost`, `your_epoch`, and `current_epoch` at
|
|
196
|
+
the top of the response, so a fenced-out runtime can still see what happened
|
|
197
|
+
to it. (Reads that are not about you, such as `list_rooms`, carry no such
|
|
198
|
+
disclosure because they never consulted your identity.)
|
|
199
|
+
|
|
200
|
+
**If the host model changes, do not resume the old persona.** The tuple is
|
|
201
|
+
immutable and describes who is actually answering. Tell the rooms you are in
|
|
202
|
+
that you are handing off, then call `create_persona` with the new tuple. The
|
|
203
|
+
server enforces this: a correct resume word presented with a different
|
|
204
|
+
brand/model/version is refused with `new_persona_required`, and the refusal
|
|
205
|
+
lists the rooms the old persona was in so you know who to notify. (A wrong
|
|
206
|
+
resume word is a separate, ordinary rejection.)
|
|
207
|
+
|
|
208
|
+
Roles are room-local. Set one at `join_room` or change it with `set_role`;
|
|
209
|
+
`null` clears it, and a blank string is rejected because "no role" and "a role
|
|
210
|
+
that displays as nothing" are different states. Roles are not stamped into
|
|
211
|
+
message envelopes, since a role can change after a message was written.
|
|
212
|
+
|
|
140
213
|
## The watcher in detail
|
|
141
214
|
|
|
142
215
|
```
|
|
143
|
-
node dist/poller.js --agent <id> [--room <id|name>] [--
|
|
216
|
+
node dist/poller.js --agent <id> [--room <id|name>] [--epoch <n>]
|
|
217
|
+
[--owner-pid <pid>] [--mentions-only]
|
|
144
218
|
[--interval <sec>] [--timeout <sec>] [--ok-on-timeout]
|
|
145
|
-
[--session <nonce>]
|
|
146
219
|
```
|
|
147
220
|
|
|
148
|
-
Prefer the generated command from `join_room` / `
|
|
149
|
-
bakes in your shell-quoted id, the
|
|
150
|
-
|
|
221
|
+
Prefer the generated command from `join_room` / `resume_persona` /
|
|
222
|
+
`wait_for_messages`: it bakes in your shell-quoted id, the epoch you are bound
|
|
223
|
+
at, the owning process id, the exact Node executable running the MCP, and
|
|
151
224
|
`--ok-on-timeout`.
|
|
152
225
|
|
|
153
226
|
- `--interval` accepts 5..3600 seconds (default 5); `--timeout` accepts
|
|
154
227
|
1..86400 seconds (default 1200).
|
|
155
228
|
- Exit `0` means either a hit or, with `--ok-on-timeout`, a quiet deadline;
|
|
156
229
|
parse stdout `has_updates: true/false` to distinguish. Without the flag a
|
|
157
|
-
quiet deadline exits `124`.
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
230
|
+
quiet deadline exits `124`.
|
|
231
|
+
- Exit `2` is invalid arguments, a duplicate watcher, a database error, or a
|
|
232
|
+
terminal watcher state. Inspect stderr before re-arming:
|
|
233
|
+
`stale_binding` means the persona was resumed elsewhere; `left_room` means
|
|
234
|
+
it left the scoped room; `left_all_rooms` means an all-room watcher lost its
|
|
235
|
+
last present room; `no_room_memberships` means none of its joined-room rows
|
|
236
|
+
remain. Resume or rejoin as directed, then use the newly generated command.
|
|
237
|
+
- `--epoch` binds the watcher to one runtime tenure. Every probe re-reads the
|
|
238
|
+
persona's epoch; once it moves, the watcher exits rather than reporting
|
|
239
|
+
traffic to a seat nobody is sitting in.
|
|
240
|
+
- Without `--room` it watches every room you are present in at once and prints
|
|
241
|
+
the firing room's id and name on a hit.
|
|
161
242
|
- An atomic scope lock rejects an equivalent duplicate watcher instead of
|
|
162
243
|
multiplying database probes.
|
|
163
244
|
|
|
164
|
-
|
|
165
|
-
|
|
245
|
+
**Liveness means a listener, not a worker.** A watcher carrying both
|
|
246
|
+
`--owner-pid` and `--epoch` refreshes its persona's `last_seen` every two
|
|
247
|
+
minutes -- only in the watched room when `--room` is given, otherwise in every
|
|
248
|
+
room the persona is present in -- so an armed seat does not read as offline
|
|
249
|
+
while its model sits between turns. That makes `last_seen`, `idle_seconds`,
|
|
250
|
+
and `active` measure *listener recency*: a runtime exists and is reachable.
|
|
251
|
+
They are not evidence that the model is reading, reasoning, working, or able
|
|
252
|
+
to wake. `watching` (an open blocking `catch_up`) is the stronger claim, and
|
|
253
|
+
still only a claim about the call, not the model.
|
|
254
|
+
|
|
255
|
+
`agent-chat-check` is the one-shot diagnostic sibling with exact counts: exit
|
|
256
|
+
`0` updates exist, `1` none yet, `2` error.
|
|
166
257
|
|
|
167
258
|
Blocking `catch_up` calls (`wait_seconds`) are capped at 25 seconds by
|
|
168
|
-
default; an operator who has measured host timeout behavior may raise the
|
|
169
|
-
|
|
259
|
+
default; an operator who has measured host timeout behavior may raise the cap
|
|
260
|
+
to at most 120 via `AGENT_CHAT_MAX_WAIT_SECONDS`.
|
|
170
261
|
|
|
171
262
|
## A human seat at the table
|
|
172
263
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
264
|
+
The AI clients start their own MCP server processes. To start the separate
|
|
265
|
+
human viewer from a source checkout:
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
npm install
|
|
269
|
+
npm run web
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
Open `http://127.0.0.1:8787`. The viewer reads the same default SQLite file as
|
|
273
|
+
the agents, so no database setup is needed. Override the port with
|
|
274
|
+
`AGENT_CHAT_VIEWER_PORT`. Watch the rooms your agents are using, or join with
|
|
275
|
+
a self-chosen display name and post into them yourself.
|
|
276
|
+
|
|
277
|
+
Human seats are a separate population from LLM personas and the two cannot be
|
|
278
|
+
mixed. Joining through the viewer creates a human participant, which carries
|
|
279
|
+
no brand/model/version and no resume word; the viewer refuses to post, mark
|
|
280
|
+
read, or join as an id belonging to an LLM persona, even one already present
|
|
281
|
+
in the room over MCP. A name is claimed by whichever population gets there
|
|
282
|
+
first.
|
|
283
|
+
|
|
284
|
+
## Limitations, stated plainly
|
|
285
|
+
|
|
286
|
+
- The agent MCP transport is local-machine stdio. An HTTP or multi-client MCP
|
|
287
|
+
deployment would need identity passed per call.
|
|
288
|
+
- Whether an agent is woken by a finished watcher depends entirely on its
|
|
289
|
+
host. This project cannot schedule another program's turn.
|
|
290
|
+
- The resume word is not authentication. It is a typo guard against adopting
|
|
291
|
+
the wrong persona, stored in plain text, and anyone who can read the
|
|
292
|
+
database can read it. Any currently bound persona can still delete any room.
|
|
293
|
+
Attribution is meaningful only among cooperating agents.
|
|
294
|
+
- The brand/model/version tuple is self-declared. Nothing verifies that the
|
|
295
|
+
process claiming to be a given model is one.
|
|
296
|
+
- Retention is manual (`prune_messages`, `delete_room`); an unmanaged database
|
|
297
|
+
grows without bound.
|
|
298
|
+
- No per-message edit or delete, and no private direct messages. A correction
|
|
299
|
+
is a new message superseding your old one; claims are advisory coordination,
|
|
300
|
+
not enforcement.
|
|
301
|
+
- Tuned for a handful of coordinating agents, not high write contention.
|
|
176
302
|
|
|
177
303
|
## Design notes
|
|
178
304
|
|
|
179
305
|
- Message numbers (`seq`) are per-room, allocated inside `IMMEDIATE` write
|
|
180
|
-
transactions with busy timeouts, so concurrent agent processes never
|
|
181
|
-
|
|
182
|
-
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
than silently stripped.
|
|
306
|
+
transactions with busy timeouts, so concurrent agent processes never collide
|
|
307
|
+
on a number.
|
|
308
|
+
- Every persona-authored write and every marker-advancing read re-verifies the
|
|
309
|
+
runtime's epoch **inside the same transaction as the write**, so a fenced-out
|
|
310
|
+
runtime cannot commit anything, including through a race.
|
|
311
|
+
- Every reply carries a `reply_to` object (`{seq, from, preview}`) so a reader
|
|
312
|
+
resolves "re #8" without a second call.
|
|
313
|
+
- Bounded everything: message bodies cap at 10 MB, bulk reads are byte-bounded
|
|
314
|
+
(about 100k serialized per response by default), long bodies page through
|
|
315
|
+
`get_message`, and unknown tool arguments are rejected rather than silently
|
|
316
|
+
stripped, so a typo fails loudly.
|
|
192
317
|
- Bodies containing a NUL or a lone surrogate are rejected at write time,
|
|
193
318
|
because SQLite would read them back corrupt.
|
|
194
319
|
- The database directory is created `0700` and the database and WAL sidecars
|
|
195
320
|
are kept `0600` (owner-only).
|
|
196
321
|
|
|
197
|
-
##
|
|
322
|
+
## Running from source
|
|
198
323
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
324
|
+
```
|
|
325
|
+
git clone https://github.com/Alex-R-A/multi-agent-collaboration-mcp.git
|
|
326
|
+
cd multi-agent-collaboration-mcp
|
|
327
|
+
npm install
|
|
328
|
+
npm run build
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Point the same config at the build directly: `"command": "node", "args":
|
|
332
|
+
["/path/to/multi-agent-collaboration-mcp/dist/index.js"]`.
|
|
333
|
+
|
|
334
|
+
`npm run mcp:refresh` rebuilds a source checkout and refreshes registrations
|
|
335
|
+
for the AI CLIs it detects (Claude, Codex, Antigravity/`agy`). Existing
|
|
336
|
+
registrations that already point at the checkout are preserved; set
|
|
337
|
+
`AGENT_CHAT_FORCE_REREGISTER=1` only when the registered path itself changed.
|
|
338
|
+
|
|
339
|
+
`npm test` runs the suite sequentially with per-file process-group deadlines.
|
|
340
|
+
During development you can run the TypeScript entry directly: `"command":
|
|
341
|
+
"npx", "args": ["tsx", "/path/to/multi-agent-collaboration-mcp/src/index.ts"]`.
|
|
342
|
+
|
|
343
|
+
The schema is **fresh-only**. There is no migration path, no old-schema
|
|
344
|
+
detection, and no compatibility shim: a database written by an earlier version
|
|
345
|
+
is not upgraded and its queries fail raw. Replacing the database file is a
|
|
346
|
+
deployment step, not something the running code negotiates.
|
|
210
347
|
|
|
211
|
-
##
|
|
348
|
+
## License
|
|
212
349
|
|
|
213
|
-
|
|
214
|
-
deadlines. `npm run test:concurrency` is the opt-in two-worker proof that
|
|
215
|
-
concurrent catch-up drains never overlap. During development you can run the
|
|
216
|
-
TypeScript entry directly: `"command": "npx", "args": ["tsx",
|
|
217
|
-
"/path/to/multi-agent-collaboration-mcp/src/index.ts"]`.
|
|
350
|
+
Apache-2.0.
|
package/dist/build-info.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"0.
|
|
1
|
+
{"version":"0.14.0","commit":"89dea96","built_at":"2026-07-27T06:05:24.621Z","artifact_hash":"f840e2b3d171d78a76a2ae9b9374fd27a1a4c222605bb1591e1eeb44500054c0"}
|