@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.
- package/dist/server.js +134 -34
- 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("
|
|
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("
|
|
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
|
|
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("
|
|
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("
|
|
40155
|
-
const { error: error2 } = await supabase.from("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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", "
|
|
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("
|
|
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("
|
|
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("
|
|
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
|
-
|
|
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("
|
|
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("
|
|
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("
|
|
46950
|
-
const { data: requests } = await supabase.from("
|
|
46951
|
-
const { data: bugs } = await supabase.from("
|
|
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
|
|
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,
|
|
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
|
},
|