@productbrain/mcp 0.0.1-beta.26 → 0.0.1-beta.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-PVWT5LIB.js → chunk-R4LVIGFQ.js} +135 -4
- package/dist/chunk-R4LVIGFQ.js.map +1 -0
- package/dist/{chunk-EVF3CYZN.js → chunk-YCHKN75N.js} +112 -21
- package/dist/chunk-YCHKN75N.js.map +1 -0
- package/dist/http.js +2 -2
- package/dist/index.js +2 -2
- package/dist/{smart-capture-NX4QDLLY.js → smart-capture-WWGVXMQ2.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-EVF3CYZN.js.map +0 -1
- package/dist/chunk-PVWT5LIB.js.map +0 -1
- /package/dist/{smart-capture-NX4QDLLY.js.map → smart-capture-WWGVXMQ2.js.map} +0 -0
|
@@ -10,10 +10,11 @@ import {
|
|
|
10
10
|
mcpQuery,
|
|
11
11
|
recordSessionActivity,
|
|
12
12
|
registerSmartCaptureTools,
|
|
13
|
+
requireActiveSession,
|
|
13
14
|
requireWriteAccess,
|
|
14
15
|
setSessionOriented,
|
|
15
16
|
startAgentSession
|
|
16
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-YCHKN75N.js";
|
|
17
18
|
|
|
18
19
|
// src/server.ts
|
|
19
20
|
import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -429,6 +430,9 @@ The relation was **not applied** \u2014 it will be created when the proposal is
|
|
|
429
430
|
const created = results.filter((r) => r.ok && !r.proposalCreated);
|
|
430
431
|
const proposals = results.filter((r) => r.ok && r.proposalCreated);
|
|
431
432
|
const failed = results.filter((r) => !r.ok);
|
|
433
|
+
for (let i = 0; i < created.length; i++) {
|
|
434
|
+
await recordSessionActivity({ relationCreated: true });
|
|
435
|
+
}
|
|
432
436
|
const lines = [`# Batch Link Results
|
|
433
437
|
`];
|
|
434
438
|
lines.push(`**${created.length}** created, **${proposals.length}** proposals, **${failed.length}** failed out of ${relations.length} total.
|
|
@@ -690,6 +694,82 @@ Use \`suggest-links\` to discover potential connections, or \`relate-entries\` t
|
|
|
690
694
|
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
691
695
|
}
|
|
692
696
|
);
|
|
697
|
+
server.registerTool(
|
|
698
|
+
"get-build-context",
|
|
699
|
+
{
|
|
700
|
+
title: "Get Build Context",
|
|
701
|
+
description: "Assemble a structured build spec for any entry. Collection-agnostic: works with bets, features, epics, or any collection type. Returns the entry data, related entries by collection, applicable business rules, glossary terms, and chain refs to consult. Use this when starting a build to get full context in one call \u2014 no need to call orient, gather-context, and search separately.\n\nPass an entry ID (e.g. 'ENT-wc7u71', 'BET-001') or name. The output adapts to the entry's collection schema.",
|
|
702
|
+
inputSchema: {
|
|
703
|
+
entryId: z.string().describe("Entry ID or name (e.g. 'ENT-wc7u71', 'PB as Shared Memory')"),
|
|
704
|
+
maxHops: z.number().min(1).max(3).default(2).optional().describe("Relation traversal depth (default 2)")
|
|
705
|
+
},
|
|
706
|
+
annotations: { readOnlyHint: true }
|
|
707
|
+
},
|
|
708
|
+
async ({ entryId, maxHops }) => {
|
|
709
|
+
requireActiveSession();
|
|
710
|
+
const result = await mcpQuery("chain.assembleBuildContext", {
|
|
711
|
+
entryId,
|
|
712
|
+
maxHops: maxHops ?? 2
|
|
713
|
+
});
|
|
714
|
+
const { entry, relatedByCollection, businessRules, glossaryTerms, rulesToHonor, chainRefs, contextTruncated } = result;
|
|
715
|
+
const lines = [
|
|
716
|
+
`# Build Context: ${entry.name}`,
|
|
717
|
+
`**Entry:** ${entry.entryId ?? entry.name} [${entry.collectionSlug}]`,
|
|
718
|
+
`**Status:** ${entry.status}`,
|
|
719
|
+
""
|
|
720
|
+
];
|
|
721
|
+
if (Object.keys(entry.data).length > 0) {
|
|
722
|
+
lines.push("## Entry Data");
|
|
723
|
+
for (const [key, val] of Object.entries(entry.data)) {
|
|
724
|
+
const str = typeof val === "string" ? val : JSON.stringify(val);
|
|
725
|
+
if (str.length > 200) {
|
|
726
|
+
lines.push(`- **${key}:** ${str.slice(0, 200)}...`);
|
|
727
|
+
} else {
|
|
728
|
+
lines.push(`- **${key}:** ${str}`);
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
lines.push("");
|
|
732
|
+
}
|
|
733
|
+
if (businessRules.length > 0) {
|
|
734
|
+
lines.push("## Business Rules to Honor");
|
|
735
|
+
for (const r of businessRules) {
|
|
736
|
+
const id = r.entryId ?? r.name;
|
|
737
|
+
lines.push(`- **${id}:** ${r.name}`);
|
|
738
|
+
if (r.description) lines.push(` ${r.description.slice(0, 150)}${r.description.length > 150 ? "..." : ""}`);
|
|
739
|
+
}
|
|
740
|
+
lines.push("");
|
|
741
|
+
}
|
|
742
|
+
if (glossaryTerms.length > 0) {
|
|
743
|
+
lines.push("## Glossary Terms");
|
|
744
|
+
for (const t of glossaryTerms.slice(0, 15)) {
|
|
745
|
+
const id = t.entryId ?? t.name;
|
|
746
|
+
lines.push(`- **${id}:** ${t.name}`);
|
|
747
|
+
if (t.definition) lines.push(` ${t.definition.slice(0, 120)}${t.definition.length > 120 ? "..." : ""}`);
|
|
748
|
+
}
|
|
749
|
+
if (glossaryTerms.length > 15) lines.push(` _...and ${glossaryTerms.length - 15} more_`);
|
|
750
|
+
lines.push("");
|
|
751
|
+
}
|
|
752
|
+
const relatedCount = Object.values(relatedByCollection).reduce((sum, arr) => sum + arr.length, 0);
|
|
753
|
+
if (relatedCount > 0) {
|
|
754
|
+
lines.push("## Related Entries");
|
|
755
|
+
for (const [coll, entries] of Object.entries(relatedByCollection)) {
|
|
756
|
+
lines.push(`### ${coll} (${entries.length})`);
|
|
757
|
+
for (const e of entries.slice(0, 5)) {
|
|
758
|
+
lines.push(`- ${e.entryId ?? e.name}: ${e.name} [${e.relationType}]`);
|
|
759
|
+
}
|
|
760
|
+
if (entries.length > 5) lines.push(` _...and ${entries.length - 5} more_`);
|
|
761
|
+
}
|
|
762
|
+
lines.push("");
|
|
763
|
+
}
|
|
764
|
+
lines.push("## Chain Refs to Consult");
|
|
765
|
+
lines.push(chainRefs.slice(0, 15).map((r) => `- ${r}`).join("\n"));
|
|
766
|
+
if (contextTruncated) {
|
|
767
|
+
lines.push("");
|
|
768
|
+
lines.push("_Context was truncated (limits: 50 related, 20 rules, 30 glossary). Use get-entry for full details._");
|
|
769
|
+
}
|
|
770
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
771
|
+
}
|
|
772
|
+
);
|
|
693
773
|
server.registerTool(
|
|
694
774
|
"suggest-links",
|
|
695
775
|
{
|
|
@@ -920,7 +1000,7 @@ Use \`list-collections\` to verify the result.`
|
|
|
920
1000
|
},
|
|
921
1001
|
async ({ entryId }) => {
|
|
922
1002
|
requireWriteAccess();
|
|
923
|
-
const { runContradictionCheck } = await import("./smart-capture-
|
|
1003
|
+
const { runContradictionCheck } = await import("./smart-capture-WWGVXMQ2.js");
|
|
924
1004
|
const entry = await mcpQuery("chain.getEntry", { entryId });
|
|
925
1005
|
if (!entry) {
|
|
926
1006
|
return {
|
|
@@ -1240,6 +1320,27 @@ function buildSessionSummary(log) {
|
|
|
1240
1320
|
}
|
|
1241
1321
|
return lines.join("\n");
|
|
1242
1322
|
}
|
|
1323
|
+
function extractSessionEntryIds(priorSessions) {
|
|
1324
|
+
const allSeen = /* @__PURE__ */ new Set();
|
|
1325
|
+
const all = [];
|
|
1326
|
+
let lastSessionOnly = [];
|
|
1327
|
+
for (let i = 0; i < priorSessions.length; i++) {
|
|
1328
|
+
const s = priorSessions[i];
|
|
1329
|
+
const ids = [...s.entriesCreated ?? [], ...s.entriesModified ?? []].filter((id) => id);
|
|
1330
|
+
if (i === 0) {
|
|
1331
|
+
lastSessionOnly = [...new Set(ids)].slice(0, 5);
|
|
1332
|
+
}
|
|
1333
|
+
for (const id of ids) {
|
|
1334
|
+
if (!allSeen.has(id)) {
|
|
1335
|
+
allSeen.add(id);
|
|
1336
|
+
all.push(id);
|
|
1337
|
+
if (all.length >= 10) break;
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
if (all.length >= 10) break;
|
|
1341
|
+
}
|
|
1342
|
+
return { all, lastSessionOnly };
|
|
1343
|
+
}
|
|
1243
1344
|
function registerHealthTools(server) {
|
|
1244
1345
|
server.registerTool(
|
|
1245
1346
|
"health",
|
|
@@ -1389,9 +1490,14 @@ function registerHealthTools(server) {
|
|
|
1389
1490
|
} catch {
|
|
1390
1491
|
}
|
|
1391
1492
|
}
|
|
1493
|
+
const { all: sessionEntryIds, lastSessionOnly } = extractSessionEntryIds(priorSessions);
|
|
1392
1494
|
let orientEntries = null;
|
|
1393
1495
|
try {
|
|
1394
|
-
|
|
1496
|
+
const orientArgs = {};
|
|
1497
|
+
if (task) orientArgs.task = task;
|
|
1498
|
+
if (sessionEntryIds.length > 0) orientArgs.sessionEntryIds = sessionEntryIds;
|
|
1499
|
+
if (lastSessionOnly.length > 0) orientArgs.lastSessionEntryIds = lastSessionOnly;
|
|
1500
|
+
orientEntries = await mcpQuery("chain.getOrientEntries", orientArgs);
|
|
1395
1501
|
} catch {
|
|
1396
1502
|
}
|
|
1397
1503
|
let openTensions = [];
|
|
@@ -1516,6 +1622,31 @@ function registerHealthTools(server) {
|
|
|
1516
1622
|
lines.push(`${betLine} ${sc.activeTensionCount} open tension(s).`);
|
|
1517
1623
|
lines.push("");
|
|
1518
1624
|
}
|
|
1625
|
+
if (orientEntries?.continuingFrom && orientEntries.continuingFrom.length > 0) {
|
|
1626
|
+
lines.push("## Continuing from");
|
|
1627
|
+
lines.push("_Prior-session entries most relevant to your task._");
|
|
1628
|
+
lines.push("");
|
|
1629
|
+
for (const e of orientEntries.continuingFrom) {
|
|
1630
|
+
const id = e.entryId ?? e.name;
|
|
1631
|
+
const type = e.canonicalKey ?? "generic";
|
|
1632
|
+
const coll = e.collectionSlug ? ` [${e.collectionSlug}]` : "";
|
|
1633
|
+
lines.push(`- \`${id}\` (score ${e.score}) [${type}]${coll} \u2014 ${e.name}`);
|
|
1634
|
+
if (e.reasoning) lines.push(` _${e.reasoning}_`);
|
|
1635
|
+
}
|
|
1636
|
+
lines.push("");
|
|
1637
|
+
}
|
|
1638
|
+
if (orientEntries?.lastSessionTouched && orientEntries.lastSessionTouched.length > 0) {
|
|
1639
|
+
lines.push("## Last session touched");
|
|
1640
|
+
lines.push("_Entries created or modified in your most recent session._");
|
|
1641
|
+
lines.push("");
|
|
1642
|
+
for (const e of orientEntries.lastSessionTouched) {
|
|
1643
|
+
const id = e.entryId ?? e.name;
|
|
1644
|
+
const type = e.canonicalKey ?? "generic";
|
|
1645
|
+
const coll = e.collectionSlug ? ` [${e.collectionSlug}]` : "";
|
|
1646
|
+
lines.push(`- \`${id}\` [${type}]${coll} \u2014 ${e.name}`);
|
|
1647
|
+
}
|
|
1648
|
+
lines.push("");
|
|
1649
|
+
}
|
|
1519
1650
|
if (orientEntries?.taskContext && orientEntries.taskContext.context.length > 0) {
|
|
1520
1651
|
const tc = orientEntries.taskContext;
|
|
1521
1652
|
lines.push("## Task Context");
|
|
@@ -4727,4 +4858,4 @@ export {
|
|
|
4727
4858
|
SERVER_VERSION,
|
|
4728
4859
|
createProductBrainServer
|
|
4729
4860
|
};
|
|
4730
|
-
//# sourceMappingURL=chunk-
|
|
4861
|
+
//# sourceMappingURL=chunk-R4LVIGFQ.js.map
|