@burdenoff/mcp-libs 2026.720.1 → 2026.720.3
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/modules/atheletebridge/index.cjs +26 -5
- package/dist/modules/atheletebridge/index.cjs.map +1 -1
- package/dist/modules/atheletebridge/index.js +26 -5
- package/dist/modules/atheletebridge/index.js.map +1 -1
- package/dist/modules/labsofscience/index.cjs +125 -26
- package/dist/modules/labsofscience/index.cjs.map +1 -1
- package/dist/modules/labsofscience/index.js +125 -26
- package/dist/modules/labsofscience/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -249,9 +249,10 @@ var ARCHIVE_DATASET = `
|
|
|
249
249
|
}
|
|
250
250
|
`;
|
|
251
251
|
var LIST_PIPELINES = `
|
|
252
|
-
query LabsofscienceListPipelines {
|
|
253
|
-
labListPipelines {
|
|
254
|
-
${PIPELINE_FIELDS}
|
|
252
|
+
query LabsofscienceListPipelines($pagination: PaginationInput) {
|
|
253
|
+
labListPipelines(pagination: $pagination) {
|
|
254
|
+
items { ${PIPELINE_FIELDS} }
|
|
255
|
+
${PAGE_INFO}
|
|
255
256
|
}
|
|
256
257
|
}
|
|
257
258
|
`;
|
|
@@ -301,9 +302,14 @@ var GET_INSTRUMENT = `
|
|
|
301
302
|
}
|
|
302
303
|
`;
|
|
303
304
|
var LIST_INSTRUMENTS = `
|
|
304
|
-
query LabsofscienceListInstruments(
|
|
305
|
-
|
|
306
|
-
|
|
305
|
+
query LabsofscienceListInstruments(
|
|
306
|
+
$status: LabInstrumentStatus
|
|
307
|
+
$search: String
|
|
308
|
+
$pagination: PaginationInput
|
|
309
|
+
) {
|
|
310
|
+
labListInstruments(status: $status, search: $search, pagination: $pagination) {
|
|
311
|
+
items { ${INSTRUMENT_FIELDS} }
|
|
312
|
+
${PAGE_INFO}
|
|
307
313
|
}
|
|
308
314
|
}
|
|
309
315
|
`;
|
|
@@ -384,6 +390,13 @@ var LIST_NOTEBOOK_ENTRIES = `
|
|
|
384
390
|
}
|
|
385
391
|
}
|
|
386
392
|
`;
|
|
393
|
+
var GET_NOTEBOOK_ENTRY = `
|
|
394
|
+
query LabsofscienceGetNotebookEntry($id: ID!) {
|
|
395
|
+
labNotebookEntry(id: $id) {
|
|
396
|
+
${NOTEBOOK_FIELDS}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
`;
|
|
387
400
|
var CREATE_NOTEBOOK_ENTRY = `
|
|
388
401
|
mutation LabsofscienceCreateNotebookEntry($input: LabCreateNotebookEntryInput!) {
|
|
389
402
|
labCreateNotebookEntry(input: $input) {
|
|
@@ -398,6 +411,13 @@ var SIGN_NOTEBOOK_ENTRY = `
|
|
|
398
411
|
}
|
|
399
412
|
}
|
|
400
413
|
`;
|
|
414
|
+
var WITNESS_NOTEBOOK_ENTRY = `
|
|
415
|
+
mutation LabsofscienceWitnessNotebookEntry($id: ID!) {
|
|
416
|
+
labWitnessNotebookEntry(id: $id) {
|
|
417
|
+
${NOTEBOOK_FIELDS}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
`;
|
|
401
421
|
var HEALTH = `
|
|
402
422
|
query LabsofscienceHealth {
|
|
403
423
|
labHealth
|
|
@@ -582,7 +602,11 @@ function registerProjectTools(server, ctx, track) {
|
|
|
582
602
|
{
|
|
583
603
|
title: "Archive Research Project",
|
|
584
604
|
description: "Archive a research project. Returns true on success.",
|
|
585
|
-
inputSchema: { id: z.string().describe("Project ID") }
|
|
605
|
+
inputSchema: { id: z.string().describe("Project ID") },
|
|
606
|
+
// BOFF-3611: irreversible via this tool surface — see datasets.ts's
|
|
607
|
+
// datasets_archive for why this is an explicit per-tool override
|
|
608
|
+
// rather than a fleet-wide tool-name.ts regex change.
|
|
609
|
+
annotations: { destructiveHint: true }
|
|
586
610
|
},
|
|
587
611
|
async ({ id }) => {
|
|
588
612
|
try {
|
|
@@ -1010,7 +1034,12 @@ function registerProtocolTools(server, ctx, track) {
|
|
|
1010
1034
|
{
|
|
1011
1035
|
title: "Publish Protocol",
|
|
1012
1036
|
description: "Publish a draft protocol, freezing its version for reproducibility. Returns the published protocol with its steps.",
|
|
1013
|
-
inputSchema: { id: z.string().describe("Protocol ID") }
|
|
1037
|
+
inputSchema: { id: z.string().describe("Protocol ID") },
|
|
1038
|
+
// BOFF-3611: irreversible via this tool surface — publishing freezes
|
|
1039
|
+
// the version; there is no "unpublish" mutation. Explicit override —
|
|
1040
|
+
// see datasets.ts's datasets_archive for why per-tool, not a
|
|
1041
|
+
// fleet-wide tool-name.ts regex change.
|
|
1042
|
+
annotations: { destructiveHint: true }
|
|
1014
1043
|
},
|
|
1015
1044
|
async ({ id }) => {
|
|
1016
1045
|
try {
|
|
@@ -1144,7 +1173,12 @@ function registerDatasetTools(server, ctx, track) {
|
|
|
1144
1173
|
{
|
|
1145
1174
|
title: "Archive Dataset",
|
|
1146
1175
|
description: "Archive a dataset. Returns true on success.",
|
|
1147
|
-
inputSchema: { id: z.string().describe("Dataset ID") }
|
|
1176
|
+
inputSchema: { id: z.string().describe("Dataset ID") },
|
|
1177
|
+
// BOFF-3611: irreversible via this tool surface — the backend has no
|
|
1178
|
+
// "unarchive" mutation. Explicit override because tool-name.ts's
|
|
1179
|
+
// fleet-wide inference only matches "delete"; declaring it here (not
|
|
1180
|
+
// by widening that shared regex) keeps the blast radius to this tool.
|
|
1181
|
+
annotations: { destructiveHint: true }
|
|
1148
1182
|
},
|
|
1149
1183
|
async ({ id }) => {
|
|
1150
1184
|
try {
|
|
@@ -1167,12 +1201,18 @@ function registerPipelineTools(server, ctx, track) {
|
|
|
1167
1201
|
track(mcpToolName(ctx.productName, "pipelines_list")),
|
|
1168
1202
|
{
|
|
1169
1203
|
title: "List Analysis Pipelines",
|
|
1170
|
-
description: "List
|
|
1171
|
-
inputSchema: {
|
|
1204
|
+
description: "List analysis pipelines in the bound workspace, with pagination. Returns a connection ({ items, pageInfo }).",
|
|
1205
|
+
inputSchema: {
|
|
1206
|
+
limit: z.number().int().optional().describe("Page size (default 50)"),
|
|
1207
|
+
offset: z.number().int().optional().describe("Pagination offset (default 0)"),
|
|
1208
|
+
cursor: z.string().optional().describe("Opaque pagination cursor")
|
|
1209
|
+
}
|
|
1172
1210
|
},
|
|
1173
|
-
async () => {
|
|
1211
|
+
async ({ limit, offset, cursor }) => {
|
|
1174
1212
|
try {
|
|
1175
|
-
const data = await ctx.gql.workspace.request(LIST_PIPELINES, {
|
|
1213
|
+
const data = await ctx.gql.workspace.request(LIST_PIPELINES, {
|
|
1214
|
+
pagination: { limit: limit ?? 50, offset: offset ?? 0, cursor }
|
|
1215
|
+
});
|
|
1176
1216
|
return jsonResult(data.labListPipelines);
|
|
1177
1217
|
} catch (error) {
|
|
1178
1218
|
ctx.logger.error("labsofscience pipelines_list failed", { error: String(error) });
|
|
@@ -1322,14 +1362,22 @@ function registerInstrumentTools(server, ctx, track) {
|
|
|
1322
1362
|
track(mcpToolName(ctx.productName, "instruments_list")),
|
|
1323
1363
|
{
|
|
1324
1364
|
title: "List Instruments",
|
|
1325
|
-
description: "List lab instruments, optionally filtered by availability status.",
|
|
1365
|
+
description: "List lab instruments, optionally filtered by availability status and/or a name/model search term, with pagination. Returns a connection ({ items, pageInfo }).",
|
|
1326
1366
|
inputSchema: {
|
|
1327
|
-
status: InstrumentStatusEnum.optional().describe("Filter by instrument status")
|
|
1367
|
+
status: InstrumentStatusEnum.optional().describe("Filter by instrument status"),
|
|
1368
|
+
search: z.string().optional().describe("Search by name or model"),
|
|
1369
|
+
limit: z.number().int().optional().describe("Page size (default 50)"),
|
|
1370
|
+
offset: z.number().int().optional().describe("Pagination offset (default 0)"),
|
|
1371
|
+
cursor: z.string().optional().describe("Opaque pagination cursor")
|
|
1328
1372
|
}
|
|
1329
1373
|
},
|
|
1330
|
-
async ({ status }) => {
|
|
1374
|
+
async ({ status, search, limit, offset, cursor }) => {
|
|
1331
1375
|
try {
|
|
1332
|
-
const data = await ctx.gql.workspace.request(LIST_INSTRUMENTS, {
|
|
1376
|
+
const data = await ctx.gql.workspace.request(LIST_INSTRUMENTS, {
|
|
1377
|
+
status,
|
|
1378
|
+
search,
|
|
1379
|
+
pagination: { limit: limit ?? 50, offset: offset ?? 0, cursor }
|
|
1380
|
+
});
|
|
1333
1381
|
return jsonResult(data.labListInstruments);
|
|
1334
1382
|
} catch (error) {
|
|
1335
1383
|
ctx.logger.error("labsofscience instruments_list failed", { error: String(error) });
|
|
@@ -1556,7 +1604,11 @@ function registerInventoryTools(server, ctx, track) {
|
|
|
1556
1604
|
{
|
|
1557
1605
|
title: "Archive Inventory Item",
|
|
1558
1606
|
description: "Archive an inventory item. Returns true on success.",
|
|
1559
|
-
inputSchema: { id: z.string().describe("Inventory item ID") }
|
|
1607
|
+
inputSchema: { id: z.string().describe("Inventory item ID") },
|
|
1608
|
+
// BOFF-3611: irreversible via this tool surface — see datasets.ts's
|
|
1609
|
+
// datasets_archive for why this is an explicit per-tool override
|
|
1610
|
+
// rather than a fleet-wide tool-name.ts regex change.
|
|
1611
|
+
annotations: { destructiveHint: true }
|
|
1560
1612
|
},
|
|
1561
1613
|
async ({ id }) => {
|
|
1562
1614
|
try {
|
|
@@ -1606,6 +1658,26 @@ function registerNotebookTools(server, ctx, track) {
|
|
|
1606
1658
|
}
|
|
1607
1659
|
}
|
|
1608
1660
|
);
|
|
1661
|
+
server.registerTool(
|
|
1662
|
+
track(mcpToolName(ctx.productName, "notebook_get")),
|
|
1663
|
+
{
|
|
1664
|
+
title: "Get Notebook Entry",
|
|
1665
|
+
description: "Fetch a single ELN entry by ID.",
|
|
1666
|
+
inputSchema: { id: z.string().describe("Notebook entry ID") }
|
|
1667
|
+
},
|
|
1668
|
+
async ({ id }) => {
|
|
1669
|
+
try {
|
|
1670
|
+
const data = await ctx.gql.workspace.request(GET_NOTEBOOK_ENTRY, { id });
|
|
1671
|
+
if (!data.labNotebookEntry) return errorResult(`Notebook entry ${id} not found`);
|
|
1672
|
+
return jsonResult(data.labNotebookEntry);
|
|
1673
|
+
} catch (error) {
|
|
1674
|
+
ctx.logger.error("labsofscience notebook_get failed", { error: String(error) });
|
|
1675
|
+
return errorResult(
|
|
1676
|
+
`Failed to get notebook entry: ${error instanceof Error ? error.message : String(error)}`
|
|
1677
|
+
);
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
);
|
|
1609
1681
|
server.registerTool(
|
|
1610
1682
|
track(mcpToolName(ctx.productName, "notebook_create")),
|
|
1611
1683
|
{
|
|
@@ -1644,7 +1716,11 @@ function registerNotebookTools(server, ctx, track) {
|
|
|
1644
1716
|
{
|
|
1645
1717
|
title: "Sign Notebook Entry",
|
|
1646
1718
|
description: "Sign an ELN entry for record integrity (locks editable content). Returns the signed entry.",
|
|
1647
|
-
inputSchema: { id: z.string().describe("Notebook entry ID") }
|
|
1719
|
+
inputSchema: { id: z.string().describe("Notebook entry ID") },
|
|
1720
|
+
// BOFF-3611: irreversible — there is no "unsign" mutation. Explicit
|
|
1721
|
+
// override — see datasets.ts's datasets_archive for why per-tool,
|
|
1722
|
+
// not a fleet-wide tool-name.ts regex change.
|
|
1723
|
+
annotations: { destructiveHint: true }
|
|
1648
1724
|
},
|
|
1649
1725
|
async ({ id }) => {
|
|
1650
1726
|
try {
|
|
@@ -1658,6 +1734,29 @@ function registerNotebookTools(server, ctx, track) {
|
|
|
1658
1734
|
}
|
|
1659
1735
|
}
|
|
1660
1736
|
);
|
|
1737
|
+
server.registerTool(
|
|
1738
|
+
track(mcpToolName(ctx.productName, "notebook_witness")),
|
|
1739
|
+
{
|
|
1740
|
+
title: "Witness Notebook Entry",
|
|
1741
|
+
description: "Witness a SIGNED ELN entry as a second party for record integrity. Returns the witnessed entry.",
|
|
1742
|
+
inputSchema: { id: z.string().describe("Notebook entry ID") },
|
|
1743
|
+
// BOFF-3611: irreversible — there is no "unwitness" mutation. Explicit
|
|
1744
|
+
// override — see datasets.ts's datasets_archive for why per-tool,
|
|
1745
|
+
// not a fleet-wide tool-name.ts regex change.
|
|
1746
|
+
annotations: { destructiveHint: true }
|
|
1747
|
+
},
|
|
1748
|
+
async ({ id }) => {
|
|
1749
|
+
try {
|
|
1750
|
+
const data = await ctx.gql.workspace.request(WITNESS_NOTEBOOK_ENTRY, { id });
|
|
1751
|
+
return jsonResult(data.labWitnessNotebookEntry);
|
|
1752
|
+
} catch (error) {
|
|
1753
|
+
ctx.logger.error("labsofscience notebook_witness failed", { error: String(error) });
|
|
1754
|
+
return errorResult(
|
|
1755
|
+
`Failed to witness notebook entry: ${error instanceof Error ? error.message : String(error)}`
|
|
1756
|
+
);
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
);
|
|
1661
1760
|
}
|
|
1662
1761
|
|
|
1663
1762
|
// src/modules/labsofscience/tools/health.ts
|
|
@@ -1732,9 +1831,9 @@ Science & discovery platform \u2014 a research LIMS / ELN.
|
|
|
1732
1831
|
|
|
1733
1832
|
## Tool groups
|
|
1734
1833
|
projects, experiments, runs, protocols, datasets, pipelines, instruments, inventory, notebook, health.
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
(workspace-scoped) except the public health probe.
|
|
1834
|
+
Every list query \u2014 including instruments_list and pipelines_list \u2014 returns { items, pageInfo }
|
|
1835
|
+
connections and accepts a PaginationInput { limit, offset, cursor }. All run against the WORKSPACE
|
|
1836
|
+
gateway (workspace-scoped) except the public health probe.
|
|
1738
1837
|
`;
|
|
1739
1838
|
return {
|
|
1740
1839
|
contents: [{ uri: schemaUri, text: schema, mimeType: "text/plain" }]
|
|
@@ -1784,7 +1883,7 @@ instruments_list and pipelines_list return plain arrays. All run against the WOR
|
|
|
1784
1883
|
instrumentsUri,
|
|
1785
1884
|
{
|
|
1786
1885
|
title: "Labsofscience Instrument Catalog",
|
|
1787
|
-
description: "
|
|
1886
|
+
description: "The first 50 lab instruments in the bound workspace.",
|
|
1788
1887
|
mimeType: "application/json"
|
|
1789
1888
|
},
|
|
1790
1889
|
async () => {
|
|
@@ -1792,7 +1891,7 @@ instruments_list and pipelines_list return plain arrays. All run against the WOR
|
|
|
1792
1891
|
try {
|
|
1793
1892
|
const data = await ctx.gql.workspace.request(
|
|
1794
1893
|
LIST_INSTRUMENTS,
|
|
1795
|
-
{}
|
|
1894
|
+
{ pagination: { limit: 50, offset: 0 } }
|
|
1796
1895
|
);
|
|
1797
1896
|
return {
|
|
1798
1897
|
contents: [
|
|
@@ -1823,7 +1922,7 @@ instruments_list and pipelines_list return plain arrays. All run against the WOR
|
|
|
1823
1922
|
pipelinesUri,
|
|
1824
1923
|
{
|
|
1825
1924
|
title: "Labsofscience Analysis Pipelines",
|
|
1826
|
-
description: "
|
|
1925
|
+
description: "The first 50 analysis pipelines in the bound workspace.",
|
|
1827
1926
|
mimeType: "application/json"
|
|
1828
1927
|
},
|
|
1829
1928
|
async () => {
|
|
@@ -1831,7 +1930,7 @@ instruments_list and pipelines_list return plain arrays. All run against the WOR
|
|
|
1831
1930
|
try {
|
|
1832
1931
|
const data = await ctx.gql.workspace.request(
|
|
1833
1932
|
LIST_PIPELINES,
|
|
1834
|
-
{}
|
|
1933
|
+
{ pagination: { limit: 50, offset: 0 } }
|
|
1835
1934
|
);
|
|
1836
1935
|
return {
|
|
1837
1936
|
contents: [
|