pipebrain-mcp 0.43.1 → 0.44.1

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.
Files changed (2) hide show
  1. package/dist/main.js +53 -5
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -16622,6 +16622,30 @@ var ApiClient = class _ApiClient {
16622
16622
  timeoutMs: this.timeoutMs
16623
16623
  });
16624
16624
  }
16625
+ /**
16626
+ * The inverse of {@link forOrg}: a thin copy that stamps NO `X-Org-Id`, for the
16627
+ * org-INDEPENDENT routes named above.
16628
+ *
16629
+ * IT EXISTS BECAUSE A BASE CLIENT IS NOT ALWAYS UNSCOPED. The rule above assumes the
16630
+ * caller reaches those routes through the client it started with, which holds for the
16631
+ * web application. It does not hold for `pipebrain-mcp`, which scopes its client ONCE at
16632
+ * startup from `PIPEBRAIN_ORG` and hands that scoped client to the tool registry as its
16633
+ * base — so an org-independent call made there carries a header anyway.
16634
+ *
16635
+ * That is harmless while the default is good and actively harmful when it is not. A
16636
+ * default naming an organization its holder has since been removed from makes EVERY call
16637
+ * of that session refuse, including the one call whose whole purpose is to tell the
16638
+ * caller which organizations it may name instead. Asking that question has to work from
16639
+ * inside the broken state, or it does not help in the only case it is needed.
16640
+ */
16641
+ unscoped() {
16642
+ return new _ApiClient({
16643
+ baseUrl: this.baseUrl,
16644
+ auth: this.auth,
16645
+ fetch: this.fetchImpl,
16646
+ timeoutMs: this.timeoutMs
16647
+ });
16648
+ }
16625
16649
  // --- core ------------------------------------------------------------------
16626
16650
  /** Builds the auth + active-org headers for the configured mode. */
16627
16651
  authHeaders() {
@@ -17158,9 +17182,10 @@ var ApiClient = class _ApiClient {
17158
17182
  * Takes NO project and NO org PARAMETER: a queue you point at a project is the
17159
17183
  * per-project surface this replaces, and the organization is a property of the CLIENT,
17160
17184
  * which is where every caller already binds it — `X-Org-Id` for a session and for a
17161
- * bearer caller alike, falling back to the credential's own organization when nothing
17162
- * stamped one (PIPE-410 withdrew the rule that a bearer call's organization came off
17163
- * the token). The agent tool DOES take an `org`, and it is spent on `forOrg` before it
17185
+ * bearer caller alike. A call that stamps none is refused rather than resolved against
17186
+ * the credential, because PIPE-410 (an agent credential reaches every organization its
17187
+ * owner belongs to) left no organization on a credential to resolve against. The agent
17188
+ * tool DOES take an `org`, and it is spent on `forOrg` before it
17164
17189
  * gets here. `mine` narrows to the gates whose
17165
17190
  * work the viewer claimed — plus the requirement gates, which have no claimant at
17166
17191
  * all and would otherwise be waited on by nobody; omitting it is the wide view.
@@ -17628,6 +17653,29 @@ function createMcpServer(baseClient, apiBaseUrl, orgInstructions2 = /* @__PURE__
17628
17653
  })
17629
17654
  );
17630
17655
  }
17656
+ registerStrict("list_orgs", {
17657
+ description: "List the organizations this credential may act in \u2014 each with its name, slug, id, kind (personal or shared) and your role there. THIS IS THE ONE TOOL THAT NEEDS NO `org`: every other call names the organization it acts in and is refused if it names none, and this is how you find out which names you may use. The answer is your live memberships at this moment, which is exactly what that check tests against, so an organization you have just joined appears here and one you have been removed from does not (\xA77)."
17658
+ // NO inputSchema, and the absence is the point rather than an omission. There is
17659
+ // nothing to narrow: the answer is the caller's own memberships, and a filter over a
17660
+ // list this short would be a second way to ask one question.
17661
+ }, () => (
17662
+ // A BARE ARRAY, unlike `list_waiting`'s `{ items }`, and for the reason that tool
17663
+ // gives rather than against it: the envelope has already been unwrapped by
17664
+ // `ApiClient.listOrgs`, so passing it through is what avoids deciding the shape a
17665
+ // second time. The sibling list tools return bare arrays for the same reason.
17666
+ //
17667
+ // `.unscoped()` IS LOAD-BEARING, and this is the only tool that uses it. Every other
17668
+ // tool wants whatever scope is in force; this one must have none, because it is the
17669
+ // tool a caller reaches for when the scope in force is the problem. Two ways in:
17670
+ // a call naming an organization the caller cannot use, and — worse, because the
17671
+ // caller names nothing at all — a stdio server started with a `PIPEBRAIN_ORG` whose
17672
+ // organization its holder has since left, which scopes the registry's base client
17673
+ // once at startup. In either state every other call refuses, and without this the
17674
+ // one call that could say which organizations ARE available refuses along with them.
17675
+ // The answer does not depend on scope, so dropping it costs nothing and is what
17676
+ // makes the tool's own description true.
17677
+ run(() => client2().unscoped().listOrgs(), GUIDANCE_POINTER)
17678
+ ));
17631
17679
  registerStrict("list_projects", {
17632
17680
  description: "List all projects with their key, environments, milestones (token, label, active), deliverable targets (slug, label, active), and open-issue counts \u2014 the project switcher and workflow entry point (\xA77).",
17633
17681
  // Optional pagination (§9) — bounds mirror list_issues/list_requirements; the
@@ -17649,7 +17697,7 @@ function createMcpServer(baseClient, apiBaseUrl, orgInstructions2 = /* @__PURE__
17649
17697
  }
17650
17698
  }, (args) => run(() => client2().createProject(args)));
17651
17699
  registerStrict("list_waiting", {
17652
- description: "Every gate awaiting a PERSON across ALL projects in the organization this call acts in \u2014 name that organization with `org`, or omit it to read the one this session defaults to \u2014 longest wait first: a requirement revision awaiting approval, a question awaiting an answer, and work in `verify` holding at least one criterion not yet passed. Each entry names its project, the ref the action is taken on (`KEY-R{n}` for a revision, the ISSUE\u2019s `KEY-{n}` for a question or for work at verify), and `waitingSince` \u2014 the instant the wait began, not a duration. Nothing else is a gate: work in `triage` never appears, and neither does work in verify whose criteria have ALL passed. THIS TOOL is READ-ONLY and clears nothing; what clears each gate differs. Answering a question has no tool on this surface, by design. A requirement revision is approved with `approve_requirement`. A verify gate clears as its criteria pass \u2014 an `auto` one through `set_criterion_state`, a `manual` one only ever by a person in the web app. Use it to see what your work is blocked on before asking, rather than to act on it."
17700
+ description: "Every gate awaiting a PERSON across ALL projects in the organization this call acts in \u2014 name that organization with `org`, which is refused if omitted unless this session has a default \u2014 longest wait first: a requirement revision awaiting approval, a question awaiting an answer, and work in `verify` holding at least one criterion not yet passed. Each entry names its project, the ref the action is taken on (`KEY-R{n}` for a revision, the ISSUE\u2019s `KEY-{n}` for a question or for work at verify), and `waitingSince` \u2014 the instant the wait began, not a duration. Nothing else is a gate: work in `triage` never appears, and neither does work in verify whose criteria have ALL passed. THIS TOOL is READ-ONLY and clears nothing; what clears each gate differs. Answering a question has no tool on this surface, by design. A requirement revision is approved with `approve_requirement`. A verify gate clears as its criteria pass \u2014 an `auto` one through `set_criterion_state`, a `manual` one only ever by a person in the web app. Use it to see what your work is blocked on before asking, rather than to act on it."
17653
17701
  // NO NARROWING ARGUMENTS. The one argument this tool does take — `org`, which every
17654
17702
  // tool takes — is not a narrowing: it says WHICH ORGANIZATION the call acts in, not
17655
17703
  // which of that organization's gates come back, and the caller's membership there is
@@ -18246,7 +18294,7 @@ function loadMcpConfig() {
18246
18294
  }
18247
18295
 
18248
18296
  // src/version.ts
18249
- var VERSION = "0.43.1";
18297
+ var VERSION = "0.44.1";
18250
18298
 
18251
18299
  // src/main.ts
18252
18300
  async function scopedClient(base, org) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pipebrain-mcp",
3
- "version": "0.43.1",
3
+ "version": "0.44.1",
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",