pipebrain-mcp 0.60.0 → 0.61.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/README.md +1 -1
- package/dist/main.js +2 -259
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# pipebrain-mcp
|
|
2
2
|
|
|
3
3
|
The [Pipebrain](https://pipebrain.dev) MCP server: issues, requirements, decision records,
|
|
4
|
-
conventions, content drafts and deliverables,
|
|
4
|
+
conventions, content drafts and deliverables, milestones, metadata-only secrets,
|
|
5
5
|
and more of the platform's modules, exposed to Claude Code and Claude Desktop
|
|
6
6
|
over stdio.
|
|
7
7
|
|
package/dist/main.js
CHANGED
|
@@ -432,74 +432,6 @@ function agentConfigNotice(status) {
|
|
|
432
432
|
return status === "behind" ? `This machine's shared agent configuration is not the one this build ships \u2014 run \`${UPDATE_COMMAND}\` to see what would change and update it.` : null;
|
|
433
433
|
}
|
|
434
434
|
|
|
435
|
-
// ../../libs/agent-shared/dist/asset-transfer.js
|
|
436
|
-
import { createHash as createHash2 } from "node:crypto";
|
|
437
|
-
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync } from "node:fs";
|
|
438
|
-
import { basename, extname } from "node:path";
|
|
439
|
-
var MIME_BY_EXT = {
|
|
440
|
-
".png": "image/png",
|
|
441
|
-
".jpg": "image/jpeg",
|
|
442
|
-
".jpeg": "image/jpeg",
|
|
443
|
-
".gif": "image/gif",
|
|
444
|
-
".webp": "image/webp",
|
|
445
|
-
".svg": "image/svg+xml",
|
|
446
|
-
".pdf": "application/pdf",
|
|
447
|
-
".txt": "text/plain",
|
|
448
|
-
".md": "text/markdown",
|
|
449
|
-
".json": "application/json",
|
|
450
|
-
".csv": "text/csv",
|
|
451
|
-
".html": "text/html",
|
|
452
|
-
".mp4": "video/mp4",
|
|
453
|
-
".mov": "video/quicktime",
|
|
454
|
-
".zip": "application/zip"
|
|
455
|
-
};
|
|
456
|
-
function guessContentType(filename) {
|
|
457
|
-
return MIME_BY_EXT[extname(filename).toLowerCase()] ?? "application/octet-stream";
|
|
458
|
-
}
|
|
459
|
-
async function uploadAssetFromPath(client2, apiBaseUrl, input) {
|
|
460
|
-
if (!existsSync2(input.path))
|
|
461
|
-
throw new Error(`file not found: ${input.path}`);
|
|
462
|
-
const bytes = readFileSync2(input.path);
|
|
463
|
-
const filename = basename(input.path);
|
|
464
|
-
const contentType = input.contentType ?? guessContentType(filename);
|
|
465
|
-
const sha256 = createHash2("sha256").update(bytes).digest("hex");
|
|
466
|
-
const { asset, uploadUrl } = await client2.createAsset({
|
|
467
|
-
project: input.project,
|
|
468
|
-
filename,
|
|
469
|
-
contentType,
|
|
470
|
-
size: bytes.length,
|
|
471
|
-
sha256
|
|
472
|
-
});
|
|
473
|
-
const base = apiBaseUrl.replace(/\/+$/, "");
|
|
474
|
-
const target = uploadUrl.startsWith("http") ? uploadUrl : base + uploadUrl;
|
|
475
|
-
const put = await fetch(target, {
|
|
476
|
-
method: "PUT",
|
|
477
|
-
headers: { "content-type": contentType },
|
|
478
|
-
body: bytes
|
|
479
|
-
});
|
|
480
|
-
if (!put.ok) {
|
|
481
|
-
throw new Error(`upload PUT failed (${put.status} ${put.statusText}).`);
|
|
482
|
-
}
|
|
483
|
-
const verified = await client2.completeAsset(asset.id);
|
|
484
|
-
if (verified.status !== "active") {
|
|
485
|
-
throw new Error(`verification failed (${verified.status}${verified.rejectReason ? `: ${verified.rejectReason}` : ""}).`);
|
|
486
|
-
}
|
|
487
|
-
return verified;
|
|
488
|
-
}
|
|
489
|
-
async function downloadAssetToPath(client2, input) {
|
|
490
|
-
const asset = await client2.getAsset(input.asset);
|
|
491
|
-
if (asset.status !== "active") {
|
|
492
|
-
throw new Error(`asset ${input.asset} is ${asset.status}, not active \u2014 no bytes to download.`);
|
|
493
|
-
}
|
|
494
|
-
const buf = Buffer.from(await client2.downloadAsset(input.asset));
|
|
495
|
-
const got = createHash2("sha256").update(buf).digest("hex");
|
|
496
|
-
if (got !== asset.sha256) {
|
|
497
|
-
throw new Error(`integrity check failed: downloaded sha256 ${got} != recorded ${asset.sha256}.`);
|
|
498
|
-
}
|
|
499
|
-
writeFileSync(input.path, buf);
|
|
500
|
-
return { asset, path: input.path, bytesWritten: buf.length };
|
|
501
|
-
}
|
|
502
|
-
|
|
503
435
|
// ../../libs/agent-shared/dist/binding.js
|
|
504
436
|
function apiBindingLabel(apiBaseUrl) {
|
|
505
437
|
return /\/\/(localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1\])(:|\/|$)/.test(apiBaseUrl) ? "LOCAL dev" : "production/remote";
|
|
@@ -15078,15 +15010,6 @@ var inviteRoleSchema = external_exports.enum(["ADMIN", "CONTRIBUTOR"]);
|
|
|
15078
15010
|
var requirementLifecycleSchema = external_exports.enum(["draft", "approved", "amended"]);
|
|
15079
15011
|
var decisionStatusSchema = external_exports.enum(["proposed", "accepted", "superseded"]);
|
|
15080
15012
|
var platformSchema = external_exports.enum(["bsky", "x", "reddit", "hn", "blog"]);
|
|
15081
|
-
var assetStatusSchema = external_exports.enum(["pending", "active", "rejected"]);
|
|
15082
|
-
var assetLinkTargetSchema = external_exports.enum([
|
|
15083
|
-
"deliverable_revision",
|
|
15084
|
-
"content_draft",
|
|
15085
|
-
"issue",
|
|
15086
|
-
"requirement",
|
|
15087
|
-
"run",
|
|
15088
|
-
"criterion"
|
|
15089
|
-
]);
|
|
15090
15013
|
var instructionScopeSchema = external_exports.enum([
|
|
15091
15014
|
"general",
|
|
15092
15015
|
"requirements",
|
|
@@ -15141,9 +15064,6 @@ var SECRET_NAME_RE = /^[A-Z_][A-Z0-9_]*$/;
|
|
|
15141
15064
|
var secretNameSchema = external_exports.string().regex(SECRET_NAME_RE, {
|
|
15142
15065
|
message: "secret name must be UPPER_SNAKE_CASE: start with A\u2013Z or _, then only A\u2013Z, 0\u20139, or _ (e.g. API_KEY)"
|
|
15143
15066
|
}).max(128, { message: "secret name must be at most 128 characters" });
|
|
15144
|
-
var sha256Schema = external_exports.string().regex(/^[a-fA-F0-9]{64}$/, {
|
|
15145
|
-
message: "expected a hex-encoded SHA-256 (64 hex characters)"
|
|
15146
|
-
});
|
|
15147
15067
|
var metadataSchema = external_exports.object({
|
|
15148
15068
|
system: external_exports.record(external_exports.string(), external_exports.unknown()).default({}),
|
|
15149
15069
|
client: external_exports.record(external_exports.string(), external_exports.unknown()).default({})
|
|
@@ -15799,47 +15719,6 @@ var issueDeliverableLinkSchema = external_exports.object({
|
|
|
15799
15719
|
createdAt: external_exports.iso.datetime({ offset: true }),
|
|
15800
15720
|
deletedAt: external_exports.iso.datetime({ offset: true }).nullable()
|
|
15801
15721
|
});
|
|
15802
|
-
var assetSchema = external_exports.object({
|
|
15803
|
-
id: uuidSchema,
|
|
15804
|
-
// The asset's own identifier (PIPE-362), `ASSET-{n}`: numbered per ORGANISATION, the
|
|
15805
|
-
// way conventions are, because an asset may belong to no project and may move between
|
|
15806
|
-
// projects — a per-project number would be impossible for one and stale for the other.
|
|
15807
|
-
displayId: external_exports.string().min(1),
|
|
15808
|
-
orgId: uuidSchema,
|
|
15809
|
-
// Null for an ORG-level asset (a chat attachment, PIPE-15): assets were
|
|
15810
|
-
// project-scoped until chat introduced org-level files. Project assets keep a
|
|
15811
|
-
// uuid; the DB column and every read path (assetToWire) carry the null through.
|
|
15812
|
-
projectId: uuidSchema.nullable(),
|
|
15813
|
-
filename: external_exports.string().min(1),
|
|
15814
|
-
contentType: external_exports.string().min(1),
|
|
15815
|
-
size: positiveIntSchema,
|
|
15816
|
-
sha256: sha256Schema,
|
|
15817
|
-
status: assetStatusSchema,
|
|
15818
|
-
// Set only when `status === 'rejected'`: one of object_missing / size_mismatch /
|
|
15819
|
-
// digest_mismatch / too_large.
|
|
15820
|
-
rejectReason: external_exports.string().nullable(),
|
|
15821
|
-
// Whether a server-generated thumbnail object exists for this asset (images only,
|
|
15822
|
-
// best-effort at verify). The key itself is internal, like storageKey — the bytes
|
|
15823
|
-
// are served through a separate presigned-GET route, never a value field here.
|
|
15824
|
-
hasThumbnail: external_exports.boolean(),
|
|
15825
|
-
// Count of live (non-soft-deleted) asset_links referencing this asset — derived
|
|
15826
|
-
// server-side; 0 when unlinked (and only then is the asset safe to delete).
|
|
15827
|
-
linkCount: external_exports.number().int().nonnegative(),
|
|
15828
|
-
createdBy: uuidSchema.nullable(),
|
|
15829
|
-
createdAt: external_exports.iso.datetime({ offset: true }),
|
|
15830
|
-
verifiedAt: external_exports.iso.datetime({ offset: true }).nullable(),
|
|
15831
|
-
deletedAt: external_exports.iso.datetime({ offset: true }).nullable()
|
|
15832
|
-
});
|
|
15833
|
-
var assetLinkSchema = external_exports.object({
|
|
15834
|
-
id: uuidSchema,
|
|
15835
|
-
orgId: uuidSchema,
|
|
15836
|
-
assetId: uuidSchema,
|
|
15837
|
-
targetType: assetLinkTargetSchema,
|
|
15838
|
-
targetId: uuidSchema,
|
|
15839
|
-
createdBy: uuidSchema.nullable(),
|
|
15840
|
-
createdAt: external_exports.iso.datetime({ offset: true }),
|
|
15841
|
-
deletedAt: external_exports.iso.datetime({ offset: true }).nullable()
|
|
15842
|
-
});
|
|
15843
15722
|
var statusHistoryEntrySchema = external_exports.object({
|
|
15844
15723
|
id: uuidSchema,
|
|
15845
15724
|
orgId: uuidSchema,
|
|
@@ -16477,47 +16356,6 @@ var listContentFilterSchema = external_exports.strictObject({
|
|
|
16477
16356
|
limit: external_exports.number().int().min(1, { message: "limit must be at least 1" }).max(500, { message: "limit must be at most 500" }).optional(),
|
|
16478
16357
|
offset: external_exports.number().int().nonnegative().optional()
|
|
16479
16358
|
});
|
|
16480
|
-
var createAssetInputSchema = external_exports.strictObject({
|
|
16481
|
-
// Optional since PIPE-15: omit for an ORG-level asset (a chat attachment, stored
|
|
16482
|
-
// under `staging/org/{orgId}/…`). A project ref scopes the asset to that project.
|
|
16483
|
-
project: projectRefSchema.optional(),
|
|
16484
|
-
filename: external_exports.string().min(1, { message: "filename must not be empty" }),
|
|
16485
|
-
contentType: external_exports.string().min(1, { message: "content type must not be empty" }),
|
|
16486
|
-
size: positiveIntSchema,
|
|
16487
|
-
sha256: sha256Schema
|
|
16488
|
-
});
|
|
16489
|
-
var uploadAssetInputSchema = external_exports.strictObject({
|
|
16490
|
-
// Optional since PIPE-15: omit to upload an ORG-level asset (not scoped to any
|
|
16491
|
-
// project). A project ref scopes the upload to that project.
|
|
16492
|
-
project: projectRefSchema.optional(),
|
|
16493
|
-
path: external_exports.string().min(1, { message: "path must not be empty \u2014 give the local file to upload" }),
|
|
16494
|
-
contentType: external_exports.string().min(1, { message: "content type must not be empty" }).optional()
|
|
16495
|
-
});
|
|
16496
|
-
var downloadAssetInputSchema = external_exports.strictObject({
|
|
16497
|
-
asset: uuidSchema,
|
|
16498
|
-
path: external_exports.string().min(1, { message: "path must not be empty \u2014 give the local file to write" })
|
|
16499
|
-
});
|
|
16500
|
-
var linkAssetInputSchema = external_exports.strictObject({
|
|
16501
|
-
asset: external_exports.string().min(1, { message: "asset reference must not be empty" }),
|
|
16502
|
-
targetType: external_exports.enum(["deliverable_revision", "content_draft"]),
|
|
16503
|
-
targetId: uuidSchema
|
|
16504
|
-
});
|
|
16505
|
-
var unlinkAssetInputSchema = external_exports.strictObject({
|
|
16506
|
-
linkId: uuidSchema
|
|
16507
|
-
});
|
|
16508
|
-
var assetCategorySchema = external_exports.enum(["image", "video", "document"]);
|
|
16509
|
-
var assetSortSchema = external_exports.enum(["date", "size"]);
|
|
16510
|
-
var sortDirSchema = external_exports.enum(["asc", "desc"]);
|
|
16511
|
-
var listAssetsFilterSchema = external_exports.strictObject({
|
|
16512
|
-
project: projectRefSchema.optional(),
|
|
16513
|
-
status: external_exports.array(assetStatusSchema).optional(),
|
|
16514
|
-
category: assetCategorySchema.optional(),
|
|
16515
|
-
sort: assetSortSchema.optional(),
|
|
16516
|
-
dir: sortDirSchema.optional(),
|
|
16517
|
-
text: external_exports.string().optional(),
|
|
16518
|
-
limit: external_exports.number().int().min(1, { message: "limit must be at least 1" }).max(500, { message: "limit must be at most 500" }).optional(),
|
|
16519
|
-
offset: external_exports.number().int().nonnegative().optional()
|
|
16520
|
-
});
|
|
16521
16359
|
var setOrgInstructionInputSchema = external_exports.strictObject({
|
|
16522
16360
|
scope: instructionScopeSchema,
|
|
16523
16361
|
body: external_exports.string().min(1, { message: "instruction body must not be empty \u2014 clear the scope instead" }).max(4e3, { message: "instruction body must be at most 4000 characters" })
|
|
@@ -17068,73 +16906,6 @@ var ApiClient = class _ApiClient {
|
|
|
17068
16906
|
const { contentRef, platform } = splitDeliverableRef(deliverableRef);
|
|
17069
16907
|
return this.request("POST", `/api/v1/content/${enc(contentRef)}/deliverables/${enc(platform)}/promote`, { body: input });
|
|
17070
16908
|
}
|
|
17071
|
-
// --- assets ----------------------------------------------------------------
|
|
17072
|
-
createAsset(input) {
|
|
17073
|
-
return this.request("POST", "/api/v1/assets", { body: input });
|
|
17074
|
-
}
|
|
17075
|
-
completeAsset(id) {
|
|
17076
|
-
return this.request("POST", `/api/v1/assets/${enc(id)}/complete`);
|
|
17077
|
-
}
|
|
17078
|
-
listAssets(filter = {}) {
|
|
17079
|
-
return this.requestList("GET", "/api/v1/assets", { query: filter });
|
|
17080
|
-
}
|
|
17081
|
-
getAsset(id) {
|
|
17082
|
-
return this.request("GET", `/api/v1/assets/${enc(id)}`);
|
|
17083
|
-
}
|
|
17084
|
-
/**
|
|
17085
|
-
* The presigned-GET download route (reveal plane) — navigate/fetch with auth; server
|
|
17086
|
-
* 302s to S3. Prefixed with `baseUrl` (PIPE-180): relative under the web's
|
|
17087
|
-
* same-origin '' base, absolute when the client targets a separate API origin.
|
|
17088
|
-
*/
|
|
17089
|
-
assetDownloadPath(id) {
|
|
17090
|
-
return `${this.baseUrl}/api/v1/assets/${enc(id)}/download`;
|
|
17091
|
-
}
|
|
17092
|
-
/**
|
|
17093
|
-
* Fetches an active asset's raw bytes via the download route, following the 302 to
|
|
17094
|
-
* the presigned GET (a cross-origin redirect drops the auth header, so S3 gets a
|
|
17095
|
-
* clean presigned request). Returns the bytes for a caller to write to a file — the
|
|
17096
|
-
* MCP `download_asset` tool and the CLI write to a local path and surface metadata
|
|
17097
|
-
* only, so bytes never cross a tool boundary. `active` assets only (409 otherwise).
|
|
17098
|
-
*/
|
|
17099
|
-
async downloadAsset(id) {
|
|
17100
|
-
let response;
|
|
17101
|
-
try {
|
|
17102
|
-
response = await this.fetchImpl(this.buildUrl(`/api/v1/assets/${enc(id)}/download`, void 0), {
|
|
17103
|
-
method: "GET",
|
|
17104
|
-
headers: this.authHeaders(),
|
|
17105
|
-
redirect: "follow",
|
|
17106
|
-
signal: AbortSignal.timeout(this.timeoutMs)
|
|
17107
|
-
});
|
|
17108
|
-
} catch (err) {
|
|
17109
|
-
throw toTransportError(err, this.timeoutMs);
|
|
17110
|
-
}
|
|
17111
|
-
if (!response.ok) {
|
|
17112
|
-
const rawText = await response.text();
|
|
17113
|
-
throw toApiError(response.status, rawText.length === 0 ? void 0 : safeJsonParse(rawText), rawText);
|
|
17114
|
-
}
|
|
17115
|
-
return response.arrayBuffer();
|
|
17116
|
-
}
|
|
17117
|
-
/**
|
|
17118
|
-
* The presigned-GET thumbnail route (reveal plane) — an `<img src>` follows the 302;
|
|
17119
|
-
* 404 ⇒ no thumbnail. Prefixed with `baseUrl` like {@link assetDownloadPath}.
|
|
17120
|
-
*/
|
|
17121
|
-
assetThumbnailPath(id) {
|
|
17122
|
-
return `${this.baseUrl}/api/v1/assets/${enc(id)}/thumbnail`;
|
|
17123
|
-
}
|
|
17124
|
-
/** Soft-delete an asset — 409 if it still has live references (delete is web/CLI only). */
|
|
17125
|
-
deleteAsset(id) {
|
|
17126
|
-
return this.request("DELETE", `/api/v1/assets/${enc(id)}`);
|
|
17127
|
-
}
|
|
17128
|
-
/** The live references TO an asset, resolved to display labels (the asset-detail panel). */
|
|
17129
|
-
listAssetLinks(id) {
|
|
17130
|
-
return this.requestList("GET", `/api/v1/assets/${enc(id)}/links`);
|
|
17131
|
-
}
|
|
17132
|
-
linkAsset(input) {
|
|
17133
|
-
return this.request("POST", "/api/v1/asset-links", { body: input });
|
|
17134
|
-
}
|
|
17135
|
-
unlinkAsset(linkId) {
|
|
17136
|
-
return this.request("DELETE", `/api/v1/asset-links/${enc(linkId)}`);
|
|
17137
|
-
}
|
|
17138
16909
|
// --- projects --------------------------------------------------------------
|
|
17139
16910
|
createProject(input) {
|
|
17140
16911
|
return this.request("POST", "/api/v1/projects", { body: input });
|
|
@@ -17640,7 +17411,6 @@ function createMcpServer(baseClient, apiBaseUrl, orgInstructions2 = /* @__PURE__
|
|
|
17640
17411
|
return createMcpServerWithRegistry(baseClient, apiBaseUrl, orgInstructions2, opts).server;
|
|
17641
17412
|
}
|
|
17642
17413
|
function createMcpServerWithRegistry(baseClient, apiBaseUrl, orgInstructions2 = /* @__PURE__ */ new Map(), opts = {}) {
|
|
17643
|
-
const surface = opts.surface ?? "local";
|
|
17644
17414
|
const registry2 = [];
|
|
17645
17415
|
const scope = new AsyncLocalStorage();
|
|
17646
17416
|
function client2() {
|
|
@@ -18173,7 +17943,7 @@ function createMcpServerWithRegistry(baseClient, apiBaseUrl, orgInstructions2 =
|
|
|
18173
17943
|
inputSchema: listContentFilterSchema.shape
|
|
18174
17944
|
}, (args) => run(() => client2().listContent(args), GUIDANCE_POINTER));
|
|
18175
17945
|
registerStrict("get_content", {
|
|
18176
|
-
description: "Get a content draft by display id (`KEY-C{n}`) or uuid: its revisions, latest or the `revision` you name, plus every deliverable
|
|
17946
|
+
description: "Get a content draft by display id (`KEY-C{n}`) or uuid: its revisions, latest or the `revision` you name, plus every deliverable and linked issue.",
|
|
18177
17947
|
inputSchema: { content: contentRefSchema, revision: positiveIntSchema.optional() }
|
|
18178
17948
|
}, (args) => run(() => client2().getContent(args.content, args.revision), GUIDANCE_POINTER));
|
|
18179
17949
|
registerStrict("create_content", {
|
|
@@ -18222,32 +17992,6 @@ function createMcpServerWithRegistry(baseClient, apiBaseUrl, orgInstructions2 =
|
|
|
18222
17992
|
...refusedIssueHeaderFields
|
|
18223
17993
|
}
|
|
18224
17994
|
}, ({ deliverable, ...fields }) => run(() => client2().promoteDeliverable(deliverable, fields)));
|
|
18225
|
-
registerStrict("list_assets", {
|
|
18226
|
-
description: "List project assets, filtered by status (pending/active/rejected), category (image/video/document) and filename text, sorted by date or size. No bytes cross this result.",
|
|
18227
|
-
inputSchema: listAssetsFilterSchema.shape
|
|
18228
|
-
}, (args) => run(() => client2().listAssets(args), GUIDANCE_POINTER));
|
|
18229
|
-
registerStrict("get_asset", {
|
|
18230
|
-
description: "Get an asset\u2019s metadata by uuid: filename, contentType, size, sha256, status and linkCount. No bytes and no URL come back; use `download_asset` or `ppb assets download`.",
|
|
18231
|
-
inputSchema: { asset: uuidSchema }
|
|
18232
|
-
}, (args) => run(() => client2().getAsset(args.asset), GUIDANCE_POINTER));
|
|
18233
|
-
if (surface === "local") {
|
|
18234
|
-
registerStrict("upload_asset", {
|
|
18235
|
-
description: "Upload a local file as a project asset and activate it. Only the `path` crosses the wire \u2014 never base64 or file contents. `contentType` is guessed from the extension when omitted. Returns the asset metadata; `link_asset` then attaches it to a draft or a deliverable revision.",
|
|
18236
|
-
inputSchema: uploadAssetInputSchema.shape
|
|
18237
|
-
}, (args) => run(() => uploadAssetFromPath(client2(), apiBaseUrl, args)));
|
|
18238
|
-
registerStrict("download_asset", {
|
|
18239
|
-
description: "Write an ACTIVE asset\u2019s bytes to a local file at `path`, created or overwritten. Addressed by asset uuid. The bytes are checked against the recorded sha256; the result is metadata and the path.",
|
|
18240
|
-
inputSchema: downloadAssetInputSchema.shape
|
|
18241
|
-
}, (args) => run(() => downloadAssetToPath(client2(), args)));
|
|
18242
|
-
}
|
|
18243
|
-
registerStrict("link_asset", {
|
|
18244
|
-
description: "Reference an active asset from a `deliverable_revision` (a content_deliverable_revision uuid) or a `content_draft` (a content_draft uuid, copied onto later deliverables). A non-active asset or a cross-project link is rejected.",
|
|
18245
|
-
inputSchema: linkAssetInputSchema.shape
|
|
18246
|
-
}, (args) => run(() => client2().linkAsset(args)));
|
|
18247
|
-
registerStrict("unlink_asset", {
|
|
18248
|
-
description: "Remove an asset reference by its link id. This drops the reference only; the asset itself is untouched. Any member can remove any link.",
|
|
18249
|
-
inputSchema: unlinkAssetInputSchema.shape
|
|
18250
|
-
}, (args) => run(() => client2().unlinkAsset(args.linkId)));
|
|
18251
17995
|
registerStrict("set_secret", {
|
|
18252
17996
|
description: "Create a secret or add a new version under a project and environment. Do not send a sensitive value here \u2014 it lands in the chat transcript before the server can encrypt it; use `ppb secrets set` from stdin or `--from-file`. `name` is UPPER_SNAKE_CASE, `environment` is a slug (dev/prod). See \u201CA secret value never travels in a tool call\u201D in the doctrine `get_work_context` returns.",
|
|
18253
17997
|
inputSchema: {
|
|
@@ -18387,7 +18131,7 @@ function loadMcpConfig() {
|
|
|
18387
18131
|
}
|
|
18388
18132
|
|
|
18389
18133
|
// src/version.ts
|
|
18390
|
-
var VERSION = "0.
|
|
18134
|
+
var VERSION = "0.61.0";
|
|
18391
18135
|
|
|
18392
18136
|
// src/main.ts
|
|
18393
18137
|
async function scopedClient(base, org) {
|
|
@@ -18411,7 +18155,6 @@ var client = await scopedClient(
|
|
|
18411
18155
|
var orgInstructions = await fetchOrgInstructionsSafe(client);
|
|
18412
18156
|
var server = createMcpServer(client, config2.apiUrl, orgInstructions, {
|
|
18413
18157
|
version: VERSION,
|
|
18414
|
-
surface: "local",
|
|
18415
18158
|
// The writing rules follow the organization the CALL acts in (PIPE-410). Without this,
|
|
18416
18159
|
// a `get_work_context` naming another organization returns that organization's work,
|
|
18417
18160
|
// requirements and conventions under THIS one's rules, in one document, with nothing in
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pipebrain-mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Pipebrain MCP server for Claude Code and Claude Desktop — issues, requirements, decision records, conventions, content,
|
|
3
|
+
"version": "0.61.0",
|
|
4
|
+
"description": "Pipebrain MCP server for Claude Code and Claude Desktop — issues, requirements, decision records, conventions, content, metadata-only secrets, and more of the platform's modules over the Pipebrain API.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"main": "./dist/main.js",
|