@productbrain/mcp 0.0.1-beta.26 → 0.0.1-beta.28
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-PTFZHZZJ.js} +174 -5
- package/dist/chunk-PTFZHZZJ.js.map +1 -0
- package/dist/{chunk-EVF3CYZN.js → chunk-UZDFQUAR.js} +121 -21
- package/dist/chunk-UZDFQUAR.js.map +1 -0
- package/dist/http.js +2 -2
- package/dist/index.js +2 -2
- package/dist/{smart-capture-NX4QDLLY.js → smart-capture-AEPYZ2EA.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-AEPYZ2EA.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-UZDFQUAR.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-AEPYZ2EA.js");
|
|
924
1004
|
const entry = await mcpQuery("chain.getEntry", { entryId });
|
|
925
1005
|
if (!entry) {
|
|
926
1006
|
return {
|
|
@@ -934,7 +1014,8 @@ Use \`list-collections\` to verify the result.`
|
|
|
934
1014
|
}
|
|
935
1015
|
const result = await mcpMutation("chain.commitEntry", {
|
|
936
1016
|
entryId,
|
|
937
|
-
author: getAgentSessionId() ? `agent:${getAgentSessionId()}` : void 0
|
|
1017
|
+
author: getAgentSessionId() ? `agent:${getAgentSessionId()}` : void 0,
|
|
1018
|
+
sessionId: getAgentSessionId() ?? void 0
|
|
938
1019
|
});
|
|
939
1020
|
const docId = result?._id ?? entry._id;
|
|
940
1021
|
await recordSessionActivity({ entryModified: docId });
|
|
@@ -1240,6 +1321,27 @@ function buildSessionSummary(log) {
|
|
|
1240
1321
|
}
|
|
1241
1322
|
return lines.join("\n");
|
|
1242
1323
|
}
|
|
1324
|
+
function extractSessionEntryIds(priorSessions) {
|
|
1325
|
+
const allSeen = /* @__PURE__ */ new Set();
|
|
1326
|
+
const all = [];
|
|
1327
|
+
let lastSessionOnly = [];
|
|
1328
|
+
for (let i = 0; i < priorSessions.length; i++) {
|
|
1329
|
+
const s = priorSessions[i];
|
|
1330
|
+
const ids = [...s.entriesCreated ?? [], ...s.entriesModified ?? []].filter((id) => id);
|
|
1331
|
+
if (i === 0) {
|
|
1332
|
+
lastSessionOnly = [...new Set(ids)].slice(0, 5);
|
|
1333
|
+
}
|
|
1334
|
+
for (const id of ids) {
|
|
1335
|
+
if (!allSeen.has(id)) {
|
|
1336
|
+
allSeen.add(id);
|
|
1337
|
+
all.push(id);
|
|
1338
|
+
if (all.length >= 10) break;
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
if (all.length >= 10) break;
|
|
1342
|
+
}
|
|
1343
|
+
return { all, lastSessionOnly };
|
|
1344
|
+
}
|
|
1243
1345
|
function registerHealthTools(server) {
|
|
1244
1346
|
server.registerTool(
|
|
1245
1347
|
"health",
|
|
@@ -1389,9 +1491,14 @@ function registerHealthTools(server) {
|
|
|
1389
1491
|
} catch {
|
|
1390
1492
|
}
|
|
1391
1493
|
}
|
|
1494
|
+
const { all: sessionEntryIds, lastSessionOnly } = extractSessionEntryIds(priorSessions);
|
|
1392
1495
|
let orientEntries = null;
|
|
1393
1496
|
try {
|
|
1394
|
-
|
|
1497
|
+
const orientArgs = {};
|
|
1498
|
+
if (task) orientArgs.task = task;
|
|
1499
|
+
if (sessionEntryIds.length > 0) orientArgs.sessionEntryIds = sessionEntryIds;
|
|
1500
|
+
if (lastSessionOnly.length > 0) orientArgs.lastSessionEntryIds = lastSessionOnly;
|
|
1501
|
+
orientEntries = await mcpQuery("chain.getOrientEntries", orientArgs);
|
|
1395
1502
|
} catch {
|
|
1396
1503
|
}
|
|
1397
1504
|
let openTensions = [];
|
|
@@ -1516,6 +1623,31 @@ function registerHealthTools(server) {
|
|
|
1516
1623
|
lines.push(`${betLine} ${sc.activeTensionCount} open tension(s).`);
|
|
1517
1624
|
lines.push("");
|
|
1518
1625
|
}
|
|
1626
|
+
if (orientEntries?.continuingFrom && orientEntries.continuingFrom.length > 0) {
|
|
1627
|
+
lines.push("## Continuing from");
|
|
1628
|
+
lines.push("_Prior-session entries most relevant to your task._");
|
|
1629
|
+
lines.push("");
|
|
1630
|
+
for (const e of orientEntries.continuingFrom) {
|
|
1631
|
+
const id = e.entryId ?? e.name;
|
|
1632
|
+
const type = e.canonicalKey ?? "generic";
|
|
1633
|
+
const coll = e.collectionSlug ? ` [${e.collectionSlug}]` : "";
|
|
1634
|
+
lines.push(`- \`${id}\` (score ${e.score}) [${type}]${coll} \u2014 ${e.name}`);
|
|
1635
|
+
if (e.reasoning) lines.push(` _${e.reasoning}_`);
|
|
1636
|
+
}
|
|
1637
|
+
lines.push("");
|
|
1638
|
+
}
|
|
1639
|
+
if (orientEntries?.lastSessionTouched && orientEntries.lastSessionTouched.length > 0) {
|
|
1640
|
+
lines.push("## Last session touched");
|
|
1641
|
+
lines.push("_Entries created or modified in your most recent session._");
|
|
1642
|
+
lines.push("");
|
|
1643
|
+
for (const e of orientEntries.lastSessionTouched) {
|
|
1644
|
+
const id = e.entryId ?? e.name;
|
|
1645
|
+
const type = e.canonicalKey ?? "generic";
|
|
1646
|
+
const coll = e.collectionSlug ? ` [${e.collectionSlug}]` : "";
|
|
1647
|
+
lines.push(`- \`${id}\` [${type}]${coll} \u2014 ${e.name}`);
|
|
1648
|
+
}
|
|
1649
|
+
lines.push("");
|
|
1650
|
+
}
|
|
1519
1651
|
if (orientEntries?.taskContext && orientEntries.taskContext.context.length > 0) {
|
|
1520
1652
|
const tc = orientEntries.taskContext;
|
|
1521
1653
|
lines.push("## Task Context");
|
|
@@ -3418,6 +3550,43 @@ function slotSummary(slots) {
|
|
|
3418
3550
|
}).join("\n");
|
|
3419
3551
|
}
|
|
3420
3552
|
function registerMapTools(server) {
|
|
3553
|
+
server.registerTool(
|
|
3554
|
+
"create-audience-map-set",
|
|
3555
|
+
{
|
|
3556
|
+
title: "Create Audience Map Set",
|
|
3557
|
+
description: "Create all three audience intelligence maps (Empathy, Narrowing, Jobs & Alternatives) anchored to one audience entry. The audience is pre-slotted in the anchor position of each map.",
|
|
3558
|
+
inputSchema: {
|
|
3559
|
+
audienceEntryId: z8.string().describe("Entry ID of the audience (e.g. STR-fb7hje)")
|
|
3560
|
+
}
|
|
3561
|
+
},
|
|
3562
|
+
async ({ audienceEntryId }) => {
|
|
3563
|
+
const result = await mcpMutation(
|
|
3564
|
+
"maps.createAudienceMapSet",
|
|
3565
|
+
{ audienceEntryId }
|
|
3566
|
+
);
|
|
3567
|
+
const wsCtx = await getWorkspaceContext();
|
|
3568
|
+
const lines = result.maps.map(
|
|
3569
|
+
(m) => `- **${m.templateId}**: \`${m.mapEntryId}\``
|
|
3570
|
+
);
|
|
3571
|
+
return {
|
|
3572
|
+
content: [
|
|
3573
|
+
{
|
|
3574
|
+
type: "text",
|
|
3575
|
+
text: `# Audience Map Set Created
|
|
3576
|
+
|
|
3577
|
+
**Audience:** \`${result.audienceEntryId}\`
|
|
3578
|
+
**Workspace:** ${wsCtx.workspaceSlug}
|
|
3579
|
+
|
|
3580
|
+
## Maps
|
|
3581
|
+
|
|
3582
|
+
${lines.join("\n")}
|
|
3583
|
+
|
|
3584
|
+
Use map-slot to add ingredients. View at /empathy, /narrowing, and /jobs.`
|
|
3585
|
+
}
|
|
3586
|
+
]
|
|
3587
|
+
};
|
|
3588
|
+
}
|
|
3589
|
+
);
|
|
3421
3590
|
server.registerTool(
|
|
3422
3591
|
"map",
|
|
3423
3592
|
{
|
|
@@ -4727,4 +4896,4 @@ export {
|
|
|
4727
4896
|
SERVER_VERSION,
|
|
4728
4897
|
createProductBrainServer
|
|
4729
4898
|
};
|
|
4730
|
-
//# sourceMappingURL=chunk-
|
|
4899
|
+
//# sourceMappingURL=chunk-PTFZHZZJ.js.map
|