@composer-app/mcp 0.0.1-beta.4 → 0.0.1-beta.7
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 +145 -0
- package/README.md +160 -0
- package/dist/{chunk-UVXQZ2TN.js → chunk-EJUJPBX2.js} +1365 -266
- package/dist/cli.js +1 -1
- package/dist/mcp.js +31 -3
- package/package.json +3 -2
- package/skill/SKILL.md +179 -12
package/dist/cli.js
CHANGED
package/dist/mcp.js
CHANGED
|
@@ -1,8 +1,36 @@
|
|
|
1
1
|
import {
|
|
2
|
+
__test_clearRooms,
|
|
3
|
+
__test_dispatch,
|
|
4
|
+
__test_setRoom,
|
|
5
|
+
_clearRoomsForTest,
|
|
6
|
+
_registerRoomForTest,
|
|
7
|
+
dispatchTool,
|
|
8
|
+
performAddComment,
|
|
9
|
+
performAddSuggestion,
|
|
10
|
+
performAgentStatus,
|
|
11
|
+
performDone,
|
|
12
|
+
performReplyComment,
|
|
13
|
+
performReplySuggestion,
|
|
14
|
+
performResolveThread,
|
|
2
15
|
startMcpHttpServer,
|
|
3
|
-
startMcpServer
|
|
4
|
-
|
|
16
|
+
startMcpServer,
|
|
17
|
+
teardownAllRooms
|
|
18
|
+
} from "./chunk-EJUJPBX2.js";
|
|
5
19
|
export {
|
|
20
|
+
__test_clearRooms,
|
|
21
|
+
__test_dispatch,
|
|
22
|
+
__test_setRoom,
|
|
23
|
+
_clearRoomsForTest,
|
|
24
|
+
_registerRoomForTest,
|
|
25
|
+
dispatchTool,
|
|
26
|
+
performAddComment,
|
|
27
|
+
performAddSuggestion,
|
|
28
|
+
performAgentStatus,
|
|
29
|
+
performDone,
|
|
30
|
+
performReplyComment,
|
|
31
|
+
performReplySuggestion,
|
|
32
|
+
performResolveThread,
|
|
6
33
|
startMcpHttpServer,
|
|
7
|
-
startMcpServer
|
|
34
|
+
startMcpServer,
|
|
35
|
+
teardownAllRooms
|
|
8
36
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@composer-app/mcp",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.7",
|
|
4
4
|
"description": "Composer MCP",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Josh Philpott",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"dist",
|
|
13
|
-
"skill"
|
|
13
|
+
"skill",
|
|
14
|
+
"CHANGELOG.md"
|
|
14
15
|
],
|
|
15
16
|
"keywords": [
|
|
16
17
|
"mcp",
|
package/skill/SKILL.md
CHANGED
|
@@ -69,7 +69,7 @@ just joined), then execute `step2_callTool`.
|
|
|
69
69
|
### 3. Monitor
|
|
70
70
|
Triggers: "watch this doc", or automatically after join/create.
|
|
71
71
|
Action: call `composer_next_event({ roomId })` in a loop (default timeout
|
|
72
|
-
is
|
|
72
|
+
is 30 seconds). **The loop is always-on.** Every return carries a
|
|
73
73
|
structured directive — follow it without waiting for user input.
|
|
74
74
|
|
|
75
75
|
On `mention`: handle the event (reply / suggestion / resolve as needed),
|
|
@@ -95,11 +95,13 @@ On `mention`, the event contains everything you need to act in one turn:
|
|
|
95
95
|
threadKind: "comment" | "suggestion",
|
|
96
96
|
threadText: "...", // the exact message that triggered you
|
|
97
97
|
replyId?: "...", // present when it's a reply on an existing thread
|
|
98
|
-
reason: "direct_mention" | "active_thread",
|
|
98
|
+
reason: "direct_mention" | "active_thread" | "solo_room",
|
|
99
99
|
anchoredText?: "...", // the doc text the thread is anchored to
|
|
100
100
|
headingId?: "...", // the section's headingId (use with write tools)
|
|
101
101
|
headingText?: "...",
|
|
102
|
-
sectionMarkdown?: "..."
|
|
102
|
+
sectionMarkdown?: "...", // full containing section as markdown
|
|
103
|
+
invokerUserId?: "...", // userId of whoever triggered you (use in mentions[])
|
|
104
|
+
invokerName?: "..." // their display name (use in @mention literal)
|
|
103
105
|
}
|
|
104
106
|
```
|
|
105
107
|
|
|
@@ -108,6 +110,38 @@ or `composer_add_comment` — no extra `composer_get_section` call is needed in
|
|
|
108
110
|
the common case. Reach for `sectionMarkdown` to understand surrounding context
|
|
109
111
|
before replying or suggesting.
|
|
110
112
|
|
|
113
|
+
**Ack first, then do the work.** On every `mention` event you intend to act
|
|
114
|
+
on, post a brief ack reply FIRST — before reading the full doc, before
|
|
115
|
+
drafting a suggestion. This is the "I heard you, I'm on it" signal; without
|
|
116
|
+
it the user stares at a silent sidebar while you think.
|
|
117
|
+
|
|
118
|
+
- Call `composer_reply_comment` (or `composer_reply_suggestion`) with
|
|
119
|
+
`state: "thinking"` and `mentions: [event.invokerUserId]`. For a brand-new
|
|
120
|
+
thread response use `composer_add_comment` / `composer_add_suggestion`
|
|
121
|
+
with the same `state` + `mentions` shape.
|
|
122
|
+
- Body: `@<invokerName> — on it` or equivalent terse phrasing (≤ 24 chars).
|
|
123
|
+
"On it.", "Looking.", "Checking.". No preamble, no promise of structure.
|
|
124
|
+
- Read `invokerUserId` and `invokerName` directly from the event payload
|
|
125
|
+
above — do NOT try to reconstruct them from `threadText` or from an
|
|
126
|
+
awareness lookup. They're the authoritative values the server resolved.
|
|
127
|
+
- **Skip the ack** for empty thank-yous or conversational dead-ends you
|
|
128
|
+
wouldn't reply to at all (see `reason` gates below) — the ack is a
|
|
129
|
+
signal of intent to act, not a reflex.
|
|
130
|
+
- **Skip the ack** when this mention is a yes-variant confirmation inside
|
|
131
|
+
an ask-then-auto-suggest round-trip (see §"Auto-suggest when the user
|
|
132
|
+
confirms a concrete proposal"): if the mention fired as `active_thread`
|
|
133
|
+
AND your own prior reply on this thread was a concrete yes/no
|
|
134
|
+
counter-proposal AND the human's message is a yes-variant, drop the
|
|
135
|
+
suggestion directly via `composer_add_suggestion` with
|
|
136
|
+
`fromThreadId: event.threadId`. The "I heard you" signal was already
|
|
137
|
+
delivered in the prior ack; a second ack here is noise. Only the
|
|
138
|
+
initial substantive-work mention gets an ack.
|
|
139
|
+
|
|
140
|
+
Once the ack is posted, drive state with `composer_agent_status` as you
|
|
141
|
+
work (see §"Progress status" below). On completion, rewrite the ack to
|
|
142
|
+
its final form in the same call that transitions to `ready` — do not
|
|
143
|
+
post a duplicate pointer reply.
|
|
144
|
+
|
|
111
145
|
**The event only carries the triggering message.** If the thread already has
|
|
112
146
|
replies (from the user, or from another agent), call `composer_get_thread({
|
|
113
147
|
roomId, threadId })` before replying. The return has every reply with author
|
|
@@ -133,6 +167,16 @@ need to catch up on what's already been said.
|
|
|
133
167
|
drafts they're jotting down).
|
|
134
168
|
When in doubt, reply — the user can always ignore you.
|
|
135
169
|
|
|
170
|
+
**When you skip a mention, call `composer_done({ roomId, threadId })`.**
|
|
171
|
+
The instant a mention is dequeued via `composer_next_event`, the server
|
|
172
|
+
publishes a `thinking…` indicator on that thread so the user sees you
|
|
173
|
+
picked it up — there's no flicker waiting for your first
|
|
174
|
+
`composer_agent_status` call. If you reply, the `state: "ready"`
|
|
175
|
+
transition clears the indicator on its own. If you skip without
|
|
176
|
+
replying, nothing else clears it and the user's avatar pulses forever.
|
|
177
|
+
`composer_done` is idempotent — safe to call even if the indicator was
|
|
178
|
+
already cleared.
|
|
179
|
+
|
|
136
180
|
### 4. Act
|
|
137
181
|
Triggers: direct requests like "add a summary to section 2".
|
|
138
182
|
Action: already attached; call the write tools and report back concisely.
|
|
@@ -149,13 +193,25 @@ Read tools:
|
|
|
149
193
|
|
|
150
194
|
Write tools:
|
|
151
195
|
- `composer_add_comment` — NEW comment on any span in the doc. Use when
|
|
152
|
-
raising something outside the current thread's anchor.
|
|
196
|
+
raising something outside the current thread's anchor. Accepts an
|
|
197
|
+
optional `state` ("thinking" on an ack) so the first-ever reply on a
|
|
198
|
+
thread can be the ack.
|
|
153
199
|
- `composer_add_suggestion` — propose a text replacement (lands as
|
|
154
200
|
pending). Can target any span — `fromThreadId` inherits the source
|
|
155
201
|
thread's anchor; `anchor` specifies a span elsewhere. Call it multiple
|
|
156
202
|
times in a turn to suggest in several spots.
|
|
157
203
|
- `composer_reply_comment` / `composer_reply_suggestion` — reply on an
|
|
158
|
-
existing thread.
|
|
204
|
+
existing thread. Accept an optional `state` field for the ack-first
|
|
205
|
+
flow; post with `state: "thinking"` and the invoker in `mentions[]`.
|
|
206
|
+
- `composer_agent_status` — drive state transitions (`thinking →
|
|
207
|
+
working → replying → ready`) and rewrite the final ack body on the
|
|
208
|
+
reply/comment/suggestion you own. See §"Progress status".
|
|
209
|
+
- `composer_done` — clear the live indicator on a thread you decided
|
|
210
|
+
NOT to reply to. Required when you skip a mention (off-topic chatter,
|
|
211
|
+
self-mention, conversational dead-end), because the indicator is
|
|
212
|
+
published optimistically the moment a mention is dequeued. Replying
|
|
213
|
+
with `state: "ready"` clears it on its own — only call `composer_done`
|
|
214
|
+
for the skip case.
|
|
159
215
|
- `composer_resolve_thread` — mark resolved.
|
|
160
216
|
|
|
161
217
|
There is no "just edit" tool in v1. All text changes go through suggestions
|
|
@@ -169,11 +225,18 @@ a chat window. Long replies get unwieldy fast. Rules:
|
|
|
169
225
|
- Answer in 1–3 sentences. Prefer one.
|
|
170
226
|
- Reply directly to the question asked — no preamble ("Great question!"),
|
|
171
227
|
no restating the ask, no trailing summary of what you just did.
|
|
172
|
-
- **
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
228
|
+
- **When the substantive answer is a standalone artifact, that artifact
|
|
229
|
+
IS the reply.** A "standalone artifact" means a suggestion, a cross-span
|
|
230
|
+
comment on a different anchor, or a separate document link. In that
|
|
231
|
+
case do NOT post a duplicate pointer comment — instead, rewrite your
|
|
232
|
+
existing ack in place to a thin pointer (`"Posted a suggestion below."`,
|
|
233
|
+
`"Added a comment in Section 3."`, `"See doc <link>."`) and set
|
|
234
|
+
`state: "ready"` on the same call. The suggestion / cross-span comment
|
|
235
|
+
renders as its own card; a pointer reply just duplicates what the user
|
|
236
|
+
can already see.
|
|
237
|
+
- **When the substantive answer IS a reply with text**, rewrite the ack
|
|
238
|
+
to that text and clear the state (or set `state: "ready"`) in the same
|
|
239
|
+
`composer_agent_status` call. Do not post a separate follow-up reply.
|
|
177
240
|
- If the answer genuinely needs structure (a list of 4+ items, code, a
|
|
178
241
|
table) and a suggestion isn't the right shape, post it as a suggestion
|
|
179
242
|
in the doc body instead of as a comment reply.
|
|
@@ -298,8 +361,10 @@ Two turns, not three:
|
|
|
298
361
|
2. **Turn 2 (commit on confirmation).** When the user replies with any
|
|
299
362
|
variant of yes ("yes", "sure", "go for it", "perfect", a thumbs-up
|
|
300
363
|
emoji), call `composer_add_suggestion` with `fromThreadId: event.threadId`
|
|
301
|
-
and the concrete replacement.
|
|
302
|
-
|
|
364
|
+
and the concrete replacement. **Skip the ack in this case** — the
|
|
365
|
+
prior reply already delivered the "I heard you" signal, and the
|
|
366
|
+
suggestion card IS your answer. Do NOT also post a comment reply
|
|
367
|
+
(see §"Keep comment text terse" and the ack-skip rule in §"Monitor").
|
|
303
368
|
|
|
304
369
|
If the user says no / picks a different value / redirects, follow their
|
|
305
370
|
lead — do not post the original proposal anyway.
|
|
@@ -309,6 +374,108 @@ abstract to guess a number), ask a clarifying question instead. Don't
|
|
|
309
374
|
propose something generic just to fill the slot — "Would you like me
|
|
310
375
|
to shorten this?" is worthless without a target length.
|
|
311
376
|
|
|
377
|
+
### Progress status
|
|
378
|
+
|
|
379
|
+
Once the ack is posted, drive the owning reply through a small state
|
|
380
|
+
machine using `composer_agent_status`. The UI animates state changes
|
|
381
|
+
on the reply card; the user sees progress instead of a silent pause.
|
|
382
|
+
|
|
383
|
+
```
|
|
384
|
+
composer_agent_status({
|
|
385
|
+
roomId,
|
|
386
|
+
threadId,
|
|
387
|
+
replyId?, // identifies which reply you own; omit for thread-head
|
|
388
|
+
state, // "thinking" | "working" | "replying" | "ready"
|
|
389
|
+
text?, // rewrite the reply body (only meaningful on "ready")
|
|
390
|
+
note?, // short human-readable progress line
|
|
391
|
+
kind? // "comment" | "suggestion" — disambiguates head records
|
|
392
|
+
})
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
State machine: **`thinking → working → replying → ready`**.
|
|
396
|
+
|
|
397
|
+
- `thinking` — initial ack, set by the reply/add tool that posted it.
|
|
398
|
+
- `working` — you're doing substantive work (reading the doc, computing,
|
|
399
|
+
drafting). Set this whenever you expect a gap.
|
|
400
|
+
- `replying` — you're about to write the final text. Optional, brief.
|
|
401
|
+
- `ready` — done. Call with `text: "<final ack body>"` to rewrite the
|
|
402
|
+
ack in place atomically; the awareness heartbeat for this entry is
|
|
403
|
+
pruned in the same call.
|
|
404
|
+
|
|
405
|
+
**Minimum-visible rule.** The UI collapses state changes that happen
|
|
406
|
+
faster than 400 ms, so don't worry about being too fast. DO worry about
|
|
407
|
+
being SILENT for more than ~2 seconds without calling
|
|
408
|
+
`composer_agent_status({ state: "working" })` — silence is the failure
|
|
409
|
+
mode. If you're about to do something slow (fetch the full doc, compute
|
|
410
|
+
a non-trivial diff, call another tool), transition to `working` first.
|
|
411
|
+
|
|
412
|
+
Use `note` to surface human-readable progress where it helps — e.g.
|
|
413
|
+
`note: "Reading section 3…"`, `note: "Drafting suggestion…"`,
|
|
414
|
+
`note: "Checking cross-references…"`. Short sentence fragments; the
|
|
415
|
+
user reads them at a glance.
|
|
416
|
+
|
|
417
|
+
On completion, one call does everything:
|
|
418
|
+
|
|
419
|
+
```
|
|
420
|
+
composer_agent_status({
|
|
421
|
+
roomId, threadId, replyId,
|
|
422
|
+
state: "ready",
|
|
423
|
+
text: "Posted a suggestion below."
|
|
424
|
+
})
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
This rewrites the ack body and prunes the awareness heartbeat
|
|
428
|
+
atomically. Do NOT post a separate reply to say "done" — the rewrite
|
|
429
|
+
IS the final reply.
|
|
430
|
+
|
|
431
|
+
### Worked example — ack-then-suggestion flow
|
|
432
|
+
|
|
433
|
+
A mention arrives; the user asked you to tighten a sentence in Section 3.
|
|
434
|
+
The full round-trip is four tool calls:
|
|
435
|
+
|
|
436
|
+
```
|
|
437
|
+
// 1. Mention arrives via composer_next_event:
|
|
438
|
+
// { kind: "mention", threadId: "t_abc", invokerUserId: "u_jess",
|
|
439
|
+
// invokerName: "Jess", reason: "direct_mention", ... }
|
|
440
|
+
|
|
441
|
+
// 2. Ack first — posts the "on it" reply with a thinking indicator.
|
|
442
|
+
const { replyId } = composer_reply_comment({
|
|
443
|
+
roomId,
|
|
444
|
+
threadId: "t_abc",
|
|
445
|
+
text: "@Jess — on it",
|
|
446
|
+
mentions: ["u_jess"],
|
|
447
|
+
state: "thinking",
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
// 3. Transition to working before any slow step.
|
|
451
|
+
composer_agent_status({
|
|
452
|
+
roomId,
|
|
453
|
+
threadId: "t_abc",
|
|
454
|
+
replyId,
|
|
455
|
+
state: "working",
|
|
456
|
+
note: "Reading section 3…",
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
// 4. Do the work and post the substantive artifact.
|
|
460
|
+
composer_add_suggestion({
|
|
461
|
+
roomId,
|
|
462
|
+
fromThreadId: "t_abc",
|
|
463
|
+
replacementText: "…",
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
// 5. Rewrite the ack to a thin pointer and mark ready atomically.
|
|
467
|
+
composer_agent_status({
|
|
468
|
+
roomId,
|
|
469
|
+
threadId: "t_abc",
|
|
470
|
+
replyId,
|
|
471
|
+
state: "ready",
|
|
472
|
+
text: "Posted a suggestion below.",
|
|
473
|
+
});
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
No extra pointer reply. No "done" message. The rewrite + suggestion
|
|
477
|
+
card together are the complete response.
|
|
478
|
+
|
|
312
479
|
## Anchors
|
|
313
480
|
|
|
314
481
|
Write tools take:
|