kenzoboard 0.1.2 → 0.1.4
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/index.js +171 -37
- package/dist/mcp.js +21 -57
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -85,7 +85,7 @@ var init_blob_storage = () => {};
|
|
|
85
85
|
|
|
86
86
|
// src/index.ts
|
|
87
87
|
import { resolve as resolve4, dirname as dirname4, basename as basename2 } from "path";
|
|
88
|
-
import { execSync } from "child_process";
|
|
88
|
+
import { execFileSync, execSync } from "child_process";
|
|
89
89
|
import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync5, mkdirSync as mkdirSync3, appendFileSync, cpSync, realpathSync } from "fs";
|
|
90
90
|
import { fileURLToPath as fileURLToPath2, pathToFileURL } from "url";
|
|
91
91
|
import { createInterface } from "readline";
|
|
@@ -4114,15 +4114,22 @@ async function serveCommand(args, flags, options = {}) {
|
|
|
4114
4114
|
app.get("/", (c) => c.text("Web UI not found. API available at /api/*"));
|
|
4115
4115
|
}
|
|
4116
4116
|
const url = `http://localhost:${port}`;
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
console.log(`Web UI: ${webDistPath}`);
|
|
4117
|
+
if (options.compact) {
|
|
4118
|
+
console.log("");
|
|
4119
|
+
console.log(`Kenzo is running at ${url}`);
|
|
4121
4120
|
} else {
|
|
4122
|
-
console.log(
|
|
4121
|
+
console.log(`Starting Kenzo on ${url}`);
|
|
4122
|
+
console.log(`Data file: ${dataFile}`);
|
|
4123
|
+
if (webDistPath) {
|
|
4124
|
+
console.log(`Web UI: ${webDistPath}`);
|
|
4125
|
+
} else {
|
|
4126
|
+
console.log("Web UI: not found (API only mode)");
|
|
4127
|
+
}
|
|
4123
4128
|
}
|
|
4124
4129
|
if (options.open || flags.open === true) {
|
|
4125
|
-
|
|
4130
|
+
if (!options.compact) {
|
|
4131
|
+
console.log(`Opening ${url}`);
|
|
4132
|
+
}
|
|
4126
4133
|
openBrowser(url);
|
|
4127
4134
|
}
|
|
4128
4135
|
console.log("");
|
|
@@ -4539,20 +4546,24 @@ function ensureFluxIgnored() {
|
|
|
4539
4546
|
` : "";
|
|
4540
4547
|
appendFileSync(gitignorePath, `${newline}${gitignoreEntry}
|
|
4541
4548
|
`);
|
|
4542
|
-
|
|
4549
|
+
return true;
|
|
4543
4550
|
}
|
|
4551
|
+
return false;
|
|
4544
4552
|
}
|
|
4545
4553
|
async function ensureKenzoWorkspace() {
|
|
4546
4554
|
const fluxDir = process.env.FLUX_DIR || resolve4(process.cwd(), ".flux");
|
|
4547
4555
|
const configPath = resolve4(fluxDir, "config.json");
|
|
4548
4556
|
const jsonPath = resolve4(fluxDir, "data.json");
|
|
4549
4557
|
const sqlitePath = resolve4(fluxDir, "data.sqlite");
|
|
4558
|
+
let createdWorkspace = false;
|
|
4559
|
+
let createdProject = false;
|
|
4560
|
+
let gitignoreUpdated = false;
|
|
4550
4561
|
if (!existsSync7(fluxDir)) {
|
|
4551
4562
|
mkdirSync3(fluxDir, { recursive: true });
|
|
4552
4563
|
writeConfig(fluxDir, {});
|
|
4553
4564
|
writeFileSync5(jsonPath, JSON.stringify({ projects: [], epics: [], tasks: [] }, null, 2));
|
|
4554
|
-
ensureFluxIgnored();
|
|
4555
|
-
|
|
4565
|
+
gitignoreUpdated = ensureFluxIgnored();
|
|
4566
|
+
createdWorkspace = true;
|
|
4556
4567
|
} else if (!existsSync7(configPath)) {
|
|
4557
4568
|
writeConfig(fluxDir, {});
|
|
4558
4569
|
}
|
|
@@ -4572,7 +4583,7 @@ async function ensureKenzoWorkspace() {
|
|
|
4572
4583
|
const nextConfig = readConfigRaw(fluxDir);
|
|
4573
4584
|
nextConfig.project = project.id;
|
|
4574
4585
|
writeConfig(fluxDir, nextConfig);
|
|
4575
|
-
|
|
4586
|
+
createdProject = true;
|
|
4576
4587
|
} else if (!projectId || !projects.some((project) => project.id === projectId)) {
|
|
4577
4588
|
const project = projects[0];
|
|
4578
4589
|
projectId = project.id;
|
|
@@ -4580,29 +4591,68 @@ async function ensureKenzoWorkspace() {
|
|
|
4580
4591
|
const nextConfig = readConfigRaw(fluxDir);
|
|
4581
4592
|
nextConfig.project = project.id;
|
|
4582
4593
|
writeConfig(fluxDir, nextConfig);
|
|
4583
|
-
console.log(`Using project: ${project.name} (${project.id})`);
|
|
4584
4594
|
}
|
|
4585
|
-
return { projectId, projectName };
|
|
4595
|
+
return { fluxDir, projectId, projectName, createdWorkspace, createdProject, gitignoreUpdated };
|
|
4596
|
+
}
|
|
4597
|
+
function codexCliCommand() {
|
|
4598
|
+
if (process.env.CODEX_CLI_PATH && existsSync7(process.env.CODEX_CLI_PATH)) {
|
|
4599
|
+
return process.env.CODEX_CLI_PATH;
|
|
4600
|
+
}
|
|
4601
|
+
const macAppCli = "/Applications/Codex.app/Contents/Resources/codex";
|
|
4602
|
+
return process.platform === "darwin" && existsSync7(macAppCli) ? macAppCli : "codex";
|
|
4603
|
+
}
|
|
4604
|
+
function quoteShell(value) {
|
|
4605
|
+
return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
|
|
4606
|
+
}
|
|
4607
|
+
function mcpPackageCommand() {
|
|
4608
|
+
const localMcpPath = resolve4(process.cwd(), "packages/mcp/dist/index.js");
|
|
4609
|
+
return existsSync7(localMcpPath) ? `bun ${quoteShell(localMcpPath)}` : "npx -y --package kenzoboard kenzoboard-mcp";
|
|
4610
|
+
}
|
|
4611
|
+
function mcpPackageArgs() {
|
|
4612
|
+
const localMcpPath = resolve4(process.cwd(), "packages/mcp/dist/index.js");
|
|
4613
|
+
return existsSync7(localMcpPath) ? ["bun", localMcpPath] : ["npx", "-y", "--package", "kenzoboard", "kenzoboard-mcp"];
|
|
4614
|
+
}
|
|
4615
|
+
function codexMcpCommand(fluxDir) {
|
|
4616
|
+
return `${codexCliCommand()} mcp add flux --env FLUX_DIR=${quoteShell(fluxDir)} -- ${mcpPackageCommand()}`;
|
|
4617
|
+
}
|
|
4618
|
+
function claudeMcpCommand(fluxDir) {
|
|
4619
|
+
return `claude mcp add flux --env FLUX_DIR=${quoteShell(fluxDir)} -- ${mcpPackageCommand()}`;
|
|
4620
|
+
}
|
|
4621
|
+
function printLaunchSummary(workspace) {
|
|
4622
|
+
const projectLabel = workspace.projectName && workspace.projectId ? `${workspace.projectName} (${workspace.projectId})` : "No project selected";
|
|
4623
|
+
console.log(`${c2.green}${c2.bold}Kenzo is ready.${c2.reset}`);
|
|
4624
|
+
console.log(`Project: ${projectLabel}`);
|
|
4625
|
+
if (workspace.createdWorkspace || workspace.createdProject || workspace.gitignoreUpdated) {
|
|
4626
|
+
const details = [
|
|
4627
|
+
workspace.createdWorkspace ? "local workspace" : undefined,
|
|
4628
|
+
workspace.createdProject ? "first project" : undefined,
|
|
4629
|
+
workspace.gitignoreUpdated ? ".flux/ in .gitignore" : undefined
|
|
4630
|
+
].filter(Boolean).join(", ");
|
|
4631
|
+
console.log(`${c2.dim}Set up ${details}.${c2.reset}`);
|
|
4632
|
+
}
|
|
4633
|
+
console.log("");
|
|
4634
|
+
console.log(`${c2.bold}Connect Codex:${c2.reset}`);
|
|
4635
|
+
console.log(" npx kenzoboard connect codex");
|
|
4636
|
+
console.log("");
|
|
4637
|
+
console.log(`${c2.bold}Then ask Codex:${c2.reset}`);
|
|
4638
|
+
console.log(" Pick the next ready Kenzo task, implement it, and mark it done.");
|
|
4639
|
+
console.log("");
|
|
4640
|
+
console.log(`CLI fallback: ${c2.cyan}npx kenzoboard ready${c2.reset}`);
|
|
4641
|
+
console.log(`More setup: ${c2.cyan}npx kenzoboard mcp${c2.reset}`);
|
|
4586
4642
|
}
|
|
4587
|
-
function printMcpSetup(command = publicCommandName()) {
|
|
4588
|
-
const npxMcpCommand = "npx -y --package kenzoboard kenzoboard-mcp";
|
|
4643
|
+
function printMcpSetup(command = publicCommandName(), fluxDir = findFluxDir()) {
|
|
4589
4644
|
const installedMcpCommand = "kenzoboard-mcp";
|
|
4590
4645
|
const dockerCommand = 'docker run -i --rm -v "$(pwd)/.flux:/app/packages/data" -e FLUX_DATA=/app/packages/data/flux.sqlite flux-mcp bun packages/mcp/dist/index.js';
|
|
4591
|
-
|
|
4592
|
-
console.log(`${c2.
|
|
4646
|
+
console.log(`${c2.bold}Agent setup${c2.reset} ${c2.dim}(MCP resources remain flux:// for compatibility)${c2.reset}`);
|
|
4647
|
+
console.log(`${c2.dim}Using Kenzo workspace: ${fluxDir}${c2.reset}
|
|
4593
4648
|
`);
|
|
4649
|
+
console.log(`${c2.bold}Codex one-step setup:${c2.reset}`);
|
|
4650
|
+
console.log(" npx kenzoboard connect codex");
|
|
4651
|
+
console.log("");
|
|
4594
4652
|
console.log(`${c2.bold}Codex:${c2.reset}`);
|
|
4595
|
-
|
|
4596
|
-
console.log(` codex mcp add flux -- bun ${localMcpPath}`);
|
|
4597
|
-
} else {
|
|
4598
|
-
console.log(` codex mcp add flux -- ${npxMcpCommand}`);
|
|
4599
|
-
}
|
|
4653
|
+
console.log(` ${codexMcpCommand(fluxDir)}`);
|
|
4600
4654
|
console.log(`${c2.bold}Claude Code:${c2.reset}`);
|
|
4601
|
-
|
|
4602
|
-
console.log(` claude mcp add flux -- bun ${localMcpPath}`);
|
|
4603
|
-
} else {
|
|
4604
|
-
console.log(` claude mcp add flux -- ${npxMcpCommand}`);
|
|
4605
|
-
}
|
|
4655
|
+
console.log(` ${claudeMcpCommand(fluxDir)}`);
|
|
4606
4656
|
console.log("");
|
|
4607
4657
|
console.log(`${c2.bold}Global install:${c2.reset}`);
|
|
4608
4658
|
console.log(` ${installedMcpCommand}`);
|
|
@@ -4610,18 +4660,93 @@ function printMcpSetup(command = publicCommandName()) {
|
|
|
4610
4660
|
console.log(`${c2.bold}Advanced Docker:${c2.reset}`);
|
|
4611
4661
|
console.log(` ${dockerCommand}`);
|
|
4612
4662
|
console.log("");
|
|
4613
|
-
console.log(
|
|
4663
|
+
console.log(`${c2.bold}Agent workflow:${c2.reset}`);
|
|
4664
|
+
console.log(` 1. Run ${c2.cyan}${command} ready${c2.reset} or ask the MCP server for ready tasks.`);
|
|
4665
|
+
console.log(" 2. Start one task, implement it, add notes as needed, then mark it done.");
|
|
4666
|
+
console.log(" 3. If MCP is not connected yet, Codex can still use the CLI commands from AGENTS.md.");
|
|
4614
4667
|
}
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4668
|
+
function codexCliLooksValid(command) {
|
|
4669
|
+
try {
|
|
4670
|
+
const output2 = execFileSync(command, ["mcp", "--help"], {
|
|
4671
|
+
encoding: "utf-8",
|
|
4672
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
4673
|
+
});
|
|
4674
|
+
return output2.includes("Manage external MCP servers for Codex");
|
|
4675
|
+
} catch {
|
|
4676
|
+
return false;
|
|
4677
|
+
}
|
|
4678
|
+
}
|
|
4679
|
+
function resolveCodexCli() {
|
|
4680
|
+
const candidates = [
|
|
4681
|
+
process.env.CODEX_CLI_PATH,
|
|
4682
|
+
process.platform === "darwin" ? "/Applications/Codex.app/Contents/Resources/codex" : undefined,
|
|
4683
|
+
"codex"
|
|
4684
|
+
].filter((candidate) => Boolean(candidate));
|
|
4685
|
+
for (const candidate of candidates) {
|
|
4686
|
+
if (candidate.includes("/") && !existsSync7(candidate))
|
|
4687
|
+
continue;
|
|
4688
|
+
if (codexCliLooksValid(candidate))
|
|
4689
|
+
return candidate;
|
|
4690
|
+
}
|
|
4691
|
+
return null;
|
|
4692
|
+
}
|
|
4693
|
+
function runCodex(cli, args) {
|
|
4694
|
+
return execFileSync(cli, args, {
|
|
4695
|
+
encoding: "utf-8",
|
|
4696
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
4697
|
+
});
|
|
4698
|
+
}
|
|
4699
|
+
async function connectCodexCommand(flags) {
|
|
4700
|
+
const workspace = await ensureKenzoWorkspace();
|
|
4701
|
+
const cli = resolveCodexCli();
|
|
4702
|
+
if (!cli) {
|
|
4703
|
+
console.error("OpenAI Codex CLI was not found.");
|
|
4704
|
+
console.error("Install or open Codex Desktop, then run this again.");
|
|
4705
|
+
console.error("");
|
|
4706
|
+
console.error("Manual command:");
|
|
4707
|
+
console.error(` ${codexMcpCommand(workspace.fluxDir)}`);
|
|
4708
|
+
process.exit(1);
|
|
4709
|
+
}
|
|
4710
|
+
const serverName = typeof flags.name === "string" ? flags.name : "flux";
|
|
4711
|
+
const packageArgs = mcpPackageArgs();
|
|
4712
|
+
const addArgs = [
|
|
4713
|
+
"mcp",
|
|
4714
|
+
"add",
|
|
4715
|
+
serverName,
|
|
4716
|
+
"--env",
|
|
4717
|
+
`FLUX_DIR=${workspace.fluxDir}`,
|
|
4718
|
+
"--",
|
|
4719
|
+
...packageArgs
|
|
4720
|
+
];
|
|
4721
|
+
try {
|
|
4722
|
+
runCodex(cli, ["mcp", "get", serverName]);
|
|
4723
|
+
runCodex(cli, ["mcp", "remove", serverName]);
|
|
4724
|
+
} catch {}
|
|
4725
|
+
try {
|
|
4726
|
+
runCodex(cli, addArgs);
|
|
4727
|
+
const result = runCodex(cli, ["mcp", "get", serverName]);
|
|
4728
|
+
if (!result.includes(serverName) || !result.includes(packageArgs[0])) {
|
|
4729
|
+
throw new Error("Codex did not report the expected MCP server after setup.");
|
|
4730
|
+
}
|
|
4731
|
+
console.log(`${c2.green}${c2.bold}Codex is connected to Kenzo.${c2.reset}`);
|
|
4732
|
+
console.log(`Server: ${serverName}`);
|
|
4733
|
+
console.log(`Workspace: ${workspace.fluxDir}`);
|
|
4734
|
+
console.log("");
|
|
4735
|
+
console.log(`${c2.bold}Try this in Codex:${c2.reset}`);
|
|
4736
|
+
console.log(" Use Kenzo to pick the next ready task, implement it, and mark it done.");
|
|
4737
|
+
} catch (e) {
|
|
4738
|
+
console.error("Failed to configure Codex MCP.");
|
|
4739
|
+
console.error(e?.message || String(e));
|
|
4740
|
+
console.error("");
|
|
4741
|
+
console.error("Manual command:");
|
|
4742
|
+
console.error(` ${codexMcpCommand(workspace.fluxDir)}`);
|
|
4743
|
+
process.exit(1);
|
|
4620
4744
|
}
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4745
|
+
}
|
|
4746
|
+
async function launchKenzoApp() {
|
|
4747
|
+
const workspace = await ensureKenzoWorkspace();
|
|
4748
|
+
printLaunchSummary(workspace);
|
|
4749
|
+
await serveCommand([], { port: String(defaultServePort()) }, { defaultPort: defaultServePort(), open: true, compact: true });
|
|
4625
4750
|
}
|
|
4626
4751
|
var FLUX_INSTRUCTIONS = `<!-- FLUX:START -->
|
|
4627
4752
|
## Flux Task Management
|
|
@@ -5183,6 +5308,14 @@ Select a project:`);
|
|
|
5183
5308
|
printMcpSetup();
|
|
5184
5309
|
return;
|
|
5185
5310
|
}
|
|
5311
|
+
if (parsed.command === "connect") {
|
|
5312
|
+
if (parsed.subcommand === "codex") {
|
|
5313
|
+
await connectCodexCommand(parsed.flags);
|
|
5314
|
+
return;
|
|
5315
|
+
}
|
|
5316
|
+
console.error(`Usage: ${publicCommandName()} connect codex [--name flux]`);
|
|
5317
|
+
process.exit(1);
|
|
5318
|
+
}
|
|
5186
5319
|
if (parsed.command === "dev") {
|
|
5187
5320
|
await launchKenzoApp();
|
|
5188
5321
|
return;
|
|
@@ -5294,6 +5427,7 @@ ${c2.bold}Start:${c2.reset}
|
|
|
5294
5427
|
${c2.cyan}${command} init${c2.reset} ${c2.green}[--server URL] [--api-key KEY] [--sqlite] [--git] [--force]${c2.reset}
|
|
5295
5428
|
${c2.cyan}${command} dev${c2.reset} ${c2.green}[--open]${c2.reset} Start the local Kenzo app on port ${defaultServePort()}
|
|
5296
5429
|
${c2.cyan}${command} serve${c2.reset} ${c2.green}[-p port] [--data file] [--open]${c2.reset}
|
|
5430
|
+
${c2.cyan}${command} connect codex${c2.reset} ${c2.green}[--name flux]${c2.reset} Configure Codex MCP for this workspace
|
|
5297
5431
|
${c2.cyan}${command} mcp${c2.reset} Show Codex/Claude MCP setup commands
|
|
5298
5432
|
|
|
5299
5433
|
${c2.bold}Ready Work:${c2.reset}
|
package/dist/mcp.js
CHANGED
|
@@ -15119,6 +15119,11 @@ var server = new Server({
|
|
|
15119
15119
|
tools: {}
|
|
15120
15120
|
}
|
|
15121
15121
|
});
|
|
15122
|
+
function jsonContent(value) {
|
|
15123
|
+
return {
|
|
15124
|
+
content: [{ type: "text", text: JSON.stringify(value, null, 2) }]
|
|
15125
|
+
};
|
|
15126
|
+
}
|
|
15122
15127
|
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
15123
15128
|
const projects = await getProjects2();
|
|
15124
15129
|
const resources = [
|
|
@@ -15621,11 +15626,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
15621
15626
|
}
|
|
15622
15627
|
case "create_project": {
|
|
15623
15628
|
const project = await createProject2(args2?.name, args2?.description);
|
|
15624
|
-
return {
|
|
15625
|
-
content: [
|
|
15626
|
-
{ type: "text", text: `Created project "${project.name}" with ID: ${project.id}` }
|
|
15627
|
-
]
|
|
15628
|
-
};
|
|
15629
|
+
return jsonContent({ action: "created_project", project });
|
|
15629
15630
|
}
|
|
15630
15631
|
case "update_project": {
|
|
15631
15632
|
const updates = {};
|
|
@@ -15637,15 +15638,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
15637
15638
|
if (!project) {
|
|
15638
15639
|
return { content: [{ type: "text", text: "Project not found" }], isError: true };
|
|
15639
15640
|
}
|
|
15640
|
-
return {
|
|
15641
|
-
content: [{ type: "text", text: `Updated project: ${JSON.stringify(project, null, 2)}` }]
|
|
15642
|
-
};
|
|
15641
|
+
return jsonContent({ action: "updated_project", project });
|
|
15643
15642
|
}
|
|
15644
15643
|
case "delete_project": {
|
|
15645
|
-
await deleteProject2(args2?.project_id);
|
|
15646
|
-
return {
|
|
15647
|
-
content: [{ type: "text", text: `Deleted project ${args2?.project_id}` }]
|
|
15648
|
-
};
|
|
15644
|
+
const deleted = await deleteProject2(args2?.project_id);
|
|
15645
|
+
return jsonContent({ action: "deleted_project", project_id: args2?.project_id, deleted });
|
|
15649
15646
|
}
|
|
15650
15647
|
case "list_epics": {
|
|
15651
15648
|
const epics = await getEpics2(args2?.project_id);
|
|
@@ -15655,9 +15652,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
15655
15652
|
}
|
|
15656
15653
|
case "create_epic": {
|
|
15657
15654
|
const epic = await createEpic2(args2?.project_id, args2?.title, args2?.notes, args2?.auto);
|
|
15658
|
-
return {
|
|
15659
|
-
content: [{ type: "text", text: `Created epic "${epic.title}" with ID: ${epic.id}` }]
|
|
15660
|
-
};
|
|
15655
|
+
return jsonContent({ action: "created_epic", epic });
|
|
15661
15656
|
}
|
|
15662
15657
|
case "update_epic": {
|
|
15663
15658
|
const updates = {};
|
|
@@ -15675,18 +15670,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
15675
15670
|
if (!epic) {
|
|
15676
15671
|
return { content: [{ type: "text", text: "Epic not found" }], isError: true };
|
|
15677
15672
|
}
|
|
15678
|
-
return {
|
|
15679
|
-
content: [{ type: "text", text: `Updated epic: ${JSON.stringify(epic, null, 2)}` }]
|
|
15680
|
-
};
|
|
15673
|
+
return jsonContent({ action: "updated_epic", epic });
|
|
15681
15674
|
}
|
|
15682
15675
|
case "delete_epic": {
|
|
15683
15676
|
const success = await deleteEpic2(args2?.epic_id);
|
|
15684
15677
|
if (!success) {
|
|
15685
15678
|
return { content: [{ type: "text", text: "Epic not found" }], isError: true };
|
|
15686
15679
|
}
|
|
15687
|
-
return {
|
|
15688
|
-
content: [{ type: "text", text: `Deleted epic ${args2?.epic_id}` }]
|
|
15689
|
-
};
|
|
15680
|
+
return jsonContent({ action: "deleted_epic", epic_id: args2?.epic_id, deleted: true });
|
|
15690
15681
|
}
|
|
15691
15682
|
case "list_tasks": {
|
|
15692
15683
|
const taskList = await getTasks2(args2?.project_id);
|
|
@@ -15715,9 +15706,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
15715
15706
|
acceptance_criteria: args2?.acceptance_criteria,
|
|
15716
15707
|
guardrails: args2?.guardrails
|
|
15717
15708
|
});
|
|
15718
|
-
return {
|
|
15719
|
-
content: [{ type: "text", text: `Created task "${task.title}" with ID: ${task.id}` }]
|
|
15720
|
-
};
|
|
15709
|
+
return jsonContent({ action: "created_task", task });
|
|
15721
15710
|
}
|
|
15722
15711
|
case "update_task": {
|
|
15723
15712
|
if (args2?.status === "in_progress") {
|
|
@@ -15759,23 +15748,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
15759
15748
|
if (!task) {
|
|
15760
15749
|
return { content: [{ type: "text", text: "Task not found" }], isError: true };
|
|
15761
15750
|
}
|
|
15762
|
-
return {
|
|
15763
|
-
content: [
|
|
15764
|
-
{
|
|
15765
|
-
type: "text",
|
|
15766
|
-
text: `Updated task: ${JSON.stringify({ ...task, blocked: await isTaskBlocked2(task.id) }, null, 2)}`
|
|
15767
|
-
}
|
|
15768
|
-
]
|
|
15769
|
-
};
|
|
15751
|
+
return jsonContent({ action: "updated_task", task: { ...task, blocked: await isTaskBlocked2(task.id) } });
|
|
15770
15752
|
}
|
|
15771
15753
|
case "delete_task": {
|
|
15772
15754
|
const success = await deleteTask2(args2?.task_id);
|
|
15773
15755
|
if (!success) {
|
|
15774
15756
|
return { content: [{ type: "text", text: "Task not found" }], isError: true };
|
|
15775
15757
|
}
|
|
15776
|
-
return {
|
|
15777
|
-
content: [{ type: "text", text: `Deleted task ${args2?.task_id}` }]
|
|
15778
|
-
};
|
|
15758
|
+
return jsonContent({ action: "deleted_task", task_id: args2?.task_id, deleted: true });
|
|
15779
15759
|
}
|
|
15780
15760
|
case "move_task_status": {
|
|
15781
15761
|
if (args2?.status === "in_progress") {
|
|
@@ -15802,11 +15782,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
15802
15782
|
if (!task) {
|
|
15803
15783
|
return { content: [{ type: "text", text: "Task not found" }], isError: true };
|
|
15804
15784
|
}
|
|
15805
|
-
return {
|
|
15806
|
-
content: [
|
|
15807
|
-
{ type: "text", text: `Moved task "${task.title}" to ${args2?.status}` }
|
|
15808
|
-
]
|
|
15809
|
-
};
|
|
15785
|
+
return jsonContent({ action: "moved_task_status", task });
|
|
15810
15786
|
}
|
|
15811
15787
|
case "add_task_comment": {
|
|
15812
15788
|
const body = args2?.body?.trim();
|
|
@@ -15819,18 +15795,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
15819
15795
|
if (!comment) {
|
|
15820
15796
|
return { content: [{ type: "text", text: "Task not found" }], isError: true };
|
|
15821
15797
|
}
|
|
15822
|
-
return {
|
|
15823
|
-
content: [{ type: "text", text: `Added comment ${comment.id}` }]
|
|
15824
|
-
};
|
|
15798
|
+
return jsonContent({ action: "added_task_comment", comment });
|
|
15825
15799
|
}
|
|
15826
15800
|
case "delete_task_comment": {
|
|
15827
15801
|
const success = await deleteTaskComment2(args2?.task_id, args2?.comment_id);
|
|
15828
15802
|
if (!success) {
|
|
15829
15803
|
return { content: [{ type: "text", text: "Comment not found" }], isError: true };
|
|
15830
15804
|
}
|
|
15831
|
-
return {
|
|
15832
|
-
content: [{ type: "text", text: `Deleted comment ${args2?.comment_id}` }]
|
|
15833
|
-
};
|
|
15805
|
+
return jsonContent({ action: "deleted_task_comment", task_id: args2?.task_id, comment_id: args2?.comment_id, deleted: true });
|
|
15834
15806
|
}
|
|
15835
15807
|
case "list_webhooks": {
|
|
15836
15808
|
const webhooks = await getWebhooks2();
|
|
@@ -15843,11 +15815,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
15843
15815
|
secret: args2?.secret,
|
|
15844
15816
|
project_id: args2?.project_id
|
|
15845
15817
|
});
|
|
15846
|
-
return {
|
|
15847
|
-
content: [
|
|
15848
|
-
{ type: "text", text: `Created webhook "${webhook.name}" with ID: ${webhook.id}` }
|
|
15849
|
-
]
|
|
15850
|
-
};
|
|
15818
|
+
return jsonContent({ action: "created_webhook", webhook });
|
|
15851
15819
|
}
|
|
15852
15820
|
case "update_webhook": {
|
|
15853
15821
|
const updates = {};
|
|
@@ -15867,18 +15835,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
15867
15835
|
if (!webhook) {
|
|
15868
15836
|
return { content: [{ type: "text", text: "Webhook not found" }], isError: true };
|
|
15869
15837
|
}
|
|
15870
|
-
return {
|
|
15871
|
-
content: [{ type: "text", text: `Updated webhook: ${JSON.stringify(webhook, null, 2)}` }]
|
|
15872
|
-
};
|
|
15838
|
+
return jsonContent({ action: "updated_webhook", webhook });
|
|
15873
15839
|
}
|
|
15874
15840
|
case "delete_webhook": {
|
|
15875
15841
|
const success = await deleteWebhook2(args2?.webhook_id);
|
|
15876
15842
|
if (!success) {
|
|
15877
15843
|
return { content: [{ type: "text", text: "Webhook not found" }], isError: true };
|
|
15878
15844
|
}
|
|
15879
|
-
return {
|
|
15880
|
-
content: [{ type: "text", text: `Deleted webhook ${args2?.webhook_id}` }]
|
|
15881
|
-
};
|
|
15845
|
+
return jsonContent({ action: "deleted_webhook", webhook_id: args2?.webhook_id, deleted: true });
|
|
15882
15846
|
}
|
|
15883
15847
|
case "list_webhook_deliveries": {
|
|
15884
15848
|
const limit = args2?.limit || 20;
|