@pipeshub-ai/mcp 2.2.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/bin/mcp-server.js +703 -189
- package/bin/mcp-server.js.map +19 -13
- 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 +235 -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 +20 -3
- package/esm/mcp-server/tools/_helpers.d.ts.map +1 -1
- package/esm/mcp-server/tools/_helpers.js +54 -10
- 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/pipeshubDirectory.d.ts.map +1 -1
- package/esm/mcp-server/tools/pipeshubDirectory.js +62 -8
- package/esm/mcp-server/tools/pipeshubDirectory.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 +15 -2
- package/esm/mcp-server/tools/pipeshubSearch.js.map +1 -1
- package/esm/mcp-server/tools/pipeshubSources.js +2 -2
- package/esm/mcp-server/tools/pipeshubSources.js.map +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/tool-names.js +4 -4
- 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 +279 -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 +55 -8
- package/src/mcp-server/tools/pipeshubChat.ts +78 -97
- package/src/mcp-server/tools/pipeshubDirectory.ts +65 -7
- package/src/mcp-server/tools/pipeshubGetRecordContent.ts +213 -29
- package/src/mcp-server/tools/pipeshubSearch.ts +15 -2
- package/src/mcp-server/tools/pipeshubSources.ts +2 -2
- package/src/models/lookuprecordbyidentifierop.ts +26 -0
- package/src/models/navigateknowledgegraphop.ts +56 -0
- package/src/tool-names.ts +4 -4
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));
|
|
@@ -52993,7 +53098,10 @@ var init_agentsListAgents = __esm(() => {
|
|
|
52993
53098
|
});
|
|
52994
53099
|
|
|
52995
53100
|
// src/mcp-server/tools/_helpers.ts
|
|
52996
|
-
async function readJson(response) {
|
|
53101
|
+
async function readJson(response, context = "PipesHub request") {
|
|
53102
|
+
const httpErr = await httpErrorResult(response, context);
|
|
53103
|
+
if (httpErr)
|
|
53104
|
+
return { ok: false, result: httpErr };
|
|
52997
53105
|
const text = await response.text();
|
|
52998
53106
|
if (!text) {
|
|
52999
53107
|
return {
|
|
@@ -53022,6 +53130,13 @@ ${text.slice(0, 500)}`
|
|
|
53022
53130
|
};
|
|
53023
53131
|
}
|
|
53024
53132
|
}
|
|
53133
|
+
function expiredTokenError(exp) {
|
|
53134
|
+
if (typeof exp !== "number" || !Number.isFinite(exp))
|
|
53135
|
+
return null;
|
|
53136
|
+
if (exp * 1000 > Date.now())
|
|
53137
|
+
return null;
|
|
53138
|
+
return errorResult(`The access token expired on ${new Date(exp * 1000).toISOString()}. ` + "Mint a new personal access token in PipesHub under " + "Developer Settings → Personal Access Tokens.");
|
|
53139
|
+
}
|
|
53025
53140
|
function jsonResult(value) {
|
|
53026
53141
|
return {
|
|
53027
53142
|
content: [{ type: "text", text: JSON.stringify(value, null, 2) }]
|
|
@@ -53048,11 +53163,15 @@ async function httpErrorResult(response, context) {
|
|
|
53048
53163
|
message = candidate || body;
|
|
53049
53164
|
} catch {}
|
|
53050
53165
|
}
|
|
53051
|
-
const
|
|
53166
|
+
const reason = message.slice(0, 400).trim();
|
|
53167
|
+
const detail = reason ? ` ${/[.!?]$/.test(reason) ? reason : `${reason}.`}` : "";
|
|
53052
53168
|
const auth = response.status === 401 || response.status === 403 ? " Check that the bearer token / credentials are valid and not expired." : "";
|
|
53053
53169
|
return errorResult(`${context} failed (HTTP ${response.status} ${response.statusText}).${detail}${auth}`);
|
|
53054
53170
|
}
|
|
53055
|
-
async function readValidated(response, schema) {
|
|
53171
|
+
async function readValidated(response, schema, context = "PipesHub request") {
|
|
53172
|
+
const httpErr = await httpErrorResult(response, context);
|
|
53173
|
+
if (httpErr)
|
|
53174
|
+
return { ok: false, result: httpErr };
|
|
53056
53175
|
const text = await response.text();
|
|
53057
53176
|
if (!text) {
|
|
53058
53177
|
return { ok: false, result: errorResult("Empty response from server") };
|
|
@@ -53121,15 +53240,17 @@ function trimCitations(citations) {
|
|
|
53121
53240
|
if (!Array.isArray(citations))
|
|
53122
53241
|
return [];
|
|
53123
53242
|
return citations.map((c) => {
|
|
53124
|
-
const
|
|
53243
|
+
const cd = c?.citationData ?? c;
|
|
53244
|
+
const md = cd?.metadata ?? c?.metadata ?? {};
|
|
53245
|
+
const content = typeof cd?.content === "string" ? cd.content : c?.content;
|
|
53125
53246
|
return {
|
|
53126
|
-
recordId: md.recordId ?? c?.recordId,
|
|
53127
|
-
recordName: md.recordName ?? c?.recordName,
|
|
53128
|
-
snippet: typeof
|
|
53247
|
+
recordId: md.recordId ?? cd?.recordId ?? c?.recordId,
|
|
53248
|
+
recordName: md.recordName ?? cd?.recordName ?? c?.recordName,
|
|
53249
|
+
snippet: typeof content === "string" ? content.slice(0, 280) : md.blockText ?? null,
|
|
53129
53250
|
mimeType: md.mimeType,
|
|
53130
53251
|
webUrl: md.webUrl,
|
|
53131
53252
|
pageNum: md.pageNum,
|
|
53132
|
-
chunkIndex: c?.chunkIndex ?? md.chunkIndex
|
|
53253
|
+
chunkIndex: cd?.chunkIndex ?? c?.chunkIndex ?? md.chunkIndex
|
|
53133
53254
|
};
|
|
53134
53255
|
});
|
|
53135
53256
|
}
|
|
@@ -53302,9 +53423,10 @@ var init_pipeshubChat = __esm(() => {
|
|
|
53302
53423
|
init_conversationsStreamMessage();
|
|
53303
53424
|
init_agentsStreamConversation();
|
|
53304
53425
|
init_agentsStreamMessage();
|
|
53426
|
+
init__agui();
|
|
53305
53427
|
init__helpers();
|
|
53306
53428
|
FiltersShape = object({
|
|
53307
|
-
apps: array(string2()).optional().describe("Source-scoping ids
|
|
53429
|
+
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
53430
|
kb: array(string2()).optional().describe("Legacy / unused. Leave empty.")
|
|
53309
53431
|
}).optional();
|
|
53310
53432
|
args = {
|
|
@@ -53318,40 +53440,45 @@ var init_pipeshubChat = __esm(() => {
|
|
|
53318
53440
|
chatMode: _enum([
|
|
53319
53441
|
"internal_search",
|
|
53320
53442
|
"web_search",
|
|
53321
|
-
"
|
|
53322
|
-
"quick",
|
|
53323
|
-
"verification",
|
|
53324
|
-
"deep"
|
|
53443
|
+
"quick"
|
|
53325
53444
|
]).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): `
|
|
53445
|
+
` + "- WITH `agentId` (agent chat): `quick` is the only supported mode and " + "is sent automatically, so this argument can be omitted.")
|
|
53327
53446
|
};
|
|
53328
53447
|
tool$pipeshubChat = {
|
|
53329
53448
|
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
|
-
|
|
53449
|
+
description: `Ask a question, get an answer grounded in the org's indexed data with
|
|
53450
|
+
citations. It reads a few retrieved passages — never a whole document,
|
|
53451
|
+
never a complete list.
|
|
53452
|
+
|
|
53453
|
+
**Three questions this tool gets WRONG. Check them first:**
|
|
53454
|
+
- **Structure** — "what's under this epic?", "which pages are in this
|
|
53455
|
+
space?", "what links to this ticket?", "what's in this folder?" →
|
|
53456
|
+
\`pipeshub_get_record_content\` \`mode:"navigate"\`. Ranking cannot see how
|
|
53457
|
+
records relate.
|
|
53458
|
+
- **Exhaustive** — "how many X?", "list ALL the Y", "every Z" →
|
|
53459
|
+
\`mode:"navigate"\`, which reports the group's real total. This tool
|
|
53460
|
+
undercounts and will not say so.
|
|
53461
|
+
- **One named document** — summarize it, extract from it, what does it say
|
|
53462
|
+
about X → \`pipeshub_search\` for the \`recordId\`, then \`mode:"content"\`.
|
|
53463
|
+
|
|
53464
|
+
Everything else about the org's knowledge belongs here: policies,
|
|
53465
|
+
processes, decisions, history, "what do we know about X", and any question
|
|
53466
|
+
spanning several documents.
|
|
53467
|
+
|
|
53468
|
+
**Internal search** (default, \`chatMode: "internal_search"\`): the user's
|
|
53469
|
+
documents, files, knowledge base, company policies — anything in their
|
|
53470
|
+
PipesHub-indexed sources (Drive, Box, Confluence, Slack, Gmail, Jira, the
|
|
53471
|
+
org's KB, ...).
|
|
53472
|
+
|
|
53473
|
+
**Web search** (\`chatMode: "web_search"\`): current events or public
|
|
53474
|
+
information unlikely to be in the org's knowledge base.
|
|
53475
|
+
|
|
53476
|
+
Both are plain-chat modes. **Agent chat** — pass an \`agentId\` from
|
|
53477
|
+
\`pipeshub_agents\` — runs against that agent's own prompt, tools and knowledge;
|
|
53478
|
+
\`quick\` is its only mode, requires the \`agentId\`, and is sent automatically.
|
|
53479
|
+
|
|
53352
53480
|
- "What's our policy on Y?" → \`pipeshub_chat\` (internal_search)
|
|
53353
53481
|
- "What's in the news about Z?" → \`pipeshub_chat\` (web_search)
|
|
53354
|
-
- "What is the latest version of <library>?" → \`pipeshub_chat\` (web_search)
|
|
53355
53482
|
- "Find / locate the file named X" → \`pipeshub_search\` (then
|
|
53356
53483
|
\`pipeshub_download_record\` if the user wants the bytes).
|
|
53357
53484
|
|
|
@@ -53381,9 +53508,10 @@ cited document, take \`citations[*].recordId\` and call
|
|
|
53381
53508
|
args,
|
|
53382
53509
|
tool: async (client, args2, ctx) => {
|
|
53383
53510
|
const fetchOptions = { signal: ctx.signal };
|
|
53511
|
+
const plainChatMode = args2.chatMode === "web_search" ? "web_search" : "internal_search";
|
|
53384
53512
|
let response;
|
|
53385
53513
|
if (args2.agentId) {
|
|
53386
|
-
const agentChatMode =
|
|
53514
|
+
const agentChatMode = "quick";
|
|
53387
53515
|
if (args2.conversationId) {
|
|
53388
53516
|
const [result] = await agentsStreamMessage(client, {
|
|
53389
53517
|
agentKey: args2.agentId,
|
|
@@ -53423,7 +53551,7 @@ cited document, take \`citations[*].recordId\` and call
|
|
|
53423
53551
|
modelKey: args2.modelKey,
|
|
53424
53552
|
modelName: args2.modelName,
|
|
53425
53553
|
modelFriendlyName: args2.modelFriendlyName,
|
|
53426
|
-
chatMode:
|
|
53554
|
+
chatMode: plainChatMode
|
|
53427
53555
|
}
|
|
53428
53556
|
}, { fetchOptions }).$inspect();
|
|
53429
53557
|
if (!result.ok)
|
|
@@ -53436,7 +53564,7 @@ cited document, take \`citations[*].recordId\` and call
|
|
|
53436
53564
|
modelKey: args2.modelKey,
|
|
53437
53565
|
modelName: args2.modelName,
|
|
53438
53566
|
modelFriendlyName: args2.modelFriendlyName,
|
|
53439
|
-
chatMode:
|
|
53567
|
+
chatMode: plainChatMode
|
|
53440
53568
|
}, { fetchOptions }).$inspect();
|
|
53441
53569
|
if (!result.ok)
|
|
53442
53570
|
return errorResult(result.error.message);
|
|
@@ -53445,62 +53573,36 @@ cited document, take \`citations[*].recordId\` and call
|
|
|
53445
53573
|
const httpErr = await httpErrorResult(response, "PipesHub chat request");
|
|
53446
53574
|
if (httpErr)
|
|
53447
53575
|
return httpErr;
|
|
53448
|
-
|
|
53449
|
-
let recordsUsed;
|
|
53450
|
-
let lastAccumulated = null;
|
|
53451
|
-
let errorMessage = null;
|
|
53576
|
+
const state = newChatStreamState();
|
|
53452
53577
|
try {
|
|
53453
53578
|
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)
|
|
53579
|
+
if (applyAGUIFrame(state, frame))
|
|
53479
53580
|
break;
|
|
53480
53581
|
}
|
|
53481
53582
|
} catch (e) {
|
|
53482
53583
|
return errorResult(`SSE stream failed: ${e.message}`);
|
|
53483
53584
|
}
|
|
53484
|
-
if (
|
|
53485
|
-
return errorResult(
|
|
53486
|
-
if (
|
|
53585
|
+
if (state.error)
|
|
53586
|
+
return errorResult(state.error);
|
|
53587
|
+
if (state.conversation) {
|
|
53487
53588
|
return jsonResult({
|
|
53488
|
-
...trimConversation(
|
|
53489
|
-
recordsUsed
|
|
53589
|
+
...trimConversation(state.conversation),
|
|
53590
|
+
recordsUsed: state.recordsUsed
|
|
53490
53591
|
});
|
|
53491
53592
|
}
|
|
53492
|
-
|
|
53593
|
+
const salvaged = salvagedText(state);
|
|
53594
|
+
if (salvaged) {
|
|
53493
53595
|
return jsonResult({
|
|
53494
|
-
conversationId:
|
|
53495
|
-
title:
|
|
53596
|
+
conversationId: state.conversationId,
|
|
53597
|
+
title: state.title,
|
|
53496
53598
|
status: "Inprogress",
|
|
53497
|
-
answer:
|
|
53599
|
+
answer: salvaged,
|
|
53498
53600
|
confidence: null,
|
|
53499
53601
|
citations: [],
|
|
53500
53602
|
followUpQuestions: [],
|
|
53501
53603
|
messageCount: 0,
|
|
53502
|
-
recordsUsed,
|
|
53503
|
-
warning: "Stream ended without a
|
|
53604
|
+
recordsUsed: state.recordsUsed,
|
|
53605
|
+
warning: "Stream ended without a terminal RUN_FINISHED; answer is the " + "accumulated TEXT_MESSAGE_CONTENT and citations are unavailable."
|
|
53504
53606
|
});
|
|
53505
53607
|
}
|
|
53506
53608
|
return errorResult("Stream ended without any usable frames.");
|
|
@@ -53669,10 +53771,23 @@ Typical uses:
|
|
|
53669
53771
|
- Show the user a ranked list of matching files when they ask "find /
|
|
53670
53772
|
search for X".
|
|
53671
53773
|
|
|
53774
|
+
Not for structural questions — what is under this epic, which pages are
|
|
53775
|
+
in this space, what links to this ticket. Ranking by content cannot show
|
|
53776
|
+
how records relate; use \`pipeshub_get_record_content\` \`mode:"navigate"\`.
|
|
53777
|
+
|
|
53778
|
+
**A ranked sample, never a complete list.** Hits are the top-scoring
|
|
53779
|
+
blocks from the best-matching records — not all blocks of any record, and
|
|
53780
|
+
not every record that matches. Never count them to answer "how many" /
|
|
53781
|
+
"all" / "every"; navigate the record group instead, which reports its
|
|
53782
|
+
real total.
|
|
53783
|
+
|
|
53672
53784
|
The response is trimmed to one row per hit:
|
|
53673
53785
|
\`{ recordId, recordName, score, snippet, mimeType, webUrl, ... }\`.
|
|
53674
53786
|
Highest \`score\` first; multiple hits may share the same \`recordId\`
|
|
53675
|
-
(different
|
|
53787
|
+
(different blocks of the same record).
|
|
53788
|
+
|
|
53789
|
+
When presenting results to the user, link each record using its
|
|
53790
|
+
\`webUrl\` (when present).`,
|
|
53676
53791
|
scopes: ["read"],
|
|
53677
53792
|
annotations: {
|
|
53678
53793
|
title: "Semantic search",
|
|
@@ -53690,7 +53805,7 @@ Highest \`score\` first; multiple hits may share the same \`recordId\`
|
|
|
53690
53805
|
}, { fetchOptions: { signal: ctx.signal } }).$inspect();
|
|
53691
53806
|
if (!result.ok)
|
|
53692
53807
|
return errorResult(result.error.message);
|
|
53693
|
-
const parsed = await readJson(result.value);
|
|
53808
|
+
const parsed = await readJson(result.value, "PipesHub search");
|
|
53694
53809
|
if (!parsed.ok)
|
|
53695
53810
|
return parsed.result;
|
|
53696
53811
|
const sr = parsed.value.searchResponse ?? {};
|
|
@@ -53966,44 +54081,306 @@ var init_connectorGetRecordContent = __esm(() => {
|
|
|
53966
54081
|
init_async();
|
|
53967
54082
|
});
|
|
53968
54083
|
|
|
54084
|
+
// src/models/lookuprecordbyidentifierop.ts
|
|
54085
|
+
var LookupRecordByIdentifierRequest$zodSchema;
|
|
54086
|
+
var init_lookuprecordbyidentifierop = __esm(() => {
|
|
54087
|
+
init_zod();
|
|
54088
|
+
LookupRecordByIdentifierRequest$zodSchema = object({
|
|
54089
|
+
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(),
|
|
54090
|
+
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.")
|
|
54091
|
+
});
|
|
54092
|
+
});
|
|
54093
|
+
|
|
54094
|
+
// src/funcs/connectorLookupRecordByIdentifier.ts
|
|
54095
|
+
function connectorLookupRecordByIdentifier(client$, request, options) {
|
|
54096
|
+
return new APIPromise($do9(client$, request, options));
|
|
54097
|
+
}
|
|
54098
|
+
async function $do9(client$, request, options) {
|
|
54099
|
+
const parsed$ = safeParse4(request, (value$) => LookupRecordByIdentifierRequest$zodSchema.parse(value$), "Input validation failed");
|
|
54100
|
+
if (!parsed$.ok) {
|
|
54101
|
+
return [parsed$, { status: "invalid" }];
|
|
54102
|
+
}
|
|
54103
|
+
const payload$ = parsed$.value;
|
|
54104
|
+
const body$ = null;
|
|
54105
|
+
const path$ = pathToFunc("/connectors/record/lookup")();
|
|
54106
|
+
const query$ = encodeFormQuery({
|
|
54107
|
+
connectorName: payload$.connectorName,
|
|
54108
|
+
identifiers: payload$.identifiers
|
|
54109
|
+
});
|
|
54110
|
+
const headers$ = new Headers(compactMap({
|
|
54111
|
+
Accept: "application/json"
|
|
54112
|
+
}));
|
|
54113
|
+
const securityInput = await extractSecurity(client$._options.security);
|
|
54114
|
+
const requestSecurity = resolveGlobalSecurity(securityInput);
|
|
54115
|
+
const context = {
|
|
54116
|
+
options: client$._options,
|
|
54117
|
+
baseURL: options?.serverURL ?? client$._baseURL ?? "",
|
|
54118
|
+
operationID: "lookupRecordByIdentifier",
|
|
54119
|
+
oAuth2Scopes: ["kb:read", "connector:read"],
|
|
54120
|
+
resolvedSecurity: requestSecurity,
|
|
54121
|
+
securitySource: client$._options.security,
|
|
54122
|
+
retryConfig: options?.retries || client$._options.retryConfig || { strategy: "none" },
|
|
54123
|
+
retryCodes: options?.retryCodes || [
|
|
54124
|
+
"429",
|
|
54125
|
+
"500",
|
|
54126
|
+
"502",
|
|
54127
|
+
"503",
|
|
54128
|
+
"504"
|
|
54129
|
+
]
|
|
54130
|
+
};
|
|
54131
|
+
const requestRes = client$._createRequest(context, {
|
|
54132
|
+
security: requestSecurity,
|
|
54133
|
+
method: "GET",
|
|
54134
|
+
baseURL: options?.serverURL,
|
|
54135
|
+
path: path$,
|
|
54136
|
+
headers: headers$,
|
|
54137
|
+
query: query$,
|
|
54138
|
+
body: body$,
|
|
54139
|
+
userAgent: client$._options.userAgent,
|
|
54140
|
+
timeoutMs: options?.timeoutMs || client$._options.timeoutMs || -1
|
|
54141
|
+
}, options);
|
|
54142
|
+
if (!requestRes.ok) {
|
|
54143
|
+
return [requestRes, { status: "invalid" }];
|
|
54144
|
+
}
|
|
54145
|
+
const req$ = requestRes.value;
|
|
54146
|
+
const doResult = await client$._do(req$, {
|
|
54147
|
+
context,
|
|
54148
|
+
errorCodes: [],
|
|
54149
|
+
retryConfig: context.retryConfig,
|
|
54150
|
+
retryCodes: context.retryCodes
|
|
54151
|
+
});
|
|
54152
|
+
if (!doResult.ok) {
|
|
54153
|
+
return [doResult, { status: "request-error", request: req$ }];
|
|
54154
|
+
}
|
|
54155
|
+
return [doResult, {
|
|
54156
|
+
status: "complete",
|
|
54157
|
+
request: req$,
|
|
54158
|
+
response: doResult.value
|
|
54159
|
+
}];
|
|
54160
|
+
}
|
|
54161
|
+
var init_connectorLookupRecordByIdentifier = __esm(() => {
|
|
54162
|
+
init_encodings();
|
|
54163
|
+
init_primitives();
|
|
54164
|
+
init_schemas4();
|
|
54165
|
+
init_security2();
|
|
54166
|
+
init_url();
|
|
54167
|
+
init_lookuprecordbyidentifierop();
|
|
54168
|
+
init_async();
|
|
54169
|
+
});
|
|
54170
|
+
|
|
54171
|
+
// src/models/navigateknowledgegraphop.ts
|
|
54172
|
+
var NavigateKnowledgeGraphRequest$zodSchema;
|
|
54173
|
+
var init_navigateknowledgegraphop = __esm(() => {
|
|
54174
|
+
init_zod();
|
|
54175
|
+
NavigateKnowledgeGraphRequest$zodSchema = object({
|
|
54176
|
+
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(),
|
|
54177
|
+
createdBefore: string2().describe("Filter children by source creation time. `YYYY-MM-DD` is inclusive of the whole day.").optional(),
|
|
54178
|
+
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(),
|
|
54179
|
+
limit: int().min(50).max(200).describe("Children per page. The minimum is 50 — smaller values are rejected rather than silently raised.").optional(),
|
|
54180
|
+
modifiedAfter: string2().describe("Filter children by source modification time.").optional(),
|
|
54181
|
+
modifiedBefore: string2().describe("Filter children by source modification time.").optional(),
|
|
54182
|
+
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(),
|
|
54183
|
+
nodeTypes: array(string2()).describe("Restrict children to these node types. Repeat the parameter for multiple types: `?nodeTypes=record&nodeTypes=folder`.").optional(),
|
|
54184
|
+
page: int().min(1).describe("Page number, 1-indexed.").optional()
|
|
54185
|
+
});
|
|
54186
|
+
});
|
|
54187
|
+
|
|
54188
|
+
// src/funcs/connectorNavigateKnowledgeGraph.ts
|
|
54189
|
+
function connectorNavigateKnowledgeGraph(client$, request, options) {
|
|
54190
|
+
return new APIPromise($do10(client$, request, options));
|
|
54191
|
+
}
|
|
54192
|
+
async function $do10(client$, request, options) {
|
|
54193
|
+
const parsed$ = safeParse4(request, (value$) => NavigateKnowledgeGraphRequest$zodSchema.optional().parse(value$), "Input validation failed");
|
|
54194
|
+
if (!parsed$.ok) {
|
|
54195
|
+
return [parsed$, { status: "invalid" }];
|
|
54196
|
+
}
|
|
54197
|
+
const payload$ = parsed$.value;
|
|
54198
|
+
const body$ = null;
|
|
54199
|
+
const path$ = pathToFunc("/connectors/navigate")();
|
|
54200
|
+
const query$ = encodeFormQuery({
|
|
54201
|
+
createdAfter: payload$?.createdAfter,
|
|
54202
|
+
createdBefore: payload$?.createdBefore,
|
|
54203
|
+
depth: payload$?.depth,
|
|
54204
|
+
limit: payload$?.limit,
|
|
54205
|
+
modifiedAfter: payload$?.modifiedAfter,
|
|
54206
|
+
modifiedBefore: payload$?.modifiedBefore,
|
|
54207
|
+
nodeId: payload$?.nodeId,
|
|
54208
|
+
nodeTypes: payload$?.nodeTypes,
|
|
54209
|
+
page: payload$?.page
|
|
54210
|
+
});
|
|
54211
|
+
const headers$ = new Headers(compactMap({
|
|
54212
|
+
Accept: "application/json"
|
|
54213
|
+
}));
|
|
54214
|
+
const securityInput = await extractSecurity(client$._options.security);
|
|
54215
|
+
const requestSecurity = resolveGlobalSecurity(securityInput);
|
|
54216
|
+
const context = {
|
|
54217
|
+
options: client$._options,
|
|
54218
|
+
baseURL: options?.serverURL ?? client$._baseURL ?? "",
|
|
54219
|
+
operationID: "navigateKnowledgeGraph",
|
|
54220
|
+
oAuth2Scopes: ["kb:read", "connector:read"],
|
|
54221
|
+
resolvedSecurity: requestSecurity,
|
|
54222
|
+
securitySource: client$._options.security,
|
|
54223
|
+
retryConfig: options?.retries || client$._options.retryConfig || { strategy: "none" },
|
|
54224
|
+
retryCodes: options?.retryCodes || [
|
|
54225
|
+
"429",
|
|
54226
|
+
"500",
|
|
54227
|
+
"502",
|
|
54228
|
+
"503",
|
|
54229
|
+
"504"
|
|
54230
|
+
]
|
|
54231
|
+
};
|
|
54232
|
+
const requestRes = client$._createRequest(context, {
|
|
54233
|
+
security: requestSecurity,
|
|
54234
|
+
method: "GET",
|
|
54235
|
+
baseURL: options?.serverURL,
|
|
54236
|
+
path: path$,
|
|
54237
|
+
headers: headers$,
|
|
54238
|
+
query: query$,
|
|
54239
|
+
body: body$,
|
|
54240
|
+
userAgent: client$._options.userAgent,
|
|
54241
|
+
timeoutMs: options?.timeoutMs || client$._options.timeoutMs || -1
|
|
54242
|
+
}, options);
|
|
54243
|
+
if (!requestRes.ok) {
|
|
54244
|
+
return [requestRes, { status: "invalid" }];
|
|
54245
|
+
}
|
|
54246
|
+
const req$ = requestRes.value;
|
|
54247
|
+
const doResult = await client$._do(req$, {
|
|
54248
|
+
context,
|
|
54249
|
+
errorCodes: [],
|
|
54250
|
+
retryConfig: context.retryConfig,
|
|
54251
|
+
retryCodes: context.retryCodes
|
|
54252
|
+
});
|
|
54253
|
+
if (!doResult.ok) {
|
|
54254
|
+
return [doResult, { status: "request-error", request: req$ }];
|
|
54255
|
+
}
|
|
54256
|
+
return [doResult, {
|
|
54257
|
+
status: "complete",
|
|
54258
|
+
request: req$,
|
|
54259
|
+
response: doResult.value
|
|
54260
|
+
}];
|
|
54261
|
+
}
|
|
54262
|
+
var init_connectorNavigateKnowledgeGraph = __esm(() => {
|
|
54263
|
+
init_encodings();
|
|
54264
|
+
init_primitives();
|
|
54265
|
+
init_schemas4();
|
|
54266
|
+
init_security2();
|
|
54267
|
+
init_url();
|
|
54268
|
+
init_navigateknowledgegraphop();
|
|
54269
|
+
init_async();
|
|
54270
|
+
});
|
|
54271
|
+
|
|
53969
54272
|
// src/mcp-server/tools/pipeshubGetRecordContent.ts
|
|
54273
|
+
async function renderedResult(response) {
|
|
54274
|
+
const parsed = await readJson(response);
|
|
54275
|
+
if (!parsed.ok)
|
|
54276
|
+
return parsed.result;
|
|
54277
|
+
const text = parsed.value?.text;
|
|
54278
|
+
return typeof text === "string" && text.trim().length > 0 ? { content: [{ type: "text", text }] } : jsonResult(parsed.value);
|
|
54279
|
+
}
|
|
53970
54280
|
var args4, tool$pipeshubGetRecordContent;
|
|
53971
54281
|
var init_pipeshubGetRecordContent = __esm(() => {
|
|
53972
54282
|
init_zod();
|
|
53973
54283
|
init_connectorGetRecordContent();
|
|
54284
|
+
init_connectorLookupRecordByIdentifier();
|
|
54285
|
+
init_connectorNavigateKnowledgeGraph();
|
|
53974
54286
|
init__helpers();
|
|
53975
54287
|
args4 = {
|
|
53976
|
-
|
|
54288
|
+
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."),
|
|
54289
|
+
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`."),
|
|
54290
|
+
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."),
|
|
54291
|
+
page: int().min(1).default(1).describe("Page number, 1-indexed."),
|
|
54292
|
+
limit: int().min(50).max(200).default(50).describe("Children per page. The minimum is 50 — smaller values are rejected " + "rather than silently raised."),
|
|
54293
|
+
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`."),
|
|
54294
|
+
nodeTypes: array(string2()).optional().describe('Restrict children to these node types, e.g. `["record", "folder"]`.'),
|
|
54295
|
+
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."),
|
|
54296
|
+
createdBefore: string2().optional().describe("Filter children by source creation time. `YYYY-MM-DD` is inclusive of " + "the whole day."),
|
|
54297
|
+
modifiedAfter: string2().optional().describe("Filter children by source modification time. Same formats as " + "`createdAfter`."),
|
|
54298
|
+
modifiedBefore: string2().optional().describe("Filter children by source modification time. Same formats as " + "`createdBefore`."),
|
|
54299
|
+
identifiers: union([
|
|
54300
|
+
string2().min(1).max(2048),
|
|
54301
|
+
array(string2().min(1).max(2048)).min(1).max(10)
|
|
54302
|
+
]).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`."),
|
|
54303
|
+
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
54304
|
};
|
|
53978
54305
|
tool$pipeshubGetRecordContent = {
|
|
53979
54306
|
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
|
-
|
|
54307
|
+
description: `Three operations on the org's records. Pick by what you hold:
|
|
54308
|
+
|
|
54309
|
+
\`mode:"lookup"\` — a URL, issue key (PA-1787), or external ID
|
|
54310
|
+
→ its recordId plus the record's metadata
|
|
54311
|
+
\`mode:"navigate"\` — a question about structure: what is under X,
|
|
54312
|
+
what links to Y → browses the hierarchy
|
|
54313
|
+
\`mode:"content"\` — a recordId, and you need the document's COMPLETE text
|
|
54314
|
+
|
|
54315
|
+
**\`mode:"content"\` (default)** — the only way to see a document's complete
|
|
54316
|
+
text. Use it whenever missing part of the document could make the answer
|
|
54317
|
+
wrong: summarize, extract or list ALL of something, check whether or where
|
|
54318
|
+
a doc mentions X, review, or compare named docs. \`pipeshub_chat\` cannot do
|
|
54319
|
+
these — it never sees a whole document.
|
|
54320
|
+
|
|
54321
|
+
Judge by the user's INTENT, not their keywords: "what's this doc about?",
|
|
54322
|
+
"walk me through the report", "anything in here about Y?" are all
|
|
54323
|
+
full-content tasks. Get the \`recordId\` from a \`pipeshub_search\` top hit, a
|
|
54324
|
+
chat citation, or \`mode:"lookup"\`.
|
|
54325
|
+
|
|
54326
|
+
Returns one \`content\` string: a metadata header (title, source, key fields,
|
|
54327
|
+
pre-generated summary) then the full parsed text. A record with no
|
|
54328
|
+
extractable content returns the literal \`No record found\`. Use
|
|
54329
|
+
\`pipeshub_download_record\` only for the original file bytes.
|
|
54330
|
+
|
|
54331
|
+
**\`mode:"navigate"\`** — browse the hierarchy: RecordGroup (project /
|
|
54332
|
+
space / drive / folder) → Record (epic / story / page / file) → children,
|
|
54333
|
+
with breadcrumbs, related links and record IDs.
|
|
54334
|
+
|
|
54335
|
+
Use it when the question depends on structure rather than wording: what is
|
|
54336
|
+
under this epic, which pages sit in this space, what is linked to this
|
|
54337
|
+
ticket, what is in this folder — and every "how many" / "all of" / "every"
|
|
54338
|
+
question. Search ranks by content; only this shows how records relate, and
|
|
54339
|
+
only this gives a count you can trust.
|
|
54340
|
+
|
|
54341
|
+
Omit \`nodeId\` for a flat listing of everything reachable, most recently
|
|
54342
|
+
updated first — the usual starting point. A URL, an issue key, or a
|
|
54343
|
+
\`pipeshub_sources\` id also works and resolves automatically.
|
|
54344
|
+
|
|
54345
|
+
Pass \`depth:2\` or \`depth:3\` to see several levels in ONE call — an epic's
|
|
54346
|
+
stories AND their subtasks, a space's pages AND their children — instead of
|
|
54347
|
+
one call per level. Use it whenever the question needs an overview of a
|
|
54348
|
+
hierarchy rather than a single node.
|
|
54349
|
+
|
|
54350
|
+
Opening a record also prints that record's own metadata — for a ticket,
|
|
54351
|
+
status, assignee, priority and dates — so a question about one record is
|
|
54352
|
+
often answered by this call alone. It returns no document text; for that,
|
|
54353
|
+
re-call with \`mode:"content"\`.
|
|
54354
|
+
|
|
54355
|
+
Returns \`Path\` breadcrumbs, the current node's metadata, a children listing
|
|
54356
|
+
carrying \`record_id=\` or \`node_id=\` per row plus the group's total
|
|
54357
|
+
(\`Children 1-50 of 61\`), \`Related\` cross-references, and a \`Next:\` line.
|
|
54358
|
+
One page is usually every child, so only pass \`page:2\` when that \`Next:\`
|
|
54359
|
+
line says more exist.
|
|
54360
|
+
|
|
54361
|
+
**\`mode:"lookup"\`** — turn an external reference into a recordId, the first
|
|
54362
|
+
step whenever the question names one. Returns that record's metadata (for a
|
|
54363
|
+
ticket: status, assignee, priority, dates) plus its recordId, which
|
|
54364
|
+
\`mode:"navigate"\` takes to list what is under it and \`mode:"content"\` takes
|
|
54365
|
+
to read it.
|
|
54366
|
+
|
|
54367
|
+
Handles Jira keys and URLs, Confluence, Drive, Slack permalinks, Linear,
|
|
54368
|
+
Notion, ServiceNow sys_id, SharePoint, Gmail/Outlook, and any connector
|
|
54369
|
+
whose records index a web URL. Resolution searches ALL connectors you can
|
|
54370
|
+
access, regardless of any source filter you used elsewhere.
|
|
54371
|
+
|
|
54372
|
+
A miss is a 200 with empty \`matches\` and the input echoed in
|
|
54373
|
+
\`not_found_identifiers\` — that may mean no-access, not non-existence. Use
|
|
54374
|
+
\`mode:"navigate"\` to confirm the record exists before telling the user it
|
|
54375
|
+
does not. If \`ambiguous\` is true, pick from \`matches\` rather than taking
|
|
54376
|
+
the first.
|
|
54377
|
+
|
|
54378
|
+
Navigate and lookup return a rendered text view whose closing \`Next:\` line
|
|
54379
|
+
names the exact follow-up call — follow it. When presenting a record, link
|
|
54380
|
+
it using the \`Web URL\` from its metadata header (when present).`,
|
|
54004
54381
|
scopes: ["read"],
|
|
54005
54382
|
annotations: {
|
|
54006
|
-
title: "
|
|
54383
|
+
title: "Read, browse, or resolve records",
|
|
54007
54384
|
destructiveHint: false,
|
|
54008
54385
|
idempotentHint: true,
|
|
54009
54386
|
openWorldHint: false,
|
|
@@ -54011,9 +54388,48 @@ you need the original file bytes.`,
|
|
|
54011
54388
|
},
|
|
54012
54389
|
args: args4,
|
|
54013
54390
|
tool: async (client, args5, ctx) => {
|
|
54391
|
+
const fetchOptions = { fetchOptions: { signal: ctx.signal } };
|
|
54392
|
+
if (args5.mode === "navigate") {
|
|
54393
|
+
const [r] = await connectorNavigateKnowledgeGraph(client, {
|
|
54394
|
+
nodeId: args5.nodeId,
|
|
54395
|
+
page: args5.page,
|
|
54396
|
+
limit: args5.limit,
|
|
54397
|
+
depth: args5.depth,
|
|
54398
|
+
nodeTypes: args5.nodeTypes,
|
|
54399
|
+
createdAfter: args5.createdAfter,
|
|
54400
|
+
createdBefore: args5.createdBefore,
|
|
54401
|
+
modifiedAfter: args5.modifiedAfter,
|
|
54402
|
+
modifiedBefore: args5.modifiedBefore
|
|
54403
|
+
}, fetchOptions).$inspect();
|
|
54404
|
+
if (!r.ok)
|
|
54405
|
+
return errorResult(r.error.message);
|
|
54406
|
+
const httpErr2 = await httpErrorResult(r.value, "Navigate knowledge graph");
|
|
54407
|
+
if (httpErr2)
|
|
54408
|
+
return httpErr2;
|
|
54409
|
+
return renderedResult(r.value);
|
|
54410
|
+
}
|
|
54411
|
+
if (args5.mode === "lookup") {
|
|
54412
|
+
const identifiers = typeof args5.identifiers === "string" ? [args5.identifiers] : args5.identifiers ?? [];
|
|
54413
|
+
if (identifiers.length === 0) {
|
|
54414
|
+
return errorResult('`identifiers` is required when mode is "lookup".');
|
|
54415
|
+
}
|
|
54416
|
+
const [r] = await connectorLookupRecordByIdentifier(client, {
|
|
54417
|
+
identifiers,
|
|
54418
|
+
connectorName: args5.connectorName
|
|
54419
|
+
}, fetchOptions).$inspect();
|
|
54420
|
+
if (!r.ok)
|
|
54421
|
+
return errorResult(r.error.message);
|
|
54422
|
+
const httpErr2 = await httpErrorResult(r.value, "Record lookup");
|
|
54423
|
+
if (httpErr2)
|
|
54424
|
+
return httpErr2;
|
|
54425
|
+
return renderedResult(r.value);
|
|
54426
|
+
}
|
|
54427
|
+
if (!args5.recordId) {
|
|
54428
|
+
return errorResult('`recordId` is required when mode is "content".');
|
|
54429
|
+
}
|
|
54014
54430
|
const [result] = await connectorGetRecordContent(client, {
|
|
54015
54431
|
recordId: args5.recordId
|
|
54016
|
-
},
|
|
54432
|
+
}, fetchOptions).$inspect();
|
|
54017
54433
|
if (!result.ok)
|
|
54018
54434
|
return errorResult(result.error.message);
|
|
54019
54435
|
const httpErr = await httpErrorResult(result.value, "Get record content");
|
|
@@ -54040,9 +54456,9 @@ var init_getallusersop = __esm(() => {
|
|
|
54040
54456
|
|
|
54041
54457
|
// src/funcs/usersGetAllUsers.ts
|
|
54042
54458
|
function usersGetAllUsers(client$, request, options) {
|
|
54043
|
-
return new APIPromise($
|
|
54459
|
+
return new APIPromise($do11(client$, request, options));
|
|
54044
54460
|
}
|
|
54045
|
-
async function $
|
|
54461
|
+
async function $do11(client$, request, options) {
|
|
54046
54462
|
const parsed$ = safeParse4(request, (value$) => GetAllUsersRequest$zodSchema.optional().parse(value$), "Input validation failed");
|
|
54047
54463
|
if (!parsed$.ok) {
|
|
54048
54464
|
return [parsed$, { status: "invalid" }];
|
|
@@ -54127,9 +54543,9 @@ var init_getuserbyidop = __esm(() => {
|
|
|
54127
54543
|
|
|
54128
54544
|
// src/funcs/usersGetUserById.ts
|
|
54129
54545
|
function usersGetUserById(client$, request, options) {
|
|
54130
|
-
return new APIPromise($
|
|
54546
|
+
return new APIPromise($do12(client$, request, options));
|
|
54131
54547
|
}
|
|
54132
|
-
async function $
|
|
54548
|
+
async function $do12(client$, request, options) {
|
|
54133
54549
|
const parsed$ = safeParse4(request, (value$) => GetUserByIdRequest$zodSchema.parse(value$), "Input validation failed");
|
|
54134
54550
|
if (!parsed$.ok) {
|
|
54135
54551
|
return [parsed$, { status: "invalid" }];
|
|
@@ -54216,9 +54632,9 @@ var init_getallusergroupsop = __esm(() => {
|
|
|
54216
54632
|
|
|
54217
54633
|
// src/funcs/userGroupsGetAllUserGroups.ts
|
|
54218
54634
|
function userGroupsGetAllUserGroups(client$, request, options) {
|
|
54219
|
-
return new APIPromise($
|
|
54635
|
+
return new APIPromise($do13(client$, request, options));
|
|
54220
54636
|
}
|
|
54221
|
-
async function $
|
|
54637
|
+
async function $do13(client$, request, options) {
|
|
54222
54638
|
const parsed$ = safeParse4(request, (value$) => GetAllUserGroupsRequest$zodSchema.optional().parse(value$), "Input validation failed");
|
|
54223
54639
|
if (!parsed$.ok) {
|
|
54224
54640
|
return [parsed$, { status: "invalid" }];
|
|
@@ -54308,9 +54724,9 @@ var init_getuserteamsop = __esm(() => {
|
|
|
54308
54724
|
|
|
54309
54725
|
// src/funcs/teamsGetUserTeams.ts
|
|
54310
54726
|
function teamsGetUserTeams(client$, request, options) {
|
|
54311
|
-
return new APIPromise($
|
|
54727
|
+
return new APIPromise($do14(client$, request, options));
|
|
54312
54728
|
}
|
|
54313
|
-
async function $
|
|
54729
|
+
async function $do14(client$, request, options) {
|
|
54314
54730
|
const parsed$ = safeParse4(request, (value$) => GetUserTeamsRequest$zodSchema.optional().parse(value$), "Input validation failed");
|
|
54315
54731
|
if (!parsed$.ok) {
|
|
54316
54732
|
return [parsed$, { status: "invalid" }];
|
|
@@ -54404,7 +54820,7 @@ var init_pipeshubDirectory = __esm(() => {
|
|
|
54404
54820
|
"list_groups",
|
|
54405
54821
|
"list_my_teams"
|
|
54406
54822
|
]).describe(`What to do:
|
|
54407
|
-
` + "- `whoami` — return the authenticated user's identity
|
|
54823
|
+
` + "- `whoami` — return the authenticated user's identity, confirmed " + `against the server. No other args needed.
|
|
54408
54824
|
` + "- `list_users` — paginated list of org users. Optional `page`, " + "`limit`, `search` (substring match against name or email).\n" + "- `get_user` — full profile for one user. Required `userId`. " + "Use `whoami` to find your own id first if needed.\n" + "- `list_groups` — paginated list of user groups (with `userCount`).\n" + "- `list_my_teams` — teams the authenticated user belongs to, with " + "capability flags."),
|
|
54409
54825
|
userId: string2().optional().describe("Required when `action` is `get_user`. 24-character ObjectId."),
|
|
54410
54826
|
page: number2().int().min(1).optional().describe("Pagination — 1-based page number. Used by list_* actions."),
|
|
@@ -54418,7 +54834,8 @@ actions — pick the right \`action\`:
|
|
|
54418
54834
|
|
|
54419
54835
|
- \`whoami\` — who is the caller? Use this whenever you need the
|
|
54420
54836
|
authenticated user's own id, email, or full name (e.g. before
|
|
54421
|
-
\`get_user\` on themselves).
|
|
54837
|
+
\`get_user\` on themselves). Errors if the credential is expired
|
|
54838
|
+
or revoked.
|
|
54422
54839
|
- \`list_users\` — search / page through org users.
|
|
54423
54840
|
- \`get_user\` — full \`User\` document for one user (requires \`userId\`).
|
|
54424
54841
|
- \`list_groups\` — list user groups with \`userCount\`.
|
|
@@ -54443,13 +54860,39 @@ Output shape varies by action; see each action's docs above.`,
|
|
|
54443
54860
|
if (!claims) {
|
|
54444
54861
|
return errorResult("No bearer token configured on the SDK client, so `whoami` " + "cannot resolve the caller's identity. Ask the user for " + "their email and use `list_users` with `search`.");
|
|
54445
54862
|
}
|
|
54863
|
+
const exp = claims["exp"];
|
|
54864
|
+
const expired = expiredTokenError(exp);
|
|
54865
|
+
if (expired)
|
|
54866
|
+
return expired;
|
|
54867
|
+
const tokenExpiresAt = typeof exp === "number" ? new Date(exp * 1000).toISOString() : undefined;
|
|
54868
|
+
const userId = claims["userId"];
|
|
54869
|
+
let verified = "unchecked";
|
|
54870
|
+
let unverifiedReason = "No userId claim in the token, so the identity could not be " + "confirmed with the server.";
|
|
54871
|
+
if (typeof userId === "string" && userId) {
|
|
54872
|
+
const [probe] = await usersGetUserById(client, { id: userId }, {
|
|
54873
|
+
fetchOptions
|
|
54874
|
+
}).$inspect();
|
|
54875
|
+
if (!probe.ok) {
|
|
54876
|
+
unverifiedReason = `Could not reach PipesHub to confirm the ` + `identity (${probe.error.message}). The details below come ` + `from the token itself.`;
|
|
54877
|
+
} else if (probe.value.status === 401) {
|
|
54878
|
+
return errorResult("PipesHub rejected this access token (HTTP 401 Unauthorized), " + "so the identity in it is no longer valid — it has most " + "likely been revoked. Mint a new personal access token " + "under Developer Settings → Personal Access Tokens.");
|
|
54879
|
+
} else if (probe.value.ok) {
|
|
54880
|
+
verified = true;
|
|
54881
|
+
unverifiedReason = undefined;
|
|
54882
|
+
} else {
|
|
54883
|
+
unverifiedReason = `PipesHub returned HTTP ${probe.value.status} ` + `when confirming the identity, so it could not be checked. ` + `The details below come from the token itself.`;
|
|
54884
|
+
}
|
|
54885
|
+
}
|
|
54446
54886
|
return jsonResult({
|
|
54447
54887
|
userId: claims["userId"],
|
|
54448
54888
|
orgId: claims["orgId"],
|
|
54449
54889
|
email: claims["email"],
|
|
54450
54890
|
fullName: claims["fullName"],
|
|
54451
54891
|
mobile: claims["mobile"],
|
|
54452
|
-
userSlug: claims["userSlug"]
|
|
54892
|
+
userSlug: claims["userSlug"],
|
|
54893
|
+
tokenExpiresAt,
|
|
54894
|
+
identityVerified: verified,
|
|
54895
|
+
note: unverifiedReason
|
|
54453
54896
|
});
|
|
54454
54897
|
}
|
|
54455
54898
|
case "list_users": {
|
|
@@ -54460,7 +54903,7 @@ Output shape varies by action; see each action's docs above.`,
|
|
|
54460
54903
|
}, { fetchOptions }).$inspect();
|
|
54461
54904
|
if (!result.ok)
|
|
54462
54905
|
return errorResult(result.error.message);
|
|
54463
|
-
const parsed = await readJson(result.value);
|
|
54906
|
+
const parsed = await readJson(result.value, "User listing");
|
|
54464
54907
|
if (!parsed.ok)
|
|
54465
54908
|
return parsed.result;
|
|
54466
54909
|
return jsonResult(parsed.value);
|
|
@@ -54474,7 +54917,7 @@ Output shape varies by action; see each action's docs above.`,
|
|
|
54474
54917
|
}, { fetchOptions }).$inspect();
|
|
54475
54918
|
if (!result.ok)
|
|
54476
54919
|
return errorResult(result.error.message);
|
|
54477
|
-
const parsed = await readJson(result.value);
|
|
54920
|
+
const parsed = await readJson(result.value, "User lookup");
|
|
54478
54921
|
if (!parsed.ok)
|
|
54479
54922
|
return parsed.result;
|
|
54480
54923
|
return jsonResult(parsed.value);
|
|
@@ -54487,7 +54930,7 @@ Output shape varies by action; see each action's docs above.`,
|
|
|
54487
54930
|
}, { fetchOptions }).$inspect();
|
|
54488
54931
|
if (!result.ok)
|
|
54489
54932
|
return errorResult(result.error.message);
|
|
54490
|
-
const parsed = await readJson(result.value);
|
|
54933
|
+
const parsed = await readJson(result.value, "Group listing");
|
|
54491
54934
|
if (!parsed.ok)
|
|
54492
54935
|
return parsed.result;
|
|
54493
54936
|
return jsonResult(parsed.value);
|
|
@@ -54500,7 +54943,7 @@ Output shape varies by action; see each action's docs above.`,
|
|
|
54500
54943
|
}, { fetchOptions }).$inspect();
|
|
54501
54944
|
if (!result.ok)
|
|
54502
54945
|
return errorResult(result.error.message);
|
|
54503
|
-
const parsed = await readJson(result.value);
|
|
54946
|
+
const parsed = await readJson(result.value, "Team listing");
|
|
54504
54947
|
if (!parsed.ok)
|
|
54505
54948
|
return parsed.result;
|
|
54506
54949
|
return jsonResult(parsed.value);
|
|
@@ -54540,9 +54983,9 @@ var init_getknowledgehubrootnodesop = __esm(() => {
|
|
|
54540
54983
|
|
|
54541
54984
|
// src/funcs/knowledgeHubGetKnowledgeHubRootNodes.ts
|
|
54542
54985
|
function knowledgeHubGetKnowledgeHubRootNodes(client$, request, options) {
|
|
54543
|
-
return new APIPromise($
|
|
54986
|
+
return new APIPromise($do15(client$, request, options));
|
|
54544
54987
|
}
|
|
54545
|
-
async function $
|
|
54988
|
+
async function $do15(client$, request, options) {
|
|
54546
54989
|
const parsed$ = safeParse4(request, (value$) => GetKnowledgeHubRootNodesRequest$zodSchema.optional().parse(value$), "Input validation failed");
|
|
54547
54990
|
if (!parsed$.ok) {
|
|
54548
54991
|
return [parsed$, { status: "invalid" }];
|
|
@@ -54658,9 +55101,9 @@ var init_getavailablemodelsbytypeop = __esm(() => {
|
|
|
54658
55101
|
|
|
54659
55102
|
// src/funcs/aiModelsProvidersGetAvailableModelsByType.ts
|
|
54660
55103
|
function aiModelsProvidersGetAvailableModelsByType(client$, request, options) {
|
|
54661
|
-
return new APIPromise($
|
|
55104
|
+
return new APIPromise($do16(client$, request, options));
|
|
54662
55105
|
}
|
|
54663
|
-
async function $
|
|
55106
|
+
async function $do16(client$, request, options) {
|
|
54664
55107
|
const parsed$ = safeParse4(request, (value$) => GetAvailableModelsByTypeRequest$zodSchema.parse(value$), "Input validation failed");
|
|
54665
55108
|
if (!parsed$.ok) {
|
|
54666
55109
|
return [parsed$, { status: "invalid" }];
|
|
@@ -54785,7 +55228,7 @@ are returned by default; pass \`include\` to override.`,
|
|
|
54785
55228
|
}, { fetchOptions }).$inspect();
|
|
54786
55229
|
if (!r.ok)
|
|
54787
55230
|
return errorResult(`sources: ${r.error.message}`);
|
|
54788
|
-
const parsed = await readJson(r.value);
|
|
55231
|
+
const parsed = await readJson(r.value, "Knowledge base listing");
|
|
54789
55232
|
if (!parsed.ok)
|
|
54790
55233
|
return parsed.result;
|
|
54791
55234
|
result["sources"] = (parsed.value.items ?? []).map((n) => ({
|
|
@@ -54807,7 +55250,7 @@ are returned by default; pass \`include\` to override.`,
|
|
|
54807
55250
|
}, { fetchOptions }).$inspect();
|
|
54808
55251
|
if (!r.ok)
|
|
54809
55252
|
return errorResult(`${key}: ${r.error.message}`);
|
|
54810
|
-
const parsed = await readJson(r.value);
|
|
55253
|
+
const parsed = await readJson(r.value, "Model listing");
|
|
54811
55254
|
if (!parsed.ok)
|
|
54812
55255
|
return parsed.result;
|
|
54813
55256
|
result[key] = (parsed.value.models ?? []).map((m) => ({
|
|
@@ -54986,31 +55429,39 @@ var init_tool_names = __esm(() => {
|
|
|
54986
55429
|
},
|
|
54987
55430
|
{
|
|
54988
55431
|
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
|
-
|
|
55432
|
+
description: `Ask a question, get an answer grounded in the org's indexed data with
|
|
55433
|
+
citations. It reads a few retrieved passages — never a whole document,
|
|
55434
|
+
never a complete list.
|
|
55435
|
+
|
|
55436
|
+
**Three questions this tool gets WRONG. Check them first:**
|
|
55437
|
+
- **Structure** — "what's under this epic?", "which pages are in this
|
|
55438
|
+
space?", "what links to this ticket?", "what's in this folder?" →
|
|
55439
|
+
\`pipeshub_get_record_content\` \`mode:"navigate"\`. Ranking cannot see how
|
|
55440
|
+
records relate.
|
|
55441
|
+
- **Exhaustive** — "how many X?", "list ALL the Y", "every Z" →
|
|
55442
|
+
\`mode:"navigate"\`, which reports the group's real total. This tool
|
|
55443
|
+
undercounts and will not say so.
|
|
55444
|
+
- **One named document** — summarize it, extract from it, what does it say
|
|
55445
|
+
about X → \`pipeshub_search\` for the \`recordId\`, then \`mode:"content"\`.
|
|
55446
|
+
|
|
55447
|
+
Everything else about the org's knowledge belongs here: policies,
|
|
55448
|
+
processes, decisions, history, "what do we know about X", and any question
|
|
55449
|
+
spanning several documents.
|
|
55450
|
+
|
|
55451
|
+
**Internal search** (default, \`chatMode: "internal_search"\`): the user's
|
|
55452
|
+
documents, files, knowledge base, company policies — anything in their
|
|
55453
|
+
PipesHub-indexed sources (Drive, Box, Confluence, Slack, Gmail, Jira, the
|
|
55454
|
+
org's KB, ...).
|
|
55455
|
+
|
|
55456
|
+
**Web search** (\`chatMode: "web_search"\`): current events or public
|
|
55457
|
+
information unlikely to be in the org's knowledge base.
|
|
55458
|
+
|
|
55459
|
+
Both are plain-chat modes. **Agent chat** — pass an \`agentId\` from
|
|
55460
|
+
\`pipeshub_agents\` — runs against that agent's own prompt, tools and knowledge;
|
|
55461
|
+
\`quick\` is its only mode, requires the \`agentId\`, and is sent automatically.
|
|
55462
|
+
|
|
55011
55463
|
- "What's our policy on Y?" → \`pipeshub_chat\` (internal_search)
|
|
55012
55464
|
- "What's in the news about Z?" → \`pipeshub_chat\` (web_search)
|
|
55013
|
-
- "What is the latest version of <library>?" → \`pipeshub_chat\` (web_search)
|
|
55014
55465
|
- "Find / locate the file named X" → \`pipeshub_search\` (then
|
|
55015
55466
|
\`pipeshub_download_record\` if the user wants the bytes).
|
|
55016
55467
|
|
|
@@ -55049,10 +55500,23 @@ Typical uses:
|
|
|
55049
55500
|
- Show the user a ranked list of matching files when they ask "find /
|
|
55050
55501
|
search for X".
|
|
55051
55502
|
|
|
55503
|
+
Not for structural questions — what is under this epic, which pages are
|
|
55504
|
+
in this space, what links to this ticket. Ranking by content cannot show
|
|
55505
|
+
how records relate; use \`pipeshub_get_record_content\` \`mode:"navigate"\`.
|
|
55506
|
+
|
|
55507
|
+
**A ranked sample, never a complete list.** Hits are the top-scoring
|
|
55508
|
+
blocks from the best-matching records — not all blocks of any record, and
|
|
55509
|
+
not every record that matches. Never count them to answer "how many" /
|
|
55510
|
+
"all" / "every"; navigate the record group instead, which reports its
|
|
55511
|
+
real total.
|
|
55512
|
+
|
|
55052
55513
|
The response is trimmed to one row per hit:
|
|
55053
55514
|
\`{ recordId, recordName, score, snippet, mimeType, webUrl, ... }\`.
|
|
55054
55515
|
Highest \`score\` first; multiple hits may share the same \`recordId\`
|
|
55055
|
-
(different
|
|
55516
|
+
(different blocks of the same record).
|
|
55517
|
+
|
|
55518
|
+
When presenting results to the user, link each record using its
|
|
55519
|
+
\`webUrl\` (when present).`
|
|
55056
55520
|
},
|
|
55057
55521
|
{
|
|
55058
55522
|
name: "pipeshub_download_record",
|
|
@@ -55060,34 +55524,84 @@ Highest \`score\` first; multiple hits may share the same \`recordId\`
|
|
|
55060
55524
|
},
|
|
55061
55525
|
{
|
|
55062
55526
|
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
|
-
|
|
55527
|
+
description: `Three operations on the org's records. Pick by what you hold:
|
|
55528
|
+
|
|
55529
|
+
\`mode:"lookup"\` — a URL, issue key (PA-1787), or external ID
|
|
55530
|
+
→ its recordId plus the record's metadata
|
|
55531
|
+
\`mode:"navigate"\` — a question about structure: what is under X,
|
|
55532
|
+
what links to Y → browses the hierarchy
|
|
55533
|
+
\`mode:"content"\` — a recordId, and you need the document's COMPLETE text
|
|
55534
|
+
|
|
55535
|
+
**\`mode:"content"\` (default)** — the only way to see a document's complete
|
|
55536
|
+
text. Use it whenever missing part of the document could make the answer
|
|
55537
|
+
wrong: summarize, extract or list ALL of something, check whether or where
|
|
55538
|
+
a doc mentions X, review, or compare named docs. \`pipeshub_chat\` cannot do
|
|
55539
|
+
these — it never sees a whole document.
|
|
55540
|
+
|
|
55541
|
+
Judge by the user's INTENT, not their keywords: "what's this doc about?",
|
|
55542
|
+
"walk me through the report", "anything in here about Y?" are all
|
|
55543
|
+
full-content tasks. Get the \`recordId\` from a \`pipeshub_search\` top hit, a
|
|
55544
|
+
chat citation, or \`mode:"lookup"\`.
|
|
55545
|
+
|
|
55546
|
+
Returns one \`content\` string: a metadata header (title, source, key fields,
|
|
55547
|
+
pre-generated summary) then the full parsed text. A record with no
|
|
55548
|
+
extractable content returns the literal \`No record found\`. Use
|
|
55549
|
+
\`pipeshub_download_record\` only for the original file bytes.
|
|
55550
|
+
|
|
55551
|
+
**\`mode:"navigate"\`** — browse the hierarchy: RecordGroup (project /
|
|
55552
|
+
space / drive / folder) → Record (epic / story / page / file) → children,
|
|
55553
|
+
with breadcrumbs, related links and record IDs.
|
|
55554
|
+
|
|
55555
|
+
Use it when the question depends on structure rather than wording: what is
|
|
55556
|
+
under this epic, which pages sit in this space, what is linked to this
|
|
55557
|
+
ticket, what is in this folder — and every "how many" / "all of" / "every"
|
|
55558
|
+
question. Search ranks by content; only this shows how records relate, and
|
|
55559
|
+
only this gives a count you can trust.
|
|
55560
|
+
|
|
55561
|
+
Omit \`nodeId\` for a flat listing of everything reachable, most recently
|
|
55562
|
+
updated first — the usual starting point. A URL, an issue key, or a
|
|
55563
|
+
\`pipeshub_sources\` id also works and resolves automatically.
|
|
55564
|
+
|
|
55565
|
+
Pass \`depth:2\` or \`depth:3\` to see several levels in ONE call — an epic's
|
|
55566
|
+
stories AND their subtasks, a space's pages AND their children — instead of
|
|
55567
|
+
one call per level. Use it whenever the question needs an overview of a
|
|
55568
|
+
hierarchy rather than a single node.
|
|
55569
|
+
|
|
55570
|
+
Opening a record also prints that record's own metadata — for a ticket,
|
|
55571
|
+
status, assignee, priority and dates — so a question about one record is
|
|
55572
|
+
often answered by this call alone. It returns no document text; for that,
|
|
55573
|
+
re-call with \`mode:"content"\`.
|
|
55574
|
+
|
|
55575
|
+
Returns \`Path\` breadcrumbs, the current node's metadata, a children listing
|
|
55576
|
+
carrying \`record_id=\` or \`node_id=\` per row plus the group's total
|
|
55577
|
+
(\`Children 1-50 of 61\`), \`Related\` cross-references, and a \`Next:\` line.
|
|
55578
|
+
One page is usually every child, so only pass \`page:2\` when that \`Next:\`
|
|
55579
|
+
line says more exist.
|
|
55580
|
+
|
|
55581
|
+
**\`mode:"lookup"\`** — turn an external reference into a recordId, the first
|
|
55582
|
+
step whenever the question names one. Returns that record's metadata (for a
|
|
55583
|
+
ticket: status, assignee, priority, dates) plus its recordId, which
|
|
55584
|
+
\`mode:"navigate"\` takes to list what is under it and \`mode:"content"\` takes
|
|
55585
|
+
to read it.
|
|
55586
|
+
|
|
55587
|
+
Handles Jira keys and URLs, Confluence, Drive, Slack permalinks, Linear,
|
|
55588
|
+
Notion, ServiceNow sys_id, SharePoint, Gmail/Outlook, and any connector
|
|
55589
|
+
whose records index a web URL. Resolution searches ALL connectors you can
|
|
55590
|
+
access, regardless of any source filter you used elsewhere.
|
|
55591
|
+
|
|
55592
|
+
A miss is a 200 with empty \`matches\` and the input echoed in
|
|
55593
|
+
\`not_found_identifiers\` — that may mean no-access, not non-existence. Use
|
|
55594
|
+
\`mode:"navigate"\` to confirm the record exists before telling the user it
|
|
55595
|
+
does not. If \`ambiguous\` is true, pick from \`matches\` rather than taking
|
|
55596
|
+
the first.
|
|
55597
|
+
|
|
55598
|
+
Navigate and lookup return a rendered text view whose closing \`Next:\` line
|
|
55599
|
+
names the exact follow-up call — follow it. When presenting a record, link
|
|
55600
|
+
it using the \`Web URL\` from its metadata header (when present).`
|
|
55087
55601
|
},
|
|
55088
55602
|
{
|
|
55089
55603
|
name: "pipeshub_directory",
|
|
55090
|
-
description: "Look up people, groups, and teams in PipesHub. One tool with five\nactions — pick the right `action`:\n\n- `whoami` — who is the caller? Use this whenever you need the\n authenticated user's own id, email, or full name (e.g. before\n `get_user` on themselves).\n- `list_users` — search / page through org users.\n- `get_user` — full `User` document for one user (requires `userId`).\n- `list_groups` — list user groups with `userCount`.\n- `list_my_teams` — teams the caller belongs to, with capability flags\n (`canEdit` / `canDelete` / `canManageMembers`).\n\nOutput shape varies by action; see each action's docs above."
|
|
55604
|
+
description: "Look up people, groups, and teams in PipesHub. One tool with five\nactions — pick the right `action`:\n\n- `whoami` — who is the caller? Use this whenever you need the\n authenticated user's own id, email, or full name (e.g. before\n `get_user` on themselves). Errors if the credential is expired\n or revoked.\n- `list_users` — search / page through org users.\n- `get_user` — full `User` document for one user (requires `userId`).\n- `list_groups` — list user groups with `userCount`.\n- `list_my_teams` — teams the caller belongs to, with capability flags\n (`canEdit` / `canDelete` / `canManageMembers`).\n\nOutput shape varies by action; see each action's docs above."
|
|
55091
55605
|
},
|
|
55092
55606
|
{
|
|
55093
55607
|
name: "pipeshub_agents",
|
|
@@ -58720,5 +59234,5 @@ export {
|
|
|
58720
59234
|
app
|
|
58721
59235
|
};
|
|
58722
59236
|
|
|
58723
|
-
//# debugId=
|
|
59237
|
+
//# debugId=B3EADAB5212D24DD64756E2164756E21
|
|
58724
59238
|
//# sourceMappingURL=mcp-server.js.map
|