@productbrain/mcp 0.0.1-beta.163 → 0.0.1-beta.167

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.
@@ -309,17 +309,21 @@ function audit(fn, status, durationMs, errorMsg) {
309
309
  function getAuditLog() {
310
310
  return auditBuffer;
311
311
  }
312
- async function mcpCall(fn, args = {}) {
313
- const cached = getCached(fn, args);
314
- if (cached !== void 0) {
315
- return cached;
316
- }
312
+ var TOUCH_EXCLUDED = /* @__PURE__ */ new Set([
313
+ "agent.touchSession",
314
+ "agent.startSession",
315
+ "agent.markOriented",
316
+ "agent.recordActivity",
317
+ "agent.recordWrapup",
318
+ "agent.closeSession"
319
+ ]);
320
+ async function callGateway(fn, args) {
317
321
  const siteUrl = getEnv("CONVEX_SITE_URL").replace(/\/$/, "");
318
322
  const apiKey = getActiveApiKey();
319
323
  const start = Date.now();
320
324
  let res;
321
325
  try {
322
- res = await fetch(`${siteUrl}/api/mcp`, {
326
+ res = await fetch(`${siteUrl}/api/aki`, {
323
327
  method: "POST",
324
328
  signal: AbortSignal.timeout(1e4),
325
329
  headers: {
@@ -333,38 +337,52 @@ async function mcpCall(fn, args = {}) {
333
337
  throw new Error(`MCP call "${fn}" network error: ${err.message}`);
334
338
  }
335
339
  const json = await res.json();
336
- if (!res.ok || json.error) {
337
- const msg = json.error ?? "unknown error";
338
- audit(fn, "error", Date.now() - start, json.code ? `${msg} [${json.code}]` : msg);
340
+ if (!res.ok || json.ok === false) {
341
+ const errJson = json;
342
+ const msg = errJson.error ?? errJson.message ?? "unknown error";
343
+ audit(fn, "error", Date.now() - start, errJson.code ? `${msg} [${errJson.code}]` : msg);
339
344
  throw new McpCallError(
340
345
  `MCP call "${fn}" failed (${res.status}): ${msg}`,
341
346
  res.status,
342
- json.code,
343
- Array.isArray(json.missingRequiredFields) ? json.missingRequiredFields : void 0,
344
- Array.isArray(json.fieldErrors) ? json.fieldErrors : void 0
347
+ errJson.code,
348
+ Array.isArray(errJson.missingRequiredFields) ? errJson.missingRequiredFields : void 0,
349
+ Array.isArray(errJson.fieldErrors) ? errJson.fieldErrors : void 0
345
350
  );
346
351
  }
347
352
  audit(fn, "ok", Date.now() - start);
348
- const data = json.data;
353
+ const { data, summary, next, _meta } = json;
354
+ return {
355
+ data,
356
+ summary: summary || fn,
357
+ next,
358
+ _meta
359
+ };
360
+ }
361
+ async function mcpCall(fn, args = {}) {
362
+ const cached = getCached(fn, args);
363
+ if (cached !== void 0) {
364
+ return cached;
365
+ }
366
+ const { data } = await callGateway(fn, args);
349
367
  if (isWrite(fn)) {
350
368
  invalidateReadCache();
351
369
  } else {
352
370
  setCached(fn, args, data);
353
371
  }
354
372
  const s = state();
355
- const TOUCH_EXCLUDED = /* @__PURE__ */ new Set([
356
- "agent.touchSession",
357
- "agent.startSession",
358
- "agent.markOriented",
359
- "agent.recordActivity",
360
- "agent.recordWrapup",
361
- "agent.closeSession"
362
- ]);
363
373
  if (s.agentSessionId && !TOUCH_EXCLUDED.has(fn)) {
364
374
  touchSessionActivity();
365
375
  }
366
376
  return data;
367
377
  }
378
+ async function mcpCallEnvelope(fn, args = {}) {
379
+ const { data, summary, next, _meta } = await callGateway(fn, args);
380
+ const s = state();
381
+ if (s.agentSessionId && !TOUCH_EXCLUDED.has(fn)) {
382
+ touchSessionActivity();
383
+ }
384
+ return { ok: true, summary, data, next, _meta };
385
+ }
368
386
  var resolveInFlightMap = /* @__PURE__ */ new Map();
369
387
  async function getWorkspaceId() {
370
388
  const s = state();
@@ -2356,7 +2374,10 @@ Or use \`collections action=list\` to see available collections.`
2356
2374
  limit: 5,
2357
2375
  threshold: 2
2358
2376
  }).catch(() => null) : Promise.resolve(null);
2359
- const groundingRaw = await groundingPromise;
2377
+ const groundingRaw = await Promise.race([
2378
+ groundingPromise,
2379
+ new Promise((r) => setTimeout(() => r(null), 500))
2380
+ ]);
2360
2381
  const groundingElapsedMs = Date.now() - groundingStart;
2361
2382
  const groundingEntry = groundingRaw?.[0] ?? null;
2362
2383
  const groundingRelated = groundingEntry?.related ?? [];
@@ -7454,7 +7475,8 @@ async function runWrapupReview() {
7454
7475
  if (getApiKeyScope() === "read") {
7455
7476
  return { text: "Read-only session \u2014 nothing to review.", data: null, suggestions: [], failureCode: "READONLY_SCOPE" };
7456
7477
  }
7457
- const data = await mcpCall("agent.getSessionWrapup", { sessionId });
7478
+ const kernelEnvelope = await mcpCallEnvelope("agent.getSessionWrapup", { sessionId });
7479
+ const data = kernelEnvelope.data;
7458
7480
  if (data.wrapupCompletedAt) {
7459
7481
  return { text: "Wrapup already completed this session.", data, suggestions: [], failureCode: "ALREADY_COMPLETED" };
7460
7482
  }
@@ -7593,7 +7615,17 @@ async function runWrapupReview() {
7593
7615
  }
7594
7616
  }
7595
7617
  const gapCount = getSessionGaps().length;
7596
- return { text: lines.join("\n"), data, suggestions, gapCount, coherenceVerdict, persistentGaps };
7618
+ return {
7619
+ text: lines.join("\n"),
7620
+ data,
7621
+ suggestions,
7622
+ gapCount,
7623
+ coherenceVerdict,
7624
+ persistentGaps,
7625
+ kernelSummary: kernelEnvelope.summary,
7626
+ kernelNext: kernelEnvelope.next,
7627
+ kernelMeta: kernelEnvelope._meta
7628
+ };
7597
7629
  }
7598
7630
  async function runWrapupCommitAll(data, cachedSuggestions) {
7599
7631
  requireWriteAccess();
@@ -7754,7 +7786,7 @@ function registerWrapupTools(server) {
7754
7786
  );
7755
7787
  }
7756
7788
  const useCachedReview = lastReviewSessionId === sessionId;
7757
- const data2 = useCachedReview && lastReviewData ? lastReviewData : await mcpCall("agent.getSessionWrapup", { sessionId });
7789
+ const data2 = useCachedReview && lastReviewData ? lastReviewData : (await mcpCallEnvelope("agent.getSessionWrapup", { sessionId })).data;
7758
7790
  if (data2.drafts.length === 0) {
7759
7791
  return failureResult("No uncommitted drafts to commit.", "NOT_FOUND", "No uncommitted drafts to commit.", "Nothing to commit.");
7760
7792
  }
@@ -7775,7 +7807,7 @@ function registerWrapupTools(server) {
7775
7807
  }
7776
7808
  );
7777
7809
  }
7778
- const { text, data, suggestions, failureCode, gapCount, coherenceVerdict, persistentGaps } = await runWrapupReview();
7810
+ const { text, data, suggestions, failureCode, gapCount, coherenceVerdict, persistentGaps, kernelSummary, kernelNext, kernelMeta } = await runWrapupReview();
7779
7811
  lastReviewData = data;
7780
7812
  lastReviewSuggestions = suggestions;
7781
7813
  lastReviewSessionId = getAgentSessionId();
@@ -7785,24 +7817,30 @@ ${text}` : text;
7785
7817
  if (failureCode) {
7786
7818
  return failureResult(fullText, failureCode, text);
7787
7819
  }
7788
- const next = data.drafts.length > 0 ? [{ tool: "session-wrapup", description: "Commit all drafts", parameters: { action: "commit-all" } }] : void 0;
7820
+ const localNext = data.drafts.length > 0 ? [{ tool: "session-wrapup", description: "Commit all drafts", parameters: { action: "commit-all" } }] : void 0;
7821
+ const next = kernelNext || localNext;
7789
7822
  const gapsSummary = gapCount ? `, ${gapCount} knowledge gaps detected` : "";
7790
7823
  const coherenceSummary = coherenceVerdict ? `, coherence: ${coherenceVerdict}` : "";
7791
7824
  const persistentSummary = persistentGaps?.length ? `, ${persistentGaps.length} persistent coherence gaps` : "";
7792
- return successResult(
7793
- fullText,
7794
- `Session review: ${data.drafts.length} uncommitted, ${data.committed.length} committed, ${suggestions.length} link suggestions${gapsSummary}${coherenceSummary}${persistentSummary}.`,
7795
- {
7796
- drafts: data.drafts.length,
7797
- committed: data.committed.length,
7798
- uncommitted: data.summary.uncommitted,
7799
- suggestedLinks: suggestions.length,
7800
- knowledgeGaps: gapCount ?? 0,
7801
- ...coherenceVerdict ? { coherenceVerdict } : {},
7802
- ...persistentGaps?.length ? { persistentCoherenceGaps: persistentGaps.length } : {}
7803
- },
7804
- next
7805
- );
7825
+ const summaryText = `Session review: ${data.drafts.length} uncommitted, ${data.committed.length} committed, ${suggestions.length} link suggestions${gapsSummary}${coherenceSummary}${persistentSummary}.`;
7826
+ return {
7827
+ content: [{ type: "text", text: fullText }],
7828
+ structuredContent: {
7829
+ ok: true,
7830
+ summary: kernelSummary || summaryText,
7831
+ data: {
7832
+ drafts: data.drafts.length,
7833
+ committed: data.committed.length,
7834
+ uncommitted: data.summary.uncommitted,
7835
+ suggestedLinks: suggestions.length,
7836
+ knowledgeGaps: gapCount ?? 0,
7837
+ ...coherenceVerdict ? { coherenceVerdict } : {},
7838
+ ...persistentGaps?.length ? { persistentCoherenceGaps: persistentGaps.length } : {}
7839
+ },
7840
+ next,
7841
+ _meta: kernelMeta
7842
+ }
7843
+ };
7806
7844
  };
7807
7845
  const tool = server.registerTool("session-wrapup", {
7808
7846
  title: "Session Wrapup",
@@ -10075,14 +10113,16 @@ async function handleCommitConstellation(args) {
10075
10113
  }
10076
10114
  const author = getAgentSessionId() ? `agent:${getAgentSessionId()}` : void 0;
10077
10115
  const sessionId = getAgentSessionId() ?? void 0;
10116
+ let kernelEnvelope;
10078
10117
  let result;
10079
10118
  try {
10080
- result = await mcpMutation("chain.batchCommitConstellation", {
10119
+ kernelEnvelope = await mcpCallEnvelope("chain.batchCommitConstellation", {
10081
10120
  betEntryId: betId,
10082
10121
  author,
10083
10122
  sessionId,
10084
10123
  operationId
10085
10124
  });
10125
+ result = kernelEnvelope.data;
10086
10126
  } catch (err) {
10087
10127
  const msg = err instanceof Error ? err.message : String(err);
10088
10128
  return {
@@ -10168,13 +10208,16 @@ No constellation entries were committed.`
10168
10208
  lines.push(`- \`${f.entryId}\` ${f.name}: ${f.error}`);
10169
10209
  }
10170
10210
  }
10171
- const summaryText = result.proposalCreated ? `Proposal created for ${betId}. ${result.committedIds.length} entries committed.` : `Published ${result.committedIds.length} entries for ${betId}. ${result.totalRelations} connections preserved.${hasIssues ? ` ${result.failedIds.length} failed, ${result.conflictIds.length} conflicts.` : ""}`;
10211
+ const suggestions = { contradictionWarnings, conflictPreflightSource: preflight.source };
10172
10212
  return {
10173
10213
  content: [{ type: "text", text: lines.join("\n") }],
10174
- structuredContent: success(
10175
- summaryText,
10176
- { ...result, contradictionWarnings, conflictPreflightSource: preflight.source }
10177
- )
10214
+ structuredContent: {
10215
+ ok: true,
10216
+ summary: kernelEnvelope.summary,
10217
+ data: { result, suggestions },
10218
+ next: kernelEnvelope.next,
10219
+ _meta: kernelEnvelope._meta
10220
+ }
10178
10221
  };
10179
10222
  }
10180
10223
 
@@ -15025,7 +15068,7 @@ These are principles, standards, and rules your team has committed to the Chain.
15025
15068
  "## Core Product Architecture\nThe Chain is a versioned, connected, compounding knowledge base \u2014 the SSOT for a product team.\nEverything on the Chain is one of **three primitives**:\n\n- **Entry** (atom) \u2014 a discrete knowledge unit: target audience, business rule, glossary term, metric, tension. Lives in a collection.\n- **Process** (authored) \u2014 a narrative chain with named links (Strategy Coherence, IDM Proposal). Content is inline text. Collection: `chains`.\n- **Map** (composed) \u2014 a framework assembled by reference (Lean Canvas, Empathy Map). Slots point to ingredient entries. Collection: `maps`.\n\nEntries are atoms. Processes author narrative from atoms. Maps compose frameworks from atoms.\nAll three share the same versioning, branching, gating, and relation system.\n\nThe Chain compounds: each new relation makes entries discoverable from more starting points \u2192 context gathering returns richer results \u2192 AI processes have more context \u2192 quality scores improve \u2192 next commit is smarter than the last."
15026
15069
  );
15027
15070
  sections.push(
15028
- "## Architecture\n```\nCursor (stdio) \u2192 MCP Server (mcp-server/src/index.ts)\n \u2192 POST /api/mcp with Bearer token\n \u2192 Convex HTTP Action (convex/http.ts)\n \u2192 internalQuery / internalMutation (convex/agentKnowledge/*)\n \u2192 Convex DB (workspace-scoped)\n```\nSecurity: API key auth on every request, workspace-scoped data, internal functions blocked from external clients.\nKey files: `packages/mcp-server/src/client.ts` (HTTP client + audit), `convex/schema.ts` (schema)."
15071
+ "## Architecture\n```\nCursor (stdio) \u2192 MCP Server (mcp-server/src/index.ts)\n \u2192 POST /api/aki with Bearer token\n \u2192 Convex HTTP Action (convex/http.ts)\n \u2192 internalQuery / internalMutation (convex/agentKnowledge/*)\n \u2192 Convex DB (workspace-scoped)\n```\nSecurity: API key auth on every request, workspace-scoped data, internal functions blocked from external clients.\nKey files: `packages/mcp-server/src/client.ts` (HTTP client + audit), `convex/schema.ts` (schema)."
15029
15072
  );
15030
15073
  if (collections) {
15031
15074
  const collList = collections.map((c) => {
@@ -15766,4 +15809,4 @@ export {
15766
15809
  SERVER_VERSION,
15767
15810
  createProductBrainServer
15768
15811
  };
15769
- //# sourceMappingURL=chunk-EPAHRXLQ.js.map
15812
+ //# sourceMappingURL=chunk-K2GIX46U.js.map