@pipeshub-ai/mcp 2.2.0 → 2.3.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 +2 -0
- package/bin/mcp-server.js +648 -175
- package/bin/mcp-server.js.map +17 -11
- package/bin/pipeshub.js +946 -0
- package/bin/pipeshub.js.map +14 -0
- package/esm/cli/client.d.ts +54 -0
- package/esm/cli/client.d.ts.map +1 -0
- package/esm/cli/client.js +230 -0
- package/esm/cli/client.js.map +1 -0
- package/esm/cli/commands.d.ts +30 -0
- package/esm/cli/commands.d.ts.map +1 -0
- package/esm/cli/commands.js +321 -0
- package/esm/cli/commands.js.map +1 -0
- package/esm/cli/config.d.ts +73 -0
- package/esm/cli/config.d.ts.map +1 -0
- package/esm/cli/config.js +218 -0
- package/esm/cli/config.js.map +1 -0
- package/esm/cli/init-qm.d.ts +11 -0
- package/esm/cli/init-qm.d.ts.map +1 -0
- package/esm/cli/init-qm.js +170 -0
- package/esm/cli/init-qm.js.map +1 -0
- package/esm/cli/pipeshub.d.ts +2 -0
- package/esm/cli/pipeshub.d.ts.map +1 -0
- package/esm/cli/pipeshub.js +296 -0
- package/esm/cli/pipeshub.js.map +1 -0
- package/esm/funcs/connectorLookupRecordByIdentifier.d.ts +68 -0
- package/esm/funcs/connectorLookupRecordByIdentifier.d.ts.map +1 -0
- package/esm/funcs/connectorLookupRecordByIdentifier.js +138 -0
- package/esm/funcs/connectorLookupRecordByIdentifier.js.map +1 -0
- package/esm/funcs/connectorNavigateKnowledgeGraph.d.ts +75 -0
- package/esm/funcs/connectorNavigateKnowledgeGraph.d.ts.map +1 -0
- package/esm/funcs/connectorNavigateKnowledgeGraph.js +152 -0
- package/esm/funcs/connectorNavigateKnowledgeGraph.js.map +1 -0
- package/esm/lib/base64.d.ts +1 -1
- package/esm/lib/base64.d.ts.map +1 -1
- package/esm/lib/base64.js +6 -3
- package/esm/lib/base64.js.map +1 -1
- package/esm/lib/bytes-to-base64.d.ts +16 -0
- package/esm/lib/bytes-to-base64.d.ts.map +1 -0
- package/esm/lib/bytes-to-base64.js +23 -0
- package/esm/lib/bytes-to-base64.js.map +1 -0
- package/esm/mcp-server/instructions.d.ts +1 -1
- package/esm/mcp-server/instructions.d.ts.map +1 -1
- package/esm/mcp-server/instructions.js +30 -0
- package/esm/mcp-server/instructions.js.map +1 -1
- package/esm/mcp-server/shared.d.ts +2 -2
- package/esm/mcp-server/shared.d.ts.map +1 -1
- package/esm/mcp-server/shared.js +7 -3
- package/esm/mcp-server/shared.js.map +1 -1
- package/esm/mcp-server/tools/_agui.d.ts +34 -0
- package/esm/mcp-server/tools/_agui.d.ts.map +1 -0
- package/esm/mcp-server/tools/_agui.js +91 -0
- package/esm/mcp-server/tools/_agui.js.map +1 -0
- package/esm/mcp-server/tools/_helpers.d.ts.map +1 -1
- package/esm/mcp-server/tools/_helpers.js +13 -6
- package/esm/mcp-server/tools/_helpers.js.map +1 -1
- package/esm/mcp-server/tools/pipeshubChat.d.ts +0 -3
- package/esm/mcp-server/tools/pipeshubChat.d.ts.map +1 -1
- package/esm/mcp-server/tools/pipeshubChat.js +75 -98
- package/esm/mcp-server/tools/pipeshubChat.js.map +1 -1
- package/esm/mcp-server/tools/pipeshubGetRecordContent.d.ts +118 -1
- package/esm/mcp-server/tools/pipeshubGetRecordContent.d.ts.map +1 -1
- package/esm/mcp-server/tools/pipeshubGetRecordContent.js +180 -29
- package/esm/mcp-server/tools/pipeshubGetRecordContent.js.map +1 -1
- package/esm/mcp-server/tools/pipeshubSearch.d.ts.map +1 -1
- package/esm/mcp-server/tools/pipeshubSearch.js +14 -1
- package/esm/mcp-server/tools/pipeshubSearch.js.map +1 -1
- package/esm/models/availablemodelsresponse.d.ts +1 -1
- package/esm/models/conversation.d.ts +1 -1
- package/esm/models/lookuprecordbyidentifierop.d.ts +7 -0
- package/esm/models/lookuprecordbyidentifierop.d.ts.map +1 -0
- package/esm/models/lookuprecordbyidentifierop.js +14 -0
- package/esm/models/lookuprecordbyidentifierop.js.map +1 -0
- package/esm/models/navigateknowledgegraphop.d.ts +14 -0
- package/esm/models/navigateknowledgegraphop.d.ts.map +1 -0
- package/esm/models/navigateknowledgegraphop.js +25 -0
- package/esm/models/navigateknowledgegraphop.js.map +1 -0
- package/esm/models/userteamsresponse.d.ts +1 -1
- package/esm/tool-names.js +3 -3
- package/esm/tool-names.js.map +1 -1
- package/package.json +3 -2
- package/qm/README.md +247 -0
- package/qm/SECURITY.md +134 -0
- package/qm/TROUBLESHOOTING.md +218 -0
- package/qm/qm.config.fragment.jsonc +42 -0
- package/qm/sandbox/Dockerfile +22 -0
- package/qm/sandbox/skills/pipeshub/SKILL.md +69 -0
- package/qm/sandbox/tools/pipeshub/tool.json +36 -0
- package/src/cli/client.ts +272 -0
- package/src/cli/commands.ts +403 -0
- package/src/cli/config.ts +229 -0
- package/src/cli/init-qm.ts +215 -0
- package/src/cli/pipeshub.ts +333 -0
- package/src/funcs/connectorLookupRecordByIdentifier.ts +200 -0
- package/src/funcs/connectorNavigateKnowledgeGraph.ts +215 -0
- package/src/lib/base64.ts +6 -3
- package/src/lib/bytes-to-base64.ts +24 -0
- package/src/mcp-server/instructions.ts +30 -0
- package/src/mcp-server/shared.ts +7 -3
- package/src/mcp-server/tools/_agui.ts +138 -0
- package/src/mcp-server/tools/_helpers.ts +13 -6
- package/src/mcp-server/tools/pipeshubChat.ts +78 -97
- package/src/mcp-server/tools/pipeshubGetRecordContent.ts +213 -29
- package/src/mcp-server/tools/pipeshubSearch.ts +14 -1
- package/src/models/lookuprecordbyidentifierop.ts +26 -0
- package/src/models/navigateknowledgegraphop.ts +56 -0
- package/src/tool-names.ts +3 -3
package/bin/mcp-server.js
CHANGED
|
@@ -50456,6 +50456,36 @@ the user can verify.
|
|
|
50456
50456
|
- \`pipeshub_agents\` — list the org's configured **agents** (specialized
|
|
50457
50457
|
assistants with their own prompt, tools, and knowledge scope).
|
|
50458
50458
|
|
|
50459
|
+
## Knowledge Sources
|
|
50460
|
+
|
|
50461
|
+
A source (an app connector or a KB) holds record groups (a project, space,
|
|
50462
|
+
drive, folder), which hold records (one ticket, page, file). Records nest —
|
|
50463
|
+
an epic over its stories, a page over its child pages.
|
|
50464
|
+
|
|
50465
|
+
**Every tool returns metadata or content.**
|
|
50466
|
+
|
|
50467
|
+
- \`pipeshub_search\` / \`pipeshub_chat\` — content, but only a ranked sample of
|
|
50468
|
+
blocks: never all blocks of a record, never every record that matches, never
|
|
50469
|
+
a complete list of what exists.
|
|
50470
|
+
- \`mode:"lookup"\` and \`mode:"navigate"\` — metadata: recordIds, fields, and
|
|
50471
|
+
structure. No document text. \`mode:"content"\` — one whole record.
|
|
50472
|
+
|
|
50473
|
+
**Combining them.** Search finds a starting point by wording; navigate on a
|
|
50474
|
+
\`recordId\` reveals what search structurally cannot — siblings, children,
|
|
50475
|
+
linked records, and the group's total count. For a question that must be
|
|
50476
|
+
exhaustive ("all", "how many", "every"), do NOT count search hits or trust a
|
|
50477
|
+
chat answer: navigate the record group, which reports the real total. For a
|
|
50478
|
+
record's siblings, navigate its parent — take the id from the \`Path\` line.
|
|
50479
|
+
|
|
50480
|
+
**A named record** — an issue key, a Confluence / Drive / Slack link, an
|
|
50481
|
+
external ID → \`mode:"lookup"\` FIRST. It returns that record's metadata (for a
|
|
50482
|
+
ticket: status, assignee, priority, dates) plus its \`recordId\`, which often
|
|
50483
|
+
answers the question outright. Never guess a \`recordId\`.
|
|
50484
|
+
|
|
50485
|
+
Pass a source's id from \`pipeshub_sources\` as \`apps: ["<id>"]\` to search or
|
|
50486
|
+
chat, and as \`nodeId\` to navigate. Navigate and lookup end in a \`Next:\` line
|
|
50487
|
+
naming the exact follow-up call — follow it.
|
|
50488
|
+
|
|
50459
50489
|
## Agents
|
|
50460
50490
|
|
|
50461
50491
|
Some orgs configure **agents** for specific jobs (e.g. a Slack messenger, a
|
|
@@ -50595,10 +50625,17 @@ var init_registration = __esm(() => {
|
|
|
50595
50625
|
init_requestid();
|
|
50596
50626
|
});
|
|
50597
50627
|
|
|
50598
|
-
// src/lib/base64.ts
|
|
50628
|
+
// src/lib/bytes-to-base64.ts
|
|
50599
50629
|
function bytesToBase64(u8arr) {
|
|
50600
|
-
|
|
50630
|
+
let binary = "";
|
|
50631
|
+
for (let i = 0;i < u8arr.length; i += BASE64_CHUNK) {
|
|
50632
|
+
binary += String.fromCharCode(...u8arr.subarray(i, i + BASE64_CHUNK));
|
|
50633
|
+
}
|
|
50634
|
+
return btoa(binary);
|
|
50601
50635
|
}
|
|
50636
|
+
var BASE64_CHUNK = 32768;
|
|
50637
|
+
|
|
50638
|
+
// src/lib/base64.ts
|
|
50602
50639
|
function bytesFromBase64(encoded) {
|
|
50603
50640
|
return Uint8Array.from(atob(encoded), (c) => c.charCodeAt(0));
|
|
50604
50641
|
}
|
|
@@ -51919,9 +51956,6 @@ function createRegisterPrompt(logger, server, getSDK, allowedScopes) {
|
|
|
51919
51956
|
}
|
|
51920
51957
|
|
|
51921
51958
|
// src/mcp-server/shared.ts
|
|
51922
|
-
function bytesToBase642(u8arr) {
|
|
51923
|
-
return btoa(String.fromCodePoint(...u8arr));
|
|
51924
|
-
}
|
|
51925
51959
|
async function consumeStream(stream) {
|
|
51926
51960
|
const reader = stream.getReader();
|
|
51927
51961
|
const chunks = [];
|
|
@@ -51942,13 +51976,13 @@ async function valueToBase64(value) {
|
|
|
51942
51976
|
if (value == null) {
|
|
51943
51977
|
return null;
|
|
51944
51978
|
} else if (value instanceof Uint8Array) {
|
|
51945
|
-
return
|
|
51979
|
+
return bytesToBase64(value);
|
|
51946
51980
|
} else if (value instanceof ArrayBuffer) {
|
|
51947
|
-
return
|
|
51981
|
+
return bytesToBase64(new Uint8Array(value));
|
|
51948
51982
|
} else if (value instanceof Response || value instanceof Blob) {
|
|
51949
|
-
return
|
|
51983
|
+
return bytesToBase64(new Uint8Array(await value.arrayBuffer()));
|
|
51950
51984
|
} else if (value instanceof ReadableStream) {
|
|
51951
|
-
return
|
|
51985
|
+
return bytesToBase64(await consumeStream(value));
|
|
51952
51986
|
} else if (typeof value === "string") {
|
|
51953
51987
|
return base64Schema.parse(value);
|
|
51954
51988
|
} else {
|
|
@@ -52912,6 +52946,77 @@ var init_agentsStreamMessage = __esm(() => {
|
|
|
52912
52946
|
init_async();
|
|
52913
52947
|
});
|
|
52914
52948
|
|
|
52949
|
+
// src/mcp-server/tools/_agui.ts
|
|
52950
|
+
function newChatStreamState() {
|
|
52951
|
+
return {
|
|
52952
|
+
conversation: null,
|
|
52953
|
+
recordsUsed: undefined,
|
|
52954
|
+
error: null,
|
|
52955
|
+
conversationId: null,
|
|
52956
|
+
title: null,
|
|
52957
|
+
text: new Map,
|
|
52958
|
+
rootMessageIds: new Set
|
|
52959
|
+
};
|
|
52960
|
+
}
|
|
52961
|
+
function applyAGUIFrame(state, frame) {
|
|
52962
|
+
const data = frame.data;
|
|
52963
|
+
const d = data && typeof data === "object" ? data : {};
|
|
52964
|
+
switch (frame.event) {
|
|
52965
|
+
case AGUIEvent.RUN_FINISHED: {
|
|
52966
|
+
const result = d.result;
|
|
52967
|
+
if (!result || typeof result !== "object")
|
|
52968
|
+
return false;
|
|
52969
|
+
state.conversation = result.conversation ?? null;
|
|
52970
|
+
state.recordsUsed = result.recordsUsed ?? result.meta?.recordsUsed;
|
|
52971
|
+
return true;
|
|
52972
|
+
}
|
|
52973
|
+
case AGUIEvent.RUN_ERROR: {
|
|
52974
|
+
state.error = (typeof data === "string" ? data : null) ?? d.message ?? d.error ?? frame.raw ?? "Stream error";
|
|
52975
|
+
return true;
|
|
52976
|
+
}
|
|
52977
|
+
case AGUIEvent.CUSTOM: {
|
|
52978
|
+
if (d.name === "conversation_created") {
|
|
52979
|
+
const value = d.value ?? {};
|
|
52980
|
+
state.conversationId = value.conversationId ?? state.conversationId;
|
|
52981
|
+
state.title = value.title ?? state.title;
|
|
52982
|
+
}
|
|
52983
|
+
return false;
|
|
52984
|
+
}
|
|
52985
|
+
case AGUIEvent.TEXT_MESSAGE_CONTENT: {
|
|
52986
|
+
if (typeof d.delta !== "string" || d.delta.length === 0)
|
|
52987
|
+
return false;
|
|
52988
|
+
const id = typeof d.messageId === "string" ? d.messageId : "";
|
|
52989
|
+
state.text.set(id, (state.text.get(id) ?? "") + d.delta);
|
|
52990
|
+
if (d.parentRunId == null)
|
|
52991
|
+
state.rootMessageIds.add(id);
|
|
52992
|
+
return false;
|
|
52993
|
+
}
|
|
52994
|
+
default:
|
|
52995
|
+
return false;
|
|
52996
|
+
}
|
|
52997
|
+
}
|
|
52998
|
+
function salvagedText(state) {
|
|
52999
|
+
const pick2 = (ids) => {
|
|
53000
|
+
let best = null;
|
|
53001
|
+
for (const id of ids) {
|
|
53002
|
+
const text = state.text.get(id);
|
|
53003
|
+
if (text && (best === null || text.length > best.length))
|
|
53004
|
+
best = text;
|
|
53005
|
+
}
|
|
53006
|
+
return best;
|
|
53007
|
+
};
|
|
53008
|
+
return pick2(state.rootMessageIds) ?? pick2(state.text.keys());
|
|
53009
|
+
}
|
|
53010
|
+
var AGUIEvent;
|
|
53011
|
+
var init__agui = __esm(() => {
|
|
53012
|
+
AGUIEvent = {
|
|
53013
|
+
RUN_FINISHED: "RUN_FINISHED",
|
|
53014
|
+
RUN_ERROR: "RUN_ERROR",
|
|
53015
|
+
CUSTOM: "CUSTOM",
|
|
53016
|
+
TEXT_MESSAGE_CONTENT: "TEXT_MESSAGE_CONTENT"
|
|
53017
|
+
};
|
|
53018
|
+
});
|
|
53019
|
+
|
|
52915
53020
|
// src/funcs/agentsListAgents.ts
|
|
52916
53021
|
function agentsListAgents(client$, request, options) {
|
|
52917
53022
|
return new APIPromise($do5(client$, request, options));
|
|
@@ -53121,15 +53226,17 @@ function trimCitations(citations) {
|
|
|
53121
53226
|
if (!Array.isArray(citations))
|
|
53122
53227
|
return [];
|
|
53123
53228
|
return citations.map((c) => {
|
|
53124
|
-
const
|
|
53229
|
+
const cd = c?.citationData ?? c;
|
|
53230
|
+
const md = cd?.metadata ?? c?.metadata ?? {};
|
|
53231
|
+
const content = typeof cd?.content === "string" ? cd.content : c?.content;
|
|
53125
53232
|
return {
|
|
53126
|
-
recordId: md.recordId ?? c?.recordId,
|
|
53127
|
-
recordName: md.recordName ?? c?.recordName,
|
|
53128
|
-
snippet: typeof
|
|
53233
|
+
recordId: md.recordId ?? cd?.recordId ?? c?.recordId,
|
|
53234
|
+
recordName: md.recordName ?? cd?.recordName ?? c?.recordName,
|
|
53235
|
+
snippet: typeof content === "string" ? content.slice(0, 280) : md.blockText ?? null,
|
|
53129
53236
|
mimeType: md.mimeType,
|
|
53130
53237
|
webUrl: md.webUrl,
|
|
53131
53238
|
pageNum: md.pageNum,
|
|
53132
|
-
chunkIndex: c?.chunkIndex ?? md.chunkIndex
|
|
53239
|
+
chunkIndex: cd?.chunkIndex ?? c?.chunkIndex ?? md.chunkIndex
|
|
53133
53240
|
};
|
|
53134
53241
|
});
|
|
53135
53242
|
}
|
|
@@ -53302,9 +53409,10 @@ var init_pipeshubChat = __esm(() => {
|
|
|
53302
53409
|
init_conversationsStreamMessage();
|
|
53303
53410
|
init_agentsStreamConversation();
|
|
53304
53411
|
init_agentsStreamMessage();
|
|
53412
|
+
init__agui();
|
|
53305
53413
|
init__helpers();
|
|
53306
53414
|
FiltersShape = object({
|
|
53307
|
-
apps: array(string2()).optional().describe("Source-scoping ids
|
|
53415
|
+
apps: array(string2()).optional().describe("Source-scoping ids from `pipeshub_sources` — connector instance and / " + "or knowledge base ids, mixed freely. The legacy org-wide " + "`knowledgeBase_<orgId>` id is still accepted on deployments that " + "predate per-KB sources. Empty / omitted means no app-side " + "restriction."),
|
|
53308
53416
|
kb: array(string2()).optional().describe("Legacy / unused. Leave empty.")
|
|
53309
53417
|
}).optional();
|
|
53310
53418
|
args = {
|
|
@@ -53318,40 +53426,45 @@ var init_pipeshubChat = __esm(() => {
|
|
|
53318
53426
|
chatMode: _enum([
|
|
53319
53427
|
"internal_search",
|
|
53320
53428
|
"web_search",
|
|
53321
|
-
"
|
|
53322
|
-
"quick",
|
|
53323
|
-
"verification",
|
|
53324
|
-
"deep"
|
|
53429
|
+
"quick"
|
|
53325
53430
|
]).optional().describe("Response strategy. The valid values depend on whether `agentId` is set:\n" + "- WITHOUT `agentId` (plain chat): `internal_search` — answer from the " + "org's indexed knowledge (default) — or `web_search` — answer from the " + `live web.
|
|
53326
|
-
` + "- WITH `agentId` (agent chat): `
|
|
53431
|
+
` + "- WITH `agentId` (agent chat): `quick` is the only supported mode and " + "is sent automatically, so this argument can be omitted.")
|
|
53327
53432
|
};
|
|
53328
53433
|
tool$pipeshubChat = {
|
|
53329
53434
|
name: "pipeshub_chat",
|
|
53330
|
-
description:
|
|
53331
|
-
|
|
53332
|
-
|
|
53333
|
-
|
|
53334
|
-
|
|
53335
|
-
|
|
53336
|
-
|
|
53337
|
-
|
|
53338
|
-
|
|
53339
|
-
|
|
53340
|
-
|
|
53341
|
-
|
|
53342
|
-
|
|
53343
|
-
|
|
53344
|
-
|
|
53345
|
-
|
|
53346
|
-
|
|
53347
|
-
|
|
53348
|
-
|
|
53349
|
-
|
|
53350
|
-
|
|
53351
|
-
|
|
53435
|
+
description: `Ask a question, get an answer grounded in the org's indexed data with
|
|
53436
|
+
citations. It reads a few retrieved passages — never a whole document,
|
|
53437
|
+
never a complete list.
|
|
53438
|
+
|
|
53439
|
+
**Three questions this tool gets WRONG. Check them first:**
|
|
53440
|
+
- **Structure** — "what's under this epic?", "which pages are in this
|
|
53441
|
+
space?", "what links to this ticket?", "what's in this folder?" →
|
|
53442
|
+
\`pipeshub_get_record_content\` \`mode:"navigate"\`. Ranking cannot see how
|
|
53443
|
+
records relate.
|
|
53444
|
+
- **Exhaustive** — "how many X?", "list ALL the Y", "every Z" →
|
|
53445
|
+
\`mode:"navigate"\`, which reports the group's real total. This tool
|
|
53446
|
+
undercounts and will not say so.
|
|
53447
|
+
- **One named document** — summarize it, extract from it, what does it say
|
|
53448
|
+
about X → \`pipeshub_search\` for the \`recordId\`, then \`mode:"content"\`.
|
|
53449
|
+
|
|
53450
|
+
Everything else about the org's knowledge belongs here: policies,
|
|
53451
|
+
processes, decisions, history, "what do we know about X", and any question
|
|
53452
|
+
spanning several documents.
|
|
53453
|
+
|
|
53454
|
+
**Internal search** (default, \`chatMode: "internal_search"\`): the user's
|
|
53455
|
+
documents, files, knowledge base, company policies — anything in their
|
|
53456
|
+
PipesHub-indexed sources (Drive, Box, Confluence, Slack, Gmail, Jira, the
|
|
53457
|
+
org's KB, ...).
|
|
53458
|
+
|
|
53459
|
+
**Web search** (\`chatMode: "web_search"\`): current events or public
|
|
53460
|
+
information unlikely to be in the org's knowledge base.
|
|
53461
|
+
|
|
53462
|
+
Both are plain-chat modes. **Agent chat** — pass an \`agentId\` from
|
|
53463
|
+
\`pipeshub_agents\` — runs against that agent's own prompt, tools and knowledge;
|
|
53464
|
+
\`quick\` is its only mode, requires the \`agentId\`, and is sent automatically.
|
|
53465
|
+
|
|
53352
53466
|
- "What's our policy on Y?" → \`pipeshub_chat\` (internal_search)
|
|
53353
53467
|
- "What's in the news about Z?" → \`pipeshub_chat\` (web_search)
|
|
53354
|
-
- "What is the latest version of <library>?" → \`pipeshub_chat\` (web_search)
|
|
53355
53468
|
- "Find / locate the file named X" → \`pipeshub_search\` (then
|
|
53356
53469
|
\`pipeshub_download_record\` if the user wants the bytes).
|
|
53357
53470
|
|
|
@@ -53381,9 +53494,10 @@ cited document, take \`citations[*].recordId\` and call
|
|
|
53381
53494
|
args,
|
|
53382
53495
|
tool: async (client, args2, ctx) => {
|
|
53383
53496
|
const fetchOptions = { signal: ctx.signal };
|
|
53497
|
+
const plainChatMode = args2.chatMode === "web_search" ? "web_search" : "internal_search";
|
|
53384
53498
|
let response;
|
|
53385
53499
|
if (args2.agentId) {
|
|
53386
|
-
const agentChatMode =
|
|
53500
|
+
const agentChatMode = "quick";
|
|
53387
53501
|
if (args2.conversationId) {
|
|
53388
53502
|
const [result] = await agentsStreamMessage(client, {
|
|
53389
53503
|
agentKey: args2.agentId,
|
|
@@ -53423,7 +53537,7 @@ cited document, take \`citations[*].recordId\` and call
|
|
|
53423
53537
|
modelKey: args2.modelKey,
|
|
53424
53538
|
modelName: args2.modelName,
|
|
53425
53539
|
modelFriendlyName: args2.modelFriendlyName,
|
|
53426
|
-
chatMode:
|
|
53540
|
+
chatMode: plainChatMode
|
|
53427
53541
|
}
|
|
53428
53542
|
}, { fetchOptions }).$inspect();
|
|
53429
53543
|
if (!result.ok)
|
|
@@ -53436,7 +53550,7 @@ cited document, take \`citations[*].recordId\` and call
|
|
|
53436
53550
|
modelKey: args2.modelKey,
|
|
53437
53551
|
modelName: args2.modelName,
|
|
53438
53552
|
modelFriendlyName: args2.modelFriendlyName,
|
|
53439
|
-
chatMode:
|
|
53553
|
+
chatMode: plainChatMode
|
|
53440
53554
|
}, { fetchOptions }).$inspect();
|
|
53441
53555
|
if (!result.ok)
|
|
53442
53556
|
return errorResult(result.error.message);
|
|
@@ -53445,62 +53559,36 @@ cited document, take \`citations[*].recordId\` and call
|
|
|
53445
53559
|
const httpErr = await httpErrorResult(response, "PipesHub chat request");
|
|
53446
53560
|
if (httpErr)
|
|
53447
53561
|
return httpErr;
|
|
53448
|
-
|
|
53449
|
-
let recordsUsed;
|
|
53450
|
-
let lastAccumulated = null;
|
|
53451
|
-
let errorMessage = null;
|
|
53562
|
+
const state = newChatStreamState();
|
|
53452
53563
|
try {
|
|
53453
53564
|
for await (const frame of iterateSSE(response)) {
|
|
53454
|
-
|
|
53455
|
-
case "complete": {
|
|
53456
|
-
const d = frame.data ?? {};
|
|
53457
|
-
finalConversation = d.conversation ?? null;
|
|
53458
|
-
recordsUsed = d.recordsUsed ?? d.meta?.recordsUsed;
|
|
53459
|
-
break;
|
|
53460
|
-
}
|
|
53461
|
-
case "error": {
|
|
53462
|
-
const d = frame.data ?? {};
|
|
53463
|
-
errorMessage = typeof d === "string" ? d : d.error ?? d.message ?? frame.raw ?? "Stream error";
|
|
53464
|
-
break;
|
|
53465
|
-
}
|
|
53466
|
-
case "answer_chunk": {
|
|
53467
|
-
const d = frame.data ?? {};
|
|
53468
|
-
if (typeof d.accumulated === "string") {
|
|
53469
|
-
lastAccumulated = d.accumulated;
|
|
53470
|
-
} else if (typeof d.content === "string") {
|
|
53471
|
-
lastAccumulated = (lastAccumulated ?? "") + d.content;
|
|
53472
|
-
}
|
|
53473
|
-
break;
|
|
53474
|
-
}
|
|
53475
|
-
default:
|
|
53476
|
-
break;
|
|
53477
|
-
}
|
|
53478
|
-
if (finalConversation || errorMessage)
|
|
53565
|
+
if (applyAGUIFrame(state, frame))
|
|
53479
53566
|
break;
|
|
53480
53567
|
}
|
|
53481
53568
|
} catch (e) {
|
|
53482
53569
|
return errorResult(`SSE stream failed: ${e.message}`);
|
|
53483
53570
|
}
|
|
53484
|
-
if (
|
|
53485
|
-
return errorResult(
|
|
53486
|
-
if (
|
|
53571
|
+
if (state.error)
|
|
53572
|
+
return errorResult(state.error);
|
|
53573
|
+
if (state.conversation) {
|
|
53487
53574
|
return jsonResult({
|
|
53488
|
-
...trimConversation(
|
|
53489
|
-
recordsUsed
|
|
53575
|
+
...trimConversation(state.conversation),
|
|
53576
|
+
recordsUsed: state.recordsUsed
|
|
53490
53577
|
});
|
|
53491
53578
|
}
|
|
53492
|
-
|
|
53579
|
+
const salvaged = salvagedText(state);
|
|
53580
|
+
if (salvaged) {
|
|
53493
53581
|
return jsonResult({
|
|
53494
|
-
conversationId:
|
|
53495
|
-
title:
|
|
53582
|
+
conversationId: state.conversationId,
|
|
53583
|
+
title: state.title,
|
|
53496
53584
|
status: "Inprogress",
|
|
53497
|
-
answer:
|
|
53585
|
+
answer: salvaged,
|
|
53498
53586
|
confidence: null,
|
|
53499
53587
|
citations: [],
|
|
53500
53588
|
followUpQuestions: [],
|
|
53501
53589
|
messageCount: 0,
|
|
53502
|
-
recordsUsed,
|
|
53503
|
-
warning: "Stream ended without a
|
|
53590
|
+
recordsUsed: state.recordsUsed,
|
|
53591
|
+
warning: "Stream ended without a terminal RUN_FINISHED; answer is the " + "accumulated TEXT_MESSAGE_CONTENT and citations are unavailable."
|
|
53504
53592
|
});
|
|
53505
53593
|
}
|
|
53506
53594
|
return errorResult("Stream ended without any usable frames.");
|
|
@@ -53669,10 +53757,23 @@ Typical uses:
|
|
|
53669
53757
|
- Show the user a ranked list of matching files when they ask "find /
|
|
53670
53758
|
search for X".
|
|
53671
53759
|
|
|
53760
|
+
Not for structural questions — what is under this epic, which pages are
|
|
53761
|
+
in this space, what links to this ticket. Ranking by content cannot show
|
|
53762
|
+
how records relate; use \`pipeshub_get_record_content\` \`mode:"navigate"\`.
|
|
53763
|
+
|
|
53764
|
+
**A ranked sample, never a complete list.** Hits are the top-scoring
|
|
53765
|
+
blocks from the best-matching records — not all blocks of any record, and
|
|
53766
|
+
not every record that matches. Never count them to answer "how many" /
|
|
53767
|
+
"all" / "every"; navigate the record group instead, which reports its
|
|
53768
|
+
real total.
|
|
53769
|
+
|
|
53672
53770
|
The response is trimmed to one row per hit:
|
|
53673
53771
|
\`{ recordId, recordName, score, snippet, mimeType, webUrl, ... }\`.
|
|
53674
53772
|
Highest \`score\` first; multiple hits may share the same \`recordId\`
|
|
53675
|
-
(different
|
|
53773
|
+
(different blocks of the same record).
|
|
53774
|
+
|
|
53775
|
+
When presenting results to the user, link each record using its
|
|
53776
|
+
\`webUrl\` (when present).`,
|
|
53676
53777
|
scopes: ["read"],
|
|
53677
53778
|
annotations: {
|
|
53678
53779
|
title: "Semantic search",
|
|
@@ -53966,44 +54067,306 @@ var init_connectorGetRecordContent = __esm(() => {
|
|
|
53966
54067
|
init_async();
|
|
53967
54068
|
});
|
|
53968
54069
|
|
|
54070
|
+
// src/models/lookuprecordbyidentifierop.ts
|
|
54071
|
+
var LookupRecordByIdentifierRequest$zodSchema;
|
|
54072
|
+
var init_lookuprecordbyidentifierop = __esm(() => {
|
|
54073
|
+
init_zod();
|
|
54074
|
+
LookupRecordByIdentifierRequest$zodSchema = object({
|
|
54075
|
+
connectorName: string2().describe("Connector hint to prioritise resolution order, e.g. `JIRA`, `CONFLUENCE`, `GOOGLE_DRIVE`, `SLACK`. Cannot widen beyond the connectors the caller can access.").optional(),
|
|
54076
|
+
identifiers: array(string2().min(1).max(2048)).min(1).max(10).describe("The references to resolve: URLs, issue keys such as `PA-1787`, or bare external system IDs. Paste each exactly as you found it — tracking parameters and fragments are handled. Up to 10 per call.")
|
|
54077
|
+
});
|
|
54078
|
+
});
|
|
54079
|
+
|
|
54080
|
+
// src/funcs/connectorLookupRecordByIdentifier.ts
|
|
54081
|
+
function connectorLookupRecordByIdentifier(client$, request, options) {
|
|
54082
|
+
return new APIPromise($do9(client$, request, options));
|
|
54083
|
+
}
|
|
54084
|
+
async function $do9(client$, request, options) {
|
|
54085
|
+
const parsed$ = safeParse4(request, (value$) => LookupRecordByIdentifierRequest$zodSchema.parse(value$), "Input validation failed");
|
|
54086
|
+
if (!parsed$.ok) {
|
|
54087
|
+
return [parsed$, { status: "invalid" }];
|
|
54088
|
+
}
|
|
54089
|
+
const payload$ = parsed$.value;
|
|
54090
|
+
const body$ = null;
|
|
54091
|
+
const path$ = pathToFunc("/connectors/record/lookup")();
|
|
54092
|
+
const query$ = encodeFormQuery({
|
|
54093
|
+
connectorName: payload$.connectorName,
|
|
54094
|
+
identifiers: payload$.identifiers
|
|
54095
|
+
});
|
|
54096
|
+
const headers$ = new Headers(compactMap({
|
|
54097
|
+
Accept: "application/json"
|
|
54098
|
+
}));
|
|
54099
|
+
const securityInput = await extractSecurity(client$._options.security);
|
|
54100
|
+
const requestSecurity = resolveGlobalSecurity(securityInput);
|
|
54101
|
+
const context = {
|
|
54102
|
+
options: client$._options,
|
|
54103
|
+
baseURL: options?.serverURL ?? client$._baseURL ?? "",
|
|
54104
|
+
operationID: "lookupRecordByIdentifier",
|
|
54105
|
+
oAuth2Scopes: ["kb:read", "connector:read"],
|
|
54106
|
+
resolvedSecurity: requestSecurity,
|
|
54107
|
+
securitySource: client$._options.security,
|
|
54108
|
+
retryConfig: options?.retries || client$._options.retryConfig || { strategy: "none" },
|
|
54109
|
+
retryCodes: options?.retryCodes || [
|
|
54110
|
+
"429",
|
|
54111
|
+
"500",
|
|
54112
|
+
"502",
|
|
54113
|
+
"503",
|
|
54114
|
+
"504"
|
|
54115
|
+
]
|
|
54116
|
+
};
|
|
54117
|
+
const requestRes = client$._createRequest(context, {
|
|
54118
|
+
security: requestSecurity,
|
|
54119
|
+
method: "GET",
|
|
54120
|
+
baseURL: options?.serverURL,
|
|
54121
|
+
path: path$,
|
|
54122
|
+
headers: headers$,
|
|
54123
|
+
query: query$,
|
|
54124
|
+
body: body$,
|
|
54125
|
+
userAgent: client$._options.userAgent,
|
|
54126
|
+
timeoutMs: options?.timeoutMs || client$._options.timeoutMs || -1
|
|
54127
|
+
}, options);
|
|
54128
|
+
if (!requestRes.ok) {
|
|
54129
|
+
return [requestRes, { status: "invalid" }];
|
|
54130
|
+
}
|
|
54131
|
+
const req$ = requestRes.value;
|
|
54132
|
+
const doResult = await client$._do(req$, {
|
|
54133
|
+
context,
|
|
54134
|
+
errorCodes: [],
|
|
54135
|
+
retryConfig: context.retryConfig,
|
|
54136
|
+
retryCodes: context.retryCodes
|
|
54137
|
+
});
|
|
54138
|
+
if (!doResult.ok) {
|
|
54139
|
+
return [doResult, { status: "request-error", request: req$ }];
|
|
54140
|
+
}
|
|
54141
|
+
return [doResult, {
|
|
54142
|
+
status: "complete",
|
|
54143
|
+
request: req$,
|
|
54144
|
+
response: doResult.value
|
|
54145
|
+
}];
|
|
54146
|
+
}
|
|
54147
|
+
var init_connectorLookupRecordByIdentifier = __esm(() => {
|
|
54148
|
+
init_encodings();
|
|
54149
|
+
init_primitives();
|
|
54150
|
+
init_schemas4();
|
|
54151
|
+
init_security2();
|
|
54152
|
+
init_url();
|
|
54153
|
+
init_lookuprecordbyidentifierop();
|
|
54154
|
+
init_async();
|
|
54155
|
+
});
|
|
54156
|
+
|
|
54157
|
+
// src/models/navigateknowledgegraphop.ts
|
|
54158
|
+
var NavigateKnowledgeGraphRequest$zodSchema;
|
|
54159
|
+
var init_navigateknowledgegraphop = __esm(() => {
|
|
54160
|
+
init_zod();
|
|
54161
|
+
NavigateKnowledgeGraphRequest$zodSchema = object({
|
|
54162
|
+
createdAfter: string2().describe("Filter children by source creation time. ISO 8601 `YYYY-MM-DD`, or a full datetime that MUST carry a timezone offset — a naive datetime is rejected rather than assumed to be UTC.").optional(),
|
|
54163
|
+
createdBefore: string2().describe("Filter children by source creation time. `YYYY-MM-DD` is inclusive of the whole day.").optional(),
|
|
54164
|
+
depth: int().min(1).max(3).describe("Levels of descendants to return in one call. Above 1, `rows` is a flat list of all descendants down to that level rather than only direct children, and each row carries its own `level`.").optional(),
|
|
54165
|
+
limit: int().min(50).max(200).describe("Children per page. The minimum is 50 — smaller values are rejected rather than silently raised.").optional(),
|
|
54166
|
+
modifiedAfter: string2().describe("Filter children by source modification time.").optional(),
|
|
54167
|
+
modifiedBefore: string2().describe("Filter children by source modification time.").optional(),
|
|
54168
|
+
nodeId: string2().min(1).max(2048).describe("The node to open. Take it from an `id` in a previous navigate or lookup response. Omit it entirely for the flat listing of everything reachable — the usual starting point. A URL or an issue key such as `PA-1787` also works: it is resolved to its record automatically.").optional(),
|
|
54169
|
+
nodeTypes: array(string2()).describe("Restrict children to these node types. Repeat the parameter for multiple types: `?nodeTypes=record&nodeTypes=folder`.").optional(),
|
|
54170
|
+
page: int().min(1).describe("Page number, 1-indexed.").optional()
|
|
54171
|
+
});
|
|
54172
|
+
});
|
|
54173
|
+
|
|
54174
|
+
// src/funcs/connectorNavigateKnowledgeGraph.ts
|
|
54175
|
+
function connectorNavigateKnowledgeGraph(client$, request, options) {
|
|
54176
|
+
return new APIPromise($do10(client$, request, options));
|
|
54177
|
+
}
|
|
54178
|
+
async function $do10(client$, request, options) {
|
|
54179
|
+
const parsed$ = safeParse4(request, (value$) => NavigateKnowledgeGraphRequest$zodSchema.optional().parse(value$), "Input validation failed");
|
|
54180
|
+
if (!parsed$.ok) {
|
|
54181
|
+
return [parsed$, { status: "invalid" }];
|
|
54182
|
+
}
|
|
54183
|
+
const payload$ = parsed$.value;
|
|
54184
|
+
const body$ = null;
|
|
54185
|
+
const path$ = pathToFunc("/connectors/navigate")();
|
|
54186
|
+
const query$ = encodeFormQuery({
|
|
54187
|
+
createdAfter: payload$?.createdAfter,
|
|
54188
|
+
createdBefore: payload$?.createdBefore,
|
|
54189
|
+
depth: payload$?.depth,
|
|
54190
|
+
limit: payload$?.limit,
|
|
54191
|
+
modifiedAfter: payload$?.modifiedAfter,
|
|
54192
|
+
modifiedBefore: payload$?.modifiedBefore,
|
|
54193
|
+
nodeId: payload$?.nodeId,
|
|
54194
|
+
nodeTypes: payload$?.nodeTypes,
|
|
54195
|
+
page: payload$?.page
|
|
54196
|
+
});
|
|
54197
|
+
const headers$ = new Headers(compactMap({
|
|
54198
|
+
Accept: "application/json"
|
|
54199
|
+
}));
|
|
54200
|
+
const securityInput = await extractSecurity(client$._options.security);
|
|
54201
|
+
const requestSecurity = resolveGlobalSecurity(securityInput);
|
|
54202
|
+
const context = {
|
|
54203
|
+
options: client$._options,
|
|
54204
|
+
baseURL: options?.serverURL ?? client$._baseURL ?? "",
|
|
54205
|
+
operationID: "navigateKnowledgeGraph",
|
|
54206
|
+
oAuth2Scopes: ["kb:read", "connector:read"],
|
|
54207
|
+
resolvedSecurity: requestSecurity,
|
|
54208
|
+
securitySource: client$._options.security,
|
|
54209
|
+
retryConfig: options?.retries || client$._options.retryConfig || { strategy: "none" },
|
|
54210
|
+
retryCodes: options?.retryCodes || [
|
|
54211
|
+
"429",
|
|
54212
|
+
"500",
|
|
54213
|
+
"502",
|
|
54214
|
+
"503",
|
|
54215
|
+
"504"
|
|
54216
|
+
]
|
|
54217
|
+
};
|
|
54218
|
+
const requestRes = client$._createRequest(context, {
|
|
54219
|
+
security: requestSecurity,
|
|
54220
|
+
method: "GET",
|
|
54221
|
+
baseURL: options?.serverURL,
|
|
54222
|
+
path: path$,
|
|
54223
|
+
headers: headers$,
|
|
54224
|
+
query: query$,
|
|
54225
|
+
body: body$,
|
|
54226
|
+
userAgent: client$._options.userAgent,
|
|
54227
|
+
timeoutMs: options?.timeoutMs || client$._options.timeoutMs || -1
|
|
54228
|
+
}, options);
|
|
54229
|
+
if (!requestRes.ok) {
|
|
54230
|
+
return [requestRes, { status: "invalid" }];
|
|
54231
|
+
}
|
|
54232
|
+
const req$ = requestRes.value;
|
|
54233
|
+
const doResult = await client$._do(req$, {
|
|
54234
|
+
context,
|
|
54235
|
+
errorCodes: [],
|
|
54236
|
+
retryConfig: context.retryConfig,
|
|
54237
|
+
retryCodes: context.retryCodes
|
|
54238
|
+
});
|
|
54239
|
+
if (!doResult.ok) {
|
|
54240
|
+
return [doResult, { status: "request-error", request: req$ }];
|
|
54241
|
+
}
|
|
54242
|
+
return [doResult, {
|
|
54243
|
+
status: "complete",
|
|
54244
|
+
request: req$,
|
|
54245
|
+
response: doResult.value
|
|
54246
|
+
}];
|
|
54247
|
+
}
|
|
54248
|
+
var init_connectorNavigateKnowledgeGraph = __esm(() => {
|
|
54249
|
+
init_encodings();
|
|
54250
|
+
init_primitives();
|
|
54251
|
+
init_schemas4();
|
|
54252
|
+
init_security2();
|
|
54253
|
+
init_url();
|
|
54254
|
+
init_navigateknowledgegraphop();
|
|
54255
|
+
init_async();
|
|
54256
|
+
});
|
|
54257
|
+
|
|
53969
54258
|
// src/mcp-server/tools/pipeshubGetRecordContent.ts
|
|
54259
|
+
async function renderedResult(response) {
|
|
54260
|
+
const parsed = await readJson(response);
|
|
54261
|
+
if (!parsed.ok)
|
|
54262
|
+
return parsed.result;
|
|
54263
|
+
const text = parsed.value?.text;
|
|
54264
|
+
return typeof text === "string" && text.trim().length > 0 ? { content: [{ type: "text", text }] } : jsonResult(parsed.value);
|
|
54265
|
+
}
|
|
53970
54266
|
var args4, tool$pipeshubGetRecordContent;
|
|
53971
54267
|
var init_pipeshubGetRecordContent = __esm(() => {
|
|
53972
54268
|
init_zod();
|
|
53973
54269
|
init_connectorGetRecordContent();
|
|
54270
|
+
init_connectorLookupRecordByIdentifier();
|
|
54271
|
+
init_connectorNavigateKnowledgeGraph();
|
|
53974
54272
|
init__helpers();
|
|
53975
54273
|
args4 = {
|
|
53976
|
-
|
|
54274
|
+
mode: _enum(["content", "navigate", "lookup"]).default("content").describe("`content` (default) reads a record's full text by `recordId`. " + "`lookup` resolves a URL / issue key / external ID to a recordId. " + "`navigate` browses the knowledge graph tree."),
|
|
54275
|
+
recordId: string2().min(1).optional().describe("Record identifier — usually a UUID for connector-sourced records or " + "a 24-character ObjectId for uploaded records. Get it from a chat " + "citation (`citations[*].recordId`) or from a `pipeshub_search` hit. " + "Required when `mode` is `content`."),
|
|
54276
|
+
nodeId: string2().min(1).max(2048).optional().describe("The node to open. Take it from a `record_id=` or `node_id=` shown in a " + "previous navigate or lookup response, from a search hit's `recordId`, " + "or from a `pipeshub_sources` id — a KB or connector id opens that " + "source directly. Omit it entirely for the flat listing of everything " + "reachable, newest first — the usual starting point. A URL or an issue " + "key such as `PA-1787` also works: it is resolved to its record " + "automatically, so no separate lookup is needed."),
|
|
54277
|
+
page: int().min(1).default(1).describe("Page number, 1-indexed."),
|
|
54278
|
+
limit: int().min(50).max(200).default(50).describe("Children per page. The minimum is 50 — smaller values are rejected " + "rather than silently raised."),
|
|
54279
|
+
depth: int().min(1).max(3).default(1).describe("Levels of descendants to return in one call. Above 1, the listing is a " + "flat list of all descendants down to that level rather than only " + "direct children, and each row carries its own `level`."),
|
|
54280
|
+
nodeTypes: array(string2()).optional().describe('Restrict children to these node types, e.g. `["record", "folder"]`.'),
|
|
54281
|
+
createdAfter: string2().optional().describe("Filter children by source creation time. ISO 8601 `YYYY-MM-DD`, or a " + "full datetime that MUST carry a timezone offset — a naive datetime is " + "rejected rather than assumed to be UTC."),
|
|
54282
|
+
createdBefore: string2().optional().describe("Filter children by source creation time. `YYYY-MM-DD` is inclusive of " + "the whole day."),
|
|
54283
|
+
modifiedAfter: string2().optional().describe("Filter children by source modification time. Same formats as " + "`createdAfter`."),
|
|
54284
|
+
modifiedBefore: string2().optional().describe("Filter children by source modification time. Same formats as " + "`createdBefore`."),
|
|
54285
|
+
identifiers: union([
|
|
54286
|
+
string2().min(1).max(2048),
|
|
54287
|
+
array(string2().min(1).max(2048)).min(1).max(10)
|
|
54288
|
+
]).optional().describe("The reference(s) to resolve: a URL, an issue key such as `PA-1787`, or " + "a bare external system ID. Paste each exactly as you found it — " + "tracking parameters and fragments are handled. Pass a single string, " + "or an array of up to 10 to resolve them in one call. Required when " + "`mode` is `lookup`."),
|
|
54289
|
+
connectorName: string2().optional().describe("Optional hint that prioritises resolution order, e.g. `JIRA`, " + "`CONFLUENCE`, `GOOGLE_DRIVE`, `SLACK`. It cannot widen the search beyond the " + "connectors you can already access. Useful on a retry when a lookup " + "came back empty.")
|
|
53977
54290
|
};
|
|
53978
54291
|
tool$pipeshubGetRecordContent = {
|
|
53979
54292
|
name: "pipeshub_get_record_content",
|
|
53980
|
-
description: `
|
|
53981
|
-
|
|
53982
|
-
|
|
53983
|
-
|
|
53984
|
-
|
|
53985
|
-
|
|
53986
|
-
|
|
53987
|
-
|
|
53988
|
-
|
|
53989
|
-
|
|
53990
|
-
|
|
53991
|
-
|
|
53992
|
-
|
|
53993
|
-
|
|
53994
|
-
|
|
53995
|
-
|
|
53996
|
-
|
|
53997
|
-
|
|
53998
|
-
|
|
53999
|
-
|
|
54000
|
-
|
|
54001
|
-
|
|
54002
|
-
|
|
54003
|
-
|
|
54293
|
+
description: `Three operations on the org's records. Pick by what you hold:
|
|
54294
|
+
|
|
54295
|
+
\`mode:"lookup"\` — a URL, issue key (PA-1787), or external ID
|
|
54296
|
+
→ its recordId plus the record's metadata
|
|
54297
|
+
\`mode:"navigate"\` — a question about structure: what is under X,
|
|
54298
|
+
what links to Y → browses the hierarchy
|
|
54299
|
+
\`mode:"content"\` — a recordId, and you need the document's COMPLETE text
|
|
54300
|
+
|
|
54301
|
+
**\`mode:"content"\` (default)** — the only way to see a document's complete
|
|
54302
|
+
text. Use it whenever missing part of the document could make the answer
|
|
54303
|
+
wrong: summarize, extract or list ALL of something, check whether or where
|
|
54304
|
+
a doc mentions X, review, or compare named docs. \`pipeshub_chat\` cannot do
|
|
54305
|
+
these — it never sees a whole document.
|
|
54306
|
+
|
|
54307
|
+
Judge by the user's INTENT, not their keywords: "what's this doc about?",
|
|
54308
|
+
"walk me through the report", "anything in here about Y?" are all
|
|
54309
|
+
full-content tasks. Get the \`recordId\` from a \`pipeshub_search\` top hit, a
|
|
54310
|
+
chat citation, or \`mode:"lookup"\`.
|
|
54311
|
+
|
|
54312
|
+
Returns one \`content\` string: a metadata header (title, source, key fields,
|
|
54313
|
+
pre-generated summary) then the full parsed text. A record with no
|
|
54314
|
+
extractable content returns the literal \`No record found\`. Use
|
|
54315
|
+
\`pipeshub_download_record\` only for the original file bytes.
|
|
54316
|
+
|
|
54317
|
+
**\`mode:"navigate"\`** — browse the hierarchy: RecordGroup (project /
|
|
54318
|
+
space / drive / folder) → Record (epic / story / page / file) → children,
|
|
54319
|
+
with breadcrumbs, related links and record IDs.
|
|
54320
|
+
|
|
54321
|
+
Use it when the question depends on structure rather than wording: what is
|
|
54322
|
+
under this epic, which pages sit in this space, what is linked to this
|
|
54323
|
+
ticket, what is in this folder — and every "how many" / "all of" / "every"
|
|
54324
|
+
question. Search ranks by content; only this shows how records relate, and
|
|
54325
|
+
only this gives a count you can trust.
|
|
54326
|
+
|
|
54327
|
+
Omit \`nodeId\` for a flat listing of everything reachable, most recently
|
|
54328
|
+
updated first — the usual starting point. A URL, an issue key, or a
|
|
54329
|
+
\`pipeshub_sources\` id also works and resolves automatically.
|
|
54330
|
+
|
|
54331
|
+
Pass \`depth:2\` or \`depth:3\` to see several levels in ONE call — an epic's
|
|
54332
|
+
stories AND their subtasks, a space's pages AND their children — instead of
|
|
54333
|
+
one call per level. Use it whenever the question needs an overview of a
|
|
54334
|
+
hierarchy rather than a single node.
|
|
54335
|
+
|
|
54336
|
+
Opening a record also prints that record's own metadata — for a ticket,
|
|
54337
|
+
status, assignee, priority and dates — so a question about one record is
|
|
54338
|
+
often answered by this call alone. It returns no document text; for that,
|
|
54339
|
+
re-call with \`mode:"content"\`.
|
|
54340
|
+
|
|
54341
|
+
Returns \`Path\` breadcrumbs, the current node's metadata, a children listing
|
|
54342
|
+
carrying \`record_id=\` or \`node_id=\` per row plus the group's total
|
|
54343
|
+
(\`Children 1-50 of 61\`), \`Related\` cross-references, and a \`Next:\` line.
|
|
54344
|
+
One page is usually every child, so only pass \`page:2\` when that \`Next:\`
|
|
54345
|
+
line says more exist.
|
|
54346
|
+
|
|
54347
|
+
**\`mode:"lookup"\`** — turn an external reference into a recordId, the first
|
|
54348
|
+
step whenever the question names one. Returns that record's metadata (for a
|
|
54349
|
+
ticket: status, assignee, priority, dates) plus its recordId, which
|
|
54350
|
+
\`mode:"navigate"\` takes to list what is under it and \`mode:"content"\` takes
|
|
54351
|
+
to read it.
|
|
54352
|
+
|
|
54353
|
+
Handles Jira keys and URLs, Confluence, Drive, Slack permalinks, Linear,
|
|
54354
|
+
Notion, ServiceNow sys_id, SharePoint, Gmail/Outlook, and any connector
|
|
54355
|
+
whose records index a web URL. Resolution searches ALL connectors you can
|
|
54356
|
+
access, regardless of any source filter you used elsewhere.
|
|
54357
|
+
|
|
54358
|
+
A miss is a 200 with empty \`matches\` and the input echoed in
|
|
54359
|
+
\`not_found_identifiers\` — that may mean no-access, not non-existence. Use
|
|
54360
|
+
\`mode:"navigate"\` to confirm the record exists before telling the user it
|
|
54361
|
+
does not. If \`ambiguous\` is true, pick from \`matches\` rather than taking
|
|
54362
|
+
the first.
|
|
54363
|
+
|
|
54364
|
+
Navigate and lookup return a rendered text view whose closing \`Next:\` line
|
|
54365
|
+
names the exact follow-up call — follow it. When presenting a record, link
|
|
54366
|
+
it using the \`Web URL\` from its metadata header (when present).`,
|
|
54004
54367
|
scopes: ["read"],
|
|
54005
54368
|
annotations: {
|
|
54006
|
-
title: "
|
|
54369
|
+
title: "Read, browse, or resolve records",
|
|
54007
54370
|
destructiveHint: false,
|
|
54008
54371
|
idempotentHint: true,
|
|
54009
54372
|
openWorldHint: false,
|
|
@@ -54011,9 +54374,48 @@ you need the original file bytes.`,
|
|
|
54011
54374
|
},
|
|
54012
54375
|
args: args4,
|
|
54013
54376
|
tool: async (client, args5, ctx) => {
|
|
54377
|
+
const fetchOptions = { fetchOptions: { signal: ctx.signal } };
|
|
54378
|
+
if (args5.mode === "navigate") {
|
|
54379
|
+
const [r] = await connectorNavigateKnowledgeGraph(client, {
|
|
54380
|
+
nodeId: args5.nodeId,
|
|
54381
|
+
page: args5.page,
|
|
54382
|
+
limit: args5.limit,
|
|
54383
|
+
depth: args5.depth,
|
|
54384
|
+
nodeTypes: args5.nodeTypes,
|
|
54385
|
+
createdAfter: args5.createdAfter,
|
|
54386
|
+
createdBefore: args5.createdBefore,
|
|
54387
|
+
modifiedAfter: args5.modifiedAfter,
|
|
54388
|
+
modifiedBefore: args5.modifiedBefore
|
|
54389
|
+
}, fetchOptions).$inspect();
|
|
54390
|
+
if (!r.ok)
|
|
54391
|
+
return errorResult(r.error.message);
|
|
54392
|
+
const httpErr2 = await httpErrorResult(r.value, "Navigate knowledge graph");
|
|
54393
|
+
if (httpErr2)
|
|
54394
|
+
return httpErr2;
|
|
54395
|
+
return renderedResult(r.value);
|
|
54396
|
+
}
|
|
54397
|
+
if (args5.mode === "lookup") {
|
|
54398
|
+
const identifiers = typeof args5.identifiers === "string" ? [args5.identifiers] : args5.identifiers ?? [];
|
|
54399
|
+
if (identifiers.length === 0) {
|
|
54400
|
+
return errorResult('`identifiers` is required when mode is "lookup".');
|
|
54401
|
+
}
|
|
54402
|
+
const [r] = await connectorLookupRecordByIdentifier(client, {
|
|
54403
|
+
identifiers,
|
|
54404
|
+
connectorName: args5.connectorName
|
|
54405
|
+
}, fetchOptions).$inspect();
|
|
54406
|
+
if (!r.ok)
|
|
54407
|
+
return errorResult(r.error.message);
|
|
54408
|
+
const httpErr2 = await httpErrorResult(r.value, "Record lookup");
|
|
54409
|
+
if (httpErr2)
|
|
54410
|
+
return httpErr2;
|
|
54411
|
+
return renderedResult(r.value);
|
|
54412
|
+
}
|
|
54413
|
+
if (!args5.recordId) {
|
|
54414
|
+
return errorResult('`recordId` is required when mode is "content".');
|
|
54415
|
+
}
|
|
54014
54416
|
const [result] = await connectorGetRecordContent(client, {
|
|
54015
54417
|
recordId: args5.recordId
|
|
54016
|
-
},
|
|
54418
|
+
}, fetchOptions).$inspect();
|
|
54017
54419
|
if (!result.ok)
|
|
54018
54420
|
return errorResult(result.error.message);
|
|
54019
54421
|
const httpErr = await httpErrorResult(result.value, "Get record content");
|
|
@@ -54040,9 +54442,9 @@ var init_getallusersop = __esm(() => {
|
|
|
54040
54442
|
|
|
54041
54443
|
// src/funcs/usersGetAllUsers.ts
|
|
54042
54444
|
function usersGetAllUsers(client$, request, options) {
|
|
54043
|
-
return new APIPromise($
|
|
54445
|
+
return new APIPromise($do11(client$, request, options));
|
|
54044
54446
|
}
|
|
54045
|
-
async function $
|
|
54447
|
+
async function $do11(client$, request, options) {
|
|
54046
54448
|
const parsed$ = safeParse4(request, (value$) => GetAllUsersRequest$zodSchema.optional().parse(value$), "Input validation failed");
|
|
54047
54449
|
if (!parsed$.ok) {
|
|
54048
54450
|
return [parsed$, { status: "invalid" }];
|
|
@@ -54127,9 +54529,9 @@ var init_getuserbyidop = __esm(() => {
|
|
|
54127
54529
|
|
|
54128
54530
|
// src/funcs/usersGetUserById.ts
|
|
54129
54531
|
function usersGetUserById(client$, request, options) {
|
|
54130
|
-
return new APIPromise($
|
|
54532
|
+
return new APIPromise($do12(client$, request, options));
|
|
54131
54533
|
}
|
|
54132
|
-
async function $
|
|
54534
|
+
async function $do12(client$, request, options) {
|
|
54133
54535
|
const parsed$ = safeParse4(request, (value$) => GetUserByIdRequest$zodSchema.parse(value$), "Input validation failed");
|
|
54134
54536
|
if (!parsed$.ok) {
|
|
54135
54537
|
return [parsed$, { status: "invalid" }];
|
|
@@ -54216,9 +54618,9 @@ var init_getallusergroupsop = __esm(() => {
|
|
|
54216
54618
|
|
|
54217
54619
|
// src/funcs/userGroupsGetAllUserGroups.ts
|
|
54218
54620
|
function userGroupsGetAllUserGroups(client$, request, options) {
|
|
54219
|
-
return new APIPromise($
|
|
54621
|
+
return new APIPromise($do13(client$, request, options));
|
|
54220
54622
|
}
|
|
54221
|
-
async function $
|
|
54623
|
+
async function $do13(client$, request, options) {
|
|
54222
54624
|
const parsed$ = safeParse4(request, (value$) => GetAllUserGroupsRequest$zodSchema.optional().parse(value$), "Input validation failed");
|
|
54223
54625
|
if (!parsed$.ok) {
|
|
54224
54626
|
return [parsed$, { status: "invalid" }];
|
|
@@ -54308,9 +54710,9 @@ var init_getuserteamsop = __esm(() => {
|
|
|
54308
54710
|
|
|
54309
54711
|
// src/funcs/teamsGetUserTeams.ts
|
|
54310
54712
|
function teamsGetUserTeams(client$, request, options) {
|
|
54311
|
-
return new APIPromise($
|
|
54713
|
+
return new APIPromise($do14(client$, request, options));
|
|
54312
54714
|
}
|
|
54313
|
-
async function $
|
|
54715
|
+
async function $do14(client$, request, options) {
|
|
54314
54716
|
const parsed$ = safeParse4(request, (value$) => GetUserTeamsRequest$zodSchema.optional().parse(value$), "Input validation failed");
|
|
54315
54717
|
if (!parsed$.ok) {
|
|
54316
54718
|
return [parsed$, { status: "invalid" }];
|
|
@@ -54540,9 +54942,9 @@ var init_getknowledgehubrootnodesop = __esm(() => {
|
|
|
54540
54942
|
|
|
54541
54943
|
// src/funcs/knowledgeHubGetKnowledgeHubRootNodes.ts
|
|
54542
54944
|
function knowledgeHubGetKnowledgeHubRootNodes(client$, request, options) {
|
|
54543
|
-
return new APIPromise($
|
|
54945
|
+
return new APIPromise($do15(client$, request, options));
|
|
54544
54946
|
}
|
|
54545
|
-
async function $
|
|
54947
|
+
async function $do15(client$, request, options) {
|
|
54546
54948
|
const parsed$ = safeParse4(request, (value$) => GetKnowledgeHubRootNodesRequest$zodSchema.optional().parse(value$), "Input validation failed");
|
|
54547
54949
|
if (!parsed$.ok) {
|
|
54548
54950
|
return [parsed$, { status: "invalid" }];
|
|
@@ -54658,9 +55060,9 @@ var init_getavailablemodelsbytypeop = __esm(() => {
|
|
|
54658
55060
|
|
|
54659
55061
|
// src/funcs/aiModelsProvidersGetAvailableModelsByType.ts
|
|
54660
55062
|
function aiModelsProvidersGetAvailableModelsByType(client$, request, options) {
|
|
54661
|
-
return new APIPromise($
|
|
55063
|
+
return new APIPromise($do16(client$, request, options));
|
|
54662
55064
|
}
|
|
54663
|
-
async function $
|
|
55065
|
+
async function $do16(client$, request, options) {
|
|
54664
55066
|
const parsed$ = safeParse4(request, (value$) => GetAvailableModelsByTypeRequest$zodSchema.parse(value$), "Input validation failed");
|
|
54665
55067
|
if (!parsed$.ok) {
|
|
54666
55068
|
return [parsed$, { status: "invalid" }];
|
|
@@ -54986,31 +55388,39 @@ var init_tool_names = __esm(() => {
|
|
|
54986
55388
|
},
|
|
54987
55389
|
{
|
|
54988
55390
|
name: "pipeshub_chat",
|
|
54989
|
-
description:
|
|
54990
|
-
|
|
54991
|
-
|
|
54992
|
-
|
|
54993
|
-
|
|
54994
|
-
|
|
54995
|
-
|
|
54996
|
-
|
|
54997
|
-
|
|
54998
|
-
|
|
54999
|
-
|
|
55000
|
-
|
|
55001
|
-
|
|
55002
|
-
|
|
55003
|
-
|
|
55004
|
-
|
|
55005
|
-
|
|
55006
|
-
|
|
55007
|
-
|
|
55008
|
-
|
|
55009
|
-
|
|
55010
|
-
|
|
55391
|
+
description: `Ask a question, get an answer grounded in the org's indexed data with
|
|
55392
|
+
citations. It reads a few retrieved passages — never a whole document,
|
|
55393
|
+
never a complete list.
|
|
55394
|
+
|
|
55395
|
+
**Three questions this tool gets WRONG. Check them first:**
|
|
55396
|
+
- **Structure** — "what's under this epic?", "which pages are in this
|
|
55397
|
+
space?", "what links to this ticket?", "what's in this folder?" →
|
|
55398
|
+
\`pipeshub_get_record_content\` \`mode:"navigate"\`. Ranking cannot see how
|
|
55399
|
+
records relate.
|
|
55400
|
+
- **Exhaustive** — "how many X?", "list ALL the Y", "every Z" →
|
|
55401
|
+
\`mode:"navigate"\`, which reports the group's real total. This tool
|
|
55402
|
+
undercounts and will not say so.
|
|
55403
|
+
- **One named document** — summarize it, extract from it, what does it say
|
|
55404
|
+
about X → \`pipeshub_search\` for the \`recordId\`, then \`mode:"content"\`.
|
|
55405
|
+
|
|
55406
|
+
Everything else about the org's knowledge belongs here: policies,
|
|
55407
|
+
processes, decisions, history, "what do we know about X", and any question
|
|
55408
|
+
spanning several documents.
|
|
55409
|
+
|
|
55410
|
+
**Internal search** (default, \`chatMode: "internal_search"\`): the user's
|
|
55411
|
+
documents, files, knowledge base, company policies — anything in their
|
|
55412
|
+
PipesHub-indexed sources (Drive, Box, Confluence, Slack, Gmail, Jira, the
|
|
55413
|
+
org's KB, ...).
|
|
55414
|
+
|
|
55415
|
+
**Web search** (\`chatMode: "web_search"\`): current events or public
|
|
55416
|
+
information unlikely to be in the org's knowledge base.
|
|
55417
|
+
|
|
55418
|
+
Both are plain-chat modes. **Agent chat** — pass an \`agentId\` from
|
|
55419
|
+
\`pipeshub_agents\` — runs against that agent's own prompt, tools and knowledge;
|
|
55420
|
+
\`quick\` is its only mode, requires the \`agentId\`, and is sent automatically.
|
|
55421
|
+
|
|
55011
55422
|
- "What's our policy on Y?" → \`pipeshub_chat\` (internal_search)
|
|
55012
55423
|
- "What's in the news about Z?" → \`pipeshub_chat\` (web_search)
|
|
55013
|
-
- "What is the latest version of <library>?" → \`pipeshub_chat\` (web_search)
|
|
55014
55424
|
- "Find / locate the file named X" → \`pipeshub_search\` (then
|
|
55015
55425
|
\`pipeshub_download_record\` if the user wants the bytes).
|
|
55016
55426
|
|
|
@@ -55049,10 +55459,23 @@ Typical uses:
|
|
|
55049
55459
|
- Show the user a ranked list of matching files when they ask "find /
|
|
55050
55460
|
search for X".
|
|
55051
55461
|
|
|
55462
|
+
Not for structural questions — what is under this epic, which pages are
|
|
55463
|
+
in this space, what links to this ticket. Ranking by content cannot show
|
|
55464
|
+
how records relate; use \`pipeshub_get_record_content\` \`mode:"navigate"\`.
|
|
55465
|
+
|
|
55466
|
+
**A ranked sample, never a complete list.** Hits are the top-scoring
|
|
55467
|
+
blocks from the best-matching records — not all blocks of any record, and
|
|
55468
|
+
not every record that matches. Never count them to answer "how many" /
|
|
55469
|
+
"all" / "every"; navigate the record group instead, which reports its
|
|
55470
|
+
real total.
|
|
55471
|
+
|
|
55052
55472
|
The response is trimmed to one row per hit:
|
|
55053
55473
|
\`{ recordId, recordName, score, snippet, mimeType, webUrl, ... }\`.
|
|
55054
55474
|
Highest \`score\` first; multiple hits may share the same \`recordId\`
|
|
55055
|
-
(different
|
|
55475
|
+
(different blocks of the same record).
|
|
55476
|
+
|
|
55477
|
+
When presenting results to the user, link each record using its
|
|
55478
|
+
\`webUrl\` (when present).`
|
|
55056
55479
|
},
|
|
55057
55480
|
{
|
|
55058
55481
|
name: "pipeshub_download_record",
|
|
@@ -55060,30 +55483,80 @@ Highest \`score\` first; multiple hits may share the same \`recordId\`
|
|
|
55060
55483
|
},
|
|
55061
55484
|
{
|
|
55062
55485
|
name: "pipeshub_get_record_content",
|
|
55063
|
-
description: `
|
|
55064
|
-
|
|
55065
|
-
|
|
55066
|
-
|
|
55067
|
-
|
|
55068
|
-
|
|
55069
|
-
|
|
55070
|
-
|
|
55071
|
-
|
|
55072
|
-
|
|
55073
|
-
|
|
55074
|
-
|
|
55075
|
-
|
|
55076
|
-
|
|
55077
|
-
|
|
55078
|
-
|
|
55079
|
-
|
|
55080
|
-
|
|
55081
|
-
|
|
55082
|
-
|
|
55083
|
-
|
|
55084
|
-
|
|
55085
|
-
|
|
55086
|
-
|
|
55486
|
+
description: `Three operations on the org's records. Pick by what you hold:
|
|
55487
|
+
|
|
55488
|
+
\`mode:"lookup"\` — a URL, issue key (PA-1787), or external ID
|
|
55489
|
+
→ its recordId plus the record's metadata
|
|
55490
|
+
\`mode:"navigate"\` — a question about structure: what is under X,
|
|
55491
|
+
what links to Y → browses the hierarchy
|
|
55492
|
+
\`mode:"content"\` — a recordId, and you need the document's COMPLETE text
|
|
55493
|
+
|
|
55494
|
+
**\`mode:"content"\` (default)** — the only way to see a document's complete
|
|
55495
|
+
text. Use it whenever missing part of the document could make the answer
|
|
55496
|
+
wrong: summarize, extract or list ALL of something, check whether or where
|
|
55497
|
+
a doc mentions X, review, or compare named docs. \`pipeshub_chat\` cannot do
|
|
55498
|
+
these — it never sees a whole document.
|
|
55499
|
+
|
|
55500
|
+
Judge by the user's INTENT, not their keywords: "what's this doc about?",
|
|
55501
|
+
"walk me through the report", "anything in here about Y?" are all
|
|
55502
|
+
full-content tasks. Get the \`recordId\` from a \`pipeshub_search\` top hit, a
|
|
55503
|
+
chat citation, or \`mode:"lookup"\`.
|
|
55504
|
+
|
|
55505
|
+
Returns one \`content\` string: a metadata header (title, source, key fields,
|
|
55506
|
+
pre-generated summary) then the full parsed text. A record with no
|
|
55507
|
+
extractable content returns the literal \`No record found\`. Use
|
|
55508
|
+
\`pipeshub_download_record\` only for the original file bytes.
|
|
55509
|
+
|
|
55510
|
+
**\`mode:"navigate"\`** — browse the hierarchy: RecordGroup (project /
|
|
55511
|
+
space / drive / folder) → Record (epic / story / page / file) → children,
|
|
55512
|
+
with breadcrumbs, related links and record IDs.
|
|
55513
|
+
|
|
55514
|
+
Use it when the question depends on structure rather than wording: what is
|
|
55515
|
+
under this epic, which pages sit in this space, what is linked to this
|
|
55516
|
+
ticket, what is in this folder — and every "how many" / "all of" / "every"
|
|
55517
|
+
question. Search ranks by content; only this shows how records relate, and
|
|
55518
|
+
only this gives a count you can trust.
|
|
55519
|
+
|
|
55520
|
+
Omit \`nodeId\` for a flat listing of everything reachable, most recently
|
|
55521
|
+
updated first — the usual starting point. A URL, an issue key, or a
|
|
55522
|
+
\`pipeshub_sources\` id also works and resolves automatically.
|
|
55523
|
+
|
|
55524
|
+
Pass \`depth:2\` or \`depth:3\` to see several levels in ONE call — an epic's
|
|
55525
|
+
stories AND their subtasks, a space's pages AND their children — instead of
|
|
55526
|
+
one call per level. Use it whenever the question needs an overview of a
|
|
55527
|
+
hierarchy rather than a single node.
|
|
55528
|
+
|
|
55529
|
+
Opening a record also prints that record's own metadata — for a ticket,
|
|
55530
|
+
status, assignee, priority and dates — so a question about one record is
|
|
55531
|
+
often answered by this call alone. It returns no document text; for that,
|
|
55532
|
+
re-call with \`mode:"content"\`.
|
|
55533
|
+
|
|
55534
|
+
Returns \`Path\` breadcrumbs, the current node's metadata, a children listing
|
|
55535
|
+
carrying \`record_id=\` or \`node_id=\` per row plus the group's total
|
|
55536
|
+
(\`Children 1-50 of 61\`), \`Related\` cross-references, and a \`Next:\` line.
|
|
55537
|
+
One page is usually every child, so only pass \`page:2\` when that \`Next:\`
|
|
55538
|
+
line says more exist.
|
|
55539
|
+
|
|
55540
|
+
**\`mode:"lookup"\`** — turn an external reference into a recordId, the first
|
|
55541
|
+
step whenever the question names one. Returns that record's metadata (for a
|
|
55542
|
+
ticket: status, assignee, priority, dates) plus its recordId, which
|
|
55543
|
+
\`mode:"navigate"\` takes to list what is under it and \`mode:"content"\` takes
|
|
55544
|
+
to read it.
|
|
55545
|
+
|
|
55546
|
+
Handles Jira keys and URLs, Confluence, Drive, Slack permalinks, Linear,
|
|
55547
|
+
Notion, ServiceNow sys_id, SharePoint, Gmail/Outlook, and any connector
|
|
55548
|
+
whose records index a web URL. Resolution searches ALL connectors you can
|
|
55549
|
+
access, regardless of any source filter you used elsewhere.
|
|
55550
|
+
|
|
55551
|
+
A miss is a 200 with empty \`matches\` and the input echoed in
|
|
55552
|
+
\`not_found_identifiers\` — that may mean no-access, not non-existence. Use
|
|
55553
|
+
\`mode:"navigate"\` to confirm the record exists before telling the user it
|
|
55554
|
+
does not. If \`ambiguous\` is true, pick from \`matches\` rather than taking
|
|
55555
|
+
the first.
|
|
55556
|
+
|
|
55557
|
+
Navigate and lookup return a rendered text view whose closing \`Next:\` line
|
|
55558
|
+
names the exact follow-up call — follow it. When presenting a record, link
|
|
55559
|
+
it using the \`Web URL\` from its metadata header (when present).`
|
|
55087
55560
|
},
|
|
55088
55561
|
{
|
|
55089
55562
|
name: "pipeshub_directory",
|
|
@@ -58720,5 +59193,5 @@ export {
|
|
|
58720
59193
|
app
|
|
58721
59194
|
};
|
|
58722
59195
|
|
|
58723
|
-
//# debugId=
|
|
59196
|
+
//# debugId=90FD24D95D2C4D3664756E2164756E21
|
|
58724
59197
|
//# sourceMappingURL=mcp-server.js.map
|