@rallycry/conveyor-mcp 5.0.1 → 5.0.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.
package/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # @rallycry/conveyor-mcp
2
+
3
+ The Conveyor MCP server. It gives a coding agent — Claude Code, Codex, Cursor,
4
+ Windsurf, VS Code, Claude Desktop — direct access to your Conveyor cards,
5
+ plans, chat, tags, and pull requests.
6
+
7
+ ## Get your values
8
+
9
+ Open **User Settings → Connect your coding agent (MCP)** in the Conveyor web
10
+ app. It generates a token and copies a pre-filled command or config block that
11
+ already carries your API URL, token, and project id. Use that if you can.
12
+
13
+ To register the server by hand, replace the three placeholders below:
14
+
15
+ - `<api-url>` — your Conveyor API host.
16
+ - `<user-token>` — your personal token from User Settings. Treat it as a secret.
17
+ - `<project-id>` — the project to work in. Omit this variable for multi-project
18
+ mode, then pass `projectId` per tool call after calling `list_projects`.
19
+
20
+ ## Install
21
+
22
+ ### Claude Code (CLI)
23
+
24
+ ```bash
25
+ claude mcp remove conveyor -s local 2>/dev/null;
26
+ claude mcp add conveyor -s local \
27
+ -e CONVEYOR_API_URL=<api-url> \
28
+ -e CONVEYOR_USER_TOKEN=<user-token> \
29
+ -e CONVEYOR_PROJECT_ID=<project-id> \
30
+ -- npx -y @rallycry/conveyor-mcp@latest
31
+ ```
32
+
33
+ The `claude mcp remove` prefix makes the command idempotent. A bare
34
+ `claude mcp add` exits 1 with "already exists in local config" when a `conveyor`
35
+ server is already registered, which blocks a re-paste after a token rotation.
36
+
37
+ ### JSON config (Cursor, Windsurf, VS Code, Claude Desktop)
38
+
39
+ Merge this into your `mcpServers` block:
40
+
41
+ ```json
42
+ {
43
+ "mcpServers": {
44
+ "conveyor": {
45
+ "command": "npx",
46
+ "args": ["-y", "@rallycry/conveyor-mcp@latest"],
47
+ "env": {
48
+ "CONVEYOR_API_URL": "<api-url>",
49
+ "CONVEYOR_USER_TOKEN": "<user-token>",
50
+ "CONVEYOR_PROJECT_ID": "<project-id>"
51
+ }
52
+ }
53
+ }
54
+ }
55
+ ```
56
+
57
+ ### TOML config (Codex CLI, `~/.codex/config.toml`)
58
+
59
+ ```toml
60
+ [mcp_servers.conveyor]
61
+ command = "npx"
62
+ args = ["-y", "@rallycry/conveyor-mcp@latest"]
63
+
64
+ [mcp_servers.conveyor.env]
65
+ CONVEYOR_API_URL = "<api-url>"
66
+ CONVEYOR_USER_TOKEN = "<user-token>"
67
+ CONVEYOR_PROJECT_ID = "<project-id>"
68
+ ```
69
+
70
+ ## Environment variables
71
+
72
+ | Variable | Required | Purpose |
73
+ | ------------------------ | -------- | ------------------------------------------------------------------------------------ |
74
+ | `CONVEYOR_API_URL` | yes | Conveyor API host. |
75
+ | `CONVEYOR_USER_TOKEN` | yes | Your personal token. `CONVEYOR_PROJECT_TOKEN` is a backwards-compatible alias. |
76
+ | `CONVEYOR_PROJECT_ID` | no | Default project for unqualified tools. Omit it for multi-project mode. |
77
+ | `CONVEYOR_SUBPROJECT_ID` | no | Default board. Unqualified `create_task`/`list_tasks`/`search_tasks` target it. |
78
+
79
+ ## Why `npx -y …@latest`
80
+
81
+ Every form above launches the server through
82
+ `npx -y @rallycry/conveyor-mcp@latest`, so each start re-resolves the `@latest`
83
+ tag from the registry. Restarting the MCP server picks up newly published
84
+ versions, and there is no upgrade step to remember. The trade-off is a slightly
85
+ slower launch, because npx checks the registry each time.
86
+
87
+ The `@latest` tag is load-bearing. npx resolves a bare package name against the
88
+ local workspace first, so a bare `npx @rallycry/conveyor-mcp` inside a repo that
89
+ vendors a package of that name execs the unbuilt local copy and the server fails
90
+ to start. A version or tag spec forces registry resolution regardless of cwd.
91
+ Never shorten the command.
92
+
93
+ ## Verify
94
+
95
+ After you reload MCP servers, call `verify_connection`. It returns a plain
96
+ pass/fail plus, on failure, the failing layer and one next action. Then call
97
+ `get_connection_context` to confirm the account, project, and board are the ones
98
+ you intended.
99
+
100
+ ## License
101
+
102
+ MIT
@@ -208,14 +208,13 @@ var ConveyorConnection = class {
208
208
  const { projectId, subProjectId, tags, ...rest } = params;
209
209
  const resolvedProjectId = this.resolveProjectId(projectId);
210
210
  const resolvedSubProjectId = this.resolveSubProjectId(subProjectId);
211
+ const tagIds = await this.resolveTagIds(resolvedProjectId, tags ?? []);
211
212
  const result = await this.call("createProjectTask", {
212
213
  projectId: resolvedProjectId,
213
214
  subProjectId: resolvedSubProjectId,
214
215
  ...rest
215
216
  });
216
- if (tags && tags.length > 0) {
217
- await this.assignTagsToTask(result.id, resolvedProjectId, tags);
218
- }
217
+ await this.assignResolvedTags(result.id, tagIds);
219
218
  return {
220
219
  ...result,
221
220
  effectiveScope: {
@@ -230,12 +229,10 @@ var ConveyorConnection = class {
230
229
  const hasCoreUpdate = rest.title !== void 0 || rest.description !== void 0 || rest.plan !== void 0 || rest.status !== void 0 || rest.risk !== void 0 || rest.storyPointValue !== void 0 || rest.assignedUserId !== void 0 || rest.subProjectId !== void 0 || rest.githubBranch !== void 0;
231
230
  const removedTags = removeTags ?? [];
232
231
  const addedTags = addTags ?? [];
233
- if (removedTags.length > 0) {
234
- await this.removeTagsFromTask(rest.taskId, resolvedProjectId, removedTags);
235
- }
236
- if (addedTags.length > 0) {
237
- await this.assignTagsToTask(rest.taskId, resolvedProjectId, addedTags);
238
- }
232
+ const removeIds = await this.resolveTagIds(resolvedProjectId, removedTags);
233
+ const addIds = await this.resolveTagIds(resolvedProjectId, addedTags);
234
+ await this.removeResolvedTags(rest.taskId, removeIds);
235
+ await this.assignResolvedTags(rest.taskId, addIds);
239
236
  if (hasCoreUpdate) {
240
237
  const result = await this.call("updateProjectTask", { projectId: resolvedProjectId, ...rest });
241
238
  return { ...result, addedTags, removedTags };
@@ -270,13 +267,11 @@ var ConveyorConnection = class {
270
267
  }
271
268
  return [...new Set(ids)];
272
269
  }
273
- async assignTagsToTask(taskId, projectId, names) {
274
- const tagIds = await this.resolveTagIds(projectId, names);
270
+ async assignResolvedTags(taskId, tagIds) {
275
271
  if (tagIds.length === 0) return;
276
272
  await this.callService("tagService", "assignToTask", { taskId, tagIds });
277
273
  }
278
- async removeTagsFromTask(taskId, projectId, names) {
279
- const tagIds = await this.resolveTagIds(projectId, names);
274
+ async removeResolvedTags(taskId, tagIds) {
280
275
  if (tagIds.length === 0) return;
281
276
  await this.callService("tagService", "removeFromTask", { taskId, tagIds });
282
277
  }
@@ -552,7 +547,7 @@ var ConveyorConnection = class {
552
547
  ...rest
553
548
  });
554
549
  }
555
- // ── Meetings (read-only) ────────────────────────────────────────────
550
+ // ── Meetings ────────────────────────────────────────────────────────
556
551
  listMeetings(params) {
557
552
  const { projectId, ...rest } = params;
558
553
  return this.call("listMeetings", { projectId: this.resolveProjectId(projectId), ...rest });
@@ -568,6 +563,48 @@ var ConveyorConnection = class {
568
563
  ...rest
569
564
  });
570
565
  }
566
+ createMeeting(params) {
567
+ const { projectId, ...rest } = params;
568
+ return this.call("createProjectMeeting", {
569
+ projectId: this.resolveProjectId(projectId),
570
+ ...rest
571
+ });
572
+ }
573
+ updateMeeting(params) {
574
+ const { projectId, ...rest } = params;
575
+ return this.call("updateProjectMeeting", {
576
+ projectId: this.resolveProjectId(projectId),
577
+ ...rest
578
+ });
579
+ }
580
+ addMeetingChecklistItems(params) {
581
+ const { projectId, ...rest } = params;
582
+ return this.call("addProjectMeetingChecklistItems", {
583
+ projectId: this.resolveProjectId(projectId),
584
+ ...rest
585
+ });
586
+ }
587
+ checkMeetingChecklistItem(params) {
588
+ const { projectId, ...rest } = params;
589
+ return this.call("checkProjectMeetingChecklistItem", {
590
+ projectId: this.resolveProjectId(projectId),
591
+ ...rest
592
+ });
593
+ }
594
+ editMeetingChecklistItem(params) {
595
+ const { projectId, ...rest } = params;
596
+ return this.call("editProjectMeetingChecklistItem", {
597
+ projectId: this.resolveProjectId(projectId),
598
+ ...rest
599
+ });
600
+ }
601
+ removeMeetingChecklistItem(params) {
602
+ const { projectId, ...rest } = params;
603
+ return this.call("removeProjectMeetingChecklistItem", {
604
+ projectId: this.resolveProjectId(projectId),
605
+ ...rest
606
+ });
607
+ }
571
608
  /** Effective account/project/board identity + capabilities for this token. */
572
609
  getConnectionContext(projectId) {
573
610
  return this.call("getConnectionContext", {
@@ -707,13 +744,12 @@ var ConveyorConnection = class {
707
744
  async createSubtask(params) {
708
745
  const { projectId, tags, ...rest } = params;
709
746
  const resolvedProjectId = this.resolveProjectId(projectId);
747
+ const tagIds = await this.resolveTagIds(resolvedProjectId, tags ?? []);
710
748
  const result = await this.call("createProjectSubtask", {
711
749
  projectId: resolvedProjectId,
712
750
  ...rest
713
751
  });
714
- if (tags && tags.length > 0) {
715
- await this.assignTagsToTask(result.id, resolvedProjectId, tags);
716
- }
752
+ await this.assignResolvedTags(result.id, tagIds);
717
753
  return result;
718
754
  }
719
755
  /**
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ConveyorConnection
4
- } from "./chunk-7VH3ULLT.js";
4
+ } from "./chunk-XLDG5QEX.js";
5
5
 
6
6
  // src/cli.ts
7
7
  import { createRequire } from "module";
@@ -231,14 +231,14 @@ var f = {
231
231
  return { kind: "nullable", inner };
232
232
  }
233
233
  };
234
- function compileString(z10, spec) {
235
- let schema = z10.string();
234
+ function compileString(z11, spec) {
235
+ let schema = z11.string();
236
236
  if (spec.min !== void 0) schema = schema.min(spec.min);
237
237
  if (spec.max !== void 0) schema = schema.max(spec.max);
238
238
  return schema;
239
239
  }
240
- function compileNumber(z10, spec) {
241
- let schema = z10.number();
240
+ function compileNumber(z11, spec) {
241
+ let schema = z11.number();
242
242
  if (spec.int) schema = schema.int();
243
243
  if (spec.positive) schema = schema.positive();
244
244
  if (spec.nonnegative) schema = schema.nonnegative();
@@ -246,49 +246,49 @@ function compileNumber(z10, spec) {
246
246
  if (spec.max !== void 0) schema = schema.max(spec.max);
247
247
  return schema;
248
248
  }
249
- function compileArray(z10, spec) {
250
- let schema = z10.array(compileField(z10, spec.item));
249
+ function compileArray(z11, spec) {
250
+ let schema = z11.array(compileField(z11, spec.item));
251
251
  if (spec.min !== void 0) schema = schema.min(spec.min);
252
252
  return schema;
253
253
  }
254
- function compileBase(z10, spec) {
254
+ function compileBase(z11, spec) {
255
255
  switch (spec.kind) {
256
256
  case "string":
257
- return compileString(z10, spec);
257
+ return compileString(z11, spec);
258
258
  case "number":
259
- return compileNumber(z10, spec);
259
+ return compileNumber(z11, spec);
260
260
  case "boolean":
261
- return z10.boolean();
261
+ return z11.boolean();
262
262
  case "enum":
263
- return z10.enum([...spec.values]);
263
+ return z11.enum([...spec.values]);
264
264
  case "array":
265
- return compileArray(z10, spec);
265
+ return compileArray(z11, spec);
266
266
  case "object":
267
- return z10.object(compileShape(z10, spec.fields));
267
+ return z11.object(compileShape(z11, spec.fields));
268
268
  }
269
269
  }
270
270
  function descriptionOf(spec) {
271
271
  if (spec.kind === "optional" || spec.kind === "nullable") return descriptionOf(spec.inner);
272
272
  return spec.desc;
273
273
  }
274
- function compileUndescribed(z10, spec) {
274
+ function compileUndescribed(z11, spec) {
275
275
  if (spec.kind === "optional") {
276
- return compileUndescribed(z10, spec.inner).optional();
276
+ return compileUndescribed(z11, spec.inner).optional();
277
277
  }
278
278
  if (spec.kind === "nullable") {
279
- return compileUndescribed(z10, spec.inner).nullable();
279
+ return compileUndescribed(z11, spec.inner).nullable();
280
280
  }
281
- return compileBase(z10, spec);
281
+ return compileBase(z11, spec);
282
282
  }
283
- function compileField(z10, spec) {
284
- const schema = compileUndescribed(z10, spec);
283
+ function compileField(z11, spec) {
284
+ const schema = compileUndescribed(z11, spec);
285
285
  const desc = descriptionOf(spec);
286
286
  return desc === void 0 ? schema : schema.describe(desc);
287
287
  }
288
- function compileShape(z10, fields) {
288
+ function compileShape(z11, fields) {
289
289
  const shape = {};
290
290
  for (const [key, spec] of Object.entries(fields)) {
291
- shape[key] = compileField(z10, spec);
291
+ shape[key] = compileField(z11, spec);
292
292
  }
293
293
  return shape;
294
294
  }
@@ -869,7 +869,7 @@ var createSubtaskContract = defineToolContract({
869
869
  ),
870
870
  tags: f.optional(
871
871
  f.array(f.string(), {
872
- desc: 'Tag names to assign to the subtask (e.g. ["refactor"]). Unknown names are rejected \u2014 create the tag first with manage_tags. Use list_tags to see available tags.'
872
+ desc: 'Tag names to assign to the subtask (e.g. ["refactor"]). Unknown names are rejected before the subtask is created, so nothing is written and a corrected retry creates exactly one subtask. Create the tag first with manage_tags. Use list_tags to see available tags.'
873
873
  })
874
874
  )
875
875
  }
@@ -1462,10 +1462,149 @@ var readMeetingTranscriptContract = defineToolContract({
1462
1462
  }
1463
1463
  }
1464
1464
  });
1465
+ var RAW_TEXT_DESC = "The transcript itself. Plain text with `Speaker: line` labels, or a WebVTT/SRT file's contents \u2014 the format is detected, and the speaker labels become the participant list. Paste the whole thing; it is stored as the meeting's record.";
1466
+ var OCCURRED_AT_DESC = "When the meeting happened, ISO 8601 (e.g. 2026-09-02T15:00:00Z). Defaults to now. Must be a real date \u2014 no earlier than 2000, and no more than 48 hours ahead.";
1467
+ var TITLE_DESC = "Meeting title. Defaults to `Meeting <date>` when you do not name one.";
1468
+ var createMeetingContract = defineToolContract({
1469
+ name: "create_meeting",
1470
+ agent: {
1471
+ description: `File a transcript as a project meeting. Use this when you have the text of a call \u2014 a paste, an export, notes captured elsewhere \u2014 and it belongs in the project's record. The transcript is parsed into speaker segments and an AI summary is written straight after, so the meeting reads "processing" for a few seconds before its overview appears. This creates a MEETING, not cards: turning what was decided into work is still create_task's job.`,
1472
+ fields: {
1473
+ rawText: f.string({ desc: RAW_TEXT_DESC, min: 1 }),
1474
+ title: f.optional(f.string({ desc: TITLE_DESC, max: 200 })),
1475
+ occurredAt: f.optional(f.string({ desc: OCCURRED_AT_DESC }))
1476
+ }
1477
+ },
1478
+ mcp: {
1479
+ description: `File a transcript as a project meeting. The text is parsed into speaker segments and summarized automatically, so the meeting reports status "processing" briefly before its overview lands. Creates a meeting only \u2014 use the card tools to turn decisions into work. ${MCP_TAIL}`,
1480
+ fields: {
1481
+ projectId: mcpProjectId,
1482
+ rawText: f.string({ desc: RAW_TEXT_DESC, min: 1 }),
1483
+ title: f.optional(f.string({ desc: TITLE_DESC, max: 200 })),
1484
+ occurredAt: f.optional(f.string({ desc: OCCURRED_AT_DESC }))
1485
+ }
1486
+ }
1487
+ });
1488
+ var SUMMARY_DESC = "Replace the meeting's overview with this text. Markdown, and it is what every reader sees from then on \u2014 write the whole overview, not a note about it. Writing a summary marks the meeting ready, so a later regenerate is the only thing that overwrites it.";
1489
+ var updateMeetingContract = defineToolContract({
1490
+ name: "update_meeting",
1491
+ agent: {
1492
+ description: `Correct a meeting's title or date, or replace its AI summary with a better one. This is how a rewritten overview actually persists \u2014 read the transcript, write the summary you want, and pass it here. Pass at least one field; the ones you leave out are untouched.`,
1493
+ fields: {
1494
+ meetingId: f.string({ desc: MEETING_ID }),
1495
+ title: f.optional(f.string({ desc: TITLE_DESC, max: 200 })),
1496
+ occurredAt: f.optional(f.string({ desc: OCCURRED_AT_DESC })),
1497
+ summary: f.optional(f.string({ desc: SUMMARY_DESC, min: 1 }))
1498
+ }
1499
+ },
1500
+ mcp: {
1501
+ description: `Correct a meeting's title or date, or replace its AI summary with a rewritten one. Pass at least one field; omitted fields are left alone. ${MCP_TAIL}`,
1502
+ fields: {
1503
+ projectId: mcpProjectId,
1504
+ meetingId: f.string({ desc: MEETING_ID }),
1505
+ title: f.optional(f.string({ desc: TITLE_DESC, max: 200 })),
1506
+ occurredAt: f.optional(f.string({ desc: OCCURRED_AT_DESC })),
1507
+ summary: f.optional(f.string({ desc: SUMMARY_DESC, min: 1 }))
1508
+ }
1509
+ }
1510
+ });
1511
+ var CHECKLIST_ITEM_TITLE = "The item's exact title, as get_meeting lists it. Matched case-insensitively.";
1512
+ var CHECKLIST_INTRO = "A meeting's checklist is its follow-ups: one line each, ticked when done, optionally pointing at the Conveyor card that carries the work. The AI summary's proposed next steps are seeded here automatically.";
1513
+ var addMeetingChecklistItemsContract = defineToolContract({
1514
+ name: "add_meeting_checklist_items",
1515
+ agent: {
1516
+ description: `Add follow-up items to a meeting's checklist. ${CHECKLIST_INTRO} Use this for a step the summary missed, or one that came out of a later conversation. Items whose title already exists are skipped, so re-running this is safe.`,
1517
+ fields: {
1518
+ meetingId: f.string({ desc: MEETING_ID }),
1519
+ items: f.array(
1520
+ f.object({ title: f.string({ desc: "One follow-up, as a single line.", min: 1 }) }),
1521
+ { desc: "The items to add, in the order they should appear." }
1522
+ )
1523
+ }
1524
+ },
1525
+ mcp: {
1526
+ description: `Add follow-up items to a meeting's checklist. ${CHECKLIST_INTRO} Existing titles are skipped, so re-running is safe. ${MCP_TAIL}`,
1527
+ fields: {
1528
+ projectId: mcpProjectId,
1529
+ meetingId: f.string({ desc: MEETING_ID }),
1530
+ items: f.array(
1531
+ f.object({ title: f.string({ desc: "One follow-up, as a single line.", min: 1 }) }),
1532
+ { desc: "The items to add, in the order they should appear." }
1533
+ )
1534
+ }
1535
+ }
1536
+ });
1537
+ var LINKED_TASK_DESC = "Card id or slug to attach to this item \u2014 the card that carries the work. Must be in the same project. Pass it in the same call that ticks the item when you just filed the card.";
1538
+ var checkMeetingChecklistItemContract = defineToolContract({
1539
+ name: "check_meeting_checklist_item",
1540
+ agent: {
1541
+ description: `Tick or untick one of a meeting's checklist items, and optionally attach the card that carries it. This is how a next step becomes tracked work: file the card with create_task, then call this with the item's title and the new card's slug. Ticking records YOU as the person who did it. Unticking clears that, but keeps the linked card.`,
1542
+ fields: {
1543
+ meetingId: f.string({ desc: MEETING_ID }),
1544
+ title: f.string({ desc: CHECKLIST_ITEM_TITLE }),
1545
+ checked: f.boolean({ desc: "true to tick the item, false to untick it." }),
1546
+ linkedTask: f.optional(f.string({ desc: LINKED_TASK_DESC }))
1547
+ }
1548
+ },
1549
+ mcp: {
1550
+ description: `Tick or untick a meeting checklist item, optionally attaching the card that carries it. Ticking records the acting user. Unticking clears that but keeps the link. ${MCP_TAIL}`,
1551
+ fields: {
1552
+ projectId: mcpProjectId,
1553
+ meetingId: f.string({ desc: MEETING_ID }),
1554
+ title: f.string({ desc: CHECKLIST_ITEM_TITLE }),
1555
+ checked: f.boolean({ desc: "true to tick the item, false to untick it." }),
1556
+ linkedTask: f.optional(f.string({ desc: LINKED_TASK_DESC }))
1557
+ }
1558
+ }
1559
+ });
1560
+ var editMeetingChecklistItemContract = defineToolContract({
1561
+ name: "edit_meeting_checklist_item",
1562
+ agent: {
1563
+ description: `Reword one of a meeting's checklist items. Use it to sharpen a vague next step into something someone can act on; to mark it done use check_meeting_checklist_item instead.`,
1564
+ fields: {
1565
+ meetingId: f.string({ desc: MEETING_ID }),
1566
+ title: f.string({ desc: CHECKLIST_ITEM_TITLE }),
1567
+ newTitle: f.string({ desc: "The replacement text, as a single line.", min: 1 })
1568
+ }
1569
+ },
1570
+ mcp: {
1571
+ description: `Reword a meeting checklist item. To mark it done use check_meeting_checklist_item. ${MCP_TAIL}`,
1572
+ fields: {
1573
+ projectId: mcpProjectId,
1574
+ meetingId: f.string({ desc: MEETING_ID }),
1575
+ title: f.string({ desc: CHECKLIST_ITEM_TITLE }),
1576
+ newTitle: f.string({ desc: "The replacement text, as a single line.", min: 1 })
1577
+ }
1578
+ }
1579
+ });
1580
+ var removeMeetingChecklistItemContract = defineToolContract({
1581
+ name: "remove_meeting_checklist_item",
1582
+ agent: {
1583
+ description: `Delete one of a meeting's checklist items. For a step that turned out not to be needed. An item someone already ticked is a record that work happened \u2014 untick it or leave it rather than deleting it.`,
1584
+ fields: {
1585
+ meetingId: f.string({ desc: MEETING_ID }),
1586
+ title: f.string({ desc: CHECKLIST_ITEM_TITLE })
1587
+ }
1588
+ },
1589
+ mcp: {
1590
+ description: `Delete a meeting checklist item. Prefer unticking over deleting an item someone already completed. ${MCP_TAIL}`,
1591
+ fields: {
1592
+ projectId: mcpProjectId,
1593
+ meetingId: f.string({ desc: MEETING_ID }),
1594
+ title: f.string({ desc: CHECKLIST_ITEM_TITLE })
1595
+ }
1596
+ }
1597
+ });
1465
1598
  var meetingsContracts = [
1466
1599
  listMeetingsContract,
1467
1600
  getMeetingContract,
1468
- readMeetingTranscriptContract
1601
+ readMeetingTranscriptContract,
1602
+ createMeetingContract,
1603
+ updateMeetingContract,
1604
+ addMeetingChecklistItemsContract,
1605
+ checkMeetingChecklistItemContract,
1606
+ editMeetingChecklistItemContract,
1607
+ removeMeetingChecklistItemContract
1469
1608
  ];
1470
1609
  var SINCE_MINUTES = f.optional(
1471
1610
  f.number({
@@ -2088,7 +2227,7 @@ function registerCreateTask(server2, conn2) {
2088
2227
  status: z5.enum(["Planning", "Open"]).optional().describe("Initial status (default: Planning)"),
2089
2228
  subProjectId: BOARD_ASSIGN,
2090
2229
  tags: z5.array(z5.string()).optional().describe(
2091
- 'Tag names to assign to the new card (e.g. ["refactor"]). Unknown names are rejected \u2014 create the tag first with manage_tags. Use list_tags to see available tags.'
2230
+ 'Tag names to assign to the new card (e.g. ["refactor"]). Unknown names are rejected before the card is created, so nothing is written and a corrected retry creates exactly one card. Create the tag first with manage_tags. Use list_tags to see available tags.'
2092
2231
  )
2093
2232
  },
2094
2233
  async (params) => {
@@ -3064,10 +3203,11 @@ import { z as z62 } from "zod";
3064
3203
  import { z as z72 } from "zod";
3065
3204
  import { z as z82 } from "zod";
3066
3205
  import { z as z92 } from "zod";
3206
+ import { z as z10 } from "zod";
3067
3207
  var DEFAULT_SONNET_MODEL = "claude-sonnet-5";
3068
3208
  var DEFAULT_OPUS_MODEL = "claude-opus-5";
3069
3209
  var DEFAULT_HAIKU_MODEL = "claude-haiku-4-5-20251001";
3070
- var FABLE_MODEL = "claude-fable-5";
3210
+ var FABLE_MODEL = "claude-fable-5-1";
3071
3211
  var PREVIOUS_SONNET_MODEL = "claude-sonnet-4-6";
3072
3212
  var PREVIOUS_OPUS_MODEL = "claude-opus-4-8";
3073
3213
  var PTY_STREAM_PORT_BASE = 7420;
@@ -3770,10 +3910,6 @@ var ReportReviewSpawnFailureRequestSchema = z42.object({
3770
3910
  var ReportBuilderSpawnFailureRequestSchema = ReportReviewSpawnFailureRequestSchema.omit({
3771
3911
  reviewSessionId: true
3772
3912
  }).extend({ buildSessionId: z42.string() });
3773
- var RequestWorkspaceRecycleRequestSchema = z42.object({
3774
- sessionId: z42.string(),
3775
- reason: z42.string().max(2e3)
3776
- });
3777
3913
  var SpawnTaskSessionRequestSchema = z42.object({
3778
3914
  taskId: z42.string(),
3779
3915
  kind: z42.enum(["tui", "shell"])
@@ -4456,12 +4592,21 @@ var GetProjectAnalyticsSummaryRequestSchema = z62.object({
4456
4592
  rangeDays: z62.number().int().min(1).max(GET_ANALYTICS_SUMMARY_MAX_RANGE_DAYS).optional(),
4457
4593
  campaign: z62.string().max(200).optional()
4458
4594
  });
4595
+ var RequestWorkspaceRecycleRequestSchema = z72.object({
4596
+ sessionId: z72.string(),
4597
+ reason: z72.string().max(2e3)
4598
+ });
4599
+ var ReportApiOutageRequestSchema = z72.object({
4600
+ sessionId: z72.string(),
4601
+ detail: z72.string().max(2e3),
4602
+ attempts: z72.number().int().min(0).max(100)
4603
+ });
4459
4604
  var SHA_PATTERN = /^[0-9a-f]{40}$/i;
4460
- var ReviewGuideFileReferenceSchema = z72.object({
4461
- path: z72.string().min(1).max(500),
4462
- startLine: z72.number().int().positive().max(1e6).optional(),
4463
- endLine: z72.number().int().positive().max(1e6).optional(),
4464
- hunkHeader: z72.string().min(1).max(300).optional()
4605
+ var ReviewGuideFileReferenceSchema = z82.object({
4606
+ path: z82.string().min(1).max(500),
4607
+ startLine: z82.number().int().positive().max(1e6).optional(),
4608
+ endLine: z82.number().int().positive().max(1e6).optional(),
4609
+ hunkHeader: z82.string().min(1).max(300).optional()
4465
4610
  }).strict().superRefine((value, ctx) => {
4466
4611
  if (value.endLine !== void 0 && value.startLine === void 0) {
4467
4612
  ctx.addIssue({
@@ -4478,190 +4623,282 @@ var ReviewGuideFileReferenceSchema = z72.object({
4478
4623
  });
4479
4624
  }
4480
4625
  });
4481
- var ReviewGuideSectionSchema = z72.object({
4482
- title: z72.string().min(1).max(160),
4483
- explanation: z72.string().min(1).max(2e3),
4484
- classification: z72.enum(["core", "supporting"]).optional(),
4485
- files: z72.array(ReviewGuideFileReferenceSchema).min(1).max(20)
4626
+ var ReviewGuideSectionSchema = z82.object({
4627
+ title: z82.string().min(1).max(160),
4628
+ explanation: z82.string().min(1).max(2e3),
4629
+ classification: z82.enum(["core", "supporting"]).optional(),
4630
+ files: z82.array(ReviewGuideFileReferenceSchema).min(1).max(20)
4486
4631
  }).strict();
4487
- var ReviewGuideContentSchema = z72.object({
4488
- overview: z72.string().min(1).max(3e3),
4489
- sections: z72.array(ReviewGuideSectionSchema).min(1).max(12)
4632
+ var ReviewGuideContentSchema = z82.object({
4633
+ overview: z82.string().min(1).max(3e3),
4634
+ sections: z82.array(ReviewGuideSectionSchema).min(1).max(12)
4490
4635
  }).strict();
4491
4636
  var PublishReviewGuideRequestSchema = ReviewGuideContentSchema.extend({
4492
- sessionId: z72.string().min(1),
4493
- reviewedSha: z72.string().regex(SHA_PATTERN, "reviewedSha must be a 40-character commit SHA")
4637
+ sessionId: z82.string().min(1),
4638
+ reviewedSha: z82.string().regex(SHA_PATTERN, "reviewedSha must be a 40-character commit SHA")
4494
4639
  }).strict();
4495
4640
  var CONTEXT_LINK_LOCATOR_MAX2 = 300;
4496
4641
  var TAG_DESCRIPTION_MAX = CARD_DESCRIPTION_MAX;
4497
4642
  var TAG_OVERVIEW_MAX = 32e3;
4498
4643
  var TAG_REASON_MAX = 500;
4499
- var ProjectTagContextPathSchema = z82.object({
4500
- type: z82.enum(["rule", "doc", "file", "folder"]),
4501
- path: z82.string().min(1).max(500),
4502
- label: z82.string().max(100).optional(),
4644
+ var ProjectTagContextPathSchema = z92.object({
4645
+ type: z92.enum(["rule", "doc", "file", "folder"]),
4646
+ path: z92.string().min(1).max(500),
4647
+ label: z92.string().max(100).optional(),
4503
4648
  /** Verified-link tether — text that must keep existing in the file. */
4504
- locator: z82.string().min(1).max(CONTEXT_LINK_LOCATOR_MAX2).regex(/^[^\r\n]*$/, "Locator cannot contain line breaks").optional(),
4649
+ locator: z92.string().min(1).max(CONTEXT_LINK_LOCATOR_MAX2).regex(/^[^\r\n]*$/, "Locator cannot contain line breaks").optional(),
4505
4650
  /** test = must appear in a real test/describe title; code = any substring. */
4506
- locatorType: z82.enum(["test", "code"]).optional()
4651
+ locatorType: z92.enum(["test", "code"]).optional()
4507
4652
  }).refine((link) => link.locator === void 0 === (link.locatorType === void 0), {
4508
4653
  message: "locator and locatorType must be provided together"
4509
4654
  }).refine((link) => link.locator === void 0 || link.type !== "folder", {
4510
4655
  message: "folder links cannot carry a locator"
4511
4656
  });
4512
- var hexColor = z82.string().regex(/^#[0-9a-fA-F]{6}$/, "Expected #RRGGBB hex color");
4513
- var overviewPathSchema = z82.string().min(1).max(500).regex(/^[^\r\n]*$/, "Overview path cannot contain line breaks");
4514
- var CreateProjectTagRequestSchema = z82.object({
4515
- projectId: z82.string(),
4516
- name: z82.string().min(1).max(50),
4657
+ var hexColor = z92.string().regex(/^#[0-9a-fA-F]{6}$/, "Expected #RRGGBB hex color");
4658
+ var overviewPathSchema = z92.string().min(1).max(500).regex(/^[^\r\n]*$/, "Overview path cannot contain line breaks");
4659
+ var CreateProjectTagRequestSchema = z92.object({
4660
+ projectId: z92.string(),
4661
+ name: z92.string().min(1).max(50),
4517
4662
  color: hexColor.optional(),
4518
- description: z82.string().max(TAG_DESCRIPTION_MAX).optional(),
4519
- overview: z82.string().max(TAG_OVERVIEW_MAX).optional(),
4663
+ description: z92.string().max(TAG_DESCRIPTION_MAX).optional(),
4664
+ overview: z92.string().max(TAG_OVERVIEW_MAX).optional(),
4520
4665
  /** Source the overview from this repo file (stored overview stays as the pending fallback). */
4521
4666
  overviewPath: overviewPathSchema.optional(),
4522
- contextPaths: z82.array(ProjectTagContextPathSchema).max(20).optional(),
4667
+ contextPaths: z92.array(ProjectTagContextPathSchema).max(20).optional(),
4523
4668
  /** Parents to link at create time (multi-parent DAG). */
4524
- parentTagIds: z82.array(z82.string()).max(25).optional(),
4525
- requestingUserId: z82.string().optional()
4669
+ parentTagIds: z92.array(z92.string()).max(25).optional(),
4670
+ requestingUserId: z92.string().optional()
4526
4671
  });
4527
- var UpdateProjectTagRequestSchema = z82.object({
4528
- projectId: z82.string(),
4529
- tagId: z82.string(),
4530
- name: z82.string().min(1).max(50).optional(),
4672
+ var UpdateProjectTagRequestSchema = z92.object({
4673
+ projectId: z92.string(),
4674
+ tagId: z92.string(),
4675
+ name: z92.string().min(1).max(50).optional(),
4531
4676
  color: hexColor.optional(),
4532
- description: z82.string().max(TAG_DESCRIPTION_MAX).optional(),
4677
+ description: z92.string().max(TAG_DESCRIPTION_MAX).optional(),
4533
4678
  /** Full markdown glossary body; null clears it. Rejected while overviewPath is set. */
4534
- overview: z82.string().max(TAG_OVERVIEW_MAX).nullable().optional(),
4679
+ overview: z92.string().max(TAG_OVERVIEW_MAX).nullable().optional(),
4535
4680
  /** Repo file to source the overview from; null clears back to the stored overview. */
4536
4681
  overviewPath: overviewPathSchema.nullable().optional(),
4537
4682
  /** Full replacement of the tag's context links when provided. */
4538
- contextPaths: z82.array(ProjectTagContextPathSchema).max(20).optional(),
4683
+ contextPaths: z92.array(ProjectTagContextPathSchema).max(20).optional(),
4539
4684
  /** Full-set replacement of the tag's parent tags (multi-parent DAG). */
4540
- parentTagIds: z82.array(z82.string()).max(25).optional(),
4685
+ parentTagIds: z92.array(z92.string()).max(25).optional(),
4541
4686
  /** One-line revision provenance, recorded in the tag's history. */
4542
- reason: z82.string().max(TAG_REASON_MAX).optional(),
4687
+ reason: z92.string().max(TAG_REASON_MAX).optional(),
4543
4688
  /** Card the caller was working in — stamped into the revision history. */
4544
- taskId: z82.string().optional(),
4545
- requestingUserId: z82.string().optional()
4689
+ taskId: z92.string().optional(),
4690
+ requestingUserId: z92.string().optional()
4546
4691
  });
4547
- var PostToProjectChatRequestSchema = z82.object({
4548
- projectId: z82.string(),
4549
- content: z82.string().min(1).max(2e4),
4550
- requestingUserId: z82.string().optional(),
4692
+ var PostToProjectChatRequestSchema = z92.object({
4693
+ projectId: z92.string(),
4694
+ content: z92.string().min(1).max(2e4),
4695
+ requestingUserId: z92.string().optional(),
4551
4696
  /** Marks the post so the server can persist it beyond chat (tag-audit summaries land in tag history). */
4552
- kind: z82.enum(["tag_audit_summary"]).optional()
4553
- });
4554
- var StartTagAuditRequestSchema = z82.object({
4555
- projectId: z82.string(),
4556
- requestingUserId: z82.string().optional()
4557
- });
4558
- var StartTaskAuditRequestSchema = z82.object({
4559
- projectId: z82.string(),
4560
- taskIds: z82.array(z82.string()).min(1).max(20),
4561
- requestingUserId: z82.string().optional()
4562
- });
4563
- var GetActiveAuditSessionsRequestSchema = z82.object({
4564
- projectId: z82.string()
4565
- });
4566
- var ReportTaskAuditResultRequestSchema = z82.object({
4567
- projectId: z82.string(),
4568
- taskId: z82.string(),
4569
- summary: z82.string(),
4570
- turnGrades: z82.array(
4571
- z82.object({
4572
- turnIndex: z82.number(),
4573
- phase: z82.enum(["planning", "building", "human"]),
4574
- grade: z82.enum(["correct", "neutral", "blunder"]),
4575
- reasoning: z82.string(),
4576
- eventType: z82.string(),
4577
- eventSummary: z82.string()
4697
+ kind: z92.enum(["tag_audit_summary"]).optional()
4698
+ });
4699
+ var StartTagAuditRequestSchema = z92.object({
4700
+ projectId: z92.string(),
4701
+ requestingUserId: z92.string().optional()
4702
+ });
4703
+ var StartTaskAuditRequestSchema = z92.object({
4704
+ projectId: z92.string(),
4705
+ taskIds: z92.array(z92.string()).min(1).max(20),
4706
+ requestingUserId: z92.string().optional()
4707
+ });
4708
+ var GetActiveAuditSessionsRequestSchema = z92.object({
4709
+ projectId: z92.string()
4710
+ });
4711
+ var ReportTaskAuditResultRequestSchema = z92.object({
4712
+ projectId: z92.string(),
4713
+ taskId: z92.string(),
4714
+ summary: z92.string(),
4715
+ turnGrades: z92.array(
4716
+ z92.object({
4717
+ turnIndex: z92.number(),
4718
+ phase: z92.enum(["planning", "building", "human"]),
4719
+ grade: z92.enum(["correct", "neutral", "blunder"]),
4720
+ reasoning: z92.string(),
4721
+ eventType: z92.string(),
4722
+ eventSummary: z92.string()
4578
4723
  })
4579
4724
  ),
4580
- planningAccuracy: z82.number().nullable(),
4581
- buildingAccuracy: z82.number().nullable(),
4582
- humanAccuracy: z82.number().nullable(),
4583
- planningCorrect: z82.number(),
4584
- planningNeutral: z82.number(),
4585
- planningBlunder: z82.number(),
4586
- buildingCorrect: z82.number(),
4587
- buildingNeutral: z82.number(),
4588
- buildingBlunder: z82.number(),
4589
- humanCorrect: z82.number(),
4590
- humanNeutral: z82.number(),
4591
- humanBlunder: z82.number(),
4592
- humanEvaluations: z82.array(
4593
- z82.object({
4594
- messageIndex: z82.number(),
4595
- rating: z82.union([z82.literal(-1), z82.literal(0), z82.literal(1)]),
4596
- reasoning: z82.string()
4725
+ planningAccuracy: z92.number().nullable(),
4726
+ buildingAccuracy: z92.number().nullable(),
4727
+ humanAccuracy: z92.number().nullable(),
4728
+ planningCorrect: z92.number(),
4729
+ planningNeutral: z92.number(),
4730
+ planningBlunder: z92.number(),
4731
+ buildingCorrect: z92.number(),
4732
+ buildingNeutral: z92.number(),
4733
+ buildingBlunder: z92.number(),
4734
+ humanCorrect: z92.number(),
4735
+ humanNeutral: z92.number(),
4736
+ humanBlunder: z92.number(),
4737
+ humanEvaluations: z92.array(
4738
+ z92.object({
4739
+ messageIndex: z92.number(),
4740
+ rating: z92.union([z92.literal(-1), z92.literal(0), z92.literal(1)]),
4741
+ reasoning: z92.string()
4597
4742
  })
4598
4743
  ).optional(),
4599
- suggestionIds: z82.array(z82.string()),
4600
- auditCostUsd: z82.number().nullable(),
4601
- model: z82.string().nullable(),
4744
+ suggestionIds: z92.array(z92.string()),
4745
+ auditCostUsd: z92.number().nullable(),
4746
+ model: z92.string().nullable(),
4602
4747
  /** When set, the audit is marked failed with this message instead. */
4603
- error: z82.string().optional()
4748
+ error: z92.string().optional()
4604
4749
  });
4605
- var GetTaskAuditsRequestSchema = z82.object({
4606
- projectId: z82.string(),
4607
- limit: z82.number().int().positive().max(200).optional().default(50)
4750
+ var GetTaskAuditsRequestSchema = z92.object({
4751
+ projectId: z92.string(),
4752
+ limit: z92.number().int().positive().max(200).optional().default(50)
4608
4753
  });
4609
- var GetTaskAuditRequestSchema = z82.object({
4610
- projectId: z82.string(),
4611
- auditId: z82.string()
4754
+ var GetTaskAuditRequestSchema = z92.object({
4755
+ projectId: z92.string(),
4756
+ auditId: z92.string()
4612
4757
  });
4613
- var GetTaskAuditAggregatesRequestSchema = z82.object({
4614
- projectId: z82.string()
4758
+ var GetTaskAuditAggregatesRequestSchema = z92.object({
4759
+ projectId: z92.string()
4615
4760
  });
4616
- var DeleteTaskAuditRequestSchema = z82.object({
4617
- projectId: z82.string(),
4618
- auditId: z82.string(),
4619
- requestingUserId: z82.string().optional()
4761
+ var DeleteTaskAuditRequestSchema = z92.object({
4762
+ projectId: z92.string(),
4763
+ auditId: z92.string(),
4764
+ requestingUserId: z92.string().optional()
4620
4765
  });
4621
- var MarkInitialPromptSubmittedRequestSchema = z82.object({
4622
- sessionId: z82.string()
4766
+ var MarkInitialPromptSubmittedRequestSchema = z92.object({
4767
+ sessionId: z92.string()
4623
4768
  });
4769
+ var MEETING_CHECKLIST_TITLE_MAX = 300;
4624
4770
  var MEETING_TRANSCRIPT_MAX_CHARS = 2e6;
4625
4771
  var MEETING_TITLE_MAX = 200;
4626
- var CreateMeetingFromTranscriptRequestSchema = z92.object({
4627
- projectId: z92.string().cuid(),
4628
- rawText: z92.string().min(1).max(MEETING_TRANSCRIPT_MAX_CHARS),
4629
- title: z92.string().min(1).max(MEETING_TITLE_MAX).optional(),
4772
+ var MEETING_OCCURRED_AT_MIN_YEAR = 2e3;
4773
+ var MEETING_OCCURRED_AT_MAX_FUTURE_MS = 48 * 60 * 60 * 1e3;
4774
+ var OCCURRED_AT_RANGE_MESSAGE = `occurredAt must be a real date: no earlier than ${MEETING_OCCURRED_AT_MIN_YEAR}, and no more than 48 hours in the future.`;
4775
+ var MeetingOccurredAtSchema = z10.string().datetime().refine((value) => {
4776
+ const ms = Date.parse(value);
4777
+ if (Number.isNaN(ms)) return false;
4778
+ if (ms > Date.now() + MEETING_OCCURRED_AT_MAX_FUTURE_MS) return false;
4779
+ return new Date(ms).getUTCFullYear() >= MEETING_OCCURRED_AT_MIN_YEAR;
4780
+ }, OCCURRED_AT_RANGE_MESSAGE);
4781
+ var CreateMeetingFromTranscriptRequestSchema = z10.object({
4782
+ projectId: z10.string().cuid(),
4783
+ rawText: z10.string().min(1).max(MEETING_TRANSCRIPT_MAX_CHARS),
4784
+ title: z10.string().min(1).max(MEETING_TITLE_MAX).optional(),
4630
4785
  /** ISO 8601. Defaults to now when the source carries no date. */
4631
- occurredAt: z92.string().datetime().optional(),
4786
+ occurredAt: MeetingOccurredAtSchema.optional(),
4632
4787
  /** Override auto-detection. Rarely needed; detection handles the three formats. */
4633
- format: z92.enum(["text", "vtt", "srt"]).optional(),
4634
- source: z92.enum(["manual", "slack"]).optional()
4635
- });
4636
- var GetMeetingRequestSchema = z92.object({
4637
- projectId: z92.string().cuid(),
4638
- meetingId: z92.string().cuid()
4639
- });
4640
- var UpdateMeetingRequestSchema = z92.object({
4641
- projectId: z92.string().cuid(),
4642
- meetingId: z92.string().cuid(),
4643
- title: z92.string().min(1).max(MEETING_TITLE_MAX).optional(),
4644
- occurredAt: z92.string().datetime().optional()
4645
- });
4646
- var RegenerateMeetingSummaryRequestSchema = z92.object({
4647
- projectId: z92.string().cuid(),
4648
- meetingId: z92.string().cuid()
4649
- });
4650
- var DeleteMeetingRequestSchema = z92.object({
4651
- projectId: z92.string().cuid(),
4652
- meetingId: z92.string().cuid()
4653
- });
4654
- var ListMeetingsRequestSchema = z92.object({
4655
- projectId: z92.string().cuid(),
4656
- limit: z92.number().int().min(1).max(50).optional(),
4657
- search: z92.string().max(200).optional()
4658
- });
4659
- var ReadMeetingTranscriptRequestSchema = z92.object({
4660
- projectId: z92.string().cuid(),
4661
- meetingId: z92.string().cuid(),
4662
- offset: z92.number().int().min(0).optional(),
4663
- limit: z92.number().int().min(1).max(500).optional()
4664
- });
4788
+ format: z10.enum(["text", "vtt", "srt"]).optional(),
4789
+ source: z10.enum(["manual", "slack"]).optional()
4790
+ });
4791
+ var GetMeetingRequestSchema = z10.object({
4792
+ projectId: z10.string().cuid(),
4793
+ meetingId: z10.string().cuid()
4794
+ });
4795
+ var UpdateMeetingRequestSchema = z10.object({
4796
+ projectId: z10.string().cuid(),
4797
+ meetingId: z10.string().cuid(),
4798
+ title: z10.string().min(1).max(MEETING_TITLE_MAX).optional(),
4799
+ occurredAt: MeetingOccurredAtSchema.optional()
4800
+ });
4801
+ var RegenerateMeetingSummaryRequestSchema = z10.object({
4802
+ projectId: z10.string().cuid(),
4803
+ meetingId: z10.string().cuid()
4804
+ });
4805
+ var DeleteMeetingRequestSchema = z10.object({
4806
+ projectId: z10.string().cuid(),
4807
+ meetingId: z10.string().cuid()
4808
+ });
4809
+ var checklistTitle = z10.string().min(1).max(MEETING_CHECKLIST_TITLE_MAX);
4810
+ var ListMeetingChecklistRequestSchema = z10.object({
4811
+ projectId: z10.string().cuid(),
4812
+ meetingId: z10.string().cuid()
4813
+ });
4814
+ var AddMeetingChecklistItemsRequestSchema = z10.object({
4815
+ projectId: z10.string().cuid(),
4816
+ meetingId: z10.string().cuid(),
4817
+ items: z10.array(z10.object({ title: checklistTitle })).min(1).max(50)
4818
+ });
4819
+ var UpdateMeetingChecklistItemRequestSchema = z10.object({
4820
+ projectId: z10.string().cuid(),
4821
+ meetingId: z10.string().cuid(),
4822
+ itemId: z10.string().cuid(),
4823
+ title: checklistTitle.optional(),
4824
+ ordinal: z10.number().int().min(0).optional(),
4825
+ /** Explicit null clears the link; undefined leaves it alone. */
4826
+ linkedTaskId: z10.string().cuid().nullable().optional()
4827
+ }).refine(
4828
+ (v) => v.title !== void 0 || v.ordinal !== void 0 || v.linkedTaskId !== void 0,
4829
+ "Pass at least one of title, ordinal, or linkedTaskId."
4830
+ );
4831
+ var DeleteMeetingChecklistItemRequestSchema = z10.object({
4832
+ projectId: z10.string().cuid(),
4833
+ meetingId: z10.string().cuid(),
4834
+ itemId: z10.string().cuid()
4835
+ });
4836
+ var SetMeetingChecklistItemCheckedRequestSchema = z10.object({
4837
+ projectId: z10.string().cuid(),
4838
+ meetingId: z10.string().cuid(),
4839
+ itemId: z10.string().cuid(),
4840
+ checked: z10.boolean(),
4841
+ /** Attach the card in the same call that ticks the item. */
4842
+ linkedTaskId: z10.string().cuid().nullable().optional()
4843
+ });
4844
+ var ListMeetingsRequestSchema = z10.object({
4845
+ projectId: z10.string().cuid(),
4846
+ limit: z10.number().int().min(1).max(50).optional(),
4847
+ search: z10.string().max(200).optional()
4848
+ });
4849
+ var ReadMeetingTranscriptRequestSchema = z10.object({
4850
+ projectId: z10.string().cuid(),
4851
+ meetingId: z10.string().cuid(),
4852
+ offset: z10.number().int().min(0).optional(),
4853
+ limit: z10.number().int().min(1).max(500).optional()
4854
+ });
4855
+ var MEETING_SUMMARY_MAX_CHARS = 5e4;
4856
+ var AddProjectMeetingChecklistItemsRequestSchema = z10.object({
4857
+ projectId: z10.string().cuid(),
4858
+ meetingId: z10.string().cuid(),
4859
+ items: z10.array(z10.object({ title: z10.string().min(1).max(MEETING_CHECKLIST_TITLE_MAX) })).min(1).max(50),
4860
+ requestingUserId: z10.string().optional()
4861
+ });
4862
+ var CheckProjectMeetingChecklistItemRequestSchema = z10.object({
4863
+ projectId: z10.string().cuid(),
4864
+ meetingId: z10.string().cuid(),
4865
+ title: z10.string().min(1).max(MEETING_CHECKLIST_TITLE_MAX),
4866
+ checked: z10.boolean(),
4867
+ /** Card id or slug. Resolved server-side and required to be in the project. */
4868
+ linkedTask: z10.string().min(1).optional(),
4869
+ requestingUserId: z10.string().optional()
4870
+ });
4871
+ var EditProjectMeetingChecklistItemRequestSchema = z10.object({
4872
+ projectId: z10.string().cuid(),
4873
+ meetingId: z10.string().cuid(),
4874
+ title: z10.string().min(1).max(MEETING_CHECKLIST_TITLE_MAX),
4875
+ newTitle: z10.string().min(1).max(MEETING_CHECKLIST_TITLE_MAX),
4876
+ requestingUserId: z10.string().optional()
4877
+ });
4878
+ var RemoveProjectMeetingChecklistItemRequestSchema = z10.object({
4879
+ projectId: z10.string().cuid(),
4880
+ meetingId: z10.string().cuid(),
4881
+ title: z10.string().min(1).max(MEETING_CHECKLIST_TITLE_MAX),
4882
+ requestingUserId: z10.string().optional()
4883
+ });
4884
+ var CreateProjectMeetingRequestSchema = z10.object({
4885
+ projectId: z10.string().cuid(),
4886
+ rawText: z10.string().min(1).max(MEETING_TRANSCRIPT_MAX_CHARS),
4887
+ title: z10.string().min(1).max(MEETING_TITLE_MAX).optional(),
4888
+ occurredAt: MeetingOccurredAtSchema.optional(),
4889
+ requestingUserId: z10.string().optional()
4890
+ });
4891
+ var UpdateProjectMeetingRequestSchema = z10.object({
4892
+ projectId: z10.string().cuid(),
4893
+ meetingId: z10.string().cuid(),
4894
+ title: z10.string().min(1).max(MEETING_TITLE_MAX).optional(),
4895
+ occurredAt: MeetingOccurredAtSchema.optional(),
4896
+ summary: z10.string().min(1).max(MEETING_SUMMARY_MAX_CHARS).optional(),
4897
+ requestingUserId: z10.string().optional()
4898
+ }).refine(
4899
+ (v) => v.title !== void 0 || v.occurredAt !== void 0 || v.summary !== void 0,
4900
+ "Pass at least one of title, occurredAt, or summary."
4901
+ );
4665
4902
  var TASK_CHAT_HISTORY_LIMIT = 20;
4666
4903
  var PM_CHAT_HISTORY_LIMIT = 40;
4667
4904
  var AGENT_CHAT_HISTORY_FETCH_LIMIT = Math.max(TASK_CHAT_HISTORY_LIMIT, PM_CHAT_HISTORY_LIMIT) + 10;
@@ -4689,8 +4926,11 @@ var ANTHROPIC_CATALOG = [
4689
4926
  anthropicEntry(PREVIOUS_SONNET_MODEL, "Sonnet 4.6", 3, 15),
4690
4927
  // The Haiku line (4.5 and older) predates the tuning surface and 400s on it.
4691
4928
  anthropicEntry(DEFAULT_HAIKU_MODEL, "Haiku 4.5", 1, 5, { supportsEffort: false }),
4692
- anthropicEntry(FABLE_MODEL, "Fable 5 (experimental)", 10, 50, { experimental: true })
4929
+ anthropicEntry(FABLE_MODEL, "Fable 5.1", 10, 50)
4693
4930
  ];
4931
+ var CLAUDESPACE_WORKLOAD_LABEL = "rc-workload";
4932
+ var CLAUDESPACE_WORKLOAD_VALUE = "claudespace";
4933
+ var CONVEYOR_POD_SELECTOR = `${CLAUDESPACE_WORKLOAD_LABEL}=${CLAUDESPACE_WORKLOAD_VALUE}`;
4694
4934
  var MS_PER_DAY = 24 * 60 * 60 * 1e3;
4695
4935
  var POSTGRES_ENV = {
4696
4936
  POSTGRES_HOST_AUTH_METHOD: "trust",
@@ -5090,7 +5330,34 @@ ${content}` }] };
5090
5330
  }
5091
5331
 
5092
5332
  // src/tools/meetings.ts
5333
+ function describeItem(item) {
5334
+ const box = item.checked ? "[x]" : "[ ]";
5335
+ const who = item.checked && item.checkedBy ? ` \u2014 ${item.checkedBy}` : "";
5336
+ const card = item.linkedTaskSlug ? ` (${item.linkedTaskSlug})` : "";
5337
+ return `${box} ${item.title}${who}${card}`;
5338
+ }
5339
+ function registerChecklistTools2(server2, conn2) {
5340
+ registerContractTool(server2, addMeetingChecklistItemsContract, async (params) => {
5341
+ const res = await conn2.addMeetingChecklistItems(params);
5342
+ const text = res.length === 0 ? "No items added \u2014 every title is already on this checklist." : `Added ${res.length}:
5343
+ ${res.map(describeItem).join("\n")}`;
5344
+ return { content: [{ type: "text", text }] };
5345
+ });
5346
+ registerContractTool(server2, checkMeetingChecklistItemContract, async (params) => {
5347
+ const res = await conn2.checkMeetingChecklistItem(params);
5348
+ return { content: [{ type: "text", text: describeItem(res) }] };
5349
+ });
5350
+ registerContractTool(server2, editMeetingChecklistItemContract, async (params) => {
5351
+ const res = await conn2.editMeetingChecklistItem(params);
5352
+ return { content: [{ type: "text", text: describeItem(res) }] };
5353
+ });
5354
+ registerContractTool(server2, removeMeetingChecklistItemContract, async (params) => {
5355
+ const res = await conn2.removeMeetingChecklistItem(params);
5356
+ return { content: [{ type: "text", text: `Removed "${res.title}".` }] };
5357
+ });
5358
+ }
5093
5359
  function registerMeetingTools(server2, conn2) {
5360
+ registerChecklistTools2(server2, conn2);
5094
5361
  registerContractTool(server2, listMeetingsContract, async (params) => {
5095
5362
  const res = await conn2.listMeetings(params);
5096
5363
  if (res.meetings.length === 0) {
@@ -5109,6 +5376,24 @@ function registerMeetingTools(server2, conn2) {
5109
5376
  const res = await conn2.getMeeting(params);
5110
5377
  return { content: [{ type: "text", text: JSON.stringify(res, null, 2) }] };
5111
5378
  });
5379
+ registerContractTool(server2, createMeetingContract, async (params) => {
5380
+ const res = await conn2.createMeeting(params);
5381
+ return {
5382
+ content: [
5383
+ {
5384
+ type: "text",
5385
+ text: `Created "${res.title}" (${res.segmentCount} segments, ${res.participants.length} participants).
5386
+ The AI summary is being written now; read it back with get_meeting in a few seconds.
5387
+ ${res.url}`
5388
+ }
5389
+ ]
5390
+ };
5391
+ });
5392
+ registerContractTool(server2, updateMeetingContract, async (params) => {
5393
+ const res = await conn2.updateMeeting(params);
5394
+ return { content: [{ type: "text", text: `Updated "${res.title}".
5395
+ ${res.url}` }] };
5396
+ });
5112
5397
  registerContractTool(server2, readMeetingTranscriptContract, async (params) => {
5113
5398
  const res = await conn2.readMeetingTranscript(params);
5114
5399
  const header = `${res.title} \u2014 segments ${res.offset + 1}-${res.offset + res.lines.length} of ${res.segmentCount}`;
@@ -1,4 +1,4 @@
1
- import { ListDriveFilesResponse, ReadDriveFileResponse, DriveFileDTO, DeleteDriveFileResponse, ProjectIntegrationsSummary, GaAnalyticsSummaryDTO, ProjectChannelDTO, ReadChannelMessagesResponse, PostChannelMessageResponse, ListMeetingsResponse, MeetingForAgent, ReadMeetingTranscriptResponse } from '@project/shared';
1
+ import { ListDriveFilesResponse, ReadDriveFileResponse, DriveFileDTO, DeleteDriveFileResponse, ProjectIntegrationsSummary, GaAnalyticsSummaryDTO, ProjectChannelDTO, ReadChannelMessagesResponse, PostChannelMessageResponse, ListMeetingsResponse, MeetingForAgent, ReadMeetingTranscriptResponse, MeetingChecklistItemForAgent } from '@project/shared';
2
2
 
3
3
  interface ConveyorMcpConfig {
4
4
  apiUrl: string;
@@ -427,8 +427,8 @@ declare class ConveyorConnection {
427
427
  }>;
428
428
  /** Resolve tag names to IDs within a project, throwing on any unknown name. */
429
429
  private resolveTagIds;
430
- private assignTagsToTask;
431
- private removeTagsFromTask;
430
+ private assignResolvedTags;
431
+ private removeResolvedTags;
432
432
  /** Guarded status transition used by the review tools (approve/request). */
433
433
  transitionTaskStatus(params: {
434
434
  projectId?: string;
@@ -685,6 +685,46 @@ declare class ConveyorConnection {
685
685
  offset?: number;
686
686
  limit?: number;
687
687
  }): Promise<ReadMeetingTranscriptResponse>;
688
+ createMeeting(params: {
689
+ projectId?: string;
690
+ rawText: string;
691
+ title?: string;
692
+ occurredAt?: string;
693
+ }): Promise<MeetingForAgent>;
694
+ updateMeeting(params: {
695
+ projectId?: string;
696
+ meetingId: string;
697
+ title?: string;
698
+ occurredAt?: string;
699
+ summary?: string;
700
+ }): Promise<MeetingForAgent>;
701
+ addMeetingChecklistItems(params: {
702
+ projectId?: string;
703
+ meetingId: string;
704
+ items: {
705
+ title: string;
706
+ }[];
707
+ }): Promise<MeetingChecklistItemForAgent[]>;
708
+ checkMeetingChecklistItem(params: {
709
+ projectId?: string;
710
+ meetingId: string;
711
+ title: string;
712
+ checked: boolean;
713
+ linkedTask?: string;
714
+ }): Promise<MeetingChecklistItemForAgent>;
715
+ editMeetingChecklistItem(params: {
716
+ projectId?: string;
717
+ meetingId: string;
718
+ title: string;
719
+ newTitle: string;
720
+ }): Promise<MeetingChecklistItemForAgent>;
721
+ removeMeetingChecklistItem(params: {
722
+ projectId?: string;
723
+ meetingId: string;
724
+ title: string;
725
+ }): Promise<{
726
+ title: string;
727
+ }>;
688
728
  /** Effective account/project/board identity + capabilities for this token. */
689
729
  getConnectionContext(projectId?: string): Promise<ConnectionContext>;
690
730
  /** Layered verify-by-scope probe (auth → account → project → board →
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { A as ActivePtySession, d as ConveyorConnection, e as ConveyorMcpConfig, P as PtyAttachSnapshot, c as PtyDataChunk } from './connection-DtGKRfga.js';
1
+ export { A as ActivePtySession, d as ConveyorConnection, e as ConveyorMcpConfig, P as PtyAttachSnapshot, c as PtyDataChunk } from './connection-B7CwszOV.js';
2
2
  export { AttachTunnelOptions, ResolvedPtySession, RunTunnelOptions, TunnelConnection, TunnelHandle, TunnelSession, TunnelTty, WaitForPtySessionOptions, attachTunnel, runTunnel, waitForPtySession } from './tunnel.js';
3
3
  import '@project/shared';
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  } from "./chunk-HIVOGGE3.js";
6
6
  import {
7
7
  ConveyorConnection
8
- } from "./chunk-7VH3ULLT.js";
8
+ } from "./chunk-XLDG5QEX.js";
9
9
  export {
10
10
  ConveyorConnection,
11
11
  attachTunnel,
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-HIVOGGE3.js";
5
5
  import {
6
6
  ConveyorConnection
7
- } from "./chunk-7VH3ULLT.js";
7
+ } from "./chunk-XLDG5QEX.js";
8
8
 
9
9
  // src/tunnel-cli.ts
10
10
  var HELP = `conveyor-tunnel \u2014 attach your local terminal to a cloud Claude Code session.
package/dist/tunnel.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { A as ActivePtySession, P as PtyAttachSnapshot, c as PtyDataChunk } from './connection-DtGKRfga.js';
1
+ import { A as ActivePtySession, P as PtyAttachSnapshot, c as PtyDataChunk } from './connection-B7CwszOV.js';
2
2
  import '@project/shared';
3
3
 
4
4
  /**
package/dist/wait-cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ConveyorConnection
4
- } from "./chunk-7VH3ULLT.js";
4
+ } from "./chunk-XLDG5QEX.js";
5
5
  import {
6
6
  runWait
7
7
  } from "./chunk-OPZL4NDT.js";
@@ -1,4 +1,4 @@
1
- import { C as CardCollectionPage, a as CardCollectionDelta } from './connection-DtGKRfga.js';
1
+ import { C as CardCollectionPage, a as CardCollectionDelta } from './connection-B7CwszOV.js';
2
2
  import { WaitFilter, WaitResult } from './wait.js';
3
3
  import '@project/shared';
4
4
 
package/dist/wait.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { b as CardCollectionItem } from './connection-DtGKRfga.js';
1
+ import { b as CardCollectionItem } from './connection-B7CwszOV.js';
2
2
  import '@project/shared';
3
3
 
4
4
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rallycry/conveyor-mcp",
3
- "version": "5.0.1",
3
+ "version": "5.0.2",
4
4
  "description": "Conveyor MCP server for Claude Code PM integration",
5
5
  "keywords": [
6
6
  "claude",