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.
Files changed (3) hide show
  1. package/dist/index.js +171 -37
  2. package/dist/mcp.js +21 -57
  3. 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
- console.log(`Starting Kenzo on ${url}`);
4118
- console.log(`Data file: ${dataFile}`);
4119
- if (webDistPath) {
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("Web UI: not found (API only mode)");
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
- console.log(`Opening ${url}`);
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
- console.log(`Added .flux/ to ${gitRoot ? gitignorePath : ".gitignore"}`);
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
- console.log(`Created local Kenzo workspace at ${fluxDir}`);
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
- console.log(`Created first project: ${project.name} (${project.id})`);
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
- const localMcpPath = resolve4(process.cwd(), "packages/mcp/dist/index.js");
4592
- console.log(`${c2.bold}Agent setup${c2.reset} ${c2.dim}(MCP resources remain flux:// for compatibility)${c2.reset}
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
- if (existsSync7(localMcpPath)) {
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
- if (existsSync7(localMcpPath)) {
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(`Run ${c2.cyan}${command} ready${c2.reset} to see agent-ready work.`);
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
- async function launchKenzoApp() {
4616
- const command = publicCommandName();
4617
- const { projectId, projectName } = await ensureKenzoWorkspace();
4618
- if (projectId && projectName) {
4619
- console.log(`Opening project: ${projectName} (${projectId})`);
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
- console.log("");
4622
- console.log(`${c2.bold}Next step after Kenzo opens:${c2.reset}`);
4623
- printMcpSetup(command);
4624
- await serveCommand([], { port: String(defaultServePort()) }, { defaultPort: defaultServePort(), open: true });
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kenzoboard",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Kenzo board for human-led AI work, powered by the Flux engine",
5
5
  "type": "module",
6
6
  "bin": {