pipebrain-mcp 0.50.0 → 0.52.0
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/main.js +123 -30
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -383,9 +383,9 @@ var AGENT_CONFIG_ENTRIES = [
|
|
|
383
383
|
{ target: "skills/capture-correction/SKILL.md", sha256: "907ee8fc8e7ea15c8296acd23a816e1f9c6454edcf37a93f18af79b1c542fb75" },
|
|
384
384
|
{ target: "skills/pipebrain-header-pass/SKILL.md", sha256: "10545e3c1c5215b031e1c76281e65cd2ecf7420b3f07a4221824591a8263c5fc" },
|
|
385
385
|
{ target: "skills/pipebrain-secrets/SKILL.md", sha256: "52c2136a3cca5612981d50b926195eae3e804911e1e9723dd5eba76e66b52d6f" },
|
|
386
|
-
{ target: "skills/pipebrain-work-session/SKILL.md", sha256: "
|
|
386
|
+
{ target: "skills/pipebrain-work-session/SKILL.md", sha256: "c1b701d167c62123f6fe38dae35a7dc6c9d0a8f2a9881efabc6b98d0caf14863" },
|
|
387
387
|
{ target: "skills/pipebrain-writing/SKILL.md", sha256: "8e5ed4636afcca0cacc220d8fa5310364d2d6854a9fc68ffa03e4c428989f8b8" },
|
|
388
|
-
{ target: "skills/pipebrain/SKILL.md", sha256: "
|
|
388
|
+
{ target: "skills/pipebrain/SKILL.md", sha256: "9fdad1b78bb506e9cd91ba55f4baee0adc5f4d2c5d9d418d0e8c922554e8df74" },
|
|
389
389
|
{ target: "skills/requirements-altitude/SKILL.md", sha256: "60d1916da22a52138c046fcf4e5cd4cc420b7a5679a6652eb76573b7a69a1cf4" }
|
|
390
390
|
];
|
|
391
391
|
|
|
@@ -505,7 +505,7 @@ function apiBindingLabel(apiBaseUrl) {
|
|
|
505
505
|
}
|
|
506
506
|
|
|
507
507
|
// ../../libs/agent-shared/dist/doctrine.js
|
|
508
|
-
var DOCTRINE = "# Pipebrain doctrine\n\nHow an agent works inside Pipebrain. These rules ship with the product and are the same in every organization. Each one protects something the product guarantees.\n\n## How to write here\n\nThe person reading what you write is the operator, deciding something. They have about two minutes. Put the point first. Use short sentences and ordinary words. Headings and bullets are fine. Explain why once, not under every bullet.\n\nA criterion is one sentence: a concrete situation, and what must be true afterward. If you need a general rule, write two or three criteria instead.\n\nEvidence on a criterion opens with the verdict, then how you drove it, then what it does not cover. Keep it to one screen; name the test or command, not every file you read.\n\nA closing comment says what landed, what did not and why, what you filed by key, and whether the tests are green.\n\nAnything else you notice goes to a question, when the operator has to choose; to a new issue at triage, when it is real work; or, most often, nowhere. Never add a notes, caveats, or next-steps section. An item filed and repeated in prose gets triaged twice.\n\nYour organization may add its own writing rules below this document. Most have none.\n\n## Search before you create\n\nLook for an existing record before you add one. A duplicate splits one record's history across two keys, and nothing merges them later. Update or link the record you find.\n\n## Link by key, never paste\n\nRefer to a requirement, decision, or issue by its key. Never paste its text into a body. When the source changes the copy stays stale, and the stale copy is what gets built.\n\n## Most choices are yours\n\nInside an approved requirement you choose the design, the libraries, and the order of work. Ask only when a choice changes what a user sees, costs money, or contradicts a requirement; file that one as a question. Asking about everything makes real questions wait behind choices that were yours. A technical choice worth keeping goes in a decision record.\n\n## File decisions as questions\n\nAn open decision goes in a question on the issue, filed with `ask_questions` and carrying the options you propose. It does not belong in a body, under a heading or in a field. Prose asks nobody and records no answer, so a later session cannot tell whether it was ever decided. Withdraw a question
|
|
508
|
+
var DOCTRINE = "# Pipebrain doctrine\n\nHow an agent works inside Pipebrain. These rules ship with the product and are the same in every organization. Each one protects something the product guarantees.\n\n## How to write here\n\nThe person reading what you write is the operator, deciding something. They have about two minutes. Put the point first. Use short sentences and ordinary words. Headings and bullets are fine. Explain why once, not under every bullet.\n\nA criterion is one sentence: a concrete situation, and what must be true afterward. If you need a general rule, write two or three criteria instead.\n\nEvidence on a criterion opens with the verdict, then how you drove it, then what it does not cover. Keep it to one screen; name the test or command, not every file you read.\n\nA closing comment says what landed, what did not and why, what you filed by key, and whether the tests are green.\n\nAnything else you notice goes to a question, when the operator has to choose; to a new issue at triage, when it is real work; or, most often, nowhere. Never add a notes, caveats, or next-steps section. An item filed and repeated in prose gets triaged twice.\n\nYour organization may add its own writing rules below this document. Most have none.\n\n## Search before you create\n\nLook for an existing record before you add one. A duplicate splits one record's history across two keys, and nothing merges them later. Update or link the record you find.\n\n## Link by key, never paste\n\nRefer to a requirement, decision, or issue by its key. Never paste its text into a body. When the source changes the copy stays stale, and the stale copy is what gets built.\n\n## Most choices are yours\n\nInside an approved requirement you choose the design, the libraries, and the order of work. Ask only when a choice changes what a user sees, costs money, or contradicts a requirement; file that one as a question. Asking about everything makes real questions wait behind choices that were yours. A technical choice worth keeping goes in a decision record.\n\n## A branch and a worktree are derived from the issue\n\nReading an issue's work context returns its branch, its base and its worktree already resolved, each saying where it came from, and how the work leaves the branch. A value the issue, its ancestors and its project all leave unset is derived: the branch and the worktree label are the issue's display id in lower case, which is the project key, a hyphen and the number, and the base is main, which a project changes in its settings. Two sessions reading one issue compute the same names, so a session resuming abandoned work finds what the session before it used. Reading a project returns the work you could pick up and no placement, because no issue has been chosen yet.\n\nClaim the work naming the branch and the worktree you were given. Naming them is what reserves them: a claim is refused when another live claim in the project already holds either. A field you leave out keeps whatever the issue already records, so a claim that names nothing on an issue that records nothing reserves nothing, and a second session is free to take the same tree.\n\nA worktree is a label, not a path. Whoever runs the session maps that label to a directory, because a path recorded here would be true only on the machine that wrote it. Create a working tree when nothing on this machine answers to the label, and reuse the one already there when something does; a branch checked out in one tree cannot be checked out in another. Only the machine can answer that. What the placement tells you is a different thing worth knowing, and it says it for the branch and the worktree separately: whether another issue in this project is already placed on that same value, so you can see whether you are joining work or starting it.\n\nA claim you find under your own session identifier is work to resume rather than work to start. Read what the issue records, look at what the tree holds, and carry on from there. Claiming it again is refused, and starting it again abandons whatever the earlier session left.\n\nA working tree holding uncommitted changes is never removed. Report it and leave it alone. Nothing can tell deliberate work from residue, and removing it cannot be undone.\n\n## File decisions as questions\n\nAn open decision goes in a question on the issue, filed with `ask_questions` and carrying the options you propose. It does not belong in a body, under a heading or in a field. Prose asks nobody and records no answer, so a later session cannot tell whether it was ever decided. If your own work settles a question, answer it with `answer_question` \u2014 the answer is worth keeping, and withdrawing throws it away. Withdraw only a question that should never have been asked.\n\n## Cross-cutting requirements arrive on their own\n\nThey bind every epic and come back with a work-item read, at their latest approved revision. Never restate them in a body and never add them as explicit requirement links. A copy drifts, and an explicit link pins one revision where the read delivers the newest.\n\n## Conventions need a person's approval\n\nApproved conventions come back with the same work-item read and bind every project in the organization. Never restate one in a body and never add one as an explicit link; a copy goes stale.\n\nA convention you create or amend over the agent surface is a proposal. It is not in force until a person approves it in a browser. Until then, do not work from your own unapproved wording.\n\nA statement that stops being true when this project ends is a cross-cutting requirement. One still true on the next project is a convention. File one when an evaluator rejects work or a criterion fails, and rarely otherwise: each reaches every read, after a person reviews it.\n\n## Choosing auto or manual\n\nFirst find out what this project can drive end to end, and with which command. A criterion is `auto` when an evaluator can drive the input and read the result on the running system, including an interface where a browser harness exists. Only the evaluator's own run qualifies it; a test the implementer wrote does not. An auto criterion nobody can drive never gets evidence.\n\nMark a criterion `manual` only when the verdict needs a person's judgment. A manual row a machine could have checked holds the issue open until a person gets to it. If you cannot say how to drive a criterion, it is worded too vaguely; reword it against something observable. A manual criterion carries instructions for a stranger to the code.\n\nA manual criterion with no recorded artifact is the human gate working as designed, and not a finding.\n\nThis choice also decides who can finish the work. What gates finishing is the work rather than the caller \u2014 the status tool names what the gate reads, and the server never asks who is calling. A manual row is the one a credential cannot pass, so work carrying one waits for a person; work whose criteria are all machine-checked does not, and the session that has just passed them can set it done.\n\n## The bar for filing a bug\n\nFile a bug only when the behavior breaks an approved requirement or a defined acceptance criterion, and name which one first. Everything else, including unclear code and edge cases nobody specified, is feedback or nothing. A queue that mixes defects with taste has to be read in full before any of it can be trusted.\n\n## A decision record is written once\n\nA decision record says what was decided and why, at the time. A proposed record is still being written: correct it with `update_decision`, and accept it once it says what you decided. An accepted record is settled, so never edit one; write a superseding record instead. The chain of records shows how the thinking changed, and an edit destroys it. Read existing records before reopening a settled question.\n\n## A secret value never travels in a tool call\n\nNo tool returns a secret value, by design, and none should receive one. A value in a tool call is in the transcript before the server can encrypt it; the only remedy is rotation. Set values with the command-line tool, from a file or standard input, and inject at run time.\n\n## Setting an instruction replaces the whole body\n\nThere is no partial update. An instruction write stores exactly the body you supply and discards everything that was there. Read the live value, compose the complete replacement, write it, then read it again to confirm what landed.\n\nThis guidance and the tool descriptions are a snapshot from the session's start; an edit reaches the next session, never this one. `list_org_instructions` returns the saved rows as they are now; that is the confirming read.\n";
|
|
509
509
|
|
|
510
510
|
// ../../libs/agent-shared/dist/org-reference.js
|
|
511
511
|
var CANONICAL_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -15058,6 +15058,7 @@ var issueStatusSchema = external_exports.enum([
|
|
|
15058
15058
|
"done",
|
|
15059
15059
|
"killed"
|
|
15060
15060
|
]);
|
|
15061
|
+
var integrationModeSchema = external_exports.enum(["pull_request", "push", "none"]);
|
|
15061
15062
|
var OPEN_STATUSES = [
|
|
15062
15063
|
"triage",
|
|
15063
15064
|
"backlog",
|
|
@@ -15184,6 +15185,7 @@ var deliverableTargetLabelSchema = external_exports.string().min(1, { message: "
|
|
|
15184
15185
|
var projectNameSchema = external_exports.string().min(1, { message: "project name must not be empty" });
|
|
15185
15186
|
var tokenLabelSchema = external_exports.string().min(1, { message: "token label must not be empty" });
|
|
15186
15187
|
var contentMetadataSchema = external_exports.record(external_exports.string(), external_exports.unknown());
|
|
15188
|
+
var sessionIdSchema = external_exports.string().min(1, { message: "session must not be empty \u2014 omit it to read without a session" });
|
|
15187
15189
|
|
|
15188
15190
|
// ../../libs/domain/dist/display-id.js
|
|
15189
15191
|
var DisplayIdError = class extends Error {
|
|
@@ -15442,7 +15444,28 @@ var projectSchema = external_exports.object({
|
|
|
15442
15444
|
environments: external_exports.array(projectEnvironmentSchema),
|
|
15443
15445
|
milestones: external_exports.array(projectMilestoneSchema),
|
|
15444
15446
|
deliverableTargets: external_exports.array(projectDeliverableTargetSchema),
|
|
15445
|
-
openIssueCount: external_exports.number().int().nonnegative()
|
|
15447
|
+
openIssueCount: external_exports.number().int().nonnegative(),
|
|
15448
|
+
/**
|
|
15449
|
+
* What an issue's placement falls back to when neither it nor any ancestor carries a
|
|
15450
|
+
* value (PIPE-444). A person edits these in project settings; agents never write them,
|
|
15451
|
+
* which is what keeps one writer per field (PIPE-D46).
|
|
15452
|
+
*
|
|
15453
|
+
* `.nullable()` and REQUIRED, like `defaultEnvironmentId` above rather than optional
|
|
15454
|
+
* like the issue header fields: the columns exist on every project and the wire mapper
|
|
15455
|
+
* sends all three on every row, so an absent key would mean a server predating them
|
|
15456
|
+
* while `null` means this project sets no default. Optional would make those two
|
|
15457
|
+
* indistinguishable.
|
|
15458
|
+
*/
|
|
15459
|
+
defaultBranch: external_exports.string().nullable(),
|
|
15460
|
+
defaultWorktree: external_exports.string().nullable(),
|
|
15461
|
+
defaultBase: external_exports.string().nullable(),
|
|
15462
|
+
/**
|
|
15463
|
+
* How work leaves its branch (PIPE-445). NOT nullable, unlike the three above: those
|
|
15464
|
+
* are nullable because null there means "ask the next level up" and the walk is the
|
|
15465
|
+
* feature. There is no walk here — the value is read from the project and nowhere
|
|
15466
|
+
* else — so a null could only mean "no answer", and work context has to return one.
|
|
15467
|
+
*/
|
|
15468
|
+
defaultIntegrationMode: integrationModeSchema
|
|
15446
15469
|
});
|
|
15447
15470
|
var environmentSchema = external_exports.object({
|
|
15448
15471
|
id: uuidSchema,
|
|
@@ -16041,7 +16064,20 @@ var updateIssueInputSchema = external_exports.strictObject({
|
|
|
16041
16064
|
parent: issueRefSchema.nullable().optional(),
|
|
16042
16065
|
requirementLinks: requirementLinkChangesSchema.optional(),
|
|
16043
16066
|
deliverableLinks: deliverableLinkChangesSchema.optional(),
|
|
16044
|
-
decisionLinks: decisionLinkChangesSchema.optional()
|
|
16067
|
+
decisionLinks: decisionLinkChangesSchema.optional(),
|
|
16068
|
+
/**
|
|
16069
|
+
* Where the work happens (PIPE-444) — this is the placement write. An agent records
|
|
16070
|
+
* here what a claim did not name, or corrects what it did.
|
|
16071
|
+
*
|
|
16072
|
+
* `.nullable().optional()`, like `milestone` and `parent` above: omitting a field
|
|
16073
|
+
* leaves it, and passing `null` CLEARS the issue's own value so it falls back to the
|
|
16074
|
+
* nearest ancestor carrying one and then to the project default. The two are different
|
|
16075
|
+
* asks and a schema that could not tell them apart would make an issue's own value
|
|
16076
|
+
* impossible to remove.
|
|
16077
|
+
*/
|
|
16078
|
+
branch: external_exports.string().min(1, { message: "branch must not be empty \u2014 pass null to clear it" }).nullable().optional().describe("The branch this issue\u2019s work happens on. Pass null to clear it, so the issue inherits from the nearest ancestor carrying one and then from the project default."),
|
|
16079
|
+
worktree: external_exports.string().min(1, { message: "worktree must not be empty \u2014 pass null to clear it" }).nullable().optional().describe("A label for the working tree this issue\u2019s work happens in \u2014 never a path, which is true only on the machine that wrote it. Pass null to clear it."),
|
|
16080
|
+
base: external_exports.string().min(1, { message: "base must not be empty \u2014 pass null to clear it" }).nullable().optional().describe("What this issue\u2019s work integrates into. Pass null to clear it, so the issue inherits from its chain and then from the project default.")
|
|
16045
16081
|
});
|
|
16046
16082
|
var ISSUE_SUMMARY_MAX = 350;
|
|
16047
16083
|
function inPlainWords(schema, field) {
|
|
@@ -16079,7 +16115,18 @@ var getIssueInputSchema = external_exports.strictObject({
|
|
|
16079
16115
|
});
|
|
16080
16116
|
var getWorkContextInputSchema = external_exports.strictObject({
|
|
16081
16117
|
issue: issueRefSchema.optional(),
|
|
16082
|
-
project: projectRefSchema.optional()
|
|
16118
|
+
project: projectRefSchema.optional(),
|
|
16119
|
+
/**
|
|
16120
|
+
* The reader's own agent session (PIPE-443). It narrows the project form's
|
|
16121
|
+
* `available` list to work no OTHER session of the same person is holding.
|
|
16122
|
+
*
|
|
16123
|
+
* Accepted on BOTH forms rather than refused alongside `issue`, even though the item
|
|
16124
|
+
* form returns no list for it to narrow. A session that knows its own identifier
|
|
16125
|
+
* passes it on every call it makes; refusing it here would make that one call the
|
|
16126
|
+
* exception and buy nothing, since naming a session cannot change what an item read
|
|
16127
|
+
* returns.
|
|
16128
|
+
*/
|
|
16129
|
+
session: sessionIdSchema.optional()
|
|
16083
16130
|
}).refine((v) => v.issue === void 0 !== (v.project === void 0), {
|
|
16084
16131
|
message: "pass exactly one of `issue` or `project` \u2014 an issue names its own project, and passing neither names nothing to read"
|
|
16085
16132
|
});
|
|
@@ -16095,7 +16142,12 @@ var openReviewInputSchema = external_exports.strictObject({
|
|
|
16095
16142
|
message: "pass exactly one of `epic` or `project` + `milestone` \u2014 an epic names its own project and milestone, and passing neither names nothing to review"
|
|
16096
16143
|
});
|
|
16097
16144
|
var claimInputSchema = external_exports.strictObject({
|
|
16098
|
-
issue: issueRefSchema
|
|
16145
|
+
issue: issueRefSchema,
|
|
16146
|
+
session: sessionIdSchema.optional(),
|
|
16147
|
+
branch: external_exports.string().min(1, { message: "branch must not be empty \u2014 omit it to keep the branch already recorded" }).optional(),
|
|
16148
|
+
worktree: external_exports.string().min(1, {
|
|
16149
|
+
message: "worktree must not be empty \u2014 omit it to keep the worktree already recorded"
|
|
16150
|
+
}).optional()
|
|
16099
16151
|
});
|
|
16100
16152
|
var setBlockedInputSchema = external_exports.strictObject({
|
|
16101
16153
|
issue: issueRefSchema,
|
|
@@ -16273,6 +16325,17 @@ var listIssuesFilterSchema = external_exports.strictObject({
|
|
|
16273
16325
|
// the same reason `blocked` is one — a filter the server quietly dropped returns
|
|
16274
16326
|
// everything and reads exactly like one that matched everything.
|
|
16275
16327
|
needsHeader: external_exports.boolean().optional(),
|
|
16328
|
+
/**
|
|
16329
|
+
* The reader's own agent session (PIPE-443). Naming one drops every issue held under a
|
|
16330
|
+
* DIFFERENT session identifier, so an operator running several agents against one
|
|
16331
|
+
* repository stops having each of them offered the work the others hold. Omitting it
|
|
16332
|
+
* is today's behaviour exactly: a person in a browser has no session, and their own
|
|
16333
|
+
* claims stay in the list.
|
|
16334
|
+
*
|
|
16335
|
+
* An issue whose claim named no session is never dropped by this, whichever session
|
|
16336
|
+
* asks — the filter narrows to sessions that said who they were.
|
|
16337
|
+
*/
|
|
16338
|
+
session: sessionIdSchema.optional(),
|
|
16276
16339
|
// Pagination — server default 200, max 500 (§9); default applied server-side.
|
|
16277
16340
|
limit: external_exports.number().int().min(1, { message: "limit must be at least 1" }).max(500, { message: "limit must be at most 500" }).optional(),
|
|
16278
16341
|
offset: external_exports.number().int().nonnegative().optional()
|
|
@@ -16777,8 +16840,16 @@ var ApiClient = class _ApiClient {
|
|
|
16777
16840
|
updateIssue(ref, fields) {
|
|
16778
16841
|
return this.request("PATCH", `/api/v1/issues/${enc(ref)}`, { body: fields });
|
|
16779
16842
|
}
|
|
16780
|
-
|
|
16781
|
-
|
|
16843
|
+
/**
|
|
16844
|
+
* Claims an issue, optionally reserving where the work happens (PIPE-442). A field
|
|
16845
|
+
* `placement` omits keeps whatever the issue already recorded; the call never clears
|
|
16846
|
+
* one. Refused 409 `placement_conflict` when another live claim in the project holds
|
|
16847
|
+
* the branch or the worktree.
|
|
16848
|
+
*/
|
|
16849
|
+
claimIssue(ref, placement) {
|
|
16850
|
+
return this.request("POST", `/api/v1/issues/${enc(ref)}/claim`, {
|
|
16851
|
+
body: placement ?? {}
|
|
16852
|
+
});
|
|
16782
16853
|
}
|
|
16783
16854
|
releaseIssue(ref) {
|
|
16784
16855
|
return this.request("POST", `/api/v1/issues/${enc(ref)}/release`);
|
|
@@ -16877,8 +16948,9 @@ var ApiClient = class _ApiClient {
|
|
|
16877
16948
|
/**
|
|
16878
16949
|
* Answers a question by its stable `Q-{n}` number with EXACTLY one of `option`
|
|
16879
16950
|
* (1-based, into the question's options) or `text` (PIPE-93); answering again
|
|
16880
|
-
* revises.
|
|
16881
|
-
*
|
|
16951
|
+
* revises. Token OR session (PIPE-450): the bearer refusal PIPE-R22 r2 withdrew is
|
|
16952
|
+
* gone, and the answer records the credential behind it instead. Returns the updated
|
|
16953
|
+
* detail.
|
|
16882
16954
|
*/
|
|
16883
16955
|
answerQuestion(ref, number4, answer) {
|
|
16884
16956
|
return this.request("POST", `/api/v1/issues/${enc(ref)}/questions/${number4}/answer`, { body: answer });
|
|
@@ -17208,9 +17280,12 @@ var ApiClient = class _ApiClient {
|
|
|
17208
17280
|
}
|
|
17209
17281
|
// --- the waiting queue -----------------------------------------------------
|
|
17210
17282
|
/**
|
|
17211
|
-
*
|
|
17283
|
+
* Everything not moving on its own across ALL projects of the caller's organisation
|
|
17212
17284
|
* (PIPE-87): revisions awaiting approval, questions awaiting an answer, and work
|
|
17213
|
-
* in `verify` with a criterion not yet passed, longest wait first.
|
|
17285
|
+
* in `verify` with a criterion not yet passed, longest wait first. Not all of it
|
|
17286
|
+
* waits on a person — a question clears with `answer_question` and an `auto`
|
|
17287
|
+
* criterion with `set_criterion_state`; the one a credential cannot pass is a
|
|
17288
|
+
* criterion marked for human judgment.
|
|
17214
17289
|
*
|
|
17215
17290
|
* Takes NO project and NO org PARAMETER: a queue you point at a project is the
|
|
17216
17291
|
* per-project surface this replaces, and the organization is a property of the CLIENT,
|
|
@@ -17241,7 +17316,9 @@ var ApiClient = class _ApiClient {
|
|
|
17241
17316
|
* answer.
|
|
17242
17317
|
*/
|
|
17243
17318
|
getWorkContext(input) {
|
|
17244
|
-
return input.issue !== void 0 ? this.request("GET", `/api/v1/issues/${enc(input.issue)}/work-context`) : this.request("GET", `/api/v1/projects/${enc(input.project)}/work-context
|
|
17319
|
+
return input.issue !== void 0 ? this.request("GET", `/api/v1/issues/${enc(input.issue)}/work-context`) : this.request("GET", `/api/v1/projects/${enc(input.project)}/work-context`, {
|
|
17320
|
+
query: input.session === void 0 ? {} : { session: input.session }
|
|
17321
|
+
});
|
|
17245
17322
|
}
|
|
17246
17323
|
// --- secrets ---------------------------------------------------------------
|
|
17247
17324
|
// Metadata only: no method here returns a secret VALUE (the reveal plane is a
|
|
@@ -17675,7 +17752,7 @@ function createMcpServer(baseClient, apiBaseUrl, orgInstructions2 = /* @__PURE__
|
|
|
17675
17752
|
);
|
|
17676
17753
|
}
|
|
17677
17754
|
registerStrict("list_orgs", {
|
|
17678
|
-
description: "List the organizations this credential may act in, with each name, slug, id, kind and your role. This is the one tool that needs no `org`: every other call names the organization it acts in and is refused
|
|
17755
|
+
description: "List the organizations this credential may act in, with each name, slug, id, kind and your role. Use it to find the names you may pass. This is the one tool that needs no `org`: every other call names the organization it acts in, and omitting it is refused unless this session has a default. The answer is your memberships right now, so a joined organization appears and a left one does not."
|
|
17679
17756
|
}, () => (
|
|
17680
17757
|
// A BARE ARRAY, unlike `list_waiting`'s `{ items }`, and for the reason that tool
|
|
17681
17758
|
// gives rather than against it: the envelope has already been unwrapped by
|
|
@@ -17715,7 +17792,7 @@ function createMcpServer(baseClient, apiBaseUrl, orgInstructions2 = /* @__PURE__
|
|
|
17715
17792
|
}
|
|
17716
17793
|
}, (args) => run(() => client2().createProject(args)));
|
|
17717
17794
|
registerStrict("list_waiting", {
|
|
17718
|
-
description: "
|
|
17795
|
+
description: "Everything not moving on its own across all projects in the organization named by `org`, longest wait first: a requirement revision awaiting approval, an unanswered question, and work at verify holding a criterion that has not passed. Each entry names its project, the ref to act on, and when the wait began. Read-only. A revision clears with `approve_requirement`, a question with `answer_question`, an `auto` criterion with `set_criterion_state`. A criterion marked for human judgment waits for a person."
|
|
17719
17796
|
}, () => (
|
|
17720
17797
|
// `{ items }`, mirroring the HTTP envelope rather than unwrapping to a bare array
|
|
17721
17798
|
// like the sibling list tools. The reason is the envelope itself: this tool is a
|
|
@@ -17738,7 +17815,7 @@ function createMcpServer(baseClient, apiBaseUrl, orgInstructions2 = /* @__PURE__
|
|
|
17738
17815
|
// one description loaded into EVERY session by `anthropic/alwaysLoad`. The clauses
|
|
17739
17816
|
// that went were the ones arguing for the rule rather than stating it; what a caller
|
|
17740
17817
|
// needs to predict a refusal all stayed.
|
|
17741
|
-
description: "Everything a session needs before starting work. Call it first: it alone returns the doctrine and
|
|
17818
|
+
description: "Everything a session needs before starting work. Call it first: it alone returns the doctrine and your organization\u2019s writing rules in full. Pass `issue` or `project`, never both. An issue returns its detail plus each linked requirement\u2019s text, comments capped at `commentLimit` (default " + WORK_CONTEXT_COMMENT_LIMIT + "), with `commentCount` the true total. A project returns `available` \u2014 startable work, excluding done, killed, blocked, person-reserved, others\u2019 claims and, with `session`, your other sessions\u2019 \u2014 capped at `availableLimit` beside the true `availableCount`. Read-only.",
|
|
17742
17819
|
inputSchema: getWorkContextInputSchema,
|
|
17743
17820
|
// THE TWO ANNOTATIONS PIPE-D30 REQUIRES, and the reason each key is spelled out
|
|
17744
17821
|
// rather than built: an unknown `_meta` key is IGNORED — no error, no warning — so a
|
|
@@ -17851,7 +17928,7 @@ function createMcpServer(baseClient, apiBaseUrl, orgInstructions2 = /* @__PURE__
|
|
|
17851
17928
|
registerStrict(
|
|
17852
17929
|
"list_issues",
|
|
17853
17930
|
{
|
|
17854
|
-
description: "List issue summaries \u2014 status, priority, milestone, claimer, criteria progress and the header \u2014 filtered by project, status, type, claimer, priority, milestone, text, parent, blocked and
|
|
17931
|
+
description: "List issue summaries \u2014 status, priority, milestone, claimer, criteria progress and the header \u2014 filtered by project, status, type, claimer, priority, milestone, text, parent, blocked, needsHeader and session. With no status filter the default is buildable work: " + OPEN_STATUSES.join(", ") + '. Terminal work is excluded until you name it: pass status ["done","killed"]. An explicit filter is used verbatim, never merged. needsHeader true returns issues whose header is missing or stale; session drops work another session holds.',
|
|
17855
17932
|
inputSchema: listIssuesFilterSchema.shape
|
|
17856
17933
|
},
|
|
17857
17934
|
// The default lives in the API now, not here (PIPE-D35, Listing issues
|
|
@@ -17895,22 +17972,22 @@ function createMcpServer(baseClient, apiBaseUrl, orgInstructions2 = /* @__PURE__
|
|
|
17895
17972
|
})
|
|
17896
17973
|
), GUIDANCE_POINTER));
|
|
17897
17974
|
registerStrict("create_issue", {
|
|
17898
|
-
description: "Create an epic, task, bug or feedback. Status defaults to triage; anything but triage or killed needs a milestone, else refused `milestone_required`.
|
|
17975
|
+
description: "Create an epic, task, bug or feedback. Status defaults to triage; anything but triage or killed needs a milestone, else refused `milestone_required`. An archived milestone is refused `milestone_archived_write`. An open issue under a done or killed parent is refused `parent_terminal`. Epics, tasks and bugs carry criteria; feedback is refused `criteria_not_supported`. A `manual` criterion needs `howTo`, else refused `how_to_required`. A bug may name the criterion it was filed against. See the doctrine `get_work_context` returns, under \u201CSearch before you create\u201D.",
|
|
17899
17976
|
inputSchema: createIssueInputSchema.shape
|
|
17900
17977
|
}, (args) => run(() => client2().createIssue(args)));
|
|
17901
17978
|
registerStrict("promote_feedback", {
|
|
17902
|
-
description: "Retype a feedback report as real work \u2014 an epic or a task \u2014 so it can carry criteria and be built. Feedback itself is refused `criteria_not_supported
|
|
17979
|
+
description: "Retype a feedback report as real work \u2014 an epic or a task \u2014 so it can carry criteria and be built. Feedback itself is refused `criteria_not_supported`. Scheduling the new work into an archived milestone is refused `milestone_archived_write`. Closing the source feedback is refused `status_guard` when anything beneath it, at any depth, is not done or killed. A `manual` criterion needs `howTo`, else refused `how_to_required`. See the doctrine `get_work_context` returns, under \u201CThe bar for filing a bug\u201D.",
|
|
17903
17980
|
inputSchema: {
|
|
17904
17981
|
issue: external_exports.string().min(1),
|
|
17905
17982
|
...promoteFeedbackInputSchema.shape
|
|
17906
17983
|
}
|
|
17907
17984
|
}, ({ issue: issue2, ...fields }) => run(() => client2().promoteFeedback(issue2, fields)));
|
|
17908
17985
|
registerStrict("open_review", {
|
|
17909
|
-
description: "Open
|
|
17986
|
+
description: "Open an epic\u2019s completion review, read by whoever neither built nor evaluated it: one ready task carrying the checklist. Pass exactly one of `epic`, or `project` plus `milestone`. A first call is refused `review_target_not_epic`, `review_target_terminal` (finished epic), `milestone_required` (no milestone), `milestone_not_found` (unknown token). One review per scope; a second is refused `review_already_open`. Epic-form also holds that milestone scope; milestone-form blocks no epic. File findings under the epic, not the review. See the doctrine `get_work_context` returns, under \u201CHow to write here\u201D.",
|
|
17910
17987
|
inputSchema: openReviewInputSchema
|
|
17911
17988
|
}, (args) => run(() => client2().openReview(args)));
|
|
17912
17989
|
registerStrict("update_issue", {
|
|
17913
|
-
description: "Change an issue\u2019s fields, parent and links. Header fields are refused
|
|
17990
|
+
description: "Change an issue\u2019s fields, parent and links. Header fields are refused; `set_criteria` sets criteria, which epics, tasks and bugs carry. An archived milestone is refused `milestone_archived_write`, unless the issue or its parent carries it. A cycle-closing re-parent is refused `parent_cycle`. A finished parent refuses an open issue, `parent_terminal`; a finished one holding open work, `parent_terminal_subtree`. Attaching open work starts a parent that is not blocked, unscheduled or under finished work. See the doctrine `get_work_context` returns, under \u201CMost choices are yours\u201D.",
|
|
17914
17991
|
inputSchema: updateIssueInputSchema.shape
|
|
17915
17992
|
}, ({ issue: issue2, ...fields }) => run(() => client2().updateIssue(issue2, fields)));
|
|
17916
17993
|
registerStrict("set_issue_header", {
|
|
@@ -17918,13 +17995,13 @@ function createMcpServer(baseClient, apiBaseUrl, orgInstructions2 = /* @__PURE__
|
|
|
17918
17995
|
inputSchema: setIssueHeaderInputSchema.shape
|
|
17919
17996
|
}, ({ issue: issue2, ...fields }) => run(() => client2().setIssueHeader(issue2, fields)));
|
|
17920
17997
|
registerStrict("set_status", {
|
|
17921
|
-
description: "Move an issue to
|
|
17998
|
+
description: "Move an issue to another status. An open status under a done or killed parent is refused `parent_terminal_reopen`. verify needs every auto criterion passed; done needs every criterion passed and everything beneath it, at any depth, done or killed. An epic with no criteria is refused at both gates; a task or bug with none moves through. Blocked work cannot reach ready or in_progress until blockers clear. Work with no milestone can only be triage or killed.",
|
|
17922
17999
|
inputSchema: setStatusInputSchema.shape
|
|
17923
18000
|
}, (args) => run(() => client2().setStatus(args.issue, args.status)));
|
|
17924
18001
|
registerStrict("claim_issue", {
|
|
17925
|
-
description: "Claim an issue for this session. It succeeds only if unclaimed; under a race one caller wins and the loser is told who holds it.
|
|
17926
|
-
inputSchema:
|
|
17927
|
-
}, (
|
|
18002
|
+
description: "Claim an issue for this session and reserve where the work happens. It succeeds only if unclaimed; under a race one caller wins and the loser is told who holds it. `branch` and `worktree` are refused `placement_conflict` when another live claim in the project holds either, naming that issue. A field you omit keeps what the issue already recorded. Claiming is separate from status, and is refused `reserved_for_person` when an operator has kept the work for a person.",
|
|
18003
|
+
inputSchema: claimInputSchema.shape
|
|
18004
|
+
}, ({ issue: issue2, ...placement }) => run(() => client2().claimIssue(issue2, placement)));
|
|
17928
18005
|
registerStrict("release_issue", {
|
|
17929
18006
|
description: "Release your claim on an issue, leaving it unclaimed and its status unchanged.",
|
|
17930
18007
|
inputSchema: { issue: issueRefSchema }
|
|
@@ -17977,13 +18054,17 @@ function createMcpServer(baseClient, apiBaseUrl, orgInstructions2 = /* @__PURE__
|
|
|
17977
18054
|
});
|
|
17978
18055
|
}));
|
|
17979
18056
|
registerStrict("ask_questions", {
|
|
17980
|
-
description: "Ask the operator
|
|
18057
|
+
description: "Ask the operator questions on an issue. Send them in one call \u2014 a half-asked set costs a second pass. Each question gets a stable `Q-{n}` number, never reused; `options` are the choices you propose. Answers come back on every later read; read them before asking again. Answer one yourself with `answer_question` when your work settles it; withdraw one with `withdraw_question` if it should never have been asked. See the doctrine `get_work_context` returns, under \u201CFile decisions as questions\u201D.",
|
|
17981
18058
|
inputSchema: askQuestionsInputSchema.shape
|
|
17982
18059
|
}, (args) => run(() => client2().askQuestions(args.issue, args.questions)));
|
|
17983
18060
|
registerStrict("withdraw_question", {
|
|
17984
|
-
description: "Withdraw a question by its `Q-{n}` number, in the organization named by `org`. Only the asker may withdraw, and the asker is the person your credential belongs to, so another agent\u2019s question is not yours to clear. Use it
|
|
18061
|
+
description: "Withdraw a question by its `Q-{n}` number, in the organization named by `org`. Only the asker may withdraw, and the asker is the person your credential belongs to, so another agent\u2019s question is not yours to clear. Use it for a question that should never have been asked; one your own work settled deserves `answer_question` instead, which keeps the answer. The question is kept for the audit trail, its number retires, and later reads no longer carry it.",
|
|
17985
18062
|
inputSchema: withdrawQuestionInputSchema.shape
|
|
17986
18063
|
}, (args) => run(() => client2().withdrawQuestion(args.issue, args.number)));
|
|
18064
|
+
registerStrict("answer_question", {
|
|
18065
|
+
description: "Answer a question by its `Q-{n}` number, in the organization named by `org`. Pass exactly one of `option` (a 1-based index into the choices offered) or `text` \u2014 both, or neither, is refused here before anything is sent. Answering again revises; every answer records who answered and which credential. An out-of-range index is refused `option_out_of_range`, naming how many choices there are; a withdrawn or unknown number, `question_not_found`. Answer what your own work settled; leave the rest to the operator.",
|
|
18066
|
+
inputSchema: answerQuestionInputSchema
|
|
18067
|
+
}, (args) => run(() => client2().answerQuestion(args.issue, args.number, { option: args.option, text: args.text })));
|
|
17987
18068
|
registerStrict("list_requirements", {
|
|
17988
18069
|
description: "List requirements filtered by project and text: lifecycle (draft/approved/amended), the latest and approved revision numbers, the cross-cutting flag and the linked-epic count.",
|
|
17989
18070
|
inputSchema: listRequirementsFilterSchema.shape
|
|
@@ -18078,6 +18159,18 @@ function createMcpServer(baseClient, apiBaseUrl, orgInstructions2 = /* @__PURE__
|
|
|
18078
18159
|
description: "List decision records filtered by `project` and `text`: each one\u2019s state, its replacement when superseded, and how many requirements and work items cite it. `text` matches title and body.",
|
|
18079
18160
|
inputSchema: listDecisionsFilterSchema.shape
|
|
18080
18161
|
}, (args) => run(() => client2().listDecisions(args), GUIDANCE_POINTER));
|
|
18162
|
+
registerStrict("update_decision", {
|
|
18163
|
+
description: "Correct a decision record while it is still `proposed`: `title`, `body`, or both. An edit naming nothing to change is refused here, before anything is sent. Once a record is `accepted` or `superseded` its text is frozen, and the correction is refused `decision_frozen`, which says to write the change as a new record and supersede this one. Use `accept_decision` to accept; asking for `superseded` here is refused, because superseding must name the replacement.",
|
|
18164
|
+
inputSchema: updateDecisionInputSchema
|
|
18165
|
+
}, (args) => run(() => client2().updateDecision(args.decision, {
|
|
18166
|
+
title: args.title,
|
|
18167
|
+
body: args.body,
|
|
18168
|
+
status: args.status
|
|
18169
|
+
})));
|
|
18170
|
+
registerStrict("accept_decision", {
|
|
18171
|
+
description: "Accept a decision record that is still `proposed`: it becomes `accepted`, stamped with who accepted it and when, and its text is frozen from then on \u2014 changing it later means a new record plus `supersede_decision`. The tool names the move, so the record is the only argument. A record that is already `accepted` or `superseded` is refused `decision_transition_not_allowed`, naming what it can still do.",
|
|
18172
|
+
inputSchema: { decision: decisionRefSchema }
|
|
18173
|
+
}, (args) => run(() => client2().updateDecision(args.decision, { status: "accepted" })));
|
|
18081
18174
|
registerStrict("supersede_decision", {
|
|
18082
18175
|
description: "Replace an accepted decision record with another: `decision` becomes `superseded` and points at `replacedBy`, where the current decision lives. Refused while the record is still `proposed` (correct it instead), when a record replaces itself, when the replacement is in another project, or when its chain already leads back to this record.",
|
|
18083
18176
|
inputSchema: supersedeDecisionInputSchema.shape
|
|
@@ -18113,7 +18206,7 @@ function createMcpServer(baseClient, apiBaseUrl, orgInstructions2 = /* @__PURE__
|
|
|
18113
18206
|
registerStrict("promote_deliverable", {
|
|
18114
18207
|
// The paste exception is stated because without it an agent holding the doctrine
|
|
18115
18208
|
// would refuse this tool's whole purpose.
|
|
18116
|
-
description: "Create a NEW issue from a deliverable (`DRAFT-KEY/platform`) with a protected link pinning its current revision, which cannot be removed. Needs `title` and `type`; `status` defaults to triage, `body` seeds the issue. A `status` past triage or killed needs `milestone`,
|
|
18209
|
+
description: "Create a NEW issue from a deliverable (`DRAFT-KEY/platform`) with a protected link pinning its current revision, which cannot be removed. Needs `title` and `type`; `status` defaults to triage, `body` seeds the issue. A `status` past triage or killed needs a `milestone`, else refused `milestone_required`. An archived milestone is refused `milestone_archived_write`. Seeding `body` with the post text is the exception to linking rather than pasting. See the doctrine `get_work_context` returns, under \u201CLink by key, never paste\u201D.",
|
|
18117
18210
|
inputSchema: {
|
|
18118
18211
|
deliverable: external_exports.string().min(1),
|
|
18119
18212
|
title: external_exports.string().min(1),
|
|
@@ -18293,7 +18386,7 @@ function loadMcpConfig() {
|
|
|
18293
18386
|
}
|
|
18294
18387
|
|
|
18295
18388
|
// src/version.ts
|
|
18296
|
-
var VERSION = "0.
|
|
18389
|
+
var VERSION = "0.52.0";
|
|
18297
18390
|
|
|
18298
18391
|
// src/main.ts
|
|
18299
18392
|
async function scopedClient(base, org) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pipebrain-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.52.0",
|
|
4
4
|
"description": "Pipebrain MCP server for Claude Code and Claude Desktop — issues, requirements, decision records, conventions, prompts, content, assets, metadata-only secrets, and more of the platform's modules over the Pipebrain API.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|