@productbrain/mcp 0.0.1-beta.9532 → 0.0.1-beta.9534
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-HHH3YC56.js → chunk-APQ2MKVQ.js} +43 -12
- package/dist/{chunk-HHH3YC56.js.map → chunk-APQ2MKVQ.js.map} +1 -1
- package/dist/{chunk-GXPFXLOF.js → chunk-HOSGKIO6.js} +3 -2
- package/dist/chunk-HOSGKIO6.js.map +1 -0
- package/dist/cli/index.js +1 -1
- package/dist/http.js +2 -2
- package/dist/index.js +2 -2
- package/dist/{setup-AMF7M6X3.js → setup-3SIP3VMW.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-GXPFXLOF.js.map +0 -1
- /package/dist/{setup-AMF7M6X3.js.map → setup-3SIP3VMW.js.map} +0 -0
|
@@ -43,7 +43,7 @@ import {
|
|
|
43
43
|
trackQualityVerdict,
|
|
44
44
|
trackSessionCaptureRate,
|
|
45
45
|
trackZeroCaptureAuditFired
|
|
46
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-HOSGKIO6.js";
|
|
47
47
|
|
|
48
48
|
// src/server.ts
|
|
49
49
|
import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -12223,21 +12223,28 @@ function formatSeatSentence(action, reply, clean) {
|
|
|
12223
12223
|
}
|
|
12224
12224
|
return reply.removed ? `Unseated ${who} from ${roleLabel2} in ${teamLabel}.` : `${who} did not hold ${roleLabel2} in ${teamLabel}; nothing changed.`;
|
|
12225
12225
|
}
|
|
12226
|
+
function formatInviteSentence(reply, clean) {
|
|
12227
|
+
const who = `${clean(reply.person)} [${reply.personId}]`;
|
|
12228
|
+
return reply.inPlace ? `Invited ${who} at ${clean(reply.email)}; they keep every role they already hold.` : `Invited ${who} at ${clean(reply.email)} as a new person.`;
|
|
12229
|
+
}
|
|
12226
12230
|
|
|
12227
12231
|
// src/tools/role.ts
|
|
12228
|
-
var ROLE_ACTIONS = ["accountable", "seat", "unseat"];
|
|
12232
|
+
var ROLE_ACTIONS = ["accountable", "seat", "unseat", "invite"];
|
|
12229
12233
|
var roleSchema = z31.object({
|
|
12230
12234
|
action: z31.enum(ROLE_ACTIONS).describe(
|
|
12231
|
-
"'accountable': what this role owns (explicit), reports on (reporting), and \u2014 not yet computed \u2014 inherits via Team-Lead vacancy coverage. 'seat': put a person in this role. 'unseat': take this role from a person."
|
|
12235
|
+
"'accountable': what this role owns (explicit), reports on (reporting), and \u2014 not yet computed \u2014 inherits via Team-Lead vacancy coverage. 'seat': put a person in this role. 'unseat': take this role from a person. 'invite': send a login link by email; a placeholder person (seated by name) is invited in place and keeps every role it holds."
|
|
12232
12236
|
),
|
|
12233
|
-
roleId: z31.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 every action."),
|
|
12237
|
+
roleId: z31.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 every action except 'invite'."),
|
|
12234
12238
|
canonicalKey: z31.string().max(200).optional().describe("'accountable': narrow to one kind (e.g. objective, key_result, tension)."),
|
|
12235
12239
|
limit: z31.number().int().positive().max(200).optional().describe("'accountable': max explicit-list rows per page (default and maximum 200)."),
|
|
12236
12240
|
cursor: z31.number().optional().describe("'accountable': continue the explicit list from an earlier truncated page's nextCursor."),
|
|
12237
|
-
person: z31.string().max(200).optional().describe(
|
|
12241
|
+
person: z31.string().max(200).optional().describe(
|
|
12242
|
+
"'seat' / 'unseat': an existing person, by person id or exact email. For 'seat', give this or newPersonName, not both. 'invite': the placeholder's person id."
|
|
12243
|
+
),
|
|
12238
12244
|
newPersonName: z31.string().max(120).optional().describe(
|
|
12239
|
-
"'seat': the name of a person who has no login yet; a placeholder person is created once and reused for the same exact name. Refused when the name belongs to someone with an account."
|
|
12245
|
+
"'seat': the name of a person who has no login yet; a placeholder person is created once and reused for the same exact name. Refused when the name belongs to someone with an account. 'invite': the name of a new person to invite, instead of person."
|
|
12240
12246
|
),
|
|
12247
|
+
email: z31.string().max(320).optional().describe("'invite': where the login link goes. Required for 'invite'."),
|
|
12241
12248
|
teamId: z31.string().max(200).optional().describe(
|
|
12242
12249
|
"'seat' / 'unseat': the team, by chain id or entry id. Only needed for Team Lead, which lives in every team; any other role is seated in its home team."
|
|
12243
12250
|
)
|
|
@@ -12262,11 +12269,18 @@ var unseatVariant = z31.object({
|
|
|
12262
12269
|
person: z31.string().max(200),
|
|
12263
12270
|
teamId: z31.string().max(200).optional()
|
|
12264
12271
|
});
|
|
12265
|
-
var
|
|
12272
|
+
var inviteVariant = z31.object({
|
|
12273
|
+
action: z31.literal("invite"),
|
|
12274
|
+
email: z31.string().max(320),
|
|
12275
|
+
person: z31.string().max(200).optional(),
|
|
12276
|
+
newPersonName: z31.string().max(120).optional()
|
|
12277
|
+
});
|
|
12278
|
+
var roleActionUnion = z31.discriminatedUnion("action", [accountableVariant, seatVariant, unseatVariant, inviteVariant]);
|
|
12266
12279
|
var ROLE_ACTION_SPECS = {
|
|
12267
12280
|
accountable: { params: ["roleId", "canonicalKey", "limit", "cursor"], description: "roleId is required; canonicalKey/limit/cursor are optional." },
|
|
12268
12281
|
seat: { params: ["roleId", "person", "newPersonName", "teamId"], description: "roleId is required, plus exactly one of person or newPersonName; teamId only for Team Lead." },
|
|
12269
|
-
unseat: { params: ["roleId", "person", "teamId"], description: "roleId and person are required; teamId only for Team Lead." }
|
|
12282
|
+
unseat: { params: ["roleId", "person", "teamId"], description: "roleId and person are required; teamId only for Team Lead." },
|
|
12283
|
+
invite: { params: ["email", "person", "newPersonName"], description: "email is required, plus exactly one of person (a placeholder's id) or newPersonName." }
|
|
12270
12284
|
};
|
|
12271
12285
|
function formatHolders(result2) {
|
|
12272
12286
|
if (result2.holders.length === 0) return [` holders: none${result2.holdersTruncated ? " found, but the membership scan is incomplete" : ""}`];
|
|
@@ -12346,6 +12360,22 @@ function handleRoleSeat(roleId, person, newPersonName, teamId) {
|
|
|
12346
12360
|
function handleRoleUnseat(roleId, person, teamId) {
|
|
12347
12361
|
return runSeatAction("unseat", "organisation.unseatFromRole", { roleId, person, teamId });
|
|
12348
12362
|
}
|
|
12363
|
+
async function handleRoleInvite(email, person, newPersonName) {
|
|
12364
|
+
const params = { email, person, newPersonName };
|
|
12365
|
+
try {
|
|
12366
|
+
requireWriteAccess();
|
|
12367
|
+
const result2 = await kernelMutation("people.invite", {
|
|
12368
|
+
email,
|
|
12369
|
+
targetPersonId: person,
|
|
12370
|
+
displayName: newPersonName,
|
|
12371
|
+
sessionId: getAgentSessionId()
|
|
12372
|
+
});
|
|
12373
|
+
const message = formatInviteSentence(result2, sanitizeSingleLineField);
|
|
12374
|
+
return successResult(message, message, result2);
|
|
12375
|
+
} catch (err) {
|
|
12376
|
+
return roleErrorResult(err, "invite", params);
|
|
12377
|
+
}
|
|
12378
|
+
}
|
|
12349
12379
|
function roleErrorResult(err, action, params = {}) {
|
|
12350
12380
|
const classified = classifyError(err);
|
|
12351
12381
|
const definedParams = Object.fromEntries(Object.entries(params).filter(([, v]) => v !== void 0));
|
|
@@ -12363,13 +12393,14 @@ function registerRoleTools(server) {
|
|
|
12363
12393
|
const roleHandlers = {
|
|
12364
12394
|
accountable: (data) => handleRoleAccountable(data.roleId, data.canonicalKey, data.limit, data.cursor),
|
|
12365
12395
|
seat: (data) => handleRoleSeat(data.roleId, data.person, data.newPersonName, data.teamId),
|
|
12366
|
-
unseat: (data) => handleRoleUnseat(data.roleId, data.person, data.teamId)
|
|
12396
|
+
unseat: (data) => handleRoleUnseat(data.roleId, data.person, data.teamId),
|
|
12397
|
+
invite: (data) => handleRoleInvite(data.email, data.person, data.newPersonName)
|
|
12367
12398
|
};
|
|
12368
12399
|
server.registerTool(
|
|
12369
12400
|
"role",
|
|
12370
12401
|
{
|
|
12371
12402
|
title: "Role",
|
|
12372
|
-
description: "Workspace roles \u2014 who is accountable for what, and who holds it.
|
|
12403
|
+
description: "Workspace roles \u2014 who is accountable for what, and who holds it. Four actions:\n\n- **accountable**: what this role owns (`explicit` \u2014 the canonical ownership row for objective/key_result/tension, data.ownerRoleId for domain), 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. Also lists `holders`.\n- **seat**: put a person in this role, by person id or email, or by `newPersonName` for someone with no login yet (a placeholder person, created once per exact name). The role's home team is used; name `teamId` only for Team Lead. A held role refuses a second holder and names the holder; the person keeps their other roles in the team. Needs the team's Team Lead.\n- **unseat**: take this role from a person; their other roles in the team stay. The last active Team Lead of a team is refused.\n- **invite**: send a login link to `email`. Give `person` (a placeholder's id, as `seat` printed it) to invite that person in place: they keep every role they hold. Or give `newPersonName` to invite someone new. A person who already has a login or an invite is refused. Needs a workspace owner or admin.",
|
|
12373
12404
|
inputSchema: roleSchema,
|
|
12374
12405
|
// The hints describe the whole tool, so they say the most it can do: unseat removes a role and can
|
|
12375
12406
|
// delete a membership row (destructive), and a repeated seat still writes history and audit rows
|
|
@@ -12731,7 +12762,7 @@ var AGENT_CHEATSHEET = `# Product Brain \u2014 Agent Cheatsheet
|
|
|
12731
12762
|
| \`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 |
|
|
12732
12763
|
| \`shape\` | Review / disposition write-shape (single-concern split) advisories | \`action\`: list, show, agree, dismiss |
|
|
12733
12764
|
| \`question\` | Routed questions \u2014 create, reassign, answer, force-close, list | \`action\`: create, assign, answer, force-close, list |
|
|
12734
|
-
| \`role\` | What a role
|
|
12765
|
+
| \`role\` | What a role owns and who holds it; seat (by id, email or new name), unseat, or invite a placeholder in place | \`action\`: accountable, seat, unseat, invite |
|
|
12735
12766
|
| \`outcome\` | Record an outcome measurement and read the ones already recorded | \`action\`: record, list, show |
|
|
12736
12767
|
|
|
12737
12768
|
This table lists actions only. See \`tools/list\` for each tool's input schema; a missing or invalid parameter is named in the call's own reply.
|
|
@@ -13503,4 +13534,4 @@ export {
|
|
|
13503
13534
|
createProductBrainServer,
|
|
13504
13535
|
initFeatureFlags
|
|
13505
13536
|
};
|
|
13506
|
-
//# sourceMappingURL=chunk-
|
|
13537
|
+
//# sourceMappingURL=chunk-APQ2MKVQ.js.map
|