@sideboard-ai/core 0.1.287 → 0.1.288
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/{abletime-I4RODUKT.js → abletime-4WJUVE64.js} +4 -4
- package/dist/{abletime-4CH2IOX5.js → abletime-VFKYNSJT.js} +4 -4
- package/dist/{abletime-oauth-7OZZ3ABX.js → abletime-oauth-FW24YHYX.js} +3 -3
- package/dist/{abletime-oauth-C2HN2Q6F.js → abletime-oauth-ICMB2XV2.js} +3 -3
- package/dist/{abletime-rest-E4LBRFLM.js → abletime-rest-HFMRTUDT.js} +3 -3
- package/dist/{abletime-rest-WFI2HWBU.js → abletime-rest-OGWC7BC6.js} +3 -3
- package/dist/agents/cursor-runner.js +3 -3
- package/dist/{agents-D3PU4UCP.js → agents-GZLTMGSH.js} +19 -17
- package/dist/{agents-KU4QPB3Y.js → agents-UQMHFZSM.js} +17 -15
- package/dist/{app-settings-EQQZQNYD.js → app-settings-EHMXHNG5.js} +1 -1
- package/dist/{app-settings-NI4X5HW3.js → app-settings-MR2U6AXN.js} +1 -1
- package/dist/{chunk-UFJLNCOF.js → chunk-2N77CLRQ.js} +8 -298
- package/dist/{chunk-YNTXWFXT.js → chunk-36J3IZBS.js} +12 -12
- package/dist/{chunk-IJMUYHPT.js → chunk-3E4NOIXN.js} +3 -3
- package/dist/{chunk-5MGLNVNK.js → chunk-3W5SL5EW.js} +1 -1
- package/dist/{chunk-QPBR5SAL.js → chunk-442O6OXM.js} +25 -127
- package/dist/chunk-4BXRRHDC.js +139 -0
- package/dist/{chunk-RFPMTOV2.js → chunk-4NM72HJZ.js} +5 -5
- package/dist/{chunk-Z3EE3PUZ.js → chunk-6NVQNTJO.js} +10 -300
- package/dist/{chunk-VOIWX5HA.js → chunk-7UUILVMV.js} +1 -1
- package/dist/chunk-AF2DMY3K.js +295 -0
- package/dist/{chunk-5QOLFOAX.js → chunk-AFLNFGGB.js} +1 -1
- package/dist/{chunk-5T4YWFLD.js → chunk-AHH5USEA.js} +2 -2
- package/dist/{chunk-6CVVNAIU.js → chunk-B3BPLPKQ.js} +2 -2
- package/dist/{chunk-ZGAMETNF.js → chunk-DBOFDEQ7.js} +3 -3
- package/dist/{chunk-VQEARG5H.js → chunk-GU6DT6NO.js} +5 -5
- package/dist/{chunk-K5XSTHHP.js → chunk-HNB2HTCV.js} +1 -1
- package/dist/{chunk-KLAQ4G34.js → chunk-IA4MPG7F.js} +3 -3
- package/dist/{chunk-S2OOM7AU.js → chunk-K6IOJI3L.js} +1 -1
- package/dist/{chunk-U6QDXT4K.js → chunk-MIVX7QKI.js} +1 -1
- package/dist/{chunk-WRIMAEF2.js → chunk-MVZO7QZ2.js} +12 -12
- package/dist/{chunk-LS4FFCPL.js → chunk-MYJYINTS.js} +3 -3
- package/dist/{chunk-DEJALWKM.js → chunk-NFPWLDCH.js} +5 -5
- package/dist/chunk-NXXQFLNQ.js +300 -0
- package/dist/chunk-OH4EN323.js +89 -0
- package/dist/chunk-W2KZTDET.js +302 -0
- package/dist/{chunk-L65YT2SC.js → chunk-WQSIUZEB.js} +6 -6
- package/dist/{chunk-LKVP7JCB.js → chunk-WW5XGEMY.js} +33 -313
- package/dist/{chunk-TMM4FEZ5.js → chunk-Y67TBJD5.js} +3 -3
- package/dist/{chunk-XSDCLM3F.js → chunk-YSLCWCMJ.js} +1 -1
- package/dist/{conductor-FOKYVMUE.js → conductor-MCU63Z5U.js} +5 -5
- package/dist/{conductor-KDUL6AMD.js → conductor-ZLYZVIAV.js} +6 -6
- package/dist/{coordinator-prompt-GU5PGLG6.js → coordinator-prompt-KHCXXDRO.js} +3 -3
- package/dist/{coordinator-prompt-YARYX53V.js → coordinator-prompt-UV6THLMD.js} +3 -3
- package/dist/{global-workspace-C5HMC66E.js → global-workspace-AXTSYVAE.js} +3 -3
- package/dist/{global-workspace-SMCPOWE5.js → global-workspace-GDHZSFP6.js} +3 -3
- package/dist/index.cjs +469 -274
- package/dist/index.d.cts +24 -8
- package/dist/index.d.ts +24 -8
- package/dist/index.js +369 -256
- package/dist/mcp/run-stdio.cjs +602 -225
- package/dist/mcp/run-stdio.js +333 -187
- package/dist/optional-cli-6SW4OOX3.js +23 -0
- package/dist/optional-cli-FRUZSZ3U.js +98 -0
- package/dist/{orchestrator-NWKE56BW.js → orchestrator-5ZBHR6BJ.js} +9 -7
- package/dist/{orchestrator-2UAVOXTN.js → orchestrator-SDH6W6ZL.js} +12 -10
- package/dist/{workspaces-DQMDCRB2.js → workspaces-L2UR4KC2.js} +3 -3
- package/dist/{workspaces-KHQ5ETSQ.js → workspaces-Q2R2XGO3.js} +3 -3
- package/dist/{worktree-NKLNVNXX.js → worktree-2GOK4VYT.js} +2 -2
- package/dist/{worktree-YTZC3UQN.js → worktree-YEUTJ7MZ.js} +2 -2
- package/package.json +1 -1
package/dist/mcp/run-stdio.js
CHANGED
|
@@ -1,26 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
commentAbleTimeTask,
|
|
5
|
-
createAbleTimeTask,
|
|
6
|
-
downloadAbleTimeAttachment,
|
|
7
|
-
downloadAuthenticatedFile,
|
|
8
|
-
ensureAbleTimeTask,
|
|
9
|
-
extractHttpUrls,
|
|
10
|
-
getAbleTimeOrientation,
|
|
11
|
-
getAbleTimeTask,
|
|
12
|
-
hostMatches,
|
|
13
|
-
issueAttachmentWorktreePath,
|
|
14
|
-
listAbleTimeProjects,
|
|
15
|
-
listAbleTimeTasks,
|
|
16
|
-
looksLikeHttpUrl,
|
|
17
|
-
mergeIssueAttachments,
|
|
18
|
-
searchAbleTimeTasks,
|
|
19
|
-
toAbleTimeIssueInfo,
|
|
20
|
-
updateAbleTimeTask
|
|
21
|
-
} from "../chunk-TMM4FEZ5.js";
|
|
22
|
-
import "../chunk-5T4YWFLD.js";
|
|
23
|
-
import "../chunk-VQEARG5H.js";
|
|
24
3
|
import {
|
|
25
4
|
AGENT_GIT_ACTIONS,
|
|
26
5
|
BOARD_COLUMN_DEFS,
|
|
@@ -71,8 +50,32 @@ import {
|
|
|
71
50
|
syncBoardPins,
|
|
72
51
|
updateSchedule,
|
|
73
52
|
workspaceTagTargetRef
|
|
74
|
-
} from "../chunk-
|
|
53
|
+
} from "../chunk-442O6OXM.js";
|
|
75
54
|
import "../chunk-LX5R5JOR.js";
|
|
55
|
+
import {
|
|
56
|
+
commentAbleTimeTask,
|
|
57
|
+
createAbleTimeTask,
|
|
58
|
+
downloadAbleTimeAttachment,
|
|
59
|
+
downloadAuthenticatedFile,
|
|
60
|
+
ensureAbleTimeTask,
|
|
61
|
+
extractHttpUrls,
|
|
62
|
+
getAbleTimeOrientation,
|
|
63
|
+
getAbleTimeTask,
|
|
64
|
+
hostMatches,
|
|
65
|
+
issueAttachmentWorktreePath,
|
|
66
|
+
listAbleTimeProjects,
|
|
67
|
+
listAbleTimeTasks,
|
|
68
|
+
looksLikeHttpUrl,
|
|
69
|
+
mergeIssueAttachments,
|
|
70
|
+
searchAbleTimeTasks,
|
|
71
|
+
toAbleTimeIssueInfo,
|
|
72
|
+
updateAbleTimeTask
|
|
73
|
+
} from "../chunk-Y67TBJD5.js";
|
|
74
|
+
import "../chunk-AHH5USEA.js";
|
|
75
|
+
import "../chunk-GU6DT6NO.js";
|
|
76
|
+
import {
|
|
77
|
+
normalizeServiceOrigin
|
|
78
|
+
} from "../chunk-4BXRRHDC.js";
|
|
76
79
|
import {
|
|
77
80
|
PRESENT_PLAN_REQUIRES_PLAN_MODE,
|
|
78
81
|
PRESENT_PLAN_TOOL_DESCRIPTION,
|
|
@@ -90,7 +93,8 @@ import {
|
|
|
90
93
|
sideboardMcpProfile,
|
|
91
94
|
trustSystemCertificates,
|
|
92
95
|
worktreeMcpToolNames
|
|
93
|
-
} from "../chunk-
|
|
96
|
+
} from "../chunk-2N77CLRQ.js";
|
|
97
|
+
import "../chunk-W2KZTDET.js";
|
|
94
98
|
import "../chunk-7IAMHN2N.js";
|
|
95
99
|
import "../chunk-PXMLMBMI.js";
|
|
96
100
|
import {
|
|
@@ -106,16 +110,16 @@ import {
|
|
|
106
110
|
waitForDetachedJob,
|
|
107
111
|
waitForTurnToolResult,
|
|
108
112
|
workspaceAgentChatSummaries
|
|
109
|
-
} from "../chunk-
|
|
113
|
+
} from "../chunk-4NM72HJZ.js";
|
|
110
114
|
import {
|
|
111
115
|
clipToolResultForStore,
|
|
112
116
|
isInternalAgentStatusText,
|
|
113
117
|
looksLikeHugeToolResultDump
|
|
114
|
-
} from "../chunk-
|
|
118
|
+
} from "../chunk-AFLNFGGB.js";
|
|
115
119
|
import {
|
|
116
120
|
GLOBAL_WORKSPACE_ID,
|
|
117
121
|
isCloudCoordinatorThread
|
|
118
|
-
} from "../chunk-
|
|
122
|
+
} from "../chunk-IA4MPG7F.js";
|
|
119
123
|
import {
|
|
120
124
|
canonicalizeRepoPath,
|
|
121
125
|
formatGhLandError,
|
|
@@ -126,7 +130,7 @@ import {
|
|
|
126
130
|
resolveListPrsOptions,
|
|
127
131
|
resolveRepoRoot,
|
|
128
132
|
warmGithubAgentAuth
|
|
129
|
-
} from "../chunk-
|
|
133
|
+
} from "../chunk-3W5SL5EW.js";
|
|
130
134
|
import {
|
|
131
135
|
CLI_DIR
|
|
132
136
|
} from "../chunk-N2WW62LF.js";
|
|
@@ -147,7 +151,7 @@ import {
|
|
|
147
151
|
resolveViewerProfile,
|
|
148
152
|
resolveViewerProfileForRepo,
|
|
149
153
|
saveLinearOAuth
|
|
150
|
-
} from "../chunk-
|
|
154
|
+
} from "../chunk-MVZO7QZ2.js";
|
|
151
155
|
import "../chunk-NSTQ6QKD.js";
|
|
152
156
|
import {
|
|
153
157
|
dropNestedElectronEnvFromProcess
|
|
@@ -251,7 +255,7 @@ function createClippedMcpServer() {
|
|
|
251
255
|
}
|
|
252
256
|
|
|
253
257
|
// src/mcp/server.ts
|
|
254
|
-
import { z as
|
|
258
|
+
import { z as z7 } from "zod";
|
|
255
259
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
256
260
|
import { basename } from "path";
|
|
257
261
|
|
|
@@ -3188,6 +3192,147 @@ function registerConnectedIssueVendorTools(server, settings = loadAppSettings())
|
|
|
3188
3192
|
if (isAbleTimeConnected(settings)) registerAbleTimeTools(server);
|
|
3189
3193
|
}
|
|
3190
3194
|
|
|
3195
|
+
// src/mcp/posthog-tools.ts
|
|
3196
|
+
import { z as z5 } from "zod";
|
|
3197
|
+
var POSTHOG_METHODS = ["GET", "POST", "PATCH"];
|
|
3198
|
+
var POSTHOG_RESPONSE_MAX_CHARS = 256e3;
|
|
3199
|
+
var POSTHOG_TIMEOUT_MS = 2e4;
|
|
3200
|
+
var POSTHOG_READ_QUERY = /^\/api\/(?:projects|environments)\/[^/]+\/query$/;
|
|
3201
|
+
function isPosthogReadQuery(method, path) {
|
|
3202
|
+
if (method !== "POST") return false;
|
|
3203
|
+
return POSTHOG_READ_QUERY.test(path.trim().replace(/\/+$/, ""));
|
|
3204
|
+
}
|
|
3205
|
+
function withPosthogSlash(method, path) {
|
|
3206
|
+
const raw = path.trim();
|
|
3207
|
+
if ((method === "POST" || method === "PATCH") && raw.startsWith("/api/") && !raw.endsWith("/")) {
|
|
3208
|
+
return `${raw}/`;
|
|
3209
|
+
}
|
|
3210
|
+
return raw;
|
|
3211
|
+
}
|
|
3212
|
+
function posthogApiUrl(host, path, query) {
|
|
3213
|
+
const raw = path.trim();
|
|
3214
|
+
if (!raw.startsWith("/api/")) {
|
|
3215
|
+
throw new Error("path must start with /api/");
|
|
3216
|
+
}
|
|
3217
|
+
if (raw.includes("://") || raw.startsWith("//") || /[?#\s\\]/.test(raw) || raw.includes("..")) {
|
|
3218
|
+
throw new Error("path must be a PostHog API path, not a URL");
|
|
3219
|
+
}
|
|
3220
|
+
const origin = normalizeServiceOrigin(host, "https://us.posthog.com");
|
|
3221
|
+
const url = new URL(raw, origin);
|
|
3222
|
+
if (url.origin !== new URL(origin).origin || !url.pathname.startsWith("/api/")) {
|
|
3223
|
+
throw new Error("path must stay on the connected PostHog host");
|
|
3224
|
+
}
|
|
3225
|
+
if (query) {
|
|
3226
|
+
for (const [key, value] of Object.entries(query)) {
|
|
3227
|
+
if (!key.trim()) throw new Error("query keys must be non-empty");
|
|
3228
|
+
url.searchParams.set(key, value);
|
|
3229
|
+
}
|
|
3230
|
+
}
|
|
3231
|
+
return url.toString();
|
|
3232
|
+
}
|
|
3233
|
+
async function runPosthogApi(input) {
|
|
3234
|
+
const method = input.method;
|
|
3235
|
+
if (!POSTHOG_METHODS.includes(method)) {
|
|
3236
|
+
return mcpJson({ ok: false, error: "method must be GET, POST, or PATCH" }, true);
|
|
3237
|
+
}
|
|
3238
|
+
if (method !== "GET" && input.write !== true && !isPosthogReadQuery(method, input.path)) {
|
|
3239
|
+
return mcpJson(
|
|
3240
|
+
{
|
|
3241
|
+
ok: false,
|
|
3242
|
+
error: "POST and PATCH require write=true, and only when the user asked to change PostHog data. POST /api/projects/:id/query/ and POST /api/environments/:id/query/ are reads and do not need write=true."
|
|
3243
|
+
},
|
|
3244
|
+
true
|
|
3245
|
+
);
|
|
3246
|
+
}
|
|
3247
|
+
if (method === "GET" && input.body !== void 0) {
|
|
3248
|
+
return mcpJson({ ok: false, error: "GET does not take a body" }, true);
|
|
3249
|
+
}
|
|
3250
|
+
const integrations = loadAppSettings().integrations;
|
|
3251
|
+
const token = integrations.posthogPersonalApiKey?.trim();
|
|
3252
|
+
if (!token) {
|
|
3253
|
+
return mcpJson(
|
|
3254
|
+
{ ok: false, error: "PostHog is not connected (Settings \u2192 Connectors)." },
|
|
3255
|
+
true
|
|
3256
|
+
);
|
|
3257
|
+
}
|
|
3258
|
+
let url;
|
|
3259
|
+
try {
|
|
3260
|
+
url = posthogApiUrl(
|
|
3261
|
+
integrations.posthogHost || "https://us.posthog.com",
|
|
3262
|
+
withPosthogSlash(method, input.path),
|
|
3263
|
+
input.query
|
|
3264
|
+
);
|
|
3265
|
+
} catch (err) {
|
|
3266
|
+
return mcpJson(
|
|
3267
|
+
{ ok: false, error: err instanceof Error ? err.message : String(err) },
|
|
3268
|
+
true
|
|
3269
|
+
);
|
|
3270
|
+
}
|
|
3271
|
+
const headers = {
|
|
3272
|
+
Authorization: `Bearer ${token}`,
|
|
3273
|
+
Accept: "application/json"
|
|
3274
|
+
};
|
|
3275
|
+
let body;
|
|
3276
|
+
if (input.body !== void 0) {
|
|
3277
|
+
headers["Content-Type"] = "application/json";
|
|
3278
|
+
body = typeof input.body === "string" ? input.body : JSON.stringify(input.body);
|
|
3279
|
+
}
|
|
3280
|
+
try {
|
|
3281
|
+
const res = await httpFetch(url, {
|
|
3282
|
+
method,
|
|
3283
|
+
headers,
|
|
3284
|
+
body,
|
|
3285
|
+
signal: AbortSignal.timeout(POSTHOG_TIMEOUT_MS)
|
|
3286
|
+
});
|
|
3287
|
+
const text5 = await res.text();
|
|
3288
|
+
const truncated = text5.length > POSTHOG_RESPONSE_MAX_CHARS;
|
|
3289
|
+
const slice = truncated ? text5.slice(0, POSTHOG_RESPONSE_MAX_CHARS) : text5;
|
|
3290
|
+
let parsed = slice;
|
|
3291
|
+
if (slice.trim()) {
|
|
3292
|
+
try {
|
|
3293
|
+
parsed = JSON.parse(slice);
|
|
3294
|
+
} catch {
|
|
3295
|
+
parsed = slice;
|
|
3296
|
+
}
|
|
3297
|
+
} else {
|
|
3298
|
+
parsed = null;
|
|
3299
|
+
}
|
|
3300
|
+
return mcpJson(
|
|
3301
|
+
{
|
|
3302
|
+
ok: res.ok,
|
|
3303
|
+
status: res.status,
|
|
3304
|
+
...truncated ? { truncated: true } : {},
|
|
3305
|
+
body: parsed
|
|
3306
|
+
},
|
|
3307
|
+
!res.ok
|
|
3308
|
+
);
|
|
3309
|
+
} catch (err) {
|
|
3310
|
+
return mcpJson(
|
|
3311
|
+
{ ok: false, error: err instanceof Error ? err.message : String(err) },
|
|
3312
|
+
true
|
|
3313
|
+
);
|
|
3314
|
+
}
|
|
3315
|
+
}
|
|
3316
|
+
var POSTHOG_API_DESCRIPTION = "Call the connected PostHog project (Settings \u2192 Connectors). path must start with /api/ and is joined to the stored host. GET is the default. POST /api/projects/:id/query/ and POST /api/environments/:id/query/ are reads (HogQL and insights) and do not need write=true. Other POST and PATCH require write=true, and only when the user asked to change PostHog data. The API key is not in the environment. Do not sign in to a PostHog MCP.";
|
|
3317
|
+
function registerPosthogTools(server) {
|
|
3318
|
+
server.tool(
|
|
3319
|
+
"posthog_api",
|
|
3320
|
+
POSTHOG_API_DESCRIPTION,
|
|
3321
|
+
{
|
|
3322
|
+
method: z5.enum(POSTHOG_METHODS).describe(
|
|
3323
|
+
"GET, POST /api/projects|environments/:id/query/ for a read, or POST/PATCH when the user asked for a change"
|
|
3324
|
+
),
|
|
3325
|
+
path: z5.string().describe("PostHog path starting with /api/, not a full URL"),
|
|
3326
|
+
query: z5.record(z5.string(), z5.string()).optional().describe("Query string parameters"),
|
|
3327
|
+
body: z5.unknown().optional().describe("JSON body for POST or PATCH"),
|
|
3328
|
+
write: z5.boolean().optional().describe(
|
|
3329
|
+
"Required true for POST and PATCH that change data. Omit for GET and for POST .../query/."
|
|
3330
|
+
)
|
|
3331
|
+
},
|
|
3332
|
+
async (input) => runPosthogApi(input)
|
|
3333
|
+
);
|
|
3334
|
+
}
|
|
3335
|
+
|
|
3191
3336
|
// src/mcp/pr-list.ts
|
|
3192
3337
|
function compactPrRow(pr) {
|
|
3193
3338
|
return {
|
|
@@ -3223,7 +3368,7 @@ function formatMcpPrList(input) {
|
|
|
3223
3368
|
}
|
|
3224
3369
|
|
|
3225
3370
|
// src/mcp/schedule-tools.ts
|
|
3226
|
-
import { z as
|
|
3371
|
+
import { z as z6 } from "zod";
|
|
3227
3372
|
function text4(payload, isError = false) {
|
|
3228
3373
|
return mcpJson(payload, isError);
|
|
3229
3374
|
}
|
|
@@ -3263,18 +3408,18 @@ function registerScheduleTools(server) {
|
|
|
3263
3408
|
"create_schedule",
|
|
3264
3409
|
"Create a local schedule that, when due, sends a prompt to an existing chat (chatId) or starts a new Global orchestration chat (omit chatId). Pass chatId=self to continue this chat. If that chat is missing or archived when the job fires, Sideboard starts a new Global chat (recurring jobs then continue that chat). Exactly one of at (ISO datetime), every (15m/1h/6h/1d), or cron (5-field). Recurring jobs without chatId open a new Global chat each run. Creating or enabling a future job turns on Settings \u2192 Advanced \u2192 Caffeinate while schedules are enabled so the Mac stays awake until due. Sideboard.app must be running for the job to fire.",
|
|
3265
3410
|
{
|
|
3266
|
-
prompt:
|
|
3267
|
-
name:
|
|
3268
|
-
at:
|
|
3269
|
-
every:
|
|
3270
|
-
cron:
|
|
3271
|
-
tz:
|
|
3272
|
-
chatId:
|
|
3411
|
+
prompt: z6.string().describe("User message / goal queued when the schedule fires"),
|
|
3412
|
+
name: z6.string().optional(),
|
|
3413
|
+
at: z6.string().optional().describe("ISO datetime for a one-shot"),
|
|
3414
|
+
every: z6.string().optional().describe("Interval such as 15m, 1h, 6h, 1d"),
|
|
3415
|
+
cron: z6.string().optional().describe("5-field cron expression"),
|
|
3416
|
+
tz: z6.string().optional().describe("IANA timezone for cron (default: system)"),
|
|
3417
|
+
chatId: z6.string().optional().describe(
|
|
3273
3418
|
'Existing chat id (orchestration or workspace), or "self" for this chat. Omit to create a new Global chat on fire.'
|
|
3274
3419
|
),
|
|
3275
|
-
threadId:
|
|
3276
|
-
agent:
|
|
3277
|
-
model:
|
|
3420
|
+
threadId: z6.string().optional().describe("Legacy alias for chatId."),
|
|
3421
|
+
agent: z6.enum(["claude", "cursor", "codex", "opencode"]).optional().describe("Agent for a new Global chat (omit for Account default)"),
|
|
3422
|
+
model: z6.string().optional()
|
|
3278
3423
|
},
|
|
3279
3424
|
async (args) => {
|
|
3280
3425
|
try {
|
|
@@ -3310,20 +3455,20 @@ function registerScheduleTools(server) {
|
|
|
3310
3455
|
"update_schedule",
|
|
3311
3456
|
"Update a local schedule (prompt, cadence, target chat, enabled). Pass id from list_schedules.",
|
|
3312
3457
|
{
|
|
3313
|
-
id:
|
|
3314
|
-
prompt:
|
|
3315
|
-
name:
|
|
3316
|
-
at:
|
|
3317
|
-
every:
|
|
3318
|
-
cron:
|
|
3319
|
-
tz:
|
|
3320
|
-
chatId:
|
|
3458
|
+
id: z6.string(),
|
|
3459
|
+
prompt: z6.string().optional(),
|
|
3460
|
+
name: z6.string().optional(),
|
|
3461
|
+
at: z6.string().optional(),
|
|
3462
|
+
every: z6.string().optional(),
|
|
3463
|
+
cron: z6.string().optional(),
|
|
3464
|
+
tz: z6.string().optional(),
|
|
3465
|
+
chatId: z6.string().optional().describe(
|
|
3321
3466
|
'Existing chat (orchestration or workspace), "self", or empty string to create a new Global chat each run'
|
|
3322
3467
|
),
|
|
3323
|
-
threadId:
|
|
3324
|
-
agent:
|
|
3325
|
-
model:
|
|
3326
|
-
enabled:
|
|
3468
|
+
threadId: z6.string().optional().describe("Legacy alias for chatId."),
|
|
3469
|
+
agent: z6.enum(["claude", "cursor", "codex", "opencode"]).optional(),
|
|
3470
|
+
model: z6.string().optional(),
|
|
3471
|
+
enabled: z6.boolean().optional()
|
|
3327
3472
|
},
|
|
3328
3473
|
async (args) => {
|
|
3329
3474
|
try {
|
|
@@ -3364,7 +3509,7 @@ function registerScheduleTools(server) {
|
|
|
3364
3509
|
server.tool(
|
|
3365
3510
|
"delete_schedule",
|
|
3366
3511
|
"Delete a local schedule. Pass id from list_schedules.",
|
|
3367
|
-
{ id:
|
|
3512
|
+
{ id: z6.string() },
|
|
3368
3513
|
async ({ id }) => {
|
|
3369
3514
|
try {
|
|
3370
3515
|
deleteSchedule(id);
|
|
@@ -3377,7 +3522,7 @@ function registerScheduleTools(server) {
|
|
|
3377
3522
|
server.tool(
|
|
3378
3523
|
"run_schedule",
|
|
3379
3524
|
"Fire a schedule now (does not wait for nextRunAt). Queues the prompt on the target chat or starts a new Global chat. If Sideboard.app is running, the desktop drains the turn.",
|
|
3380
|
-
{ id:
|
|
3525
|
+
{ id: z6.string() },
|
|
3381
3526
|
async ({ id }) => {
|
|
3382
3527
|
try {
|
|
3383
3528
|
if (!getSchedule(id)) {
|
|
@@ -3683,7 +3828,7 @@ async function startMcpServer() {
|
|
|
3683
3828
|
);
|
|
3684
3829
|
}
|
|
3685
3830
|
try {
|
|
3686
|
-
const { maxConcurrentAgents } = await import("../app-settings-
|
|
3831
|
+
const { maxConcurrentAgents } = await import("../app-settings-EHMXHNG5.js");
|
|
3687
3832
|
orch.setMaxConcurrent(maxConcurrentAgents());
|
|
3688
3833
|
} catch {
|
|
3689
3834
|
}
|
|
@@ -3711,6 +3856,7 @@ async function startMcpServer() {
|
|
|
3711
3856
|
}
|
|
3712
3857
|
};
|
|
3713
3858
|
registerViewerContextTools(server);
|
|
3859
|
+
registerPosthogTools(server);
|
|
3714
3860
|
if (worktreeProfile) {
|
|
3715
3861
|
registerConnectedIssueVendorTools(server);
|
|
3716
3862
|
}
|
|
@@ -3766,16 +3912,16 @@ async function startMcpServer() {
|
|
|
3766
3912
|
"list_board",
|
|
3767
3913
|
"Home Kanban of workspaces (New, Draft, Review, Merged) \u2014 one card per checkout; sibling chats on that card are separate agents. Same cards as desktop Home. Path to merge: no PR \u2192 draft PR \u2192 open PR \u2192 merged. Archive removes the card to Settings \u2192 History. Queued/running are activity on the card, not columns. Orchestration chats are not on the board. Filters: query, repoPath, kind (ticket/PR/branch source), ownership (mine = your PRs / WIP; reviewing = someone else's PR), column, limit (default 40). create_workspace adds a workspace (and a Home card), or returns the live checkout if that ticket/PR/named branch is already checked out. That reuse is one checkout, not one agent \u2014 fork_chat to add another.",
|
|
3768
3914
|
{
|
|
3769
|
-
query:
|
|
3770
|
-
repoPath:
|
|
3771
|
-
kind:
|
|
3772
|
-
ownership:
|
|
3915
|
+
query: z7.string().optional().describe("Case-insensitive token search across title, id, labels, workspace tags, repo"),
|
|
3916
|
+
repoPath: z7.string().optional().describe("Limit to one project path from list_projects"),
|
|
3917
|
+
kind: z7.enum(["all", "tickets", "prs", "branches", "threads"]).optional().describe("Filter by worktree source (default all)"),
|
|
3918
|
+
ownership: z7.enum(["all", "mine", "reviewing"]).optional().describe(
|
|
3773
3919
|
"Mine = PRs you authored or local WIP; reviewing = someone else's PR. Uses the gh login."
|
|
3774
3920
|
),
|
|
3775
|
-
column:
|
|
3921
|
+
column: z7.enum(["new", "draft", "review", "done", "needs_you"]).optional().describe(
|
|
3776
3922
|
"Return cards for this column only (totals still include the rest). needs_you is a legacy alias for new."
|
|
3777
3923
|
),
|
|
3778
|
-
limit:
|
|
3924
|
+
limit: z7.number().int().positive().optional().describe("Max cards per column (default 40). hidden counts the remainder.")
|
|
3779
3925
|
},
|
|
3780
3926
|
async ({ query, repoPath, kind, ownership, column, limit }) => {
|
|
3781
3927
|
const workspaces = orch.listWorkspaces();
|
|
@@ -3805,7 +3951,7 @@ async function startMcpServer() {
|
|
|
3805
3951
|
server.tool(
|
|
3806
3952
|
"get_chat",
|
|
3807
3953
|
"Get a compact chat summary by id/ref. Includes last message preview, parentChatId, and child workspace chats (status + lastText). While running, includes progress (last tool/thinking) and lastActivityAt. Includes usage (billed token + costUsd totals when providers reported cost) and lastTurnUsage. blockedReason is why that agent is waiting on a person (question, plan approval, or a reported block).",
|
|
3808
|
-
{ ref:
|
|
3954
|
+
{ ref: z7.string() },
|
|
3809
3955
|
async ({ ref }) => {
|
|
3810
3956
|
const t = orch.getThread(ref);
|
|
3811
3957
|
if (!t) {
|
|
@@ -3852,17 +3998,17 @@ async function startMcpServer() {
|
|
|
3852
3998
|
"present_artifact",
|
|
3853
3999
|
"Show a document or live log in Sideboard\u2019s side column. For html/svg/markdown/react, pass the FULL document and do not also fence that same body in chat. For type=log, pass only NEW lines (same artifact_id appends). Prefer type=log for long-running job output \u2014 do not resend HTML. type=react is a single default-export component (JSX/TSX); only react/react-dom imports.",
|
|
3854
4000
|
{
|
|
3855
|
-
title:
|
|
3856
|
-
type:
|
|
4001
|
+
title: z7.string().describe("Short title shown in the artifact pane header"),
|
|
4002
|
+
type: z7.enum(["html", "svg", "markdown", "react", "log"]).describe(
|
|
3857
4003
|
"html/svg/markdown/react replace the pane. log appends content to the same artifact_id (new lines only)."
|
|
3858
4004
|
),
|
|
3859
|
-
content:
|
|
4005
|
+
content: z7.string().describe(
|
|
3860
4006
|
"html/svg/markdown/react: full document. log: only the new lines since the last call (empty is ok for a status-only update)."
|
|
3861
4007
|
),
|
|
3862
|
-
artifact_id:
|
|
3863
|
-
status:
|
|
3864
|
-
phase:
|
|
3865
|
-
mode:
|
|
4008
|
+
artifact_id: z7.string().optional().describe("Stable id. Required for type=log so later calls append to the same pane."),
|
|
4009
|
+
status: z7.enum(["running", "ok", "failed", "idle"]).optional().describe("Log header pill: running (working), ok (done), failed, idle"),
|
|
4010
|
+
phase: z7.string().optional().describe("Log subtitle (Signing, Notarizing, \u2026)"),
|
|
4011
|
+
mode: z7.enum(["append", "replace"]).optional().describe("log only: append (default) or replace the buffer")
|
|
3866
4012
|
},
|
|
3867
4013
|
async ({ title, type, artifact_id, status, phase, mode }) => {
|
|
3868
4014
|
return mcpJson(
|
|
@@ -3875,15 +4021,15 @@ async function startMcpServer() {
|
|
|
3875
4021
|
"ask_user",
|
|
3876
4022
|
"Ask the user a clarifying multiple-choice question in Sideboard\u2019s composer. Call only when work is blocked on choosing among a few concrete options (approach fork, which API, auth vs cookies). Do not call for greetings, check-ins, \u201Chello\u201D, open-ended how-can-I-help, or to invent a menu of possible next tasks \u2014 reply in chat instead. If one option is the obvious default, proceed without asking. Before calling, write a short chat message explaining the decision and what each option means. Include a description on every option. After calling, stop and wait for answers. Not for \u201Cis the plan ready?\u201D.",
|
|
3877
4023
|
{
|
|
3878
|
-
questions:
|
|
3879
|
-
|
|
3880
|
-
question:
|
|
3881
|
-
header:
|
|
3882
|
-
multiSelect:
|
|
3883
|
-
options:
|
|
3884
|
-
|
|
3885
|
-
label:
|
|
3886
|
-
description:
|
|
4024
|
+
questions: z7.array(
|
|
4025
|
+
z7.object({
|
|
4026
|
+
question: z7.string().describe("Full question text ending with ?"),
|
|
4027
|
+
header: z7.string().max(24).optional().describe("Short label shown above the question"),
|
|
4028
|
+
multiSelect: z7.boolean().optional().describe("Allow selecting multiple options"),
|
|
4029
|
+
options: z7.array(
|
|
4030
|
+
z7.object({
|
|
4031
|
+
label: z7.string(),
|
|
4032
|
+
description: z7.string().optional().describe("What this option means / when to choose it (strongly preferred)")
|
|
3887
4033
|
})
|
|
3888
4034
|
).min(2).max(6).describe("2\u20136 choices (Sideboard also offers Other)")
|
|
3889
4035
|
})
|
|
@@ -3909,9 +4055,9 @@ async function startMcpServer() {
|
|
|
3909
4055
|
"present_plan",
|
|
3910
4056
|
PRESENT_PLAN_TOOL_DESCRIPTION,
|
|
3911
4057
|
{
|
|
3912
|
-
title:
|
|
3913
|
-
content:
|
|
3914
|
-
thread_id:
|
|
4058
|
+
title: z7.string().optional().describe("Short plan title (defaults to Plan)"),
|
|
4059
|
+
content: z7.string().min(1).describe("Full plan markdown (headings, steps, risks, open questions)"),
|
|
4060
|
+
thread_id: z7.string().optional().describe("Sideboard thread id when cwd is not the worktree")
|
|
3915
4061
|
},
|
|
3916
4062
|
async ({ title, content, thread_id }) => {
|
|
3917
4063
|
const { writePlanFile } = await import("../plan-file-VAHV5WBB.js");
|
|
@@ -3940,15 +4086,15 @@ async function startMcpServer() {
|
|
|
3940
4086
|
"present_schema",
|
|
3941
4087
|
"Open Sideboard\u2019s schema-driven side column (filterable table and/or form) when the user needs to filter, edit, publish, or persist records. Do not call this just to re-display rows you already wrote as a markdown table. If the user asks for an editable / interactive table, call this even if chat already showed those rows. Pass JSON Schema + optional schemaUi. Prefer datasource=inline with embedded resource/records. Use datasource=brightsy with resource_id only when the user is logged into Brightsy.",
|
|
3942
4088
|
{
|
|
3943
|
-
title:
|
|
3944
|
-
mode:
|
|
3945
|
-
datasource:
|
|
3946
|
-
resource_id:
|
|
3947
|
-
record_id:
|
|
3948
|
-
resource:
|
|
3949
|
-
record:
|
|
3950
|
-
records:
|
|
3951
|
-
pane_id:
|
|
4089
|
+
title: z7.string().describe("Pane title"),
|
|
4090
|
+
mode: z7.enum(["table", "form"]).optional().describe("table = list/filter records; form = edit one record"),
|
|
4091
|
+
datasource: z7.enum(["brightsy", "inline"]).optional().describe("brightsy resolves via login; inline uses embedded resource/records"),
|
|
4092
|
+
resource_id: z7.string().optional().describe("Brightsy record type UUID (or generic resource id)"),
|
|
4093
|
+
record_id: z7.string().optional().describe("Record id when opening form mode"),
|
|
4094
|
+
resource: z7.record(z7.unknown()).optional().describe("Inline { id, title, schema, schemaUi?, slug? }"),
|
|
4095
|
+
record: z7.record(z7.unknown()).optional().describe("Inline record { id, data, published_at? }"),
|
|
4096
|
+
records: z7.array(z7.record(z7.unknown())).optional().describe("Inline records for table mode"),
|
|
4097
|
+
pane_id: z7.string().optional().describe("Stable pane id across updates")
|
|
3952
4098
|
},
|
|
3953
4099
|
async (args) => {
|
|
3954
4100
|
const id = args.pane_id?.trim() || `schema_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
@@ -3969,10 +4115,10 @@ async function startMcpServer() {
|
|
|
3969
4115
|
"present_files",
|
|
3970
4116
|
"Open Sideboard\u2019s Files column (CMS-style file manager: browse, upload, pick). Use datasource=brightsy when the user is logged into Brightsy account storage; datasource=memory for a session-local demo store. Prefer this over claiming a file manager UI is unavailable. Pair with present_schema when editing records that need media.",
|
|
3971
4117
|
{
|
|
3972
|
-
title:
|
|
3973
|
-
datasource:
|
|
3974
|
-
path:
|
|
3975
|
-
pane_id:
|
|
4118
|
+
title: z7.string().optional().describe("Pane title (default: Files)"),
|
|
4119
|
+
datasource: z7.enum(["brightsy", "memory"]).optional().describe("brightsy = account storage via login; memory = session demo store"),
|
|
4120
|
+
path: z7.string().optional().describe("Initial folder path (e.g. public)"),
|
|
4121
|
+
pane_id: z7.string().optional().describe("Stable pane id across updates")
|
|
3976
4122
|
},
|
|
3977
4123
|
async (args) => {
|
|
3978
4124
|
const id = args.pane_id?.trim() || `files_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
@@ -3992,8 +4138,8 @@ async function startMcpServer() {
|
|
|
3992
4138
|
"wait_for_job",
|
|
3993
4139
|
"Wait on a detached long job (tests, pack, deploy, connector CLI) started with detached-job.cjs. MCP clients kill tools around 60s, so this returns within 45s. Sideboard opens a type=log pane from this result (artifact_id = job id, content = delta). stillRunning is the source of truth \u2014 if true, call wait_for_job again. If the job is hanging, producing no useful output, or doing the wrong thing, call stop_job instead of looping forever. Do not end the turn or tell the user you will let them know later. If false, ok/failed is the result.",
|
|
3994
4140
|
{
|
|
3995
|
-
id:
|
|
3996
|
-
timeoutMs:
|
|
4141
|
+
id: z7.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
|
|
4142
|
+
timeoutMs: z7.number().optional()
|
|
3997
4143
|
},
|
|
3998
4144
|
async ({ id, timeoutMs }) => {
|
|
3999
4145
|
const result = await waitForDetachedJob(process.cwd(), id, {
|
|
@@ -4006,8 +4152,8 @@ async function startMcpServer() {
|
|
|
4006
4152
|
"stop_job",
|
|
4007
4153
|
"Stop a detached job you started with detached-job.cjs when it is hanging, producing no useful output, buffering forever, or doing the wrong thing (wrong project, infinite watch, huge dump). Do not stop a pack/test/deploy that is clearly making progress. The type=log pane updates to status=failed with the last delta. Then decide the next step.",
|
|
4008
4154
|
{
|
|
4009
|
-
id:
|
|
4010
|
-
reason:
|
|
4155
|
+
id: z7.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
|
|
4156
|
+
reason: z7.string().optional().describe("Why you are stopping (hanging, no progress, wrong output, already have the answer)")
|
|
4011
4157
|
},
|
|
4012
4158
|
async ({ id, reason }) => {
|
|
4013
4159
|
const result = await stopDetachedJob(process.cwd(), id, { reason });
|
|
@@ -4019,7 +4165,7 @@ async function startMcpServer() {
|
|
|
4019
4165
|
"list_run_scripts",
|
|
4020
4166
|
"List .sideboard/.conductor run scripts for this thread (same menu as the desktop Dev button) and which are active. Each script and active run includes preview: url (open http://localhost:<SIDEBOARD_PORT>) or window (Electron: native window is the app; url is renderer/HMR only). Never guess :3000. Worktree turns may omit ref (uses cwd).",
|
|
4021
4167
|
{
|
|
4022
|
-
ref:
|
|
4168
|
+
ref: z7.string().optional().describe("Thread id. Omit on a worktree turn (uses cwd).")
|
|
4023
4169
|
},
|
|
4024
4170
|
async ({ ref }) => {
|
|
4025
4171
|
try {
|
|
@@ -4049,8 +4195,8 @@ async function startMcpServer() {
|
|
|
4049
4195
|
"run_dev_script",
|
|
4050
4196
|
"Start a .sideboard/.conductor run script (same as the desktop Dev / play button). Several named scripts can run at once; each gets its own port, and starting one does not stop the others. Logs and Stop appear in the thread UI \u2014 do not detached-job or shell-spawn the same command. Returns {port, ports, url, preview}. preview=url \u2192 open url (browser, curl, Playwright). preview=window \u2192 Electron: the native window is the app; url is renderer/HMR only (no preload/IPC in a browser). The port is allocated SIDEBOARD_PORT, not 3000. Worktree turns may omit ref (uses cwd). Omit name for the default script.",
|
|
4051
4197
|
{
|
|
4052
|
-
ref:
|
|
4053
|
-
name:
|
|
4198
|
+
ref: z7.string().optional().describe("Thread id. Omit on a worktree turn (uses cwd)."),
|
|
4199
|
+
name: z7.string().optional().describe("Script name from list_run_scripts (default script if omitted).")
|
|
4054
4200
|
},
|
|
4055
4201
|
async ({ ref, name }) => {
|
|
4056
4202
|
try {
|
|
@@ -4078,8 +4224,8 @@ async function startMcpServer() {
|
|
|
4078
4224
|
"stop_dev_script",
|
|
4079
4225
|
"Stop a run script started with run_dev_script or the desktop Dev button (same as UI Stop). Omit name to stop all scripts on this worktree. Worktree turns may omit ref (uses cwd).",
|
|
4080
4226
|
{
|
|
4081
|
-
ref:
|
|
4082
|
-
name:
|
|
4227
|
+
ref: z7.string().optional().describe("Thread id. Omit on a worktree turn (uses cwd)."),
|
|
4228
|
+
name: z7.string().optional().describe("Script name to stop; omit to stop all active scripts.")
|
|
4083
4229
|
},
|
|
4084
4230
|
async ({ ref, name }) => {
|
|
4085
4231
|
try {
|
|
@@ -4096,9 +4242,9 @@ async function startMcpServer() {
|
|
|
4096
4242
|
"get_run_log",
|
|
4097
4243
|
"Read the Run-tab terminal for a worktree script (same stdout/stderr as the desktop Dev pane). Default is a tail \u2014 raise `tail` only if the error is missing. Worktree turns may omit ref (uses cwd). Omit name for the default script.",
|
|
4098
4244
|
{
|
|
4099
|
-
ref:
|
|
4100
|
-
name:
|
|
4101
|
-
tail:
|
|
4245
|
+
ref: z7.string().optional().describe("Thread id. Omit on a worktree turn (uses cwd)."),
|
|
4246
|
+
name: z7.string().optional().describe("Script name from list_run_scripts (default script if omitted)."),
|
|
4247
|
+
tail: z7.number().int().min(1).max(MAX_RUN_LOG_CHARS).optional().describe(
|
|
4102
4248
|
`Max characters to return from the end (default ${DEFAULT_RUN_LOG_TAIL_CHARS}). Do not request the full buffer unless the tail is truncated and you still need more.`
|
|
4103
4249
|
)
|
|
4104
4250
|
},
|
|
@@ -4136,8 +4282,8 @@ async function startMcpServer() {
|
|
|
4136
4282
|
"notify_orchestrator",
|
|
4137
4283
|
"Wake the parent Global orchestrator with a short status so it does not have to poll wait_for_turn. Use when you are blocked and the parent may have moved on (missing access, waiting on something the coordinator must handle). The message is shown on the sidebar and board until the next user message in this chat. ask_user already notifies for input-required \u2014 do not call this for the same question. Information only: never a git command. Do not use this to steer other worktrees.",
|
|
4138
4284
|
{
|
|
4139
|
-
message:
|
|
4140
|
-
reason:
|
|
4285
|
+
message: z7.string().min(1).max(1500).describe("Why you are blocked / what the parent should know (short)."),
|
|
4286
|
+
reason: z7.enum(["input-required", "blocked"]).optional().describe(
|
|
4141
4287
|
"input-required = waiting on the user in this chat; blocked = need the coordinator (default)."
|
|
4142
4288
|
)
|
|
4143
4289
|
},
|
|
@@ -4174,11 +4320,11 @@ async function startMcpServer() {
|
|
|
4174
4320
|
"set_workspace_tags",
|
|
4175
4321
|
worktreeProfile ? "Update tags on this workspace (the checkout you are in). Omit ref to use this chat. mode=replace (default), add, or remove. Short labels \u2014 the same ones the orchestrator used for this task. You cannot retag a different checkout." : "Label a project workspace so related checkouts stay recognizable in the sidebar and on the phone. Pass any chat id on that workspace. Use the same tags on every workspace from one task. mode=replace is the default; add and remove change the set. create_workspace tags= sets them at create time. Not for orchestration chats.",
|
|
4176
4322
|
{
|
|
4177
|
-
ref:
|
|
4323
|
+
ref: z7.string().optional().describe(
|
|
4178
4324
|
worktreeProfile ? "Omit for this chat. Another chat id only if it is on this same checkout." : "Chat id on the workspace to label."
|
|
4179
4325
|
),
|
|
4180
|
-
tags:
|
|
4181
|
-
mode:
|
|
4326
|
+
tags: z7.union([z7.string(), z7.array(z7.string())]).describe("Labels to set. A string may be comma-separated."),
|
|
4327
|
+
mode: z7.enum(["replace", "add", "remove"]).optional()
|
|
4182
4328
|
},
|
|
4183
4329
|
async ({ ref, tags, mode }) => {
|
|
4184
4330
|
try {
|
|
@@ -4205,14 +4351,14 @@ async function startMcpServer() {
|
|
|
4205
4351
|
if (!worktreeProfile) {
|
|
4206
4352
|
registerConnectedIssueVendorTools(server);
|
|
4207
4353
|
const { getCaffeinateHold, setCaffeinateHold } = await import("../caffeinate-hold-7JM5H5P3.js");
|
|
4208
|
-
const { resolveNewThreadOptions, resolveThreadDefaults } = await import("../app-settings-
|
|
4354
|
+
const { resolveNewThreadOptions, resolveThreadDefaults } = await import("../app-settings-EHMXHNG5.js");
|
|
4209
4355
|
const accountDefaults = resolveThreadDefaults();
|
|
4210
4356
|
const accountDefaultsHint = `Account defaults: agent=${accountDefaults.agent}, model=${accountDefaults.model?.trim() || "Auto"}, effort=${accountDefaults.effort}`;
|
|
4211
4357
|
server.tool(
|
|
4212
4358
|
"set_caffeinate",
|
|
4213
4359
|
"Keep this Mac awake with caffeinate (like Claude Code) across turns \u2014 independent of Settings toggles. Turn ON when the user will be away from the keyboard, is driving work from Slack, or asks you to keep the machine awake. Turn OFF when they say they are done, wrapping up, going to sleep, or no longer need the Mac awake. Closing or archiving this orchestration chat also releases the hold. macOS only.",
|
|
4214
4360
|
{
|
|
4215
|
-
enabled:
|
|
4361
|
+
enabled: z7.boolean().describe("true = hold caffeinate on; false = release and let the Mac sleep")
|
|
4216
4362
|
},
|
|
4217
4363
|
async ({ enabled }) => {
|
|
4218
4364
|
const threadId = process.env.SIDEBOARD_ORCHESTRATOR_THREAD_ID?.trim() || null;
|
|
@@ -4238,24 +4384,24 @@ async function startMcpServer() {
|
|
|
4238
4384
|
"create_workspace",
|
|
4239
4385
|
`Create a workspace (isolated git checkout + first chat) from branch, pr, or ticket. A ticket, PR, or named branch has one checkout \u2014 if one already matches, returns it (alreadyStarted=true) instead of a second checkout. That is not one agent: chats lists every agent on that checkout. Add another with fork_chat; send_to_chat only the chat that should do this job. Creating from the default branch still opens a new isolated checkout. Pass repoPath from list_projects. cowboy=true uses the project folder on the default branch (no isolated worktree; land is commit+push). From an orchestration chat, omit parentChatId (Sideboard binds the child to this chat) or pass the exact id from the turn reminder \u2014 never invent a uuid. Omit agent/model \u2014 Sideboard applies ${accountDefaultsHint}. Do not pass your own agent or agent=cursor; those are ignored. Setup (settings.toml, .cursor/worktrees.json, or script/setup) runs in the background in parallel with the first turn (skipped for cowboy). Pass the same tags on every workspace you open for one task (short labels such as "phone-sync") so they still match in the sidebar the next day. Reusing a checkout adds those tags.`,
|
|
4240
4386
|
{
|
|
4241
|
-
sourceType:
|
|
4242
|
-
sourceRef:
|
|
4243
|
-
agent:
|
|
4387
|
+
sourceType: z7.enum(["branch", "pr", "ticket"]),
|
|
4388
|
+
sourceRef: z7.string(),
|
|
4389
|
+
agent: z7.enum(["claude", "codex", "opencode", "brightsy", "cursor"]).optional().describe(
|
|
4244
4390
|
`Usually omit. Sideboard uses Account default agent (${accountDefaults.agent}). Passing your own agent or cursor is ignored.`
|
|
4245
4391
|
),
|
|
4246
|
-
model:
|
|
4392
|
+
model: z7.string().nullable().optional().describe(
|
|
4247
4393
|
`Usually omit to use Account default model (${accountDefaults.model?.trim() || "Auto"}). Pass null only to force Auto / agent-default.`
|
|
4248
4394
|
),
|
|
4249
|
-
repoPath:
|
|
4250
|
-
title:
|
|
4251
|
-
cowboy:
|
|
4395
|
+
repoPath: z7.string(),
|
|
4396
|
+
title: z7.string().optional(),
|
|
4397
|
+
cowboy: z7.boolean().optional().describe(
|
|
4252
4398
|
"If true, work in the project folder on the default branch (no thread/* worktree). Requires Settings \u2192 Advanced \u2192 Cowboy mode. Land is commit+push to that branch. Archive does not delete the folder."
|
|
4253
4399
|
),
|
|
4254
|
-
parentChatId:
|
|
4400
|
+
parentChatId: z7.string().optional().describe(
|
|
4255
4401
|
"Orchestration: omit (preferred) or pass YOUR chat id from the turn reminder / AGENTS.md. Do not invent uuids."
|
|
4256
4402
|
),
|
|
4257
|
-
parentThreadId:
|
|
4258
|
-
tags:
|
|
4403
|
+
parentThreadId: z7.string().optional().describe("Legacy alias for parentChatId."),
|
|
4404
|
+
tags: z7.union([z7.string(), z7.array(z7.string())]).optional().describe(
|
|
4259
4405
|
"Short labels for this workspace (or a comma-separated string). Use the same tags on every checkout for one task. Added when the checkout already exists."
|
|
4260
4406
|
)
|
|
4261
4407
|
},
|
|
@@ -4271,11 +4417,11 @@ async function startMcpServer() {
|
|
|
4271
4417
|
"start_board_card",
|
|
4272
4418
|
"Same as create_workspace for a ticket, PR, or named branch (attaches issue text when Sideboard can resolve it). Does not create a second checkout when one already matches \u2014 returns that workspace (alreadyStarted) and its chats. A workspace can have many agents. fork_chat to add one; send_to_chat only the chat that should do this job.",
|
|
4273
4419
|
{
|
|
4274
|
-
kind:
|
|
4275
|
-
ref:
|
|
4276
|
-
repoPath:
|
|
4277
|
-
title:
|
|
4278
|
-
tags:
|
|
4420
|
+
kind: z7.enum(["ticket", "pr", "branch"]),
|
|
4421
|
+
ref: z7.string().describe("Ticket identifier (ENG-12), PR number (44), or branch name from list_board"),
|
|
4422
|
+
repoPath: z7.string().describe("Project path from list_projects / list_board"),
|
|
4423
|
+
title: z7.string().optional(),
|
|
4424
|
+
tags: z7.union([z7.string(), z7.array(z7.string())]).optional().describe(
|
|
4279
4425
|
"Short labels for this workspace. Same tags on every checkout for one task. Added when the checkout already exists."
|
|
4280
4426
|
)
|
|
4281
4427
|
},
|
|
@@ -4380,9 +4526,9 @@ async function startMcpServer() {
|
|
|
4380
4526
|
"send_to_chat",
|
|
4381
4527
|
'Steer a prompt on a workspace chat (Settings \u2192 Follow-up, default steer: interrupt the in-flight turn and start now, same as the workspace composer). Use after create_workspace to start or continue a conversation. For commit/push/PR, prefer ask_git (canonical desktop-button phrases). Send "Merge PR." / ask_git merge only when the user explicitly asked to merge. force_stop=true kills the in-flight turn and clears the queue before this prompt \u2014 only when the current request is wrong and must be replaced. Do not send_to_chat to check in, resume after a halt notice, or because wait_for_turn returned stillRunning; that interrupts the child mid-thought. Call wait_for_turn again instead.',
|
|
4382
4528
|
{
|
|
4383
|
-
ref:
|
|
4384
|
-
prompt:
|
|
4385
|
-
force_stop:
|
|
4529
|
+
ref: z7.string(),
|
|
4530
|
+
prompt: z7.string(),
|
|
4531
|
+
force_stop: z7.boolean().optional()
|
|
4386
4532
|
},
|
|
4387
4533
|
async ({ ref, prompt, force_stop }) => {
|
|
4388
4534
|
if (force_stop) {
|
|
@@ -4407,8 +4553,8 @@ async function startMcpServer() {
|
|
|
4407
4553
|
"wait_for_turn",
|
|
4408
4554
|
"Wait until the chat finishes its current/queued turn, or return early with a live progress snapshot. MCP clients often kill tools around 60s, so this returns within 45s even while the child is still working. taskState is the A2A-style lifecycle: submitted (queued, not started), working, input-required (ask_user), completed, failed, canceled. stillRunning is true only for submitted/working. blockedReason is why the child is waiting on a person (the question, plan approval, or a reported block) \u2014 read it and do not send_to_chat a check-in. If stillRunning, text and usage are empty (they would be the previous turn) \u2014 read progress and call wait_for_turn again. Do not send_to_chat a check-in (that steers / interrupts). On failed, lastError/text is the failure. On canceled, the child did not finish \u2014 resume with send_to_chat or tell the user. On input-required, wait for the user in that chat. When finished, text is this turn\u2019s assistant reply and usage is that turn\u2019s tokens + costUsd (this turn, not the Claude session total; sessionCostUsd is the provider session total when present).",
|
|
4409
4555
|
{
|
|
4410
|
-
ref:
|
|
4411
|
-
timeoutMs:
|
|
4556
|
+
ref: z7.string(),
|
|
4557
|
+
timeoutMs: z7.number().optional()
|
|
4412
4558
|
},
|
|
4413
4559
|
async ({ ref, timeoutMs }) => {
|
|
4414
4560
|
const thread = await orch.waitForTurn(ref, mcpWaitForTurnTimeoutMs(timeoutMs), {
|
|
@@ -4436,7 +4582,7 @@ async function startMcpServer() {
|
|
|
4436
4582
|
server.tool(
|
|
4437
4583
|
"get_turn_result",
|
|
4438
4584
|
"Assistant message and last-turn usage when the turn finished. While stillRunning (submitted/working), text and usage are empty so a previous reply cannot be mistaken for this turn \u2014 use progress for tools/thinking. Not the full transcript. Includes taskState (A2A lifecycle) and blockedReason (why the agent is waiting on a person).",
|
|
4439
|
-
{ ref:
|
|
4585
|
+
{ ref: z7.string() },
|
|
4440
4586
|
async ({ ref }) => {
|
|
4441
4587
|
const result = orch.getTurnResult(ref);
|
|
4442
4588
|
const hint = mcpWaitTaskHint(result.taskState, result.status, result.blockedReason);
|
|
@@ -4452,9 +4598,9 @@ async function startMcpServer() {
|
|
|
4452
4598
|
"stop_chat",
|
|
4453
4599
|
"Force-stop a thread: kill any in-flight agent turn AND clear queued prompts so drainQueue cannot continue. Does not archive the worktree. Optional force defaults to true. Pass reason \u2014 a short note on why this chat is stopping. It is stored on the thread and kept when the turn unwinds. If you omit it, Sideboard still records that the queue was cleared.",
|
|
4454
4600
|
{
|
|
4455
|
-
ref:
|
|
4456
|
-
force:
|
|
4457
|
-
reason:
|
|
4601
|
+
ref: z7.string(),
|
|
4602
|
+
force: z7.boolean().optional(),
|
|
4603
|
+
reason: z7.string().optional().describe("Why this chat is stopping. Stored on the thread for the next session.")
|
|
4458
4604
|
},
|
|
4459
4605
|
async ({ ref, force, reason }) => {
|
|
4460
4606
|
const t = orch.getThread(ref);
|
|
@@ -4478,7 +4624,7 @@ async function startMcpServer() {
|
|
|
4478
4624
|
server.tool(
|
|
4479
4625
|
"archive_chat",
|
|
4480
4626
|
"Archive a thread (stops agent/dev, runs archive script, removes worktree when last chat tab). Coordinators commit, push, and open PRs by asking the worktree agent (ask_git). Merge only when the user explicitly asked.",
|
|
4481
|
-
{ ref:
|
|
4627
|
+
{ ref: z7.string() },
|
|
4482
4628
|
async ({ ref }) => {
|
|
4483
4629
|
const t = orch.getThread(ref);
|
|
4484
4630
|
if (!t) {
|
|
@@ -4504,7 +4650,7 @@ async function startMcpServer() {
|
|
|
4504
4650
|
server.tool(
|
|
4505
4651
|
"restore_chat",
|
|
4506
4652
|
"Restore an archived thread (recreates worktree from branch when needed)",
|
|
4507
|
-
{ ref:
|
|
4653
|
+
{ ref: z7.string() },
|
|
4508
4654
|
async ({ ref }) => {
|
|
4509
4655
|
try {
|
|
4510
4656
|
const restored = await orch.restore(ref);
|
|
@@ -4523,8 +4669,8 @@ async function startMcpServer() {
|
|
|
4523
4669
|
"get_diff",
|
|
4524
4670
|
"Compact diff summary (capped hunks, paginated)",
|
|
4525
4671
|
{
|
|
4526
|
-
ref:
|
|
4527
|
-
maxFiles:
|
|
4672
|
+
ref: z7.string(),
|
|
4673
|
+
maxFiles: z7.number().optional()
|
|
4528
4674
|
},
|
|
4529
4675
|
async ({ ref, maxFiles }) => {
|
|
4530
4676
|
const summary = await orch.diffSummary(ref);
|
|
@@ -4537,7 +4683,7 @@ async function startMcpServer() {
|
|
|
4537
4683
|
server.tool(
|
|
4538
4684
|
"get_pr_checks",
|
|
4539
4685
|
"Snapshot of GitHub PR checks for a worktree thread (`gh pr checks` plus merge/review gates). null = no PR. If the user gave a goal (Greptile 5/5, CI green), the worktree agent watches with `gh pr checks --watch` via /long-running \u2014 this tool is a snapshot, not a waiter. Coordinators: do not run gh from the orchestration cwd.",
|
|
4540
|
-
{ ref:
|
|
4686
|
+
{ ref: z7.string().describe("Worktree thread id/ref") },
|
|
4541
4687
|
async ({ ref }) => {
|
|
4542
4688
|
try {
|
|
4543
4689
|
const checks = await orch.getPrChecks(ref);
|
|
@@ -4551,7 +4697,7 @@ async function startMcpServer() {
|
|
|
4551
4697
|
server.tool(
|
|
4552
4698
|
"request_review",
|
|
4553
4699
|
'Start a merge-readiness Review on a worktree agent thread (same as the desktop Review button). If that worktree has a single unused idle agent (no messages), runs the review there; otherwise opens a new Review chat tab. Attaches .claude/skills/review/SKILL.md when present (else copies .sideboard/review.md into .context/review.md, or seeds that file from the stock template), and sends "Review changes in this workspace." Expect Approve / Approve with nits / Request changes / Needs more information in that chat. The review stays there so the user can read it and type next steps \u2014 do not comment on or update the PR or ticket, and do not ask_user after the review, until they ask. Pass a worktree thread ref \u2014 not the orchestrator. Then wait_for_turn (loop while stillRunning) / get_turn_result on the returned review thread id.',
|
|
4554
|
-
{ ref:
|
|
4700
|
+
{ ref: z7.string().describe("Worktree thread id/ref to review") },
|
|
4555
4701
|
async ({ ref }) => {
|
|
4556
4702
|
try {
|
|
4557
4703
|
const tab = await orch.requestReview(ref);
|
|
@@ -4573,8 +4719,8 @@ async function startMcpServer() {
|
|
|
4573
4719
|
"ask_git",
|
|
4574
4720
|
"Commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge \u2014 same prompts as the desktop git buttons (including Resolve). Always steers the worktree agent; does not push or open the PR locally. Then wait_for_turn (loop while stillRunning). Do not start a checks loop on a plain push \u2014 only if the user gave a goal (Greptile 5/5, CI green). Pass a worktree thread ref (not the orchestrator). action=ready-for-review and action=merge only when the user explicitly asked (or clicked the desktop button). Do not run git or gh from the orchestration cwd.",
|
|
4575
4721
|
{
|
|
4576
|
-
ref:
|
|
4577
|
-
action:
|
|
4722
|
+
ref: z7.string().describe("Worktree thread id/ref"),
|
|
4723
|
+
action: z7.enum(AGENT_GIT_ACTIONS).describe(
|
|
4578
4724
|
"commit-push | create-draft | create-web | resolve-conflicts | ready-for-review | merge"
|
|
4579
4725
|
)
|
|
4580
4726
|
},
|
|
@@ -4603,7 +4749,7 @@ async function startMcpServer() {
|
|
|
4603
4749
|
}
|
|
4604
4750
|
}
|
|
4605
4751
|
);
|
|
4606
|
-
const agentEnum =
|
|
4752
|
+
const agentEnum = z7.enum(["claude", "codex", "opencode", "brightsy", "cursor"]);
|
|
4607
4753
|
server.tool(
|
|
4608
4754
|
"list_models",
|
|
4609
4755
|
"List models for an agent. Prefer Auto: do not call this unless you have a reason to pin a specific model (user request, cost/latency, capability). Omit agent to list all.",
|
|
@@ -4624,11 +4770,11 @@ async function startMcpServer() {
|
|
|
4624
4770
|
"fork_workspace",
|
|
4625
4771
|
"Fork a worktree agent chat into a NEW git worktree + chat (desktop \u201CFork to new workspace\u201D). Seeds a transcript (through through_index, default all). Optional agent override. Leave model unset for Auto (default) \u2014 only pass model when you have a reason. Not for the orchestrator. Then send_to_chat / wait_for_turn (loop while stillRunning) on the returned id.",
|
|
4626
4772
|
{
|
|
4627
|
-
ref:
|
|
4628
|
-
through_index:
|
|
4773
|
+
ref: z7.string().describe("Worktree thread id/ref to fork"),
|
|
4774
|
+
through_index: z7.number().optional().describe("Inclusive message index to include in the transcript (default: all)"),
|
|
4629
4775
|
agent: agentEnum.optional().describe("Agent for the forked chat (default: same as source)"),
|
|
4630
|
-
model:
|
|
4631
|
-
title:
|
|
4776
|
+
model: z7.string().nullable().optional().describe("Usually omit (Auto). Only set from list_models when you need a specific model"),
|
|
4777
|
+
title: z7.string().optional()
|
|
4632
4778
|
},
|
|
4633
4779
|
async ({ ref, through_index, agent, model, title }) => {
|
|
4634
4780
|
try {
|
|
@@ -4662,11 +4808,11 @@ async function startMcpServer() {
|
|
|
4662
4808
|
"fork_chat",
|
|
4663
4809
|
"Add another agent chat on the SAME workspace (same files, Run, and git). Also forks a Global orchestration chat into a new orchestration tab. Pass agent when the new chat should use a different harness. Leave model unset for Auto unless you have a reason. Orchestration forks require an MCP-capable agent (claude, cursor, codex, opencode \u2014 not brightsy). Use this for a second agent on a checkout (review, another harness, parallel work on the same branch). Do not create_workspace again for that \u2014 it returns the existing checkout. Then send_to_chat / wait_for_turn (loop while stillRunning) on the returned id. Use fork_workspace only when the work needs its own git checkout.",
|
|
4664
4810
|
{
|
|
4665
|
-
ref:
|
|
4666
|
-
through_index:
|
|
4811
|
+
ref: z7.string().describe("Thread id/ref to fork (worktree agent or orchestration chat)"),
|
|
4812
|
+
through_index: z7.number().optional().describe("Inclusive message index to include in the transcript (default: all)"),
|
|
4667
4813
|
agent: agentEnum.optional().describe("Agent for the forked chat (default: same as source)"),
|
|
4668
|
-
model:
|
|
4669
|
-
title:
|
|
4814
|
+
model: z7.string().nullable().optional().describe("Usually omit (Auto). Only set from list_models when you need a specific model"),
|
|
4815
|
+
title: z7.string().optional()
|
|
4670
4816
|
},
|
|
4671
4817
|
async ({ ref, through_index, agent, model, title }) => {
|
|
4672
4818
|
try {
|
|
@@ -4704,7 +4850,7 @@ async function startMcpServer() {
|
|
|
4704
4850
|
server.tool(
|
|
4705
4851
|
"run_setup",
|
|
4706
4852
|
"Re-run workspace setup (Sideboard/Conductor settings, .cursor/worktrees.json, or script/setup). New worktrees already run this automatically.",
|
|
4707
|
-
{ ref:
|
|
4853
|
+
{ ref: z7.string() },
|
|
4708
4854
|
async ({ ref }) => {
|
|
4709
4855
|
const result = await orch.runSetup(ref);
|
|
4710
4856
|
return mcpJson(result);
|
|
@@ -4713,7 +4859,7 @@ async function startMcpServer() {
|
|
|
4713
4859
|
server.tool(
|
|
4714
4860
|
"add_project",
|
|
4715
4861
|
"Register a git repo as a Sideboard workspace",
|
|
4716
|
-
{ repoPath:
|
|
4862
|
+
{ repoPath: z7.string() },
|
|
4717
4863
|
async ({ repoPath }) => {
|
|
4718
4864
|
const ws = await orch.addWorkspace(repoPath);
|
|
4719
4865
|
return mcpJson(ws);
|
|
@@ -4722,7 +4868,7 @@ async function startMcpServer() {
|
|
|
4722
4868
|
server.tool(
|
|
4723
4869
|
"remove_project",
|
|
4724
4870
|
"Unregister a Sideboard workspace and archive its chats",
|
|
4725
|
-
{ repoPath:
|
|
4871
|
+
{ repoPath: z7.string() },
|
|
4726
4872
|
async ({ repoPath }) => {
|
|
4727
4873
|
await orch.removeWorkspace(repoPath);
|
|
4728
4874
|
return { content: [{ type: "text", text: "ok" }] };
|
|
@@ -4732,12 +4878,12 @@ async function startMcpServer() {
|
|
|
4732
4878
|
"fanout",
|
|
4733
4879
|
"Best-of-n: create one thread per agent with the same prompt (parallel attempts)",
|
|
4734
4880
|
{
|
|
4735
|
-
prompt:
|
|
4736
|
-
agents:
|
|
4737
|
-
repoPath:
|
|
4738
|
-
sourceType:
|
|
4739
|
-
sourceRef:
|
|
4740
|
-
title:
|
|
4881
|
+
prompt: z7.string(),
|
|
4882
|
+
agents: z7.array(z7.enum(["claude", "codex", "opencode", "brightsy", "cursor"])),
|
|
4883
|
+
repoPath: z7.string(),
|
|
4884
|
+
sourceType: z7.enum(["branch", "pr", "ticket"]).optional(),
|
|
4885
|
+
sourceRef: z7.string().optional(),
|
|
4886
|
+
title: z7.string().optional()
|
|
4741
4887
|
},
|
|
4742
4888
|
async (args) => {
|
|
4743
4889
|
const threads = await orch.bestOfN(args);
|
|
@@ -4755,8 +4901,8 @@ async function startMcpServer() {
|
|
|
4755
4901
|
"list_branches",
|
|
4756
4902
|
"List git branches in a registered workspace. Pass repoPath from list_projects (unmerged into the default branch by default \u2014 for create_workspace sourceType=branch).",
|
|
4757
4903
|
{
|
|
4758
|
-
repoPath:
|
|
4759
|
-
unmergedOnly:
|
|
4904
|
+
repoPath: z7.string(),
|
|
4905
|
+
unmergedOnly: z7.boolean().optional()
|
|
4760
4906
|
},
|
|
4761
4907
|
async ({ repoPath, unmergedOnly }) => {
|
|
4762
4908
|
const root = await resolveRepoRoot(repoPath);
|
|
@@ -4777,19 +4923,19 @@ async function startMcpServer() {
|
|
|
4777
4923
|
"list_prs",
|
|
4778
4924
|
`List GitHub PRs for a registered workspace (the review surface for assigned ticket work \u2014 not the tickets). Pass repoPath from list_projects. "Get me N tickets to review" \u2192 queue=review and limit=N: open non-draft PRs labeled with this project's ready-for-review GitHub label (Settings \u2192 Projects; default eng-review) with no individual user reviewer. Prefer teams that match Settings \u2192 Agents / Projects roles for this repo. A team like engineering-team is not a claim (you are on that team). Also: state (open|closed|merged|all|review), label, reviewer (me|unassigned|login), query, limit (default 40, max 250). Then create_workspace with sourceType=pr.`,
|
|
4779
4925
|
{
|
|
4780
|
-
repoPath:
|
|
4781
|
-
query:
|
|
4782
|
-
queue:
|
|
4926
|
+
repoPath: z7.string(),
|
|
4927
|
+
query: z7.string().optional().describe("GitHub search tokens (title, draft:true, \u2026)"),
|
|
4928
|
+
queue: z7.enum(["review", "mine", "approved", "changes"]).optional().describe(
|
|
4783
4929
|
"review = unclaimed ready-for-review inbox (Settings \u2192 Projects label, default eng-review). mine = review-requested:@me. approved / changes = eng-approved / eng-requested-changes."
|
|
4784
4930
|
),
|
|
4785
|
-
state:
|
|
4786
|
-
label:
|
|
4931
|
+
state: z7.enum(["open", "closed", "merged", "all", "review"]).optional().describe("GitHub PR state (default open). review is an alias for queue=review."),
|
|
4932
|
+
label: z7.string().optional().describe(
|
|
4787
4933
|
"GitHub label / workflow tag. Comma-separated AND. Examples: eng-review, eng-approved, eng-requested-changes"
|
|
4788
4934
|
),
|
|
4789
|
-
reviewer:
|
|
4935
|
+
reviewer: z7.string().optional().describe(
|
|
4790
4936
|
"me (review requested of you), unassigned (no individual reviewer; team queues like engineering-team still count), all, or a GitHub login"
|
|
4791
4937
|
),
|
|
4792
|
-
limit:
|
|
4938
|
+
limit: z7.number().int().positive().max(250).optional().describe("Page size (default 40, max 250). Raise when truncated is true.")
|
|
4793
4939
|
},
|
|
4794
4940
|
async ({ repoPath, query, queue, state, label, reviewer, limit }) => {
|
|
4795
4941
|
const root = await resolveRepoRoot(repoPath);
|
|
@@ -4822,7 +4968,7 @@ async function startMcpServer() {
|
|
|
4822
4968
|
server.tool(
|
|
4823
4969
|
"get_pr_stack",
|
|
4824
4970
|
"Load the GitHub PR stack for a thread worktree (`gh stack view --json`). Returns null JSON when the branch is not stacked. Prefer this before ask_git merge on stacked PRs (and only merge when the user explicitly asked).",
|
|
4825
|
-
{ ref:
|
|
4971
|
+
{ ref: z7.string() },
|
|
4826
4972
|
async ({ ref }) => {
|
|
4827
4973
|
const stack = await orch.getPrStack(ref);
|
|
4828
4974
|
return mcpJson(stack);
|
|
@@ -4832,8 +4978,8 @@ async function startMcpServer() {
|
|
|
4832
4978
|
"open_pr_stack_layers",
|
|
4833
4979
|
"Materialize one worktree+thread per stack layer (or a single 1-based layer). Pass a thread ref already on the stack.",
|
|
4834
4980
|
{
|
|
4835
|
-
ref:
|
|
4836
|
-
layer:
|
|
4981
|
+
ref: z7.string(),
|
|
4982
|
+
layer: z7.number().int().positive().optional()
|
|
4837
4983
|
},
|
|
4838
4984
|
async ({ ref, layer }) => {
|
|
4839
4985
|
const result = await orch.openPrStackLayers(ref, { layer });
|
|
@@ -4856,9 +5002,9 @@ async function startMcpServer() {
|
|
|
4856
5002
|
"add_stack_layer",
|
|
4857
5003
|
"Add a branch on top of the current stack (`gh stack add`) and open a worktree+thread for it.",
|
|
4858
5004
|
{
|
|
4859
|
-
ref:
|
|
4860
|
-
branchName:
|
|
4861
|
-
title:
|
|
5005
|
+
ref: z7.string(),
|
|
5006
|
+
branchName: z7.string(),
|
|
5007
|
+
title: z7.string().optional()
|
|
4862
5008
|
},
|
|
4863
5009
|
async ({ ref, branchName, title }) => {
|
|
4864
5010
|
const result = await orch.addStackLayer(ref, branchName, { title });
|
|
@@ -4876,11 +5022,11 @@ async function startMcpServer() {
|
|
|
4876
5022
|
"create_pr_stack",
|
|
4877
5023
|
"Create a new GitHub PR stack with one Sideboard worktree per layer (bottom\u2192top branch names). Requires `gh extension install github/gh-stack`.",
|
|
4878
5024
|
{
|
|
4879
|
-
repoPath:
|
|
4880
|
-
branches:
|
|
4881
|
-
agent:
|
|
4882
|
-
base:
|
|
4883
|
-
title:
|
|
5025
|
+
repoPath: z7.string(),
|
|
5026
|
+
branches: z7.array(z7.string()).min(1),
|
|
5027
|
+
agent: z7.enum(["claude", "codex", "opencode", "brightsy", "cursor"]),
|
|
5028
|
+
base: z7.string().optional(),
|
|
5029
|
+
title: z7.string().optional()
|
|
4884
5030
|
},
|
|
4885
5031
|
async (args) => {
|
|
4886
5032
|
const result = await orch.createPrStack({
|
|
@@ -4908,10 +5054,10 @@ async function startMcpServer() {
|
|
|
4908
5054
|
"list_issues",
|
|
4909
5055
|
"List or search issues (Linear, AbleTime, or GitHub; falls back to GitHub). Use Settings \u2192 Agents / Projects notes and roles to pick tickets relevant to the viewer (query + assignee=me or unassigned as the notes say). Default 40; pass query and/or limit (max 250) when truncated. assignee: me (Linear default), unassigned, all, or a user id. Pass updatedSince for new/updated tickets and new comments (\u201Cany updates since yesterday?\u201D). Then create_workspace with sourceType=ticket.",
|
|
4910
5056
|
{
|
|
4911
|
-
repoPath:
|
|
4912
|
-
query:
|
|
4913
|
-
assignee:
|
|
4914
|
-
limit:
|
|
5057
|
+
repoPath: z7.string(),
|
|
5058
|
+
query: z7.string().optional().describe("Search title, identifier, or description"),
|
|
5059
|
+
assignee: z7.string().optional().describe("me (Linear default), unassigned, all, a user id, or a GitHub login"),
|
|
5060
|
+
limit: z7.number().int().positive().max(250).optional().describe("Page size (default 40, max 250). Raise when truncated is true."),
|
|
4915
5061
|
updatedSince: mcpIssueUpdatedSinceSchema
|
|
4916
5062
|
},
|
|
4917
5063
|
async ({ repoPath, query, assignee, limit, updatedSince }) => {
|