@mycompbox/compbox-mcp 1.21.3 → 1.21.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +179 -114
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -130,7 +130,7 @@ var init_mailbox = __esm({
130
130
  "failed"
131
131
  ];
132
132
  TURN_ROLES = ["agent", "user"];
133
- START_EXECUTION_KINDS = ["plan", "orchestrate"];
133
+ START_EXECUTION_KINDS = ["plan", "orchestrate", "refine"];
134
134
  }
135
135
  });
136
136
 
@@ -863,6 +863,18 @@ var init_interview_completion = __esm({
863
863
  });
864
864
 
865
865
  // ../shared/dist/interview-conversation.js
866
+ function requestLockReason(saved) {
867
+ if (!saved)
868
+ return null;
869
+ if (saved.status !== "pending")
870
+ return "status";
871
+ if (!saved.canEdit)
872
+ return "ownership";
873
+ return null;
874
+ }
875
+ function lockedRequestMessage(reason) {
876
+ return reason === "ownership" ? "Only the request's creator can change it; you can still discuss it." : "This request is locked, so it can't be changed any more.";
877
+ }
866
878
  function renderSection(s) {
867
879
  const tag = s.required ? "needed" : "nice to have";
868
880
  return `- ${s.title} (${tag}): ${s.purpose} For example: ${s.followUps.slice(0, 2).join(" ")}`;
@@ -873,8 +885,10 @@ function renderSaved(saved) {
873
885
  const issues = saved.compliance && saved.compliance.issues.length > 0 ? `
874
886
  What the score says is missing or weak:
875
887
  ${saved.compliance.issues.slice(0, 8).map((i) => `- ${i.message}`).join("\n")}` : "";
876
- const locked = saved.status === "pending" ? "It can still be changed." : `Its status is "${saved.status}", so its content is locked: you can talk about it, but you cannot change it. Never emit the completion JSON for a locked request.`;
877
- return `THE REQUEST IS ALREADY SAVED. This conversation created the request "${saved.title}". ${score} ${locked}${issues}
888
+ const reason = requestLockReason(saved);
889
+ const locked = reason === null ? "It can still be changed." : reason === "status" ? `Its status is "${saved.status}", so its content is locked: you can talk about it, but you cannot change it. Never emit the completion JSON for a locked request.` : "Only the request's creator can change it, and the person you're talking to is not its creator, so its content is locked for them: you can talk about it, but you cannot change it. Never emit the completion JSON for a locked request. If they ask for a change, explain that only the creator can make it.";
890
+ const origin = saved.discussed ? `THE REQUEST ALREADY EXISTS. The person is discussing the existing request "${saved.title}"; this conversation did not create it.` : `THE REQUEST IS ALREADY SAVED. This conversation created the request "${saved.title}".`;
891
+ return `${origin} ${score} ${locked}${issues}
878
892
 
879
893
  Its current content:
880
894
  title: ${saved.title}
@@ -950,7 +964,7 @@ ${followUp}` : text;
950
964
  async function runConversationStep(input, deps) {
951
965
  const system = buildConversationSystemPrompt(input.saved);
952
966
  const messages = toConversationMessages(input.turns);
953
- const locked = input.saved !== null && input.saved.status !== "pending";
967
+ const lockReason = requestLockReason(input.saved);
954
968
  let requestId = input.saved?.id ?? null;
955
969
  let savedNow = null;
956
970
  let createdHere = false;
@@ -973,10 +987,11 @@ Send another message (for example "try again") when you're ready and I'll pick u
973
987
  }
974
988
  const draft = extractCompletionJson(reply);
975
989
  if (draft) {
976
- if (locked) {
977
- messages.push({ role: "assistant", content: reply }, { role: "user", content: "That request is locked and can't be changed. Reply to me in plain text instead." });
990
+ if (lockReason) {
991
+ const why = lockReason === "ownership" ? "Only the request's creator can change it, and I'm not its creator." : "That request is locked and can't be changed.";
992
+ messages.push({ role: "assistant", content: reply }, { role: "user", content: `${why} Reply to me in plain text instead.` });
978
993
  if (++repairs > JSON_REPAIRS)
979
- return { kind: "error", text: "This request is locked, so it can't be changed any more." };
994
+ return { kind: "error", text: lockedRequestMessage(lockReason) };
980
995
  continue;
981
996
  }
982
997
  let saved;
@@ -1019,7 +1034,7 @@ The request IS already saved, and the person will be shown its score. If you ask
1019
1034
  return { kind: "message", text };
1020
1035
  }
1021
1036
  }
1022
- function savedContextFromRecord(record) {
1037
+ function savedContextFromRecord(record, access) {
1023
1038
  if (typeof record !== "object" || record === null)
1024
1039
  return null;
1025
1040
  const r = record;
@@ -1054,7 +1069,9 @@ function savedContextFromRecord(record) {
1054
1069
  status: typeof r.status === "string" ? r.status : "pending",
1055
1070
  description: typeof r.description === "string" ? r.description : "",
1056
1071
  fields,
1057
- compliance: complianceFromRecord(score)
1072
+ compliance: complianceFromRecord(score),
1073
+ canEdit: access.canEdit,
1074
+ ...access.discussed ? { discussed: true } : {}
1058
1075
  };
1059
1076
  }
1060
1077
  function complianceFromRecord(score) {
@@ -2048,6 +2065,7 @@ __export(dist_exports, {
2048
2065
  isSubscriptionStatus: () => isSubscriptionStatus,
2049
2066
  isTurnRole: () => isTurnRole,
2050
2067
  isValidModelId: () => isValidModelId,
2068
+ lockedRequestMessage: () => lockedRequestMessage,
2051
2069
  looksLikeCompletionAttempt: () => looksLikeCompletionAttempt,
2052
2070
  mcpConfigSchema: () => mcpConfigSchema,
2053
2071
  mcpServerConfigSchema: () => mcpServerConfigSchema,
@@ -2057,6 +2075,7 @@ __export(dist_exports, {
2057
2075
  ok: () => ok,
2058
2076
  probeProxyHealth: () => probeProxyHealth,
2059
2077
  renderConversationPrompt: () => renderConversationPrompt,
2078
+ requestLockReason: () => requestLockReason,
2060
2079
  resolveRouting: () => resolveRouting,
2061
2080
  runConversationStep: () => runConversationStep,
2062
2081
  safeReturnTo: () => safeReturnTo,
@@ -2927,6 +2946,14 @@ var ApiClient = class {
2927
2946
  throw error;
2928
2947
  }
2929
2948
  }
2949
+ /**
2950
+ * The cloud a project deploys to: its own choice, or the organization's
2951
+ * default (veena-gcp style). `cloudConnectionId: null` on a team does NOT mean
2952
+ * "no cloud" — it means "follows the org default"; this resolves it.
2953
+ */
2954
+ async getProjectCloud(teamId) {
2955
+ return this.request("GET", `/api/v1/teams/${encodeURIComponent(teamId)}/cloud`);
2956
+ }
2930
2957
  // ---------------------------------------------------------------------------
2931
2958
  // Personal Scope Methods
2932
2959
  // ---------------------------------------------------------------------------
@@ -10487,6 +10514,7 @@ function isUuid(value) {
10487
10514
  }
10488
10515
 
10489
10516
  // src/tools/teams.ts
10517
+ import { z as z20 } from "zod";
10490
10518
  function registerTeamTools(server2) {
10491
10519
  server2.registerTool(
10492
10520
  "compbox__list_teams",
@@ -10516,22 +10544,59 @@ function registerTeamTools(server2) {
10516
10544
  }
10517
10545
  }
10518
10546
  );
10547
+ server2.registerTool(
10548
+ "compbox__get_project_cloud",
10549
+ {
10550
+ description: "Get the cloud a project (team) deploys to: provider (gcp/aws/azure), cloud project or account ID, region and deploy identity, and whether it is the project's own choice or the organization's default. A team's cloudConnectionId of null means it FOLLOWS THE ORG DEFAULT, not that it has no cloud; always call this before planning hosting, databases or deployment. Returns cloud: null only when the organization has no cloud connected.",
10551
+ inputSchema: {
10552
+ team: z20.string().min(1).describe("The project/team: UUID, name or key (e.g. 'SAISUD').")
10553
+ }
10554
+ },
10555
+ async (input) => {
10556
+ try {
10557
+ const apiClient = getApiClient();
10558
+ const found = await apiClient.getTeam(input.team);
10559
+ if (!found) {
10560
+ return createErrorResponse(new Error(`Team '${input.team}' not found`));
10561
+ }
10562
+ const { data } = await apiClient.getProjectCloud(found.data.id);
10563
+ const cloud = data.cloud;
10564
+ return createResponse({
10565
+ team: { id: found.data.id, name: found.data.name, key: found.data.key },
10566
+ hasCloud: cloud !== null,
10567
+ source: cloud === null ? "none" : data.isInherited ? "organization-default" : "project-choice",
10568
+ cloud: cloud && {
10569
+ name: cloud.name,
10570
+ provider: cloud.provider,
10571
+ projectId: cloud.projectId,
10572
+ region: cloud.region,
10573
+ serviceAccountEmail: cloud.serviceAccountEmail,
10574
+ stateStore: cloud.stateStore,
10575
+ consoleUrl: cloud.consoleUrl
10576
+ },
10577
+ guidance: cloud === null ? "No cloud is connected. An organization admin can connect one in Settings -> Cloud; until then don't assume a hosting provider." : `Plan hosting, databases and storage on ${cloud.provider.toUpperCase()} (${cloud.projectId}, ${cloud.region}). CompBox stacks deploy through GitHub Actions with keyless sign-in, so never plan stored cloud keys.`
10578
+ });
10579
+ } catch (error) {
10580
+ return createErrorResponse(error);
10581
+ }
10582
+ }
10583
+ );
10519
10584
  }
10520
10585
 
10521
10586
  // src/tools/team-hierarchy.ts
10522
- import { z as z20 } from "zod";
10587
+ import { z as z21 } from "zod";
10523
10588
  var createTeamChildSchema = {
10524
- parentId: z20.string().uuid().describe("The UUID of the parent team that will own the new child team."),
10525
- name: z20.string().min(1).max(255).describe("Display name for the child team."),
10526
- key: z20.string().min(1).max(10).regex(/^[A-Z][A-Z0-9-]*$/).describe("Unique team key for the child team. Must start with an uppercase letter and contain only uppercase letters, digits, or hyphens."),
10527
- level: z20.enum(["group", "product-line", "product", "discipline"]).describe("Hierarchy level for the child team (required).")
10589
+ parentId: z21.string().uuid().describe("The UUID of the parent team that will own the new child team."),
10590
+ name: z21.string().min(1).max(255).describe("Display name for the child team."),
10591
+ key: z21.string().min(1).max(10).regex(/^[A-Z][A-Z0-9-]*$/).describe("Unique team key for the child team. Must start with an uppercase letter and contain only uppercase letters, digits, or hyphens."),
10592
+ level: z21.enum(["group", "product-line", "product", "discipline"]).describe("Hierarchy level for the child team (required).")
10528
10593
  };
10529
10594
  var getTeamPathSchema = {
10530
- teamId: z20.string().uuid().describe("The UUID of the team whose ordered ancestor path should be returned.")
10595
+ teamId: z21.string().uuid().describe("The UUID of the team whose ordered ancestor path should be returned.")
10531
10596
  };
10532
10597
  var moveTeamSchema = {
10533
- teamId: z20.string().uuid().describe("The UUID of the team to move within the hierarchy."),
10534
- newParentId: z20.string().uuid().nullable().describe("The UUID of the new parent team. Pass null to move the team to the root level.")
10598
+ teamId: z21.string().uuid().describe("The UUID of the team to move within the hierarchy."),
10599
+ newParentId: z21.string().uuid().nullable().describe("The UUID of the new parent team. Pass null to move the team to the root level.")
10535
10600
  };
10536
10601
  function registerTeamHierarchyTools(server2) {
10537
10602
  server2.registerTool(
@@ -10631,7 +10696,7 @@ function registerTeamHierarchyTools(server2) {
10631
10696
 
10632
10697
  // src/tools/composite.ts
10633
10698
  init_dist();
10634
- import { z as z21 } from "zod";
10699
+ import { z as z22 } from "zod";
10635
10700
  var COMPOSITE_TIMEOUT_MS = 12e4;
10636
10701
  function withTimeout(promise, ms, operationName) {
10637
10702
  return new Promise((resolve, reject) => {
@@ -10657,41 +10722,41 @@ function withTimeout(promise, ms, operationName) {
10657
10722
  var estimatedComplexityValues = ["trivial", "simple", "moderate", "complex"];
10658
10723
  var estimatedEffortValues = ["trivial", "small", "medium", "large", "xl"];
10659
10724
  var riskLevelValues = ["low", "medium", "high"];
10660
- var externalLinkSchema = z21.object({
10661
- url: z21.string().describe("URL of the external resource"),
10662
- title: z21.string().describe("Display title for the link")
10725
+ var externalLinkSchema = z22.object({
10726
+ url: z22.string().describe("URL of the external resource"),
10727
+ title: z22.string().describe("Display title for the link")
10663
10728
  });
10664
- var structuredDescSchema = z21.object({
10665
- summary: z21.string().describe("Brief human-readable summary (required)"),
10666
- aiInstructions: z21.string().optional().describe("Specific instructions for AI agents implementing this item"),
10667
- acceptanceCriteria: z21.array(z21.string()).optional().describe("List of acceptance criteria that must be met"),
10668
- filesInvolved: z21.array(z21.string()).optional().describe("File paths that will be involved in this work"),
10669
- functionsToModify: z21.array(z21.string()).optional().describe("Functions to modify in format 'filePath:functionName'"),
10670
- testingStrategy: z21.string().optional().describe("Description of how this work should be tested"),
10671
- testFiles: z21.array(z21.string()).optional().describe("Test file paths"),
10672
- relatedItemIds: z21.array(z21.string()).optional().describe("Related feature or task identifiers"),
10673
- externalLinks: z21.array(externalLinkSchema).optional().describe("External documentation or reference links"),
10674
- technicalNotes: z21.string().optional().describe("Technical implementation notes or constraints"),
10675
- riskLevel: z21.enum(riskLevelValues).optional().describe("Risk level assessment: low, medium, or high"),
10676
- estimatedEffort: z21.enum(estimatedEffortValues).optional().describe("Effort estimate: trivial, small, medium, large, or xl")
10729
+ var structuredDescSchema = z22.object({
10730
+ summary: z22.string().describe("Brief human-readable summary (required)"),
10731
+ aiInstructions: z22.string().optional().describe("Specific instructions for AI agents implementing this item"),
10732
+ acceptanceCriteria: z22.array(z22.string()).optional().describe("List of acceptance criteria that must be met"),
10733
+ filesInvolved: z22.array(z22.string()).optional().describe("File paths that will be involved in this work"),
10734
+ functionsToModify: z22.array(z22.string()).optional().describe("Functions to modify in format 'filePath:functionName'"),
10735
+ testingStrategy: z22.string().optional().describe("Description of how this work should be tested"),
10736
+ testFiles: z22.array(z22.string()).optional().describe("Test file paths"),
10737
+ relatedItemIds: z22.array(z22.string()).optional().describe("Related feature or task identifiers"),
10738
+ externalLinks: z22.array(externalLinkSchema).optional().describe("External documentation or reference links"),
10739
+ technicalNotes: z22.string().optional().describe("Technical implementation notes or constraints"),
10740
+ riskLevel: z22.enum(riskLevelValues).optional().describe("Risk level assessment: low, medium, or high"),
10741
+ estimatedEffort: z22.enum(estimatedEffortValues).optional().describe("Effort estimate: trivial, small, medium, large, or xl")
10677
10742
  });
10678
- var compositeTaskSchema = z21.object({
10679
- title: z21.string().min(1).max(500).describe("Task title (required)"),
10680
- executionOrder: z21.number().int().positive().optional().describe("Execution order within the feature (1, 2, 3...). Lower numbers first."),
10681
- estimatedComplexity: z21.enum(estimatedComplexityValues).optional().describe("Complexity: trivial (<1hr), simple (1-4hr), moderate (1-3d), complex (>3d)"),
10743
+ var compositeTaskSchema = z22.object({
10744
+ title: z22.string().min(1).max(500).describe("Task title (required)"),
10745
+ executionOrder: z22.number().int().positive().optional().describe("Execution order within the feature (1, 2, 3...). Lower numbers first."),
10746
+ estimatedComplexity: z22.enum(estimatedComplexityValues).optional().describe("Complexity: trivial (<1hr), simple (1-4hr), moderate (1-3d), complex (>3d)"),
10682
10747
  structuredDesc: structuredDescSchema.optional().describe("Structured description with summary, aiInstructions, acceptanceCriteria, etc.")
10683
10748
  });
10684
- var compositeFeatureSchema = z21.object({
10685
- title: z21.string().min(1).max(500).describe("Feature title (required)"),
10686
- executionOrder: z21.number().int().positive().describe("Execution order within the epic (required). Lower numbers first."),
10687
- estimatedComplexity: z21.enum(estimatedComplexityValues).describe("Complexity (required): trivial, simple, moderate, or complex"),
10688
- canParallelize: z21.boolean().optional().describe("Whether this feature can run alongside other features in parallel"),
10689
- parallelGroup: z21.string().max(100).optional().describe("Group identifier for features that can run together"),
10690
- dependencies: z21.array(z21.number().int().min(0)).optional().describe(
10749
+ var compositeFeatureSchema = z22.object({
10750
+ title: z22.string().min(1).max(500).describe("Feature title (required)"),
10751
+ executionOrder: z22.number().int().positive().describe("Execution order within the epic (required). Lower numbers first."),
10752
+ estimatedComplexity: z22.enum(estimatedComplexityValues).describe("Complexity (required): trivial, simple, moderate, or complex"),
10753
+ canParallelize: z22.boolean().optional().describe("Whether this feature can run alongside other features in parallel"),
10754
+ parallelGroup: z22.string().max(100).optional().describe("Group identifier for features that can run together"),
10755
+ dependencies: z22.array(z22.number().int().min(0)).optional().describe(
10691
10756
  "Array of 0-based indices referencing earlier features in this array that must complete first"
10692
10757
  ),
10693
10758
  structuredDesc: structuredDescSchema.optional().describe("Structured description with summary, aiInstructions, acceptanceCriteria, etc."),
10694
- tasks: z21.array(compositeTaskSchema).min(1).describe("Array of tasks for this feature (at least 1 required)")
10759
+ tasks: z22.array(compositeTaskSchema).min(1).describe("Array of tasks for this feature (at least 1 required)")
10695
10760
  });
10696
10761
  function registerCompositeTools(server2) {
10697
10762
  server2.registerTool(
@@ -10721,19 +10786,19 @@ Use this instead of individual create calls when building a complete implementat
10721
10786
 
10722
10787
  Optionally pass epicRequestId to link this epic to an approved Epic Request.`,
10723
10788
  inputSchema: {
10724
- name: z21.string().min(1).max(255).describe("Epic name (required)"),
10725
- team: z21.string().min(1).describe("Team ID, name, or key (required). Use compbox__list_teams to find available teams."),
10726
- description: z21.string().max(DESCRIPTION_MAX).optional().describe("Epic description"),
10727
- icon: z21.string().max(50).optional().describe("Icon identifier (e.g., 'rocket', 'star')"),
10728
- color: z21.string().max(20).optional().describe("Hex color code (e.g., '#FF5733')"),
10729
- epicRequestId: z21.string().uuid().optional().describe(
10789
+ name: z22.string().min(1).max(255).describe("Epic name (required)"),
10790
+ team: z22.string().min(1).describe("Team ID, name, or key (required). Use compbox__list_teams to find available teams."),
10791
+ description: z22.string().max(DESCRIPTION_MAX).optional().describe("Epic description"),
10792
+ icon: z22.string().max(50).optional().describe("Icon identifier (e.g., 'rocket', 'star')"),
10793
+ color: z22.string().max(20).optional().describe("Hex color code (e.g., '#FF5733')"),
10794
+ epicRequestId: z22.string().uuid().optional().describe(
10730
10795
  "UUID of an Epic Request to link to this epic. When provided without deferConversion, the Epic Request will be marked as converted. With deferConversion: true, conversion is skipped (ER must be in 'planning' status)."
10731
10796
  ),
10732
- bypassGovernance: z21.boolean().optional(),
10733
- deferConversion: z21.boolean().optional().describe(
10797
+ bypassGovernance: z22.boolean().optional(),
10798
+ deferConversion: z22.boolean().optional().describe(
10734
10799
  "When true, governance accepts 'planning' status and skips auto-conversion of the Epic Request. Used by the planner pipeline which handles conversion in its final VERIFY stage."
10735
10800
  ),
10736
- features: z21.array(compositeFeatureSchema).min(1).describe(
10801
+ features: z22.array(compositeFeatureSchema).min(1).describe(
10737
10802
  "Array of features to create. Each feature must have at least 1 task. Features are created in order, so dependencies must reference earlier indices (0-based)."
10738
10803
  )
10739
10804
  }
@@ -10829,19 +10894,19 @@ Optionally pass epicRequestId to link this epic to an approved Epic Request.`,
10829
10894
  {
10830
10895
  description: "Run all validations for a task and mark it complete if all pass.\n\nThis composite tool combines:\n- compbox__run_all_validations\n- compbox__complete_work (if validations pass)\n\nBehavior:\n- Runs all validation checks defined on the task\n- If ALL validations pass, marks the task as complete with the provided summary\n- If ANY validation fails, returns the failure details WITHOUT completing the task\n- If no validations are defined, completes the task immediately\n\nUse this at the end of implementing a task to ensure all acceptance criteria are met before marking it done.",
10831
10896
  inputSchema: {
10832
- taskId: z21.string().describe(
10897
+ taskId: z22.string().describe(
10833
10898
  "The task identifier. Accepts UUID or human-readable identifier (e.g., 'COM-123-1')."
10834
10899
  ),
10835
- summary: z21.string().max(5e3).optional().describe(
10900
+ summary: z22.string().max(5e3).optional().describe(
10836
10901
  "Summary of work completed. Will be logged as an AI note when the task is marked complete."
10837
10902
  ),
10838
- workingDirectory: z21.string().max(1e3).optional().describe(
10903
+ workingDirectory: z22.string().max(1e3).optional().describe(
10839
10904
  "Working directory for running validation commands. Defaults to current working directory."
10840
10905
  ),
10841
- stopOnFirstFailure: z21.boolean().optional().describe(
10906
+ stopOnFirstFailure: z22.boolean().optional().describe(
10842
10907
  "If true, stops running validations after the first failure. Default is false (run all)."
10843
10908
  ),
10844
- skipValidations: z21.boolean().optional().describe(
10909
+ skipValidations: z22.boolean().optional().describe(
10845
10910
  "If true, skips running validations and completes the task immediately. Use with caution - only for tasks where validations are not applicable."
10846
10911
  )
10847
10912
  }
@@ -10954,17 +11019,17 @@ Optionally pass epicRequestId to link this epic to an approved Epic Request.`,
10954
11019
  }
10955
11020
 
10956
11021
  // src/tools/workflow.ts
10957
- import { z as z22 } from "zod";
11022
+ import { z as z23 } from "zod";
10958
11023
  function registerWorkflowTools(server2) {
10959
11024
  server2.registerTool(
10960
11025
  "compbox__get_next_required_action",
10961
11026
  {
10962
11027
  description: "Analyze current work item state and suggest the next required action to maintain compliance with CompBox best practices. Returns prioritized list of suggestions with tool names and example parameters.\n\nUse this when you're unsure what to do next with a feature, task, or epic to ensure proper workflow compliance and tracking.",
10963
11028
  inputSchema: {
10964
- itemId: z22.string().describe(
11029
+ itemId: z23.string().describe(
10965
11030
  "The feature, task, or epic identifier. Accepts UUID or human-readable identifier (e.g., 'COM-123' for features, 'COM-123-1' for tasks). Epics use UUID, identifier (e.g., 'ENG-E1'), or exact name."
10966
11031
  ),
10967
- itemType: z22.enum(["feature", "task", "epic"]).describe(
11032
+ itemType: z23.enum(["feature", "task", "epic"]).describe(
10968
11033
  "Whether this is a 'feature', 'task', or 'epic'."
10969
11034
  )
10970
11035
  }
@@ -11165,7 +11230,7 @@ function registerWorkflowTools(server2) {
11165
11230
  {
11166
11231
  description: "Get the current state of an AI session and allowed state transitions. The session state machine tracks workflow progress through states: STARTED \u2192 PLANNING \u2192 IMPLEMENTING \u2192 VALIDATING \u2192 COMPLETING.\n\nUse this to understand where you are in the workflow and what transitions are allowed.",
11167
11232
  inputSchema: {
11168
- sessionId: z22.string().describe(
11233
+ sessionId: z23.string().describe(
11169
11234
  "The session ID to query. Get this from compbox__start_session or compbox__get_active_session."
11170
11235
  )
11171
11236
  }
@@ -11195,17 +11260,17 @@ function registerWorkflowTools(server2) {
11195
11260
  // src/tools/project-flags.ts
11196
11261
  import * as fs from "fs/promises";
11197
11262
  import * as path from "path";
11198
- import { z as z23 } from "zod";
11263
+ import { z as z24 } from "zod";
11199
11264
  function registerProjectFlagTools(server2) {
11200
11265
  server2.registerTool(
11201
11266
  "compbox__mark_docs_audit_complete",
11202
11267
  {
11203
11268
  description: "Mark a project's documentation audit as complete by writing the .compbox/docs-audit.json sentinel file. This creates the .compbox/ directory if needed and writes a JSON file that prevents the Request Formulator from prompting about documentation audits on future invocations. Use this when a user confirms their project is already documented.",
11204
- inputSchema: z23.object({
11205
- projectRoot: z23.string().optional().describe(
11269
+ inputSchema: z24.object({
11270
+ projectRoot: z24.string().optional().describe(
11206
11271
  "Project root directory (default: current working directory)"
11207
11272
  ),
11208
- epicRequestId: z23.string().optional().describe(
11273
+ epicRequestId: z24.string().optional().describe(
11209
11274
  "Optional Epic Request ID if the audit was completed via a CompBox epic request"
11210
11275
  )
11211
11276
  })
@@ -11257,7 +11322,7 @@ function registerProjectFlagTools(server2) {
11257
11322
  }
11258
11323
 
11259
11324
  // src/tools/changelog.ts
11260
- import { z as z24 } from "zod";
11325
+ import { z as z25 } from "zod";
11261
11326
  var entityTypes = ["epic", "feature", "task"];
11262
11327
  function registerChangelogTools(server2) {
11263
11328
  server2.registerTool(
@@ -11265,31 +11330,31 @@ function registerChangelogTools(server2) {
11265
11330
  {
11266
11331
  description: "Query entity change history with formatted output. Returns field-level changes showing what was modified, when, and by whom. Each entry shows 'field: oldValue \u2192 newValue'. Useful for understanding how an entity evolved over time or tracking specific field changes.\n\nUse cases:\n- See all changes to a feature or task\n- Track status changes over time\n- Find who changed a specific field\n- Audit changes within a date range\n- Review epic-wide changes across all features/tasks",
11267
11332
  inputSchema: {
11268
- entityType: z24.enum(entityTypes).describe(
11333
+ entityType: z25.enum(entityTypes).describe(
11269
11334
  "Type of entity to query (required). 'epic' for epic changes, 'feature' for feature changes, 'task' for task changes."
11270
11335
  ),
11271
- entityId: z24.string().describe(
11336
+ entityId: z25.string().describe(
11272
11337
  "UUID of the entity to query (required). The specific epic, feature, or task ID."
11273
11338
  ),
11274
- epicId: z24.string().uuid().optional().describe(
11339
+ epicId: z25.string().uuid().optional().describe(
11275
11340
  "Filter by epic ID (optional). Accepts UUID or identifier (e.g., 'ENG-E1'). When provided, only returns changes for entities within this epic. Useful for narrowing down results in a multi-epic query."
11276
11341
  ),
11277
- field: z24.string().max(255).optional().describe(
11342
+ field: z25.string().max(255).optional().describe(
11278
11343
  "Filter by specific field name (optional). Examples: 'statusId', 'title', 'assigneeId', 'description'. Only changes to this field will be returned."
11279
11344
  ),
11280
- changedBy: z24.string().uuid().optional().describe(
11345
+ changedBy: z25.string().uuid().optional().describe(
11281
11346
  "Filter by user ID who made the change (optional). Only returns changes made by this user."
11282
11347
  ),
11283
- since: z24.string().optional().describe(
11348
+ since: z25.string().optional().describe(
11284
11349
  "Filter changes on or after this date (optional). Accepts ISO-8601 date (e.g., '2024-01-15') or duration (e.g., '-P7D' for last 7 days, '-P1M' for last month)."
11285
11350
  ),
11286
- until: z24.string().optional().describe(
11351
+ until: z25.string().optional().describe(
11287
11352
  "Filter changes before this date (optional). Accepts ISO-8601 date format."
11288
11353
  ),
11289
- limit: z24.number().int().min(1).max(100).optional().describe(
11354
+ limit: z25.number().int().min(1).max(100).optional().describe(
11290
11355
  "Maximum number of entries to return (default: 20, max: 100)."
11291
11356
  ),
11292
- cursor: z24.string().optional().describe(
11357
+ cursor: z25.string().optional().describe(
11293
11358
  "Pagination cursor from a previous response. Pass this to fetch the next page of results."
11294
11359
  )
11295
11360
  }
@@ -11342,7 +11407,7 @@ function registerChangelogTools(server2) {
11342
11407
  }
11343
11408
 
11344
11409
  // src/tools/sessions.ts
11345
- import { z as z25 } from "zod";
11410
+ import { z as z26 } from "zod";
11346
11411
  import * as fs2 from "fs";
11347
11412
  import * as path2 from "path";
11348
11413
  function readLocalManifest() {
@@ -11403,13 +11468,13 @@ function registerSessionTools(server2) {
11403
11468
  {
11404
11469
  description: "Start a new AI session for an epic. Creates a session record, abandons any existing active session, and returns the previous session's handoff data plus epic progress. Call this at the START of any work session to properly track AI activity. Optionally scope the session to a specific feature within the epic by providing featureId.",
11405
11470
  inputSchema: {
11406
- epicId: z25.string().describe(
11471
+ epicId: z26.string().describe(
11407
11472
  "The epic to start a session for. Accepts epic ID (UUID), identifier (e.g., 'ENG-E1'), or exact epic name."
11408
11473
  ),
11409
- externalId: z25.string().optional().describe(
11474
+ externalId: z26.string().optional().describe(
11410
11475
  "Optional external session identifier (e.g., from Copilot or another AI tool)."
11411
11476
  ),
11412
- featureId: z25.string().uuid().optional().describe(
11477
+ featureId: z26.string().uuid().optional().describe(
11413
11478
  "Optional feature ID (UUID) to scope this session to a specific feature within the epic. When provided, the session tracks work on a single feature. Omit for epic-wide sessions (default behavior)."
11414
11479
  )
11415
11480
  }
@@ -11437,19 +11502,19 @@ function registerSessionTools(server2) {
11437
11502
  {
11438
11503
  description: "End the active AI session for an epic with handoff data. Records summary, next steps, blockers, and decisions for the next session. Call this at the END of a work session. If the session was feature-scoped, the response includes featureId indicating which feature was targeted.",
11439
11504
  inputSchema: {
11440
- epicId: z25.string().describe(
11505
+ epicId: z26.string().describe(
11441
11506
  "The epic whose active session to end. Accepts epic ID (UUID), identifier (e.g., 'ENG-E1'), or exact epic name."
11442
11507
  ),
11443
- summary: z25.string().describe("Summary of work completed during this session."),
11444
- nextSteps: z25.array(z25.string()).optional().describe("Recommended next actions for the successor session."),
11445
- blockers: z25.array(z25.string()).optional().describe("Blockers encountered during this session."),
11446
- decisions: z25.array(
11447
- z25.object({
11448
- decision: z25.string(),
11449
- rationale: z25.string().optional()
11508
+ summary: z26.string().describe("Summary of work completed during this session."),
11509
+ nextSteps: z26.array(z26.string()).optional().describe("Recommended next actions for the successor session."),
11510
+ blockers: z26.array(z26.string()).optional().describe("Blockers encountered during this session."),
11511
+ decisions: z26.array(
11512
+ z26.object({
11513
+ decision: z26.string(),
11514
+ rationale: z26.string().optional()
11450
11515
  })
11451
11516
  ).optional().describe("Key decisions made during this session with rationale."),
11452
- contextBlob: z25.string().optional().describe("Optional free-form context blob for the next session.")
11517
+ contextBlob: z26.string().optional().describe("Optional free-form context blob for the next session.")
11453
11518
  }
11454
11519
  },
11455
11520
  async (input) => {
@@ -11473,7 +11538,7 @@ function registerSessionTools(server2) {
11473
11538
  {
11474
11539
  description: "Check if there is an active AI session for an epic. Returns the session if active, or null.",
11475
11540
  inputSchema: {
11476
- epicId: z25.string().describe(
11541
+ epicId: z26.string().describe(
11477
11542
  "The epic to check. Accepts epic ID (UUID), identifier (e.g., 'ENG-E1'), or exact epic name."
11478
11543
  )
11479
11544
  }
@@ -11493,7 +11558,7 @@ function registerSessionTools(server2) {
11493
11558
  {
11494
11559
  description: "Get the last completed session for an epic. Returns previous session handoff data without starting a new session. Use this to review what happened in the previous session.",
11495
11560
  inputSchema: {
11496
- epicId: z25.string().describe(
11561
+ epicId: z26.string().describe(
11497
11562
  "The epic to query. Accepts epic ID (UUID), identifier (e.g., 'ENG-E1'), or exact epic name."
11498
11563
  )
11499
11564
  }
@@ -11513,10 +11578,10 @@ function registerSessionTools(server2) {
11513
11578
  {
11514
11579
  description: "Get the history of AI sessions for an epic. Returns past sessions ordered by most recent first.",
11515
11580
  inputSchema: {
11516
- epicId: z25.string().describe(
11581
+ epicId: z26.string().describe(
11517
11582
  "The epic to query. Accepts epic ID (UUID), identifier (e.g., 'ENG-E1'), or exact epic name."
11518
11583
  ),
11519
- limit: z25.number().int().min(1).max(100).optional().describe("Maximum number of sessions to return (default: 10, max: 100).")
11584
+ limit: z26.number().int().min(1).max(100).optional().describe("Maximum number of sessions to return (default: 10, max: 100).")
11520
11585
  }
11521
11586
  },
11522
11587
  async (input) => {
@@ -11535,7 +11600,7 @@ function registerSessionTools(server2) {
11535
11600
  }
11536
11601
 
11537
11602
  // src/tools/compliance.ts
11538
- import { z as z26 } from "zod";
11603
+ import { z as z27 } from "zod";
11539
11604
  var TIER_EMOJI = {
11540
11605
  pass: "\u2705",
11541
11606
  advisory: "\u26A0\uFE0F",
@@ -11606,7 +11671,7 @@ function registerComplianceTools(server2) {
11606
11671
  {
11607
11672
  description: "Trigger a compliance audit for an Epic Request. Evaluates the epic request against compliance rules and returns a detailed score with dimension breakdown and issues. The audit result is persisted on the epic request for future reference.",
11608
11673
  inputSchema: {
11609
- id: z26.string().min(1).describe(
11674
+ id: z27.string().min(1).describe(
11610
11675
  "The epic request to audit. Accepts UUID or identifier (e.g., 'ER-1')."
11611
11676
  )
11612
11677
  }
@@ -11628,7 +11693,7 @@ function registerComplianceTools(server2) {
11628
11693
  {
11629
11694
  description: "Trigger a full compliance audit for an Epic. Evaluates the epic and all its features and tasks against compliance rules. Returns a detailed score with dimension breakdown and issues. The audit result is persisted on the epic for future reference.",
11630
11695
  inputSchema: {
11631
- id: z26.string().min(1).describe(
11696
+ id: z27.string().min(1).describe(
11632
11697
  "The epic to audit. Accepts UUID, identifier (e.g., 'ENG-E1'), or exact name."
11633
11698
  )
11634
11699
  }
@@ -11665,20 +11730,20 @@ function registerComplianceTools(server2) {
11665
11730
  }
11666
11731
 
11667
11732
  // src/tools/skill-packs/manage.ts
11668
- import { z as z29 } from "zod";
11733
+ import { z as z30 } from "zod";
11669
11734
 
11670
11735
  // src/tools/skill-packs/get-manifest.ts
11671
- import { z as z27 } from "zod";
11736
+ import { z as z28 } from "zod";
11672
11737
  function registerGetPackManifestTool(server2) {
11673
11738
  server2.registerTool(
11674
11739
  "compbox__get_pack_manifest",
11675
11740
  {
11676
11741
  description: "Get the detailed manifest for a specific version of a skill pack.\n\nThe manifest describes the pack's contents including:\n- Agents: AI agents included in the pack\n- Skills: Individual skills/capabilities\n- Instructions: Documentation and usage guides\n- Dependencies: Other packs this pack depends on\n\nUse this to understand what a skill pack contains before installing it, or to see the details of an installed pack's current version.",
11677
11742
  inputSchema: {
11678
- id: z27.string().describe(
11743
+ id: z28.string().describe(
11679
11744
  "Skill pack ID or name (e.g., '@mycompbox/planning' or UUID)"
11680
11745
  ),
11681
- version: z27.string().optional().describe(
11746
+ version: z28.string().optional().describe(
11682
11747
  "Specific version to get manifest for (e.g., '1.2.3'). If not provided, uses latest stable version."
11683
11748
  )
11684
11749
  }
@@ -11768,7 +11833,7 @@ function registerGetPackManifestTool(server2) {
11768
11833
  }
11769
11834
 
11770
11835
  // src/tools/skill-packs/sync-local.ts
11771
- import { z as z28 } from "zod";
11836
+ import { z as z29 } from "zod";
11772
11837
  import * as fs3 from "fs/promises";
11773
11838
  import * as path3 from "path";
11774
11839
  import { existsSync } from "fs";
@@ -11778,7 +11843,7 @@ function registerSyncLocalPacksTool(server2) {
11778
11843
  {
11779
11844
  description: "Detect drift between local skill pack installations and the registry.\n\nThis tool compares:\n1. .compbox/manifest.json (local installation record)\n2. Actual files in .github/ (agents, skills, instructions, presets)\n3. Database registry (what's officially installed)\n\nReports:\n- **Untracked files**: Files exist locally but not in manifest\n- **Missing files**: Files in manifest but not on filesystem\n- **Registry mismatches**: Local manifest differs from database registry\n- **Version differences**: Installed version vs. available version\n\nUse this to audit local installations and identify cleanup/sync needs.",
11780
11845
  inputSchema: {
11781
- projectRoot: z28.string().optional().describe(
11846
+ projectRoot: z29.string().optional().describe(
11782
11847
  "Project root directory (default: current working directory). Must contain .compbox/ and .github/ directories."
11783
11848
  )
11784
11849
  }
@@ -11970,21 +12035,21 @@ function registerSkillPackTools(server2) {
11970
12035
  "compbox__manage_skill_packs",
11971
12036
  {
11972
12037
  description: "Manage Skill Packs with action-based routing. This composite tool provides 5 actions:\n\n**list** - List available skill packs from the registry (supports filtering by official/search)\n**get** - Get details about a specific skill pack by ID or name\n**install** - Install a skill pack by ID/name and version\n**update** - Update an installed skill pack to a new version (or 'latest')\n**list_installed** - List all installed skill packs with their status\n\nUse this to discover, install, and manage skill packs during AI sessions.",
11973
- inputSchema: z29.object({
11974
- action: z29.enum(["list", "get", "install", "update", "list_installed"]).describe(
12038
+ inputSchema: z30.object({
12039
+ action: z30.enum(["list", "get", "install", "update", "list_installed"]).describe(
11975
12040
  "The action to perform: 'list' (browse registry), 'get' (pack details), 'install', 'update', or 'list_installed' (your installed packs)"
11976
12041
  ),
11977
12042
  // Used by: list, get, install, update
11978
- id: z29.string().optional().describe("Skill pack ID or name (e.g., '@mycompbox/planning'). Required for get/install/update actions."),
12043
+ id: z30.string().optional().describe("Skill pack ID or name (e.g., '@mycompbox/planning'). Required for get/install/update actions."),
11979
12044
  // Used by: list
11980
- cursor: z29.string().optional().describe("Pagination cursor from previous response (list action only)"),
11981
- limit: z29.number().int().min(1).max(100).optional().describe("Maximum results per page, default 20, max 100 (list action only)"),
11982
- isOfficial: z29.boolean().optional().describe("Filter by official packs (list action only)"),
11983
- query: z29.string().optional().describe("Search query to filter by name (list action only)"),
12045
+ cursor: z30.string().optional().describe("Pagination cursor from previous response (list action only)"),
12046
+ limit: z30.number().int().min(1).max(100).optional().describe("Maximum results per page, default 20, max 100 (list action only)"),
12047
+ isOfficial: z30.boolean().optional().describe("Filter by official packs (list action only)"),
12048
+ query: z30.string().optional().describe("Search query to filter by name (list action only)"),
11984
12049
  // Used by: get
11985
- includeVersions: z29.boolean().optional().describe("Include all versions in response (get action only)"),
12050
+ includeVersions: z30.boolean().optional().describe("Include all versions in response (get action only)"),
11986
12051
  // Used by: install, update
11987
- version: z29.string().optional().describe("Version to install/update to (e.g., '1.2.3' or 'latest'). Required for install/update actions.")
12052
+ version: z30.string().optional().describe("Version to install/update to (e.g., '1.2.3' or 'latest'). Required for install/update actions.")
11988
12053
  })
11989
12054
  },
11990
12055
  async (input) => {
@@ -12270,7 +12335,7 @@ function withLegacyToolCallRewrite(transport) {
12270
12335
  var SERVER_NAME = "compbox-mcp";
12271
12336
  function resolveServerVersion() {
12272
12337
  if (true) {
12273
- return "1.21.3";
12338
+ return "1.21.5";
12274
12339
  }
12275
12340
  const require2 = createRequire(import.meta.url);
12276
12341
  for (const candidate of ["../package.json", "./package.json"]) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mycompbox/compbox-mcp",
3
- "version": "1.21.3",
3
+ "version": "1.21.5",
4
4
  "description": "CompBox MCP server - Uses HTTP API client (no direct database access)",
5
5
  "license": "MIT",
6
6
  "type": "module",