@productbrain/mcp 0.0.1-beta.5543 → 0.0.1-beta.5547
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.
|
@@ -15334,6 +15334,9 @@ function stripControlChars(str) {
|
|
|
15334
15334
|
if (!str) return str;
|
|
15335
15335
|
return str.replace(ANSI_AND_CONTROL_RE2, "");
|
|
15336
15336
|
}
|
|
15337
|
+
function sanitizeSingleLineField(str) {
|
|
15338
|
+
return stripControlChars(str).replace(/\s+/g, " ").trim();
|
|
15339
|
+
}
|
|
15337
15340
|
|
|
15338
15341
|
// src/tools/question.ts
|
|
15339
15342
|
var QUESTION_ACTIONS = ["create", "adopt", "assign", "snooze", "decline", "answer", "force-close", "list"];
|
|
@@ -15598,6 +15601,93 @@ function registerQuestionTools(server) {
|
|
|
15598
15601
|
);
|
|
15599
15602
|
}
|
|
15600
15603
|
|
|
15604
|
+
// src/tools/role.ts
|
|
15605
|
+
import { z as z34 } from "zod/v3";
|
|
15606
|
+
var ROLE_ACTIONS = ["accountable"];
|
|
15607
|
+
var roleSchema = z34.object({
|
|
15608
|
+
action: z34.enum(ROLE_ACTIONS).describe("'accountable': what this role owns (explicit), reports on (reporting), and \u2014 not yet computed \u2014 inherits via Team-Lead vacancy coverage."),
|
|
15609
|
+
roleId: z34.string().max(200).optional().describe("The role, by the human chain id `chain.getEntry` or `pb get` would print for it, or a raw entry id. Required for 'accountable'."),
|
|
15610
|
+
canonicalKey: z34.string().max(200).optional().describe("'accountable': narrow to one kind (e.g. objective, key_result, tension)."),
|
|
15611
|
+
limit: z34.number().int().positive().max(200).optional().describe("'accountable': max explicit-list rows per page (default and maximum 200)."),
|
|
15612
|
+
cursor: z34.number().optional().describe("'accountable': continue the explicit list from an earlier truncated page's nextCursor.")
|
|
15613
|
+
});
|
|
15614
|
+
var accountableVariant = z34.object({
|
|
15615
|
+
action: z34.literal("accountable"),
|
|
15616
|
+
roleId: z34.string().max(200),
|
|
15617
|
+
canonicalKey: z34.string().max(200).optional(),
|
|
15618
|
+
limit: z34.number().int().positive().max(200).optional(),
|
|
15619
|
+
cursor: z34.number().optional()
|
|
15620
|
+
});
|
|
15621
|
+
var roleActionUnion = z34.discriminatedUnion("action", [accountableVariant]);
|
|
15622
|
+
var ROLE_ACTION_SPECS = {
|
|
15623
|
+
accountable: { params: ["roleId", "canonicalKey", "limit", "cursor"], description: "roleId is required; canonicalKey/limit/cursor are optional." }
|
|
15624
|
+
};
|
|
15625
|
+
function formatRow(row) {
|
|
15626
|
+
const id = row.entryId ?? row.id;
|
|
15627
|
+
return ` ${id} ${sanitizeSingleLineField(row.name)} [${row.canonicalKey ?? "?"}/${row.status}]`;
|
|
15628
|
+
}
|
|
15629
|
+
function formatSection(label, rows, truncated, cursorHint) {
|
|
15630
|
+
if (rows.length === 0) return [` ${label}: not recorded yet`];
|
|
15631
|
+
const lines = [` ${label}:`, ...rows.map(formatRow)];
|
|
15632
|
+
if (truncated) lines.push(` (more exist \u2014 ${cursorHint ?? "raise limit (capped at 200, no cursor for this list)"})`);
|
|
15633
|
+
return lines;
|
|
15634
|
+
}
|
|
15635
|
+
function formatRoleAccountable(result2) {
|
|
15636
|
+
const roleLabel = `${sanitizeSingleLineField(result2.role.name)} (${result2.role.entryId ?? result2.role.id})`;
|
|
15637
|
+
const explicitCursorHint = result2.nextCursor !== null ? `raise limit or continue with cursor ${result2.nextCursor}` : "raise limit";
|
|
15638
|
+
return [
|
|
15639
|
+
`${roleLabel} \u2014 accountability:`,
|
|
15640
|
+
...formatSection("explicit (owns)", result2.explicit, result2.explicitTruncated, explicitCursorHint),
|
|
15641
|
+
...formatSection("reporting (reports on)", result2.reporting, result2.reportingTruncated),
|
|
15642
|
+
` inherited: not-computed \u2014 ${result2.inheritedNotComputedReason}`
|
|
15643
|
+
].join("\n");
|
|
15644
|
+
}
|
|
15645
|
+
async function handleRoleAccountable(roleId, canonicalKey, limit, cursor) {
|
|
15646
|
+
try {
|
|
15647
|
+
const raw = await kernelQuery("chain.listByRole", { roleId, canonicalKey, limit, cursor });
|
|
15648
|
+
const result2 = raw;
|
|
15649
|
+
const message = formatRoleAccountable(result2);
|
|
15650
|
+
return successResult(message, message, result2);
|
|
15651
|
+
} catch (err) {
|
|
15652
|
+
return roleErrorResult(err, "accountable", { roleId, canonicalKey, limit, cursor });
|
|
15653
|
+
}
|
|
15654
|
+
}
|
|
15655
|
+
function roleErrorResult(err, action, params = {}) {
|
|
15656
|
+
const classified = classifyError(err);
|
|
15657
|
+
const definedParams = Object.fromEntries(Object.entries(params).filter(([, v]) => v !== void 0));
|
|
15658
|
+
return failureResult(
|
|
15659
|
+
classified.message,
|
|
15660
|
+
classified.code,
|
|
15661
|
+
classified.message,
|
|
15662
|
+
classified.recovery ?? "Use action='accountable' with roleId set to a real role's chain id or entry id.",
|
|
15663
|
+
classified.availableActions ?? [{ tool: "role", description: `Retry ${action}`, parameters: { action, ...definedParams } }],
|
|
15664
|
+
classified.diagnostics
|
|
15665
|
+
);
|
|
15666
|
+
}
|
|
15667
|
+
function registerRoleTools(server) {
|
|
15668
|
+
const roleHandlers = {
|
|
15669
|
+
accountable: (data) => handleRoleAccountable(data.roleId, data.canonicalKey, data.limit, data.cursor)
|
|
15670
|
+
};
|
|
15671
|
+
server.registerTool(
|
|
15672
|
+
"role",
|
|
15673
|
+
{
|
|
15674
|
+
title: "Role",
|
|
15675
|
+
description: "Workspace roles \u2014 who is accountable for what. One action:\n\n- **accountable**: what this role owns (`explicit`, data.ownerRoleId), reports on (`reporting`, data.reporterRoleId \u2014 key results and tensions only, a separate fact from ownership), and \u2014 always `not-computed` today, never faked as empty \u2014 inherits via Team-Lead vacancy coverage.",
|
|
15676
|
+
inputSchema: roleSchema,
|
|
15677
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
|
|
15678
|
+
},
|
|
15679
|
+
thinWrapper(async (args) => {
|
|
15680
|
+
const parsed = parseOrFail(roleSchema, args);
|
|
15681
|
+
if (!parsed.ok) return parsed.result;
|
|
15682
|
+
const { action } = parsed.data;
|
|
15683
|
+
return runWithToolContext(
|
|
15684
|
+
{ tool: "role", action },
|
|
15685
|
+
() => dispatchDiscriminated("role", roleActionUnion, parsed.data, ROLE_ACTION_SPECS, roleHandlers)
|
|
15686
|
+
);
|
|
15687
|
+
})
|
|
15688
|
+
);
|
|
15689
|
+
}
|
|
15690
|
+
|
|
15601
15691
|
// src/resources/index.ts
|
|
15602
15692
|
import { existsSync as existsSync3 } from "fs";
|
|
15603
15693
|
import { dirname, join, resolve as resolve4 } from "path";
|
|
@@ -15607,7 +15697,7 @@ import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
15607
15697
|
// src/resources/agentCheatsheet.ts
|
|
15608
15698
|
var AGENT_CHEATSHEET = `# Product Brain \u2014 Agent Cheatsheet
|
|
15609
15699
|
|
|
15610
|
-
## Core Tools (Serves
|
|
15700
|
+
## Core Tools (Serves 14 default compound tools; 2 more (chain, chain-review) behind PB_MODULES=gitchain \u2014 map retired, L29)
|
|
15611
15701
|
| Tool | Purpose | Key params |
|
|
15612
15702
|
|---|---|---|
|
|
15613
15703
|
| \`orient\` | Workspace context, governance, active work packages, session start | \`action\`: start, task, record-activation |
|
|
@@ -15623,6 +15713,7 @@ var AGENT_CHEATSHEET = `# Product Brain \u2014 Agent Cheatsheet
|
|
|
15623
15713
|
| \`feedback\` | Submit product feedback (any key, no session required); \`list\` reads back your own workspace's feedback (no gate); vendor triage: queue / note / group / status | \`action\`: submit, list, queue, note, group, status |
|
|
15624
15714
|
| \`shape\` | Review / disposition write-shape (single-concern split) advisories | \`action\`: list, show, agree, dismiss |
|
|
15625
15715
|
| \`question\` | Routed questions \u2014 create/adopt, own, snooze, decline, answer, force-close | \`action\`: create, adopt, assign, snooze, decline, answer, force-close |
|
|
15716
|
+
| \`role\` | What a role is accountable for \u2014 owns, reports on, and (not yet computed) inherits via Team-Lead vacancy coverage | \`action\`: accountable |
|
|
15626
15717
|
|
|
15627
15718
|
## Collection Prefixes
|
|
15628
15719
|
GLO (glossary), BR (business-rules), PRI (principles), STD (standards),
|
|
@@ -16109,12 +16200,12 @@ ${entry.labels.map((l) => `- ${l.name ?? l.slug}`).join("\n")}`);
|
|
|
16109
16200
|
}
|
|
16110
16201
|
|
|
16111
16202
|
// src/prompts/index.ts
|
|
16112
|
-
import { z as
|
|
16203
|
+
import { z as z35 } from "zod/v3";
|
|
16113
16204
|
function registerPrompts(server) {
|
|
16114
16205
|
server.prompt(
|
|
16115
16206
|
"review-against-rules",
|
|
16116
16207
|
"Review code or a design decision against all business rules for a given domain. Fetches the rules and asks you to do a structured compliance review.",
|
|
16117
|
-
{ domain:
|
|
16208
|
+
{ domain: z35.string().describe("Business rule domain (e.g. 'Identity & Access', 'Governance & Decision-Making')") },
|
|
16118
16209
|
async ({ domain }) => {
|
|
16119
16210
|
const entries = await kernelQuery("chain.listEntries", { collectionSlug: "business-rules" });
|
|
16120
16211
|
const rules = entries.filter((e) => e.data?.domain === domain);
|
|
@@ -16167,7 +16258,7 @@ Provide a structured review with a compliance status for each rule (COMPLIANT /
|
|
|
16167
16258
|
server.prompt(
|
|
16168
16259
|
"name-check",
|
|
16169
16260
|
"Check variable names, field names, or API names against the glossary for terminology alignment. Flags drift from canonical terms.",
|
|
16170
|
-
{ names:
|
|
16261
|
+
{ names: z35.string().describe("Comma-separated list of names to check (e.g. 'vendor_id, compliance_level, formulator_type')") },
|
|
16171
16262
|
async ({ names }) => {
|
|
16172
16263
|
const terms = await kernelQuery("chain.listEntries", { collectionSlug: "glossary" });
|
|
16173
16264
|
const glossaryContext = terms.map(
|
|
@@ -16203,7 +16294,7 @@ Format as a table: Name | Status | Canonical Form | Action Needed`
|
|
|
16203
16294
|
server.prompt(
|
|
16204
16295
|
"draft-decision-record",
|
|
16205
16296
|
"Draft a structured decision record from a description of what was decided. Includes context from recent decisions and relevant rules.",
|
|
16206
|
-
{ context:
|
|
16297
|
+
{ context: z35.string().describe("Description of the decision (e.g. 'We decided to use MRSL v3.1 as the conformance baseline because...')") },
|
|
16207
16298
|
async ({ context }) => {
|
|
16208
16299
|
const recentDecisions = await kernelQuery("chain.listEntries", { collectionSlug: "decisions" });
|
|
16209
16300
|
const sorted = [...recentDecisions].sort((a, b) => (b.data?.date ?? "") > (a.data?.date ?? "") ? 1 : -1).slice(0, 5);
|
|
@@ -16241,8 +16332,8 @@ After drafting, I can log it using the capture tool with collection "decisions".
|
|
|
16241
16332
|
"draft-rule-from-context",
|
|
16242
16333
|
"Draft a new business rule from an observation or discovery made while coding. Fetches existing rules for the domain to ensure consistency.",
|
|
16243
16334
|
{
|
|
16244
|
-
observation:
|
|
16245
|
-
domain:
|
|
16335
|
+
observation: z35.string().describe("What you observed or discovered (e.g. 'Suppliers can have multiple org types in Gateway')"),
|
|
16336
|
+
domain: z35.string().describe("Which domain this rule belongs to (e.g. 'Governance & Decision-Making')")
|
|
16246
16337
|
},
|
|
16247
16338
|
async ({ observation, domain }) => {
|
|
16248
16339
|
const allRules = await kernelQuery("chain.listEntries", { collectionSlug: "business-rules" });
|
|
@@ -16308,7 +16399,7 @@ var INSTRUCTIONS = [
|
|
|
16308
16399
|
"- **Self-documenting**: orient and server instructions teach agents how PB works. Cursor rules supplement but don't replace.",
|
|
16309
16400
|
"",
|
|
16310
16401
|
"### Tool Rename Notice (WP-484 S3, one release)",
|
|
16311
|
-
"Serves
|
|
16402
|
+
"Serves 14 default compound tools (WP-559 adds `shape` \u2014 review/disposition for write-shape advisories; WP-638 S3 adds `question` \u2014 routed-question routing/ownership/lifecycle; WP-730 S2 adds `role` \u2014 role accountability); 2 more (chain, chain-review) behind PB_MODULES=gitchain.",
|
|
16312
16403
|
"Old standalone names are gone \u2014 no alias window (ASM-43: zero external consumers). Map: `start_pb`\u2192`orient action=start`, `record_activation`\u2192`orient action=record-activation`, `session-wrapup`\u2192`session action=wrapup-review|wrapup-commit`, `facilitate`\u2192`session action=resume|commit-constellation`, `update-entry`\u2192`entries action=update`, `commit-entry`\u2192`entries action=commit`, `get-history`\u2192`entries action=history`, `move-entry`\u2192`entries action=move`, `verify-entry`\u2192`entries action=verify`, `graph`\u2192`relations action=find|suggest`, `documents`\u2192`context action=last-verified-brief`, `labels`\u2192`collections action=label-*`, `verify`\u2192`quality action=verify-chain`, `audit`\u2192`quality action=audit`, `health`\u2192`workspace action=check|whoami|status|self-test`, `get-usage-summary`\u2192`workspace action=usage`, `governance-proposals`\u2192`workspace action=proposals-*`, `skills`\u2192`workflows action=load-skill`, `chain-version`\u2192`chain action=version.*`, `chain-branch`\u2192`chain-review action=branch.*`.",
|
|
16313
16404
|
"",
|
|
16314
16405
|
"## Your Workspace Principles",
|
|
@@ -16380,6 +16471,7 @@ function createProductBrainServer() {
|
|
|
16380
16471
|
registerFeedbackTool(server);
|
|
16381
16472
|
registerShapeTools(server);
|
|
16382
16473
|
registerQuestionTools(server);
|
|
16474
|
+
registerRoleTools(server);
|
|
16383
16475
|
if (enabledModules.has("gitchain")) registerGitChainTools(server);
|
|
16384
16476
|
registerResources(server);
|
|
16385
16477
|
registerPrompts(server);
|
|
@@ -16519,4 +16611,4 @@ export {
|
|
|
16519
16611
|
createProductBrainServer,
|
|
16520
16612
|
initFeatureFlags
|
|
16521
16613
|
};
|
|
16522
|
-
//# sourceMappingURL=chunk-
|
|
16614
|
+
//# sourceMappingURL=chunk-N7Y43VJY.js.map
|