@productbrain/mcp 0.0.1-beta.2087 → 0.0.1-beta.2093

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.
@@ -203,22 +203,19 @@ import { z } from "zod/v3";
203
203
  // src/errors.ts
204
204
  var MCP_CALL_ERROR_RE = /^MCP call "([^"]+)" failed \(\d+\): (.+)$/s;
205
205
  function asKernelCallError(err) {
206
- if (err instanceof Error && typeof err.code === "string") {
207
- const code = err.code;
208
- const match = MCP_CALL_ERROR_RE.exec(err.message);
209
- if (match) {
210
- const e = err;
211
- return {
212
- code,
213
- fn: match[1],
214
- cleanMessage: match[2],
215
- // NOTE: match[2] not match[1] — group 1 is now fn scope (DEC-798)
216
- missingRequiredFields: Array.isArray(e.missingRequiredFields) ? e.missingRequiredFields : void 0,
217
- fieldErrors: Array.isArray(e.fieldErrors) ? e.fieldErrors : void 0
218
- };
219
- }
220
- }
221
- return void 0;
206
+ if (!(err instanceof Error)) return void 0;
207
+ const e = err;
208
+ if (typeof e.code !== "string") return void 0;
209
+ const match = MCP_CALL_ERROR_RE.exec(e.message);
210
+ if (!match) return void 0;
211
+ return {
212
+ code: e.code,
213
+ fn: match[1],
214
+ cleanMessage: match[2],
215
+ // NOTE: match[2] not match[1] — group 1 is now fn scope (DEC-798)
216
+ missingRequiredFields: Array.isArray(e.missingRequiredFields) ? e.missingRequiredFields : void 0,
217
+ fieldErrors: Array.isArray(e.fieldErrors) ? e.fieldErrors : void 0
218
+ };
222
219
  }
223
220
  var GateError = class extends Error {
224
221
  constructor(message) {
@@ -751,7 +748,10 @@ function buildFieldQualityChecks(col) {
751
748
  addCheck({
752
749
  id: `field-${field.key}-min-length`,
753
750
  label: `${field.key} min ${field.minLength} chars`,
754
- check: (ctx) => typeof ctx.data[field.key] === "string" && ctx.data[field.key].length >= field.minLength,
751
+ check: (ctx) => {
752
+ const value = ctx.data[field.key];
753
+ return typeof value === "string" && value.length >= field.minLength;
754
+ },
755
755
  suggestion: () => `Add more detail to ${labelFor(field.key)} (minimum ${field.minLength} characters).`
756
756
  });
757
757
  }
@@ -759,7 +759,10 @@ function buildFieldQualityChecks(col) {
759
759
  addCheck({
760
760
  id: `field-${field.key}-max-length`,
761
761
  label: `${field.key} max ${field.maxLength} chars`,
762
- check: (ctx) => typeof ctx.data[field.key] !== "string" || ctx.data[field.key].length <= field.maxLength,
762
+ check: (ctx) => {
763
+ const value = ctx.data[field.key];
764
+ return typeof value !== "string" || value.length <= field.maxLength;
765
+ },
763
766
  suggestion: () => `Shorten ${labelFor(field.key)} to ${field.maxLength} characters or fewer.`
764
767
  });
765
768
  }
@@ -4818,25 +4821,26 @@ async function handleGather(server, entryId, task, mode, maxHops, maxResults, st
4818
4821
  if (!result2?.root) {
4819
4822
  return notFoundResult(entryId, `Entry '${entryId}' not found. Try search to find the right ID.`);
4820
4823
  }
4824
+ const root2 = result2.root;
4821
4825
  if (result2.context.length === 0) {
4822
- const recorded = recordGap({ query: result2.root.entryId, tool: "context", action: "gather", gapType: "context_graph_empty" });
4826
+ const recorded = recordGap({ query: root2.entryId, tool: "context", action: "gather", gapType: "context_graph_empty" });
4823
4827
  if (recorded) {
4824
- getWorkspaceId().then((wsId) => trackKnowledgeGap(wsId, { query: result2.root.entryId, tool: "context", action: "gather", gap_type: "context_graph_empty" })).catch(() => {
4828
+ getWorkspaceId().then((wsId) => trackKnowledgeGap(wsId, { query: root2.entryId, tool: "context", action: "gather", gap_type: "context_graph_empty" })).catch(() => {
4825
4829
  });
4826
4830
  }
4827
4831
  return {
4828
4832
  content: [{
4829
4833
  type: "text",
4830
- text: `# Context for ${result2.root.entryId}: ${result2.root.name}
4834
+ text: `# Context for ${root2.entryId}: ${root2.name}
4831
4835
 
4832
4836
  _No relations found._ This entry is not yet connected to the knowledge graph.
4833
4837
 
4834
4838
  Use \`graph action=suggest\` to discover potential connections.`
4835
4839
  }],
4836
4840
  structuredContent: success(
4837
- `No relations found for ${result2.root.entryId}. Entry not yet connected.`,
4838
- { root: result2.root, context: [], totalFound: 0 },
4839
- [{ tool: "graph", description: "Discover connections", parameters: { action: "suggest", entryId: result2.root.entryId } }]
4841
+ `No relations found for ${root2.entryId}. Entry not yet connected.`,
4842
+ { root: root2, context: [], totalFound: 0 },
4843
+ [{ tool: "graph", description: "Discover connections", parameters: { action: "suggest", entryId: root2.entryId } }]
4840
4844
  )
4841
4845
  };
4842
4846
  }
@@ -4847,7 +4851,7 @@ Use \`graph action=suggest\` to discover potential connections.`
4847
4851
  byCollection2.get(key).push(entry);
4848
4852
  }
4849
4853
  const lines2 = [
4850
- `# Context for ${result2.root.entryId}: ${result2.root.name} (graph mode)`,
4854
+ `# Context for ${root2.entryId}: ${root2.name} (graph mode)`,
4851
4855
  `_${result2.totalFound} related entries across ${byCollection2.size} collections (${result2.hopsTraversed} hops)_`,
4852
4856
  ""
4853
4857
  ];
@@ -4868,9 +4872,9 @@ Use \`graph action=suggest\` to discover potential connections.`
4868
4872
  }
4869
4873
  lines2.push("");
4870
4874
  }
4871
- const rootId2 = result2.root.entryId ?? "root";
4875
+ const rootId2 = root2.entryId ?? "root";
4872
4876
  const nodes2 = [
4873
- { id: rootId2, name: result2.root.name, collectionName: "" },
4877
+ { id: rootId2, name: root2.name, collectionName: "" },
4874
4878
  ...result2.context.map((e) => ({
4875
4879
  id: e.entryId ?? String(Math.random()),
4876
4880
  name: e.name,
@@ -4885,8 +4889,8 @@ Use \`graph action=suggest\` to discover potential connections.`
4885
4889
  return {
4886
4890
  content: [{ type: "text", text: lines2.join("\n") }],
4887
4891
  structuredContent: success(
4888
- `Gathered ${result2.totalFound} related entries for ${result2.root.entryId} (${result2.hopsTraversed} hops, graph mode).`,
4889
- { nodes: nodes2, edges: edges2, root: result2.root, totalFound: result2.totalFound }
4892
+ `Gathered ${result2.totalFound} related entries for ${root2.entryId} (${result2.hopsTraversed} hops, graph mode).`,
4893
+ { nodes: nodes2, edges: edges2, root: root2, totalFound: result2.totalFound }
4890
4894
  )
4891
4895
  };
4892
4896
  }
@@ -5088,25 +5092,26 @@ _This helps future sessions start with better constraints and context._`
5088
5092
  if (!result?.root) {
5089
5093
  return notFoundResult(entryId, `Entry '${entryId}' not found. Try search to find the right ID.`);
5090
5094
  }
5095
+ const root = result.root;
5091
5096
  if (result.related.length === 0) {
5092
- const recorded = recordGap({ query: result.root.entryId, tool: "context", action: "gather", gapType: "context_entry_isolated" });
5097
+ const recorded = recordGap({ query: root.entryId, tool: "context", action: "gather", gapType: "context_entry_isolated" });
5093
5098
  if (recorded) {
5094
- getWorkspaceId().then((wsId) => trackKnowledgeGap(wsId, { query: result.root.entryId, tool: "context", action: "gather", gap_type: "context_entry_isolated" })).catch(() => {
5099
+ getWorkspaceId().then((wsId) => trackKnowledgeGap(wsId, { query: root.entryId, tool: "context", action: "gather", gap_type: "context_entry_isolated" })).catch(() => {
5095
5100
  });
5096
5101
  }
5097
5102
  return {
5098
5103
  content: [{
5099
5104
  type: "text",
5100
- text: `# Context for ${result.root.entryId}: ${result.root.name}
5105
+ text: `# Context for ${root.entryId}: ${root.name}
5101
5106
 
5102
5107
  _No relations found._ This entry is not yet connected to the knowledge graph.
5103
5108
 
5104
5109
  Use \`graph action=suggest\` to discover potential connections, or \`relations action=create\` to link manually.`
5105
5110
  }],
5106
5111
  structuredContent: success(
5107
- `No relations found for ${result.root.entryId}. Entry not yet connected.`,
5108
- { root: result.root, related: [], totalRelations: 0 },
5109
- [{ tool: "graph", description: "Discover connections", parameters: { action: "suggest", entryId: result.root.entryId } }]
5112
+ `No relations found for ${root.entryId}. Entry not yet connected.`,
5113
+ { root, related: [], totalRelations: 0 },
5114
+ [{ tool: "graph", description: "Discover connections", parameters: { action: "suggest", entryId: root.entryId } }]
5110
5115
  )
5111
5116
  };
5112
5117
  }
@@ -5117,7 +5122,7 @@ Use \`graph action=suggest\` to discover potential connections, or \`relations a
5117
5122
  byCollection.get(key).push(entry);
5118
5123
  }
5119
5124
  const lines = [
5120
- `# Context for ${result.root.entryId}: ${result.root.name}`,
5125
+ `# Context for ${root.entryId}: ${root.name}`,
5121
5126
  `_${result.totalRelations} related entries across ${byCollection.size} collections (${result.hopsTraversed} hops traversed)_`,
5122
5127
  ""
5123
5128
  ];
@@ -5131,9 +5136,9 @@ Use \`graph action=suggest\` to discover potential connections, or \`relations a
5131
5136
  }
5132
5137
  lines.push("");
5133
5138
  }
5134
- const rootId = result.root.entryId ?? "root";
5139
+ const rootId = root.entryId ?? "root";
5135
5140
  const nodes = [
5136
- { id: rootId, name: result.root.name, collectionName: "" },
5141
+ { id: rootId, name: root.name, collectionName: "" },
5137
5142
  ...result.related.map((e) => ({
5138
5143
  id: e.entryId ?? String(Math.random()),
5139
5144
  name: e.name,
@@ -5148,8 +5153,8 @@ Use \`graph action=suggest\` to discover potential connections, or \`relations a
5148
5153
  return {
5149
5154
  content: [{ type: "text", text: lines.join("\n") }],
5150
5155
  structuredContent: success(
5151
- `Gathered ${result.totalRelations} related entries for ${result.root.entryId} (${result.hopsTraversed} hops).`,
5152
- { nodes, edges, root: result.root, totalRelations: result.totalRelations }
5156
+ `Gathered ${result.totalRelations} related entries for ${root.entryId} (${result.hopsTraversed} hops).`,
5157
+ { nodes, edges, root, totalRelations: result.totalRelations }
5153
5158
  )
5154
5159
  };
5155
5160
  }
@@ -10214,7 +10219,7 @@ function buildPlannedWorkSection(work, priorSessions, recoveryBlock) {
10214
10219
  }
10215
10220
  if (priorSessions.length > 0 && !hasPlannedWork(work) && !recoveryBlock) {
10216
10221
  const last = priorSessions[0];
10217
- const date = new Date(last.startedAt).toISOString().split("T")[0];
10222
+ const date = last.startedAt !== void 0 ? new Date(last.startedAt).toISOString().split("T")[0] : "unknown date";
10218
10223
  const created = Array.isArray(last.entriesCreated) ? last.entriesCreated.length : last.entriesCreated ?? 0;
10219
10224
  const modified = Array.isArray(last.entriesModified) ? last.entriesModified.length : last.entriesModified ?? 0;
10220
10225
  if (created > 0 || modified > 0) {
@@ -12241,7 +12246,7 @@ async function _handleOrient({ mode = "full", tier, task, scope }) {
12241
12246
  priorSessions = orientView.priorSessions ?? [];
12242
12247
  recoveryBlock = orientView.recoveryBlock ?? null;
12243
12248
  }
12244
- const hasTaskGrounding = Boolean(task && orientView?.taskContext?.context?.length > 0);
12249
+ const hasTaskGrounding = Boolean(task && (orientView?.taskContext?.context?.length ?? 0) > 0);
12245
12250
  if (wsCtx && hasTaskGrounding && orientView?.writeBackHints) {
12246
12251
  const hints = Array.isArray(orientView.writeBackHints) ? orientView.writeBackHints : [];
12247
12252
  if (hints.length > 0) {
@@ -12362,8 +12367,9 @@ async function _handleOrient({ mode = "full", tier, task, scope }) {
12362
12367
  lines.push(` ${h.collectionSlug}: ${h.hint}`);
12363
12368
  }
12364
12369
  }
12365
- if (orientView?.activeWorkPackages?.length > 0) {
12366
- for (const e of orientView.activeWorkPackages) {
12370
+ const briefActiveWps = orientView?.activeWorkPackages ?? [];
12371
+ if (briefActiveWps.length > 0) {
12372
+ for (const e of briefActiveWps) {
12367
12373
  const tensions = e.linkedTensions;
12368
12374
  const tensionPart = tensions?.length ? ` \u2014 ${tensions.map((t) => `${t.entryId ?? t.name} (${t.severity ?? "\u2014"})`).join(", ")}` : "";
12369
12375
  const originPart = e.origin ? ` (origin: ${e.origin})` : "";
@@ -12635,13 +12641,18 @@ async function _handleOrient({ mode = "full", tier, task, scope }) {
12635
12641
  const coll = e.collectionSlug ? ` [${e.collectionSlug}]` : "";
12636
12642
  const originTag = e.origin ? ` (origin: ${e.origin})` : "";
12637
12643
  lines.push(`- \`${id}\` (score ${e.score})${coll}${originTag}${e.name !== id ? ` \u2014 ${e.name}` : ""}`);
12638
- if (e.preview) lines.push(` _${e.preview}_`);
12639
12644
  }
12640
12645
  lines.push("");
12641
12646
  }
12642
12647
  if (orientView?.taskContext?.constellationEntries && orientView.taskContext.constellationEntries.length > 0) {
12648
+ const constellationEntries = orientView.taskContext.constellationEntries.map((e) => ({
12649
+ entryId: e.entryId ?? e.name,
12650
+ name: e.name,
12651
+ collectionSlug: e.collectionSlug ?? "unclassified",
12652
+ canonicalKey: e.canonicalKey
12653
+ }));
12643
12654
  lines.push(...formatBetConstellationLines(
12644
- orientView.taskContext.constellationEntries,
12655
+ constellationEntries,
12645
12656
  orientView.taskContext.constellationBetName
12646
12657
  ));
12647
12658
  }
@@ -12685,11 +12696,12 @@ async function _handleOrient({ mode = "full", tier, task, scope }) {
12685
12696
  }
12686
12697
  }
12687
12698
  if (orientView) {
12688
- if (orientView.activeWorkPackages?.length > 0) {
12699
+ const fullActiveWps = orientView.activeWorkPackages ?? [];
12700
+ if (fullActiveWps.length > 0) {
12689
12701
  lines.push("## Active work packages \u2014 current scope");
12690
12702
  lines.push("_Work outside these work packages requires explicit user confirmation._");
12691
12703
  lines.push("");
12692
- for (const e of orientView.activeWorkPackages) {
12704
+ for (const e of fullActiveWps) {
12693
12705
  lines.push(fmt(e));
12694
12706
  const tensions = e.linkedTensions;
12695
12707
  if (tensions?.length) {
@@ -12702,44 +12714,51 @@ async function _handleOrient({ mode = "full", tier, task, scope }) {
12702
12714
  }
12703
12715
  lines.push("");
12704
12716
  }
12705
- if (orientView.activeGoals?.length > 0) {
12717
+ const fullActiveGoals = orientView.activeGoals ?? [];
12718
+ if (fullActiveGoals.length > 0) {
12706
12719
  lines.push("## Active goals");
12707
- orientView.activeGoals.forEach((e) => lines.push(fmt(e)));
12720
+ fullActiveGoals.forEach((e) => lines.push(fmt(e)));
12708
12721
  lines.push("");
12709
12722
  }
12710
- if (orientView.strategyHighlights?.length > 0) {
12723
+ const fullStrategyHighlights = orientView.strategyHighlights ?? [];
12724
+ if (fullStrategyHighlights.length > 0) {
12711
12725
  lines.push("## Strategy highlights");
12712
12726
  lines.push("_One-sentence strategy, positioning, moat, business model, GTM \u2014 high-level strategic context._");
12713
12727
  lines.push("");
12714
- orientView.strategyHighlights.forEach((e) => lines.push(fmt(e)));
12728
+ fullStrategyHighlights.forEach((e) => lines.push(fmt(e)));
12715
12729
  lines.push("");
12716
12730
  }
12717
- if (orientView.playingField?.length > 0) {
12731
+ const fullPlayingField = orientView.playingField ?? [];
12732
+ if (fullPlayingField.length > 0) {
12718
12733
  lines.push("## Playing field");
12719
12734
  lines.push("_Products and opportunities in the strategic landscape._");
12720
12735
  lines.push("");
12721
- orientView.playingField.forEach((e) => lines.push(fmt(e)));
12736
+ fullPlayingField.forEach((e) => lines.push(fmt(e)));
12722
12737
  lines.push("");
12723
12738
  }
12724
- if (orientView.recentDecisions?.length > 0) {
12739
+ const fullRecentDecisions = orientView.recentDecisions ?? [];
12740
+ if (fullRecentDecisions.length > 0) {
12725
12741
  lines.push("## Recent decisions");
12726
- orientView.recentDecisions.forEach((e) => lines.push(fmt(e)));
12742
+ fullRecentDecisions.forEach((e) => lines.push(fmt(e)));
12727
12743
  lines.push("");
12728
12744
  }
12729
- if (orientView.recentlySuperseded?.length > 0) {
12745
+ const fullRecentlySuperseded = orientView.recentlySuperseded ?? [];
12746
+ if (fullRecentlySuperseded.length > 0) {
12730
12747
  lines.push("## Recently superseded");
12731
- orientView.recentlySuperseded.forEach((e) => lines.push(fmt(e)));
12748
+ fullRecentlySuperseded.forEach((e) => lines.push(fmt(e)));
12732
12749
  lines.push("");
12733
12750
  }
12734
- if (orientView.staleEntries?.length > 0) {
12751
+ const fullStaleEntries = orientView.staleEntries ?? [];
12752
+ if (fullStaleEntries.length > 0) {
12735
12753
  lines.push("## Needs confirmation");
12736
12754
  lines.push(`_Domain stratum entries not confirmed in ${orientView.stalenessThresholdDays} days._`);
12737
- orientView.staleEntries.forEach((e) => lines.push(fmt(e)));
12755
+ fullStaleEntries.forEach((e) => lines.push(fmt(e)));
12738
12756
  lines.push("");
12739
12757
  }
12740
- if (orientView.architectureNotes?.length > 0) {
12758
+ const fullArchitectureNotes = orientView.architectureNotes ?? [];
12759
+ if (fullArchitectureNotes.length > 0) {
12741
12760
  lines.push("## Architecture notes");
12742
- orientView.architectureNotes.forEach((e) => lines.push(fmt(e)));
12761
+ fullArchitectureNotes.forEach((e) => lines.push(fmt(e)));
12743
12762
  lines.push("");
12744
12763
  }
12745
12764
  const mapGovernanceEntry = (e) => ({
@@ -14181,6 +14200,7 @@ ${lines.join("\n")}`, mimeType: "text/markdown" }]
14181
14200
  server.resource(
14182
14201
  "chain-entry",
14183
14202
  new ResourceTemplate("productbrain://entries/{entryId}", {
14203
+ list: void 0,
14184
14204
  complete: {
14185
14205
  entryId: async (value) => {
14186
14206
  if (!value || value.length < 1) return [];
@@ -14238,6 +14258,7 @@ ${entry.labels.map((l) => `- ${l.name ?? l.slug}`).join("\n")}`);
14238
14258
  server.resource(
14239
14259
  "chain-context",
14240
14260
  new ResourceTemplate("productbrain://context/{entryId}", {
14261
+ list: void 0,
14241
14262
  complete: {
14242
14263
  entryId: async (value) => {
14243
14264
  if (!value || value.length < 1) return [];
@@ -14344,6 +14365,7 @@ ${entry.labels.map((l) => `- ${l.name ?? l.slug}`).join("\n")}`);
14344
14365
  server.resource(
14345
14366
  "chain-search",
14346
14367
  new ResourceTemplate("productbrain://search/{query}", {
14368
+ list: void 0,
14347
14369
  complete: {
14348
14370
  query: async (value) => {
14349
14371
  if (!value) return ["glossary:", "business-rules:", "decisions:", "tensions:"];
@@ -14791,4 +14813,4 @@ export {
14791
14813
  createProductBrainServer,
14792
14814
  initFeatureFlags
14793
14815
  };
14794
- //# sourceMappingURL=chunk-XIERWSPE.js.map
14816
+ //# sourceMappingURL=chunk-QTY3D7P4.js.map