@vailent/pulse-mcp 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/server.js +134 -34
  2. package/package.json +1 -1
package/dist/server.js CHANGED
@@ -39920,6 +39920,7 @@ async function handlePods(params) {
39920
39920
  if (params.name !== void 0) updates.name = params.name.trim();
39921
39921
  if (params.color !== void 0) updates.color = params.color;
39922
39922
  if (params.isActive !== void 0) updates.is_active = params.isActive;
39923
+ if (params.slackChannelId !== void 0) updates.slack_channel_id = params.slackChannelId || null;
39923
39924
  const { data, error: error2 } = await supabase.from("pods").update(updates).eq("id", podId).select().single();
39924
39925
  if (error2) return err(error2.message);
39925
39926
  return ok(data, `Updated pod: ${data?.name}`);
@@ -39992,6 +39993,41 @@ async function handlePodMembers(params) {
39992
39993
  return err(`Unknown action: ${action}`, "INVALID_ACTION");
39993
39994
  }
39994
39995
  }
39996
+ async function handlePodRepos(params) {
39997
+ const supabase = getAdminClient();
39998
+ const action = params.action;
39999
+ const podId = params.podId;
40000
+ if (!podId) return err("podId is required", "MISSING_PARAM");
40001
+ switch (action) {
40002
+ case "list": {
40003
+ const { data, error: error2 } = await supabase.from("github_repos").select("*").eq("pod_id", podId).order("repo_full_name");
40004
+ if (error2) return err(error2.message);
40005
+ return ok(data, `${(data || []).length} repos linked to pod`, (data || []).length);
40006
+ }
40007
+ case "add": {
40008
+ const repoFullName = params.repoFullName;
40009
+ if (!repoFullName?.trim()) return err("repoFullName is required (e.g. owner/repo)", "MISSING_PARAM");
40010
+ const { data, error: error2 } = await supabase.from("github_repos").insert({
40011
+ repo_full_name: repoFullName.trim(),
40012
+ pod_id: podId,
40013
+ project_id: params.projectId || null,
40014
+ default_branch: params.defaultBranch || "main",
40015
+ is_active: true
40016
+ }).select().single();
40017
+ if (error2) return err(error2.message);
40018
+ return ok(data, `Linked ${repoFullName} to pod`);
40019
+ }
40020
+ case "remove": {
40021
+ const repoId = params.repoId;
40022
+ if (!repoId) return err("repoId is required", "MISSING_PARAM");
40023
+ const { error: error2 } = await supabase.from("github_repos").delete().eq("id", repoId).eq("pod_id", podId);
40024
+ if (error2) return err(error2.message);
40025
+ return ok({ deleted: repoId }, "Repo unlinked from pod");
40026
+ }
40027
+ default:
40028
+ return err(`Unknown action: ${action}`, "INVALID_ACTION");
40029
+ }
40030
+ }
39995
40031
 
39996
40032
  // lib/current-user.ts
39997
40033
  import { execSync } from "child_process";
@@ -40067,7 +40103,7 @@ async function handleFeatures(params) {
40067
40103
  const action = params.action;
40068
40104
  switch (action) {
40069
40105
  case "list": {
40070
- let query = supabase.from("features").select("*").order("week_start", { ascending: false });
40106
+ let query = supabase.from("work_items").select("*").order("week_start", { ascending: false });
40071
40107
  if (params.podId) {
40072
40108
  query = query.eq("pod_id", params.podId);
40073
40109
  } else {
@@ -40092,7 +40128,7 @@ async function handleFeatures(params) {
40092
40128
  case "get": {
40093
40129
  const featureId = params.featureId;
40094
40130
  if (!featureId) return err("featureId is required", "MISSING_PARAM");
40095
- const { data, error: error2 } = await supabase.from("features").select("*").eq("id", featureId).single();
40131
+ const { data, error: error2 } = await supabase.from("work_items").select("*").eq("id", featureId).single();
40096
40132
  if (error2 || !data) return err("Feature not found", "NOT_FOUND");
40097
40133
  return ok(data, `Feature: ${data.title}`);
40098
40134
  }
@@ -40103,7 +40139,8 @@ async function handleFeatures(params) {
40103
40139
  if (!podId) return err("podId is required", "MISSING_PARAM");
40104
40140
  const isTask = params.size === "task";
40105
40141
  const id = `f-${Date.now().toString(36)}`;
40106
- const { data, error: error2 } = await supabase.from("features").insert({
40142
+ const currentUser = await getCurrentUser();
40143
+ const { data, error: error2 } = await supabase.from("work_items").insert({
40107
40144
  id,
40108
40145
  title: title.trim(),
40109
40146
  pod_id: podId,
@@ -40116,7 +40153,10 @@ async function handleFeatures(params) {
40116
40153
  week_start: params.weekStart || null,
40117
40154
  status: "in_progress",
40118
40155
  has_blocker: false,
40119
- sort_order: params.sortOrder || 0
40156
+ sort_order: params.sortOrder || 0,
40157
+ created_by: currentUser?.id || null,
40158
+ created_by_name: currentUser?.fullName || null,
40159
+ created_via: "mcp"
40120
40160
  }).select("*").single();
40121
40161
  if (error2) return err(error2.message);
40122
40162
  return ok(data, `Created ${isTask ? "task" : "feature"}: ${title}`);
@@ -40144,15 +40184,15 @@ async function handleFeatures(params) {
40144
40184
  for (const [key, col] of Object.entries(allowedFields)) {
40145
40185
  if (params[key] !== void 0) updates[col] = params[key];
40146
40186
  }
40147
- const { error: error2 } = await supabase.from("features").update(updates).eq("id", featureId);
40187
+ const { error: error2 } = await supabase.from("work_items").update(updates).eq("id", featureId);
40148
40188
  if (error2) return err(error2.message);
40149
40189
  return ok({ id: featureId, ...updates }, `Updated feature ${featureId}`);
40150
40190
  }
40151
40191
  case "delete": {
40152
40192
  const featureId = params.featureId;
40153
40193
  if (!featureId) return err("featureId is required", "MISSING_PARAM");
40154
- await supabase.from("feature_requests").update({ accepted_feature_id: null }).eq("accepted_feature_id", featureId);
40155
- const { error: error2 } = await supabase.from("features").delete().eq("id", featureId);
40194
+ await supabase.from("work_items").update({ accepted_feature_id: null }).eq("accepted_feature_id", featureId);
40195
+ const { error: error2 } = await supabase.from("work_items").delete().eq("id", featureId);
40156
40196
  if (error2) return err(error2.message);
40157
40197
  return ok({ deleted: featureId }, "Feature deleted");
40158
40198
  }
@@ -40160,7 +40200,7 @@ async function handleFeatures(params) {
40160
40200
  const featureId = params.featureId;
40161
40201
  const note = params.note;
40162
40202
  if (!featureId || !note?.trim()) return err("featureId and note are required", "MISSING_PARAM");
40163
- const { data: feature } = await supabase.from("features").select("pod_id, title").eq("id", featureId).single();
40203
+ const { data: feature } = await supabase.from("work_items").select("pod_id, title").eq("id", featureId).single();
40164
40204
  await supabase.from("events").insert({
40165
40205
  source: "manual_ui",
40166
40206
  event_type: "note",
@@ -40168,14 +40208,14 @@ async function handleFeatures(params) {
40168
40208
  ai_extraction: { featureTitle: feature?.title, podId: feature?.pod_id, summary: note.trim() },
40169
40209
  processed_at: (/* @__PURE__ */ new Date()).toISOString()
40170
40210
  });
40171
- await supabase.from("features").update({ updated_at: (/* @__PURE__ */ new Date()).toISOString() }).eq("id", featureId);
40211
+ await supabase.from("work_items").update({ updated_at: (/* @__PURE__ */ new Date()).toISOString() }).eq("id", featureId);
40172
40212
  return ok({ featureId, note: note.trim() }, `Note added to feature`);
40173
40213
  }
40174
40214
  case "reorder": {
40175
40215
  const items = params.items;
40176
40216
  if (!items?.length) return err("items array is required", "MISSING_PARAM");
40177
40217
  for (const item of items) {
40178
- await supabase.from("features").update({ sort_order: item.sortOrder }).eq("id", item.id);
40218
+ await supabase.from("work_items").update({ sort_order: item.sortOrder }).eq("id", item.id);
40179
40219
  }
40180
40220
  return ok({ updated: items.length }, `Reordered ${items.length} features`);
40181
40221
  }
@@ -40259,7 +40299,7 @@ async function handleRequests(params) {
40259
40299
  case "list": {
40260
40300
  const podId = params.podId;
40261
40301
  if (!podId) return err("podId is required", "MISSING_PARAM");
40262
- let query = supabase.from("feature_requests").select("*").eq("pod_id", podId);
40302
+ let query = supabase.from("work_items").select("*").eq("pod_id", podId);
40263
40303
  if (params.type) query = query.eq("type", params.type);
40264
40304
  if (params.status) query = query.eq("status", params.status);
40265
40305
  query = query.order("created_at", { ascending: false }).limit(params.limit || 50);
@@ -40271,7 +40311,7 @@ async function handleRequests(params) {
40271
40311
  const podId = params.podId;
40272
40312
  const title = params.title;
40273
40313
  if (!podId || !title?.trim()) return err("podId and title are required", "MISSING_PARAM");
40274
- const { data, error: error2 } = await supabase.from("feature_requests").insert({
40314
+ const { data, error: error2 } = await supabase.from("work_items").insert({
40275
40315
  title: title.trim(),
40276
40316
  description: params.description || null,
40277
40317
  pod_id: podId,
@@ -40293,9 +40333,9 @@ async function handleRequests(params) {
40293
40333
  if (!requestId || !triageAction) return err("requestId and triageAction are required", "MISSING_PARAM");
40294
40334
  if (triageAction === "accept") {
40295
40335
  const featureId = `f-${Date.now().toString(36)}`;
40296
- const { data: req } = await supabase.from("feature_requests").select("title, pod_id").eq("id", requestId).single();
40336
+ const { data: req } = await supabase.from("work_items").select("title, pod_id").eq("id", requestId).single();
40297
40337
  if (!req) return err("Request not found", "NOT_FOUND");
40298
- await supabase.from("features").insert({
40338
+ await supabase.from("work_items").insert({
40299
40339
  id: featureId,
40300
40340
  title: req.title,
40301
40341
  pod_id: req.pod_id,
@@ -40308,7 +40348,7 @@ async function handleRequests(params) {
40308
40348
  size: "feature",
40309
40349
  week_start: params.weekStart || null
40310
40350
  });
40311
- await supabase.from("feature_requests").update({
40351
+ await supabase.from("work_items").update({
40312
40352
  status: "accepted",
40313
40353
  accepted_feature_id: featureId,
40314
40354
  updated_at: (/* @__PURE__ */ new Date()).toISOString()
@@ -40325,7 +40365,7 @@ async function handleRequests(params) {
40325
40365
  if (!newStatus) return err(`Unknown triage action: ${triageAction}`, "INVALID_ACTION");
40326
40366
  const updates = { status: newStatus, updated_at: (/* @__PURE__ */ new Date()).toISOString() };
40327
40367
  if (triageAction === "convert") updates.type = "feature_request";
40328
- await supabase.from("feature_requests").update(updates).eq("id", requestId);
40368
+ await supabase.from("work_items").update(updates).eq("id", requestId);
40329
40369
  return ok({ requestId, action: triageAction }, `Request ${triageAction}d`);
40330
40370
  }
40331
40371
  default:
@@ -40337,10 +40377,10 @@ async function handleBugs(params) {
40337
40377
  const action = params.action;
40338
40378
  switch (action) {
40339
40379
  case "list": {
40340
- let query = supabase.from("feature_requests").select("*").eq("type", "bug");
40380
+ let query = supabase.from("work_items").select("*").eq("type", "bug");
40341
40381
  if (params.podId) query = query.eq("pod_id", params.podId);
40342
40382
  if (params.status) query = query.eq("status", params.status);
40343
- else query = query.in("status", ["open", "accepted"]);
40383
+ else query = query.in("status", ["open", "in_progress"]);
40344
40384
  query = query.order("created_at", { ascending: false }).limit(params.limit || 50);
40345
40385
  const { data, error: error2 } = await query;
40346
40386
  if (error2) return err(error2.message);
@@ -40350,7 +40390,7 @@ async function handleBugs(params) {
40350
40390
  const podId = params.podId;
40351
40391
  const title = params.title;
40352
40392
  if (!podId || !title?.trim()) return err("podId and title are required", "MISSING_PARAM");
40353
- const { data, error: error2 } = await supabase.from("feature_requests").insert({
40393
+ const { data, error: error2 } = await supabase.from("work_items").insert({
40354
40394
  title: title.trim(),
40355
40395
  description: params.description || null,
40356
40396
  pod_id: podId,
@@ -40373,14 +40413,14 @@ async function handleBugs(params) {
40373
40413
  if (params.status !== void 0) updates.status = params.status;
40374
40414
  if (params.podId !== void 0) updates.pod_id = params.podId;
40375
40415
  if (params.projectName !== void 0) updates.project_name = params.projectName;
40376
- const { error: error2 } = await supabase.from("feature_requests").update(updates).eq("id", bugId);
40416
+ const { error: error2 } = await supabase.from("work_items").update(updates).eq("id", bugId);
40377
40417
  if (error2) return err(error2.message);
40378
40418
  return ok({ id: bugId }, "Bug updated");
40379
40419
  }
40380
40420
  case "delete": {
40381
40421
  const bugId = params.bugId;
40382
40422
  if (!bugId) return err("bugId is required", "MISSING_PARAM");
40383
- const { error: error2 } = await supabase.from("feature_requests").delete().eq("id", bugId);
40423
+ const { error: error2 } = await supabase.from("work_items").delete().eq("id", bugId);
40384
40424
  if (error2) return err(error2.message);
40385
40425
  return ok({ deleted: bugId }, "Bug deleted");
40386
40426
  }
@@ -40390,7 +40430,11 @@ async function handleBugs(params) {
40390
40430
  const updates = { updated_at: (/* @__PURE__ */ new Date()).toISOString() };
40391
40431
  if (params.weekStart !== void 0) updates.week_start = params.weekStart;
40392
40432
  if (params.sortOrder !== void 0) updates.sort_order = params.sortOrder;
40393
- const { error: error2 } = await supabase.from("feature_requests").update(updates).eq("id", bugId);
40433
+ if (params.weekStart) {
40434
+ const { data: bug } = await supabase.from("work_items").select("status").eq("id", bugId).single();
40435
+ if (bug?.status === "open") updates.status = "in_progress";
40436
+ }
40437
+ const { error: error2 } = await supabase.from("work_items").update(updates).eq("id", bugId);
40394
40438
  if (error2) return err(error2.message);
40395
40439
  return ok({ id: bugId, ...updates }, `Bug scheduled${params.weekStart ? ` to week of ${params.weekStart}` : ""}`);
40396
40440
  }
@@ -40472,6 +40516,47 @@ async function handleEvents(params) {
40472
40516
  if (error2) return err(error2.message);
40473
40517
  return ok(data, `${(data || []).length} events for pod ${podId}`, (data || []).length);
40474
40518
  }
40519
+ case "list_prs": {
40520
+ const featureTitle = params.featureTitle;
40521
+ const shortCode = params.shortCode;
40522
+ if (!featureTitle && !shortCode) return err("featureTitle or shortCode is required", "MISSING_PARAM");
40523
+ let query = supabase.from("events").select("event_type, raw_payload, ai_extraction, created_at").eq("source", "github").in("event_type", ["pr_opened", "pr_merged"]);
40524
+ if (shortCode) {
40525
+ query = query.filter("ai_extraction->>linked_short_code", "eq", shortCode);
40526
+ } else {
40527
+ query = query.filter("ai_extraction->>featureTitle", "eq", featureTitle);
40528
+ }
40529
+ query = query.order("created_at", { ascending: false }).limit(50);
40530
+ const { data, error: error2 } = await query;
40531
+ if (error2) return err(error2.message);
40532
+ const opened = /* @__PURE__ */ new Set();
40533
+ const merged = /* @__PURE__ */ new Set();
40534
+ const prs = [];
40535
+ for (const ev of data || []) {
40536
+ const prNum = ev.raw_payload?.pr_number;
40537
+ if (prNum == null) continue;
40538
+ if (ev.event_type === "pr_opened") opened.add(prNum);
40539
+ if (ev.event_type === "pr_merged") merged.add(prNum);
40540
+ }
40541
+ const seen = /* @__PURE__ */ new Set();
40542
+ for (const ev of data || []) {
40543
+ const prNum = ev.raw_payload?.pr_number;
40544
+ if (prNum == null || seen.has(prNum)) continue;
40545
+ seen.add(prNum);
40546
+ prs.push({
40547
+ number: prNum,
40548
+ title: ev.raw_payload?.pr_title || ev.ai_extraction?.whatWasBuilt || "",
40549
+ status: merged.has(prNum) ? "merged" : "open",
40550
+ repo: ev.ai_extraction?.repo || "",
40551
+ date: ev.created_at
40552
+ });
40553
+ }
40554
+ return ok(
40555
+ { prs, totalOpened: opened.size, totalMerged: merged.size, unmerged: opened.size - merged.size },
40556
+ `${prs.length} PR(s): ${merged.size} merged, ${opened.size - merged.size} open`,
40557
+ prs.length
40558
+ );
40559
+ }
40475
40560
  default:
40476
40561
  return err(`Unknown action: ${action}`, "INVALID_ACTION");
40477
40562
  }
@@ -40483,7 +40568,7 @@ async function handleHistory(params) {
40483
40568
  const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1e3).toISOString();
40484
40569
  const items = [];
40485
40570
  if (!params.type || params.type === "feature") {
40486
- let q = supabase.from("features").select("id, title, status, pod_id, project_name, week_start, updated_at").in("status", ["shipped", "missed", "killed"]).gte("updated_at", cutoff).order("updated_at", { ascending: false }).limit(limit);
40571
+ let q = supabase.from("work_items").select("id, title, status, pod_id, project_name, week_start, updated_at").in("status", ["shipped", "missed", "killed"]).gte("updated_at", cutoff).order("updated_at", { ascending: false }).limit(limit);
40487
40572
  if (params.podId) q = q.eq("pod_id", params.podId);
40488
40573
  if (params.projectName) q = q.eq("project_name", params.projectName);
40489
40574
  const { data } = await q;
@@ -40492,7 +40577,7 @@ async function handleHistory(params) {
40492
40577
  }
40493
40578
  }
40494
40579
  if (!params.type || ["bug", "request", "feedback"].includes(params.type)) {
40495
- let q = supabase.from("feature_requests").select("id, title, type, status, pod_id, project_name, source, updated_at, created_at").not("status", "eq", "open").gte("created_at", cutoff).order("created_at", { ascending: false }).limit(limit);
40580
+ let q = supabase.from("work_items").select("id, title, type, status, pod_id, project_name, source, updated_at, created_at").not("status", "eq", "open").gte("created_at", cutoff).order("created_at", { ascending: false }).limit(limit);
40496
40581
  if (params.podId) q = q.eq("pod_id", params.podId);
40497
40582
  const { data } = await q;
40498
40583
  for (const r of data || []) {
@@ -46946,9 +47031,9 @@ async function handleBriefing(params) {
46946
47031
  const nextWeekKey = formatWeekStart(addDays(thisWeekStart, 7));
46947
47032
  const { data: allPods } = await supabase.from("pods").select("id, name, color, ship_streak").eq("is_active", true);
46948
47033
  const relevantPodIds = podIds || (allPods || []).map((p) => p.id);
46949
- const { data: features } = await supabase.from("features").select("id, title, pod_id, project_name, track, phase, implementation_step, week_start, status, has_blocker, blocker_text, size").in("pod_id", relevantPodIds).order("week_start", { ascending: false }).limit(50);
46950
- const { data: requests } = await supabase.from("feature_requests").select("id, title, pod_id, type, priority, source, created_at").in("pod_id", relevantPodIds).eq("status", "open").limit(20);
46951
- const { data: bugs } = await supabase.from("feature_requests").select("id, title, pod_id, project_name, priority, status, created_at").in("pod_id", relevantPodIds).eq("type", "bug").in("status", ["open", "accepted"]).limit(20);
47034
+ const { data: features } = await supabase.from("work_items").select("id, title, pod_id, project_name, track, phase, implementation_step, week_start, status, has_blocker, blocker_text, size").in("pod_id", relevantPodIds).order("week_start", { ascending: false }).limit(50);
47035
+ const { data: requests } = await supabase.from("work_items").select("id, title, pod_id, type, priority, source, created_at").in("pod_id", relevantPodIds).eq("status", "open").limit(20);
47036
+ const { data: bugs } = await supabase.from("work_items").select("id, title, pod_id, project_name, priority, status, created_at").in("pod_id", relevantPodIds).eq("type", "bug").in("status", ["open", "accepted"]).limit(20);
46952
47037
  const podName = (id) => (allPods || []).find((p) => p.id === id)?.name ?? id;
46953
47038
  const featuresContext = (features || []).map((f) => `- "${f.title}" pod=${podName(f.pod_id)} size=${f.size} phase=${f.phase}${f.implementation_step ? ` step=${f.implementation_step}` : ""} status=${f.status}${f.has_blocker ? " BLOCKED" : ""} week=${f.week_start}`).join("\n");
46954
47039
  const bugsContext = (bugs || []).map((b) => `- "${b.title}" pod=${podName(b.pod_id)} priority=${b.priority || "medium"}`).join("\n");
@@ -47123,13 +47208,14 @@ var server = new McpServer({
47123
47208
  });
47124
47209
  server.tool(
47125
47210
  "pulse_pods",
47126
- "Manage pods (squads). Actions: list (all active pods with members), get (single pod by ID), create (new pod), update (name/color/active).",
47211
+ "Manage pods (squads). Actions: list (all active pods with members), get (single pod by ID), create (new pod), update (name/color/active/slackChannelId).",
47127
47212
  {
47128
47213
  action: external_exports.enum(["list", "get", "create", "update"]),
47129
47214
  podId: external_exports.string().optional().describe("Pod ID (for get/update)"),
47130
47215
  name: external_exports.string().optional().describe("Pod name (for create/update)"),
47131
47216
  color: external_exports.string().optional().describe("Hex color"),
47132
- isActive: external_exports.boolean().optional().describe("Active status")
47217
+ isActive: external_exports.boolean().optional().describe("Active status"),
47218
+ slackChannelId: external_exports.string().optional().nullable().describe("Slack channel ID to link (for update). Null to unlink.")
47133
47219
  },
47134
47220
  async (params) => handlePods(params)
47135
47221
  );
@@ -47147,6 +47233,19 @@ server.tool(
47147
47233
  },
47148
47234
  async (params) => handlePodMembers(params)
47149
47235
  );
47236
+ server.tool(
47237
+ "pulse_pod_repos",
47238
+ "Manage GitHub repos linked to pods. Actions: list, add, remove.",
47239
+ {
47240
+ action: external_exports.enum(["list", "add", "remove"]),
47241
+ podId: external_exports.string().describe("Pod ID"),
47242
+ repoId: external_exports.string().optional().describe("Repo ID (for remove)"),
47243
+ repoFullName: external_exports.string().optional().describe("Full repo name e.g. owner/repo (for add)"),
47244
+ projectId: external_exports.string().optional().describe("Project/workstream ID to link (for add)"),
47245
+ defaultBranch: external_exports.string().optional().describe("Default branch (defaults to main)")
47246
+ },
47247
+ async (params) => handlePodRepos(params)
47248
+ );
47150
47249
  server.tool(
47151
47250
  "pulse_features",
47152
47251
  "Manage features and tasks. Actions: list (filter by pod/workstream/week/status/size), get, create (feature or task via size param), update (phase/step/status/blocker/week/prdText/prdFileUrl), delete, add_note, reorder.",
@@ -47217,7 +47316,7 @@ server.tool(
47217
47316
  );
47218
47317
  server.tool(
47219
47318
  "pulse_bugs",
47220
- "Track bugs. Actions: list (open bugs by pod), create, update (status/priority/podId/projectName), delete, schedule (set week_start for backlog management).",
47319
+ "Track bugs. Actions: list (open/in_progress bugs by pod), create, update (status/priority/podId/projectName), delete, schedule (set week_start \u2014 auto-promotes open\u2192in_progress).",
47221
47320
  {
47222
47321
  action: external_exports.enum(["list", "create", "update", "delete", "schedule"]),
47223
47322
  bugId: external_exports.string().optional().describe("Bug ID"),
@@ -47225,7 +47324,7 @@ server.tool(
47225
47324
  title: external_exports.string().optional().describe("Bug title"),
47226
47325
  description: external_exports.string().optional().describe("Description"),
47227
47326
  priority: external_exports.string().optional().describe("Priority: critical, high, medium, low"),
47228
- status: external_exports.string().optional().describe("Status: open, accepted, declined, deferred"),
47327
+ status: external_exports.string().optional().describe("Status: open, in_progress, shipped, killed"),
47229
47328
  projectName: external_exports.string().optional().describe("Workstream name"),
47230
47329
  source: external_exports.string().optional().describe("Source"),
47231
47330
  weekStart: external_exports.string().optional().nullable().describe("Week to schedule (null to unschedule)"),
@@ -47247,10 +47346,11 @@ server.tool(
47247
47346
  );
47248
47347
  server.tool(
47249
47348
  "pulse_events",
47250
- "View activity events. Actions: list (recent), list_by_feature, list_by_pod.",
47349
+ "View activity events. Actions: list (recent), list_by_feature, list_by_pod, list_prs (PRs for a feature with merge status).",
47251
47350
  {
47252
- action: external_exports.enum(["list", "list_by_feature", "list_by_pod"]),
47253
- featureTitle: external_exports.string().optional().describe("Feature title (for list_by_feature)"),
47351
+ action: external_exports.enum(["list", "list_by_feature", "list_by_pod", "list_prs"]),
47352
+ featureTitle: external_exports.string().optional().describe("Feature title (for list_by_feature, list_prs)"),
47353
+ shortCode: external_exports.string().optional().describe("Short code e.g. PULSE-142 (for list_prs)"),
47254
47354
  podId: external_exports.string().optional().describe("Pod ID (for list_by_pod)"),
47255
47355
  limit: external_exports.number().optional().describe("Max results")
47256
47356
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vailent/pulse-mcp",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Pulse MCP server — manage pods, features, workstreams, bugs, and more from Claude Code",
5
5
  "type": "module",
6
6
  "bin": {