@pipeshub-ai/mcp 2.0.1 → 2.2.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.
Files changed (117) hide show
  1. package/README.md +90 -2
  2. package/bin/mcp-server.js +1156 -213
  3. package/bin/mcp-server.js.map +30 -16
  4. package/esm/funcs/agentsListAgents.d.ts +10 -0
  5. package/esm/funcs/agentsListAgents.d.ts.map +1 -0
  6. package/esm/funcs/agentsListAgents.js +83 -0
  7. package/esm/funcs/agentsListAgents.js.map +1 -0
  8. package/esm/funcs/agentsStreamConversation.d.ts +10 -0
  9. package/esm/funcs/agentsStreamConversation.d.ts.map +1 -0
  10. package/esm/funcs/agentsStreamConversation.js +83 -0
  11. package/esm/funcs/agentsStreamConversation.js.map +1 -0
  12. package/esm/funcs/agentsStreamMessage.d.ts +10 -0
  13. package/esm/funcs/agentsStreamMessage.d.ts.map +1 -0
  14. package/esm/funcs/agentsStreamMessage.js +86 -0
  15. package/esm/funcs/agentsStreamMessage.js.map +1 -0
  16. package/esm/funcs/connectorGetRecordContent.d.ts +43 -0
  17. package/esm/funcs/connectorGetRecordContent.d.ts.map +1 -0
  18. package/esm/funcs/connectorGetRecordContent.js +114 -0
  19. package/esm/funcs/connectorGetRecordContent.js.map +1 -0
  20. package/esm/funcs/conversationsStreamConversation.d.ts.map +1 -1
  21. package/esm/funcs/conversationsStreamConversation.js +2 -4
  22. package/esm/funcs/conversationsStreamConversation.js.map +1 -1
  23. package/esm/funcs/conversationsStreamMessage.d.ts.map +1 -1
  24. package/esm/funcs/conversationsStreamMessage.js +0 -7
  25. package/esm/funcs/conversationsStreamMessage.js.map +1 -1
  26. package/esm/funcs/userGroupsGetAllUserGroups.js +1 -1
  27. package/esm/funcs/userGroupsGetAllUserGroups.js.map +1 -1
  28. package/esm/hooks/registration.d.ts.map +1 -1
  29. package/esm/hooks/registration.js +2 -1
  30. package/esm/hooks/registration.js.map +1 -1
  31. package/esm/hooks/request-context.d.ts +10 -0
  32. package/esm/hooks/request-context.d.ts.map +1 -0
  33. package/esm/hooks/request-context.js +38 -0
  34. package/esm/hooks/request-context.js.map +1 -0
  35. package/esm/hooks/requestid.d.ts +5 -0
  36. package/esm/hooks/requestid.d.ts.map +1 -0
  37. package/esm/hooks/requestid.js +58 -0
  38. package/esm/hooks/requestid.js.map +1 -0
  39. package/esm/mcp-server/instructions.d.ts +2 -0
  40. package/esm/mcp-server/instructions.d.ts.map +1 -0
  41. package/esm/mcp-server/instructions.js +106 -0
  42. package/esm/mcp-server/instructions.js.map +1 -0
  43. package/esm/mcp-server/prompts/pipeshubAssistant.d.ts +8 -0
  44. package/esm/mcp-server/prompts/pipeshubAssistant.d.ts.map +1 -0
  45. package/esm/mcp-server/prompts/pipeshubAssistant.js +31 -0
  46. package/esm/mcp-server/prompts/pipeshubAssistant.js.map +1 -0
  47. package/esm/mcp-server/server.d.ts.map +1 -1
  48. package/esm/mcp-server/server.js +16 -62
  49. package/esm/mcp-server/server.js.map +1 -1
  50. package/esm/mcp-server/tools/_helpers.d.ts +78 -0
  51. package/esm/mcp-server/tools/_helpers.d.ts.map +1 -1
  52. package/esm/mcp-server/tools/_helpers.js +155 -1
  53. package/esm/mcp-server/tools/_helpers.js.map +1 -1
  54. package/esm/mcp-server/tools/pipeshubAgents.d.ts +8 -0
  55. package/esm/mcp-server/tools/pipeshubAgents.d.ts.map +1 -0
  56. package/esm/mcp-server/tools/pipeshubAgents.js +62 -0
  57. package/esm/mcp-server/tools/pipeshubAgents.js.map +1 -0
  58. package/esm/mcp-server/tools/pipeshubChat.d.ts +6 -1
  59. package/esm/mcp-server/tools/pipeshubChat.d.ts.map +1 -1
  60. package/esm/mcp-server/tools/pipeshubChat.js +79 -23
  61. package/esm/mcp-server/tools/pipeshubChat.js.map +1 -1
  62. package/esm/mcp-server/tools/pipeshubDirectory.d.ts.map +1 -1
  63. package/esm/mcp-server/tools/pipeshubDirectory.js +0 -1
  64. package/esm/mcp-server/tools/pipeshubDirectory.js.map +1 -1
  65. package/esm/mcp-server/tools/pipeshubDownloadRecord.d.ts.map +1 -1
  66. package/esm/mcp-server/tools/pipeshubDownloadRecord.js +0 -3
  67. package/esm/mcp-server/tools/pipeshubDownloadRecord.js.map +1 -1
  68. package/esm/mcp-server/tools/pipeshubGetRecordContent.d.ts +8 -0
  69. package/esm/mcp-server/tools/pipeshubGetRecordContent.d.ts.map +1 -0
  70. package/esm/mcp-server/tools/pipeshubGetRecordContent.js +63 -0
  71. package/esm/mcp-server/tools/pipeshubGetRecordContent.js.map +1 -0
  72. package/esm/mcp-server/tools/pipeshubSearch.d.ts.map +1 -1
  73. package/esm/mcp-server/tools/pipeshubSearch.js +8 -7
  74. package/esm/mcp-server/tools/pipeshubSearch.js.map +1 -1
  75. package/esm/mcp-server/tools/pipeshubSources.d.ts.map +1 -1
  76. package/esm/mcp-server/tools/pipeshubSources.js +0 -4
  77. package/esm/mcp-server/tools/pipeshubSources.js.map +1 -1
  78. package/esm/mcp-server/tools.d.ts.map +1 -1
  79. package/esm/mcp-server/tools.js +13 -1
  80. package/esm/mcp-server/tools.js.map +1 -1
  81. package/esm/models/agentops.d.ts +119 -0
  82. package/esm/models/agentops.d.ts.map +1 -0
  83. package/esm/models/agentops.js +97 -0
  84. package/esm/models/agentops.js.map +1 -0
  85. package/esm/models/getrecordcontentop.d.ts +6 -0
  86. package/esm/models/getrecordcontentop.d.ts.map +1 -0
  87. package/esm/models/getrecordcontentop.js +5 -0
  88. package/esm/models/getrecordcontentop.js.map +1 -0
  89. package/esm/tool-names.d.ts.map +1 -1
  90. package/esm/tool-names.js +10 -2
  91. package/esm/tool-names.js.map +1 -1
  92. package/package.json +3 -2
  93. package/src/funcs/agentsListAgents.ts +141 -0
  94. package/src/funcs/agentsStreamConversation.ts +144 -0
  95. package/src/funcs/agentsStreamMessage.ts +147 -0
  96. package/src/funcs/connectorGetRecordContent.ts +179 -0
  97. package/src/funcs/conversationsStreamConversation.ts +2 -4
  98. package/src/funcs/conversationsStreamMessage.ts +0 -8
  99. package/src/funcs/userGroupsGetAllUserGroups.ts +1 -1
  100. package/src/hooks/registration.ts +2 -1
  101. package/src/hooks/request-context.ts +47 -0
  102. package/src/hooks/requestid.ts +62 -0
  103. package/src/mcp-server/instructions.ts +106 -0
  104. package/src/mcp-server/prompts/pipeshubAssistant.ts +37 -0
  105. package/src/mcp-server/server.ts +18 -64
  106. package/src/mcp-server/tools/_helpers.ts +216 -1
  107. package/src/mcp-server/tools/pipeshubAgents.ts +68 -0
  108. package/src/mcp-server/tools/pipeshubChat.ts +78 -23
  109. package/src/mcp-server/tools/pipeshubDirectory.ts +0 -1
  110. package/src/mcp-server/tools/pipeshubDownloadRecord.ts +0 -4
  111. package/src/mcp-server/tools/pipeshubGetRecordContent.ts +67 -0
  112. package/src/mcp-server/tools/pipeshubSearch.ts +8 -7
  113. package/src/mcp-server/tools/pipeshubSources.ts +0 -5
  114. package/src/mcp-server/tools.ts +14 -1
  115. package/src/models/agentops.ts +160 -0
  116. package/src/models/getrecordcontentop.ts +11 -0
  117. package/src/tool-names.ts +10 -2
package/bin/mcp-server.js CHANGED
@@ -50387,8 +50387,213 @@ var init_mcp = __esm(() => {
50387
50387
  };
50388
50388
  });
50389
50389
 
50390
+ // src/mcp-server/instructions.ts
50391
+ var PIPESHUB_INSTRUCTIONS = `# PipesHub MCP — instructions for the LLM
50392
+
50393
+ PipesHub is the user's workplace AI platform. It indexes their documents,
50394
+ knowledge base content, and connector sources (Drive, Box, Confluence,
50395
+ Slack, Jira, Gmail, ...). When in doubt, the answer is in PipesHub.
50396
+
50397
+ ## Full-document tasks: \`pipeshub_search\` → \`pipeshub_get_record_content\`
50398
+
50399
+ \`pipeshub_chat\` answers from a handful of retrieved passages — it never
50400
+ reads a whole document. Whenever the task depends on a document's
50401
+ COMPLETE content, fetch the document itself:
50402
+
50403
+ 1. \`pipeshub_search\` with the document's name / topic.
50404
+ 2. Take the top hit's \`recordId\`.
50405
+ 3. \`pipeshub_get_record_content\`, and answer from the returned content.
50406
+
50407
+ Tasks that need this path — anything where missing part of the document
50408
+ could make the answer wrong:
50409
+
50410
+ - Summarize / TL;DR / key points / takeaways / action items of a doc.
50411
+ - Extract or list ALL of something (dates, owners, requirements, ...).
50412
+ - Check whether / where a doc mentions something.
50413
+ - Translate, rewrite, outline, review, or reformat a doc.
50414
+ - Compare named docs (fetch each \`recordId\`).
50415
+ - Any question explicitly scoped to ONE named document — chat retrieval
50416
+ cannot be restricted to a single record.
50417
+
50418
+ ## Default tool: \`pipeshub_chat\`
50419
+
50420
+ **Use \`pipeshub_chat\` for any question that could plausibly be answered
50421
+ by the user's PipesHub-indexed data** and is not a full-document task:
50422
+
50423
+ - A question that may span several documents, or where you don't yet
50424
+ know which record holds the answer (e.g. "what did Aashil say about
50425
+ onboarding?").
50426
+ - Anything about company / org policies, processes, decisions, or
50427
+ history (e.g. "what's our vacation policy?", "who owns the auth
50428
+ service?").
50429
+ - Anything explicitly mentioning PipesHub itself, or its sources
50430
+ (Drive / Box / Confluence / Slack / Gmail / Jira / etc.) when the
50431
+ user has those connected.
50432
+ - Open-ended "what do we know about X" questions where the answer
50433
+ likely lives in the org's documents.
50434
+
50435
+ Do NOT answer those from your own knowledge — \`pipeshub_chat\` grounds
50436
+ the answer in the user's actual indexed content and returns citations
50437
+ the user can verify.
50438
+
50439
+ ## When to use the other tools
50440
+
50441
+ - \`pipeshub_search\` — locate a document by name or topic and resolve it
50442
+ to a \`recordId\`. To read or summarize one specific document, search,
50443
+ then pass the top hit's \`recordId\` to \`pipeshub_get_record_content\`.
50444
+ - \`pipeshub_download_record\` — when the user wants the actual file
50445
+ bytes (download, attach, open). Get the \`recordId\` either from
50446
+ citations on a prior \`pipeshub_chat\` response or from
50447
+ \`pipeshub_search\`.
50448
+ - \`pipeshub_get_record_content\` — when you need a record's full parsed
50449
+ content (returned as a single \`content\` string: metadata header plus
50450
+ the document's text) without downloading the original file. Prefer this
50451
+ over download when the question is about what the record says.
50452
+ - \`pipeshub_directory\` — people, groups, teams, and \`whoami\` lookups.
50453
+ Not for documents.
50454
+ - \`pipeshub_sources\` — call once at the start of a session to discover
50455
+ which connectors / KB / models are available, then cache the result.
50456
+ - \`pipeshub_agents\` — list the org's configured **agents** (specialized
50457
+ assistants with their own prompt, tools, and knowledge scope).
50458
+
50459
+ ## Agents
50460
+
50461
+ Some orgs configure **agents** for specific jobs (e.g. a Slack messenger, a
50462
+ Jira ticket creator, a Salesforce CRM updater). To run a turn against an
50463
+ agent, call \`pipeshub_chat\` with its \`agentId\` (from \`pipeshub_agents\`)
50464
+ — optionally with an agent \`chatMode\` (\`auto\` by default, or \`quick\` /
50465
+ \`verification\` / \`deep\`). Keep passing the same \`agentId\` plus the
50466
+ returned \`conversationId\` on follow-up turns.
50467
+
50468
+ **When to route to an agent vs plain chat:**
50469
+ - The user names a system/action that maps to an agent (e.g. "post to
50470
+ Slack", "create a Jira ticket", "update the Salesforce deal") → call
50471
+ \`pipeshub_agents\`, pick the matching agent, and use it.
50472
+ - Plain question about the org's knowledge or the public web → just use
50473
+ \`pipeshub_chat\` (no \`agentId\`) with \`internal_search\` or \`web_search\`.
50474
+
50475
+ **If you are unsure which agent or route fits the request**, call
50476
+ \`pipeshub_agents\` FIRST and read the returned names/descriptions, then
50477
+ either pick the best match or present the list to the user and let them
50478
+ choose. Do NOT guess an agent blindly, and do NOT refuse — list the agents
50479
+ and decide from real data. The list may be empty (no agents configured),
50480
+ in which case fall back to plain \`pipeshub_chat\`.
50481
+
50482
+ ## Conversation lifecycle
50483
+
50484
+ \`pipeshub_chat\` is a single tool that handles both starting and
50485
+ continuing conversations (plain or with an \`agentId\`). On the first turn
50486
+ omit \`conversationId\`; on every subsequent turn pass back the
50487
+ \`conversationId\` returned by the previous call (along with the same
50488
+ \`agentId\` if you used one). Server-side context is preserved — do NOT
50489
+ replay prior messages. Only start a fresh conversation when the user
50490
+ explicitly asks to clear context.
50491
+ `;
50492
+
50493
+ // node_modules/nanoid/url-alphabet/index.js
50494
+ var urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
50495
+
50496
+ // node_modules/nanoid/index.js
50497
+ import { webcrypto as crypto3 } from "node:crypto";
50498
+ function fillPool(bytes) {
50499
+ if (bytes < 0)
50500
+ throw new RangeError("Wrong ID size");
50501
+ try {
50502
+ if (!pool || pool.length < bytes) {
50503
+ pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER);
50504
+ crypto3.getRandomValues(pool);
50505
+ poolOffset = 0;
50506
+ } else if (poolOffset + bytes > pool.length) {
50507
+ crypto3.getRandomValues(pool);
50508
+ poolOffset = 0;
50509
+ }
50510
+ } catch (e) {
50511
+ pool = undefined;
50512
+ throw e;
50513
+ }
50514
+ poolOffset += bytes;
50515
+ }
50516
+ function nanoid2(size = 21) {
50517
+ fillPool(size |= 0);
50518
+ let id = "";
50519
+ for (let i = poolOffset - size;i < poolOffset; i++) {
50520
+ id += urlAlphabet[pool[i] & 63];
50521
+ }
50522
+ return id;
50523
+ }
50524
+ var POOL_SIZE_MULTIPLIER = 128, pool, poolOffset;
50525
+ var init_nanoid = () => {};
50526
+
50527
+ // src/hooks/request-context.ts
50528
+ import { AsyncLocalStorage } from "node:async_hooks";
50529
+ function bindNewRequestId() {
50530
+ storage.enterWith({ random: nanoid2() });
50531
+ }
50532
+ function getRequestContextStore() {
50533
+ return storage.getStore();
50534
+ }
50535
+ function newRequestId() {
50536
+ return `mcp-${nanoid2()}`;
50537
+ }
50538
+ var storage;
50539
+ var init_request_context = __esm(() => {
50540
+ init_nanoid();
50541
+ storage = new AsyncLocalStorage;
50542
+ });
50543
+
50544
+ // src/hooks/requestid.ts
50545
+ function decodeJwtPayload(token) {
50546
+ try {
50547
+ const base64Url = token.split(".")[1];
50548
+ if (!base64Url)
50549
+ return null;
50550
+ const base642 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
50551
+ const padded = base642 + "=".repeat((4 - base642.length % 4) % 4);
50552
+ const claims = JSON.parse(Buffer.from(padded, "base64").toString("utf8"));
50553
+ return typeof claims === "object" && claims !== null ? claims : null;
50554
+ } catch {
50555
+ return null;
50556
+ }
50557
+ }
50558
+ function userIdFromRequest(request) {
50559
+ const auth = request.headers.get("authorization") ?? "";
50560
+ if (!auth.toLowerCase().startsWith("bearer "))
50561
+ return null;
50562
+ const token = auth.slice(7).trim();
50563
+ const claims = decodeJwtPayload(token);
50564
+ return claims?.["userId"] || null;
50565
+ }
50566
+
50567
+ class RequestIDHook {
50568
+ beforeRequest(_hookCtx, request) {
50569
+ if (request.headers.get(REQUEST_ID_HEADER)) {
50570
+ return request;
50571
+ }
50572
+ const store = getRequestContextStore();
50573
+ if (!store) {
50574
+ request.headers.set(REQUEST_ID_HEADER, newRequestId());
50575
+ return request;
50576
+ }
50577
+ if (!store.finalId) {
50578
+ const userId = userIdFromRequest(request);
50579
+ store.finalId = userId ? `mcp-${userId}-${store.random}` : `mcp-${store.random}`;
50580
+ }
50581
+ request.headers.set(REQUEST_ID_HEADER, store.finalId);
50582
+ return request;
50583
+ }
50584
+ }
50585
+ var REQUEST_ID_HEADER = "x-request-id";
50586
+ var init_requestid = __esm(() => {
50587
+ init_request_context();
50588
+ });
50589
+
50390
50590
  // src/hooks/registration.ts
50391
- function initHooks(hooks) {}
50591
+ function initHooks(hooks) {
50592
+ hooks.registerBeforeRequestHook(new RequestIDHook);
50593
+ }
50594
+ var init_registration = __esm(() => {
50595
+ init_requestid();
50596
+ });
50392
50597
 
50393
50598
  // src/lib/base64.ts
50394
50599
  function bytesToBase64(u8arr) {
@@ -50978,6 +51183,7 @@ class SDKHooks {
50978
51183
  }
50979
51184
  }
50980
51185
  var init_hooks = __esm(() => {
51186
+ init_registration();
50981
51187
  init_clientcredentials();
50982
51188
  });
50983
51189
 
@@ -51802,9 +52008,15 @@ async function formatResult(response) {
51802
52008
  } else if (contentType.startsWith("audio/")) {
51803
52009
  const data = await valueToBase64(await response.arrayBuffer());
51804
52010
  content = data == null ? [] : [{ type: "audio", data, mimeType: contentType }];
51805
- } else {
52011
+ } else if (contentType.startsWith("text/") || contentType.includes("json") || contentType.includes("xml") || contentType.includes("yaml")) {
51806
52012
  const text = await response.text();
51807
52013
  content = [{ type: "text", text }];
52014
+ } else {
52015
+ const blob = await valueToBase64(await response.arrayBuffer());
52016
+ content = blob == null ? [] : [{
52017
+ type: "resource",
52018
+ resource: { uri: response.url, mimeType: contentType, blob }
52019
+ }];
51808
52020
  }
51809
52021
  return response.ok ? { content } : { content, isError: true };
51810
52022
  }
@@ -52302,7 +52514,7 @@ async function $do(client$, request, options) {
52302
52514
  options: client$._options,
52303
52515
  baseURL: options?.serverURL ?? client$._baseURL ?? "",
52304
52516
  operationID: "streamConversation",
52305
- oAuth2Scopes: ["conversation:write"],
52517
+ oAuth2Scopes: ["conversation:chat"],
52306
52518
  resolvedSecurity: requestSecurity,
52307
52519
  securitySource: client$._options.security,
52308
52520
  retryConfig: options?.retries || client$._options.retryConfig || { strategy: "none" },
@@ -52460,112 +52672,478 @@ var init_conversationsStreamMessage = __esm(() => {
52460
52672
  init_async();
52461
52673
  });
52462
52674
 
52463
- // src/mcp-server/tools/_helpers.ts
52464
- async function readJson(response) {
52465
- const text = await response.text();
52466
- if (!text) {
52467
- return {
52468
- ok: false,
52469
- result: {
52470
- content: [{ type: "text", text: "Empty response from server" }],
52471
- isError: true
52472
- }
52473
- };
52474
- }
52475
- try {
52476
- return { ok: true, value: JSON.parse(text) };
52477
- } catch (e) {
52478
- return {
52479
- ok: false,
52480
- result: {
52481
- content: [{
52482
- type: "text",
52483
- text: `Failed to parse response as JSON: ${e.message}
52484
-
52485
- Raw body:
52486
- ${text.slice(0, 500)}`
52487
- }],
52488
- isError: true
52489
- }
52490
- };
52491
- }
52675
+ // src/models/agentops.ts
52676
+ var ListAgentsRequest$zodSchema, AgentStreamConversationBody$zodSchema, AgentStreamCreateConversationRequest$zodSchema, AgentAddMessageStreamRequest$zodSchema, AgentWebSearch$zodSchema, AgentToolsetTool$zodSchema, AgentToolset$zodSchema, AgentKnowledge$zodSchema, AgentSummary$zodSchema, AgentListPagination$zodSchema, AgentListEnvelope$zodSchema;
52677
+ var init_agentops = __esm(() => {
52678
+ init_zod();
52679
+ init_filters();
52680
+ ListAgentsRequest$zodSchema = object({
52681
+ page: int().optional(),
52682
+ limit: int().optional(),
52683
+ search: string2().optional(),
52684
+ sortBy: string2().optional(),
52685
+ sortOrder: _enum(["asc", "desc"]).optional()
52686
+ });
52687
+ AgentStreamConversationBody$zodSchema = object({
52688
+ query: string2().min(1),
52689
+ recordIds: array(string2()).optional(),
52690
+ filters: Filters$zodSchema.optional(),
52691
+ chatMode: string2().optional(),
52692
+ modelKey: string2().optional(),
52693
+ modelName: string2().optional(),
52694
+ modelFriendlyName: string2().optional(),
52695
+ tools: array(string2()).optional(),
52696
+ timezone: string2().optional(),
52697
+ currentTime: string2().optional()
52698
+ });
52699
+ AgentStreamCreateConversationRequest$zodSchema = object({
52700
+ agentKey: string2().min(1),
52701
+ body: AgentStreamConversationBody$zodSchema
52702
+ });
52703
+ AgentAddMessageStreamRequest$zodSchema = object({
52704
+ agentKey: string2().min(1),
52705
+ conversationId: string2(),
52706
+ body: AgentStreamConversationBody$zodSchema
52707
+ });
52708
+ AgentWebSearch$zodSchema = object({
52709
+ provider: string2().optional(),
52710
+ providerKey: string2().optional(),
52711
+ providerLabel: string2().optional()
52712
+ });
52713
+ AgentToolsetTool$zodSchema = object({
52714
+ name: string2().nullish(),
52715
+ fullName: string2().nullish()
52716
+ });
52717
+ AgentToolset$zodSchema = object({
52718
+ name: string2().nullish(),
52719
+ displayName: string2().nullish(),
52720
+ instanceName: string2().nullish(),
52721
+ tools: array(AgentToolsetTool$zodSchema).default([])
52722
+ });
52723
+ AgentKnowledge$zodSchema = object({
52724
+ name: string2().nullish(),
52725
+ displayName: string2().nullish(),
52726
+ type: string2().nullish()
52727
+ });
52728
+ AgentSummary$zodSchema = object({
52729
+ _key: string2(),
52730
+ name: string2(),
52731
+ description: string2().nullish(),
52732
+ systemPrompt: string2().nullish(),
52733
+ startMessage: string2().nullish(),
52734
+ tags: array(string2()).default([]),
52735
+ webSearch: AgentWebSearch$zodSchema.nullish(),
52736
+ isActive: boolean2().nullish(),
52737
+ toolsets: array(AgentToolset$zodSchema).default([]),
52738
+ knowledge: array(AgentKnowledge$zodSchema).default([])
52739
+ });
52740
+ AgentListPagination$zodSchema = object({
52741
+ totalItems: number2().nullish(),
52742
+ total: number2().nullish(),
52743
+ hasNext: boolean2().nullish(),
52744
+ hasNextPage: boolean2().nullish()
52745
+ });
52746
+ AgentListEnvelope$zodSchema = object({
52747
+ success: boolean2().nullish(),
52748
+ agents: array(AgentSummary$zodSchema).default([]),
52749
+ pagination: AgentListPagination$zodSchema.nullish()
52750
+ });
52751
+ });
52752
+
52753
+ // src/funcs/agentsStreamConversation.ts
52754
+ function agentsStreamConversation(client$, request, options) {
52755
+ return new APIPromise($do3(client$, request, options));
52492
52756
  }
52493
- function jsonResult(value) {
52494
- return {
52495
- content: [{ type: "text", text: JSON.stringify(value, null, 2) }]
52757
+ async function $do3(client$, request, options) {
52758
+ const parsed$ = safeParse4(request, (value$) => AgentStreamCreateConversationRequest$zodSchema.parse(value$), "Input validation failed");
52759
+ if (!parsed$.ok) {
52760
+ return [parsed$, { status: "invalid" }];
52761
+ }
52762
+ const payload$ = parsed$.value;
52763
+ const body$ = encodeJSON("body", payload$.body, { explode: true });
52764
+ const pathParams$ = {
52765
+ agentKey: encodeSimple("agentKey", payload$.agentKey, {
52766
+ explode: false,
52767
+ charEncoding: "percent"
52768
+ })
52496
52769
  };
52497
- }
52498
- function errorResult(message) {
52499
- return {
52500
- content: [{ type: "text", text: message }],
52501
- isError: true
52770
+ const path$ = pathToFunc("/agents/{agentKey}/conversations/stream")(pathParams$);
52771
+ const headers$ = new Headers(compactMap({
52772
+ "Content-Type": "application/json",
52773
+ Accept: "text/event-stream"
52774
+ }));
52775
+ const securityInput = await extractSecurity(client$._options.security);
52776
+ const requestSecurity = resolveGlobalSecurity(securityInput);
52777
+ const context = {
52778
+ options: client$._options,
52779
+ baseURL: options?.serverURL ?? client$._baseURL ?? "",
52780
+ operationID: "streamAgentConversation",
52781
+ oAuth2Scopes: ["agent:execute"],
52782
+ resolvedSecurity: requestSecurity,
52783
+ securitySource: client$._options.security,
52784
+ retryConfig: options?.retries || client$._options.retryConfig || { strategy: "none" },
52785
+ retryCodes: options?.retryCodes || [
52786
+ "429",
52787
+ "500",
52788
+ "502",
52789
+ "503",
52790
+ "504"
52791
+ ]
52502
52792
  };
52503
- }
52504
- async function resolveSecurity2(client) {
52505
- const sec = client._options.security;
52506
- if (typeof sec === "function") {
52507
- return await sec();
52793
+ const requestRes = client$._createRequest(context, {
52794
+ security: requestSecurity,
52795
+ method: "POST",
52796
+ baseURL: options?.serverURL,
52797
+ path: path$,
52798
+ headers: headers$,
52799
+ body: body$,
52800
+ userAgent: client$._options.userAgent,
52801
+ timeoutMs: options?.timeoutMs || -1
52802
+ }, options);
52803
+ if (!requestRes.ok) {
52804
+ return [requestRes, { status: "invalid" }];
52508
52805
  }
52509
- return sec;
52510
- }
52511
- async function decodeBearer(client) {
52512
- const sec = await resolveSecurity2(client);
52513
- const token = sec?.bearerAuth;
52514
- if (!token)
52515
- return null;
52516
- const parts = token.split(".");
52517
- const claims = parts[1];
52518
- if (!claims)
52519
- return null;
52520
- try {
52521
- const padded = claims + "=".repeat((4 - claims.length % 4) % 4);
52522
- const json = Buffer.from(padded.replace(/-/g, "+").replace(/_/g, "/"), "base64").toString("utf8");
52523
- return JSON.parse(json);
52524
- } catch {
52525
- return null;
52806
+ const req$ = requestRes.value;
52807
+ const doResult = await client$._do(req$, {
52808
+ context,
52809
+ errorCodes: [],
52810
+ retryConfig: context.retryConfig,
52811
+ retryCodes: context.retryCodes
52812
+ });
52813
+ if (!doResult.ok) {
52814
+ return [doResult, { status: "request-error", request: req$ }];
52526
52815
  }
52816
+ return [doResult, {
52817
+ status: "complete",
52818
+ request: req$,
52819
+ response: doResult.value
52820
+ }];
52527
52821
  }
52528
- function trimConversation(conv) {
52529
- const messages = Array.isArray(conv?.messages) ? conv.messages : [];
52530
- const lastBot = [...messages].reverse().find((m) => m?.messageType === "bot_response");
52531
- return {
52532
- conversationId: conv?._id,
52533
- title: conv?.title,
52534
- status: conv?.status,
52535
- answer: lastBot?.content ?? null,
52536
- confidence: lastBot?.confidence ?? null,
52537
- citations: trimCitations(lastBot?.citations),
52538
- followUpQuestions: lastBot?.followUpQuestions?.map((q) => typeof q === "string" ? q : q?.question).filter(Boolean) ?? [],
52539
- messageCount: messages.length
52540
- };
52541
- }
52542
- function trimCitations(citations) {
52543
- if (!Array.isArray(citations))
52544
- return [];
52545
- return citations.map((c) => {
52546
- const md = c?.metadata ?? {};
52547
- return {
52548
- recordId: md.recordId ?? c?.recordId,
52549
- recordName: md.recordName ?? c?.recordName,
52550
- snippet: typeof c?.content === "string" ? c.content.slice(0, 280) : md.blockText ?? null,
52551
- mimeType: md.mimeType,
52552
- webUrl: md.webUrl,
52553
- pageNum: md.pageNum,
52554
- chunkIndex: c?.chunkIndex ?? md.chunkIndex
52555
- };
52556
- });
52822
+ var init_agentsStreamConversation = __esm(() => {
52823
+ init_encodings();
52824
+ init_primitives();
52825
+ init_schemas4();
52826
+ init_security2();
52827
+ init_url();
52828
+ init_agentops();
52829
+ init_async();
52830
+ });
52831
+
52832
+ // src/funcs/agentsStreamMessage.ts
52833
+ function agentsStreamMessage(client$, request, options) {
52834
+ return new APIPromise($do4(client$, request, options));
52557
52835
  }
52558
- async function* iterateSSE(response) {
52559
- if (!response.body)
52560
- return;
52561
- const reader = response.body.getReader();
52562
- const decoder = new TextDecoder("utf-8");
52563
- let buf = "";
52564
- let event = "message";
52565
- let dataLines = [];
52566
- const flush = () => {
52567
- if (dataLines.length === 0) {
52568
- event = "message";
52836
+ async function $do4(client$, request, options) {
52837
+ const parsed$ = safeParse4(request, (value$) => AgentAddMessageStreamRequest$zodSchema.parse(value$), "Input validation failed");
52838
+ if (!parsed$.ok) {
52839
+ return [parsed$, { status: "invalid" }];
52840
+ }
52841
+ const payload$ = parsed$.value;
52842
+ const body$ = encodeJSON("body", payload$.body, { explode: true });
52843
+ const pathParams$ = {
52844
+ agentKey: encodeSimple("agentKey", payload$.agentKey, {
52845
+ explode: false,
52846
+ charEncoding: "percent"
52847
+ }),
52848
+ conversationId: encodeSimple("conversationId", payload$.conversationId, {
52849
+ explode: false,
52850
+ charEncoding: "percent"
52851
+ })
52852
+ };
52853
+ const path$ = pathToFunc("/agents/{agentKey}/conversations/{conversationId}/messages/stream")(pathParams$);
52854
+ const headers$ = new Headers(compactMap({
52855
+ "Content-Type": "application/json",
52856
+ Accept: "text/event-stream"
52857
+ }));
52858
+ const securityInput = await extractSecurity(client$._options.security);
52859
+ const requestSecurity = resolveGlobalSecurity(securityInput);
52860
+ const context = {
52861
+ options: client$._options,
52862
+ baseURL: options?.serverURL ?? client$._baseURL ?? "",
52863
+ operationID: "streamAgentConversationMessage",
52864
+ oAuth2Scopes: ["agent:execute"],
52865
+ resolvedSecurity: requestSecurity,
52866
+ securitySource: client$._options.security,
52867
+ retryConfig: options?.retries || client$._options.retryConfig || { strategy: "none" },
52868
+ retryCodes: options?.retryCodes || [
52869
+ "429",
52870
+ "500",
52871
+ "502",
52872
+ "503",
52873
+ "504"
52874
+ ]
52875
+ };
52876
+ const requestRes = client$._createRequest(context, {
52877
+ security: requestSecurity,
52878
+ method: "POST",
52879
+ baseURL: options?.serverURL,
52880
+ path: path$,
52881
+ headers: headers$,
52882
+ body: body$,
52883
+ userAgent: client$._options.userAgent,
52884
+ timeoutMs: options?.timeoutMs || -1
52885
+ }, options);
52886
+ if (!requestRes.ok) {
52887
+ return [requestRes, { status: "invalid" }];
52888
+ }
52889
+ const req$ = requestRes.value;
52890
+ const doResult = await client$._do(req$, {
52891
+ context,
52892
+ errorCodes: [],
52893
+ retryConfig: context.retryConfig,
52894
+ retryCodes: context.retryCodes
52895
+ });
52896
+ if (!doResult.ok) {
52897
+ return [doResult, { status: "request-error", request: req$ }];
52898
+ }
52899
+ return [doResult, {
52900
+ status: "complete",
52901
+ request: req$,
52902
+ response: doResult.value
52903
+ }];
52904
+ }
52905
+ var init_agentsStreamMessage = __esm(() => {
52906
+ init_encodings();
52907
+ init_primitives();
52908
+ init_schemas4();
52909
+ init_security2();
52910
+ init_url();
52911
+ init_agentops();
52912
+ init_async();
52913
+ });
52914
+
52915
+ // src/funcs/agentsListAgents.ts
52916
+ function agentsListAgents(client$, request, options) {
52917
+ return new APIPromise($do5(client$, request, options));
52918
+ }
52919
+ async function $do5(client$, request, options) {
52920
+ const parsed$ = safeParse4(request, (value$) => ListAgentsRequest$zodSchema.optional().parse(value$), "Input validation failed");
52921
+ if (!parsed$.ok) {
52922
+ return [parsed$, { status: "invalid" }];
52923
+ }
52924
+ const payload$ = parsed$.value;
52925
+ const body$ = null;
52926
+ const path$ = pathToFunc("/agents")();
52927
+ const query$ = encodeFormQuery({
52928
+ page: payload$?.page,
52929
+ limit: payload$?.limit,
52930
+ search: payload$?.search,
52931
+ sort_by: payload$?.sortBy,
52932
+ sort_order: payload$?.sortOrder
52933
+ });
52934
+ const headers$ = new Headers(compactMap({
52935
+ Accept: "application/json"
52936
+ }));
52937
+ const securityInput = await extractSecurity(client$._options.security);
52938
+ const requestSecurity = resolveGlobalSecurity(securityInput);
52939
+ const context = {
52940
+ options: client$._options,
52941
+ baseURL: options?.serverURL ?? client$._baseURL ?? "",
52942
+ operationID: "listAgents",
52943
+ oAuth2Scopes: ["agent:read"],
52944
+ resolvedSecurity: requestSecurity,
52945
+ securitySource: client$._options.security,
52946
+ retryConfig: options?.retries || client$._options.retryConfig || { strategy: "none" },
52947
+ retryCodes: options?.retryCodes || [
52948
+ "429",
52949
+ "500",
52950
+ "502",
52951
+ "503",
52952
+ "504"
52953
+ ]
52954
+ };
52955
+ const requestRes = client$._createRequest(context, {
52956
+ security: requestSecurity,
52957
+ method: "GET",
52958
+ baseURL: options?.serverURL,
52959
+ path: path$,
52960
+ headers: headers$,
52961
+ query: query$,
52962
+ body: body$,
52963
+ userAgent: client$._options.userAgent,
52964
+ timeoutMs: options?.timeoutMs || client$._options.timeoutMs || -1
52965
+ }, options);
52966
+ if (!requestRes.ok) {
52967
+ return [requestRes, { status: "invalid" }];
52968
+ }
52969
+ const req$ = requestRes.value;
52970
+ const doResult = await client$._do(req$, {
52971
+ context,
52972
+ errorCodes: [],
52973
+ retryConfig: context.retryConfig,
52974
+ retryCodes: context.retryCodes
52975
+ });
52976
+ if (!doResult.ok) {
52977
+ return [doResult, { status: "request-error", request: req$ }];
52978
+ }
52979
+ return [doResult, {
52980
+ status: "complete",
52981
+ request: req$,
52982
+ response: doResult.value
52983
+ }];
52984
+ }
52985
+ var init_agentsListAgents = __esm(() => {
52986
+ init_encodings();
52987
+ init_primitives();
52988
+ init_schemas4();
52989
+ init_security2();
52990
+ init_url();
52991
+ init_agentops();
52992
+ init_async();
52993
+ });
52994
+
52995
+ // src/mcp-server/tools/_helpers.ts
52996
+ async function readJson(response) {
52997
+ const text = await response.text();
52998
+ if (!text) {
52999
+ return {
53000
+ ok: false,
53001
+ result: {
53002
+ content: [{ type: "text", text: "Empty response from server" }],
53003
+ isError: true
53004
+ }
53005
+ };
53006
+ }
53007
+ try {
53008
+ return { ok: true, value: JSON.parse(text) };
53009
+ } catch (e) {
53010
+ return {
53011
+ ok: false,
53012
+ result: {
53013
+ content: [{
53014
+ type: "text",
53015
+ text: `Failed to parse response as JSON: ${e.message}
53016
+
53017
+ Raw body:
53018
+ ${text.slice(0, 500)}`
53019
+ }],
53020
+ isError: true
53021
+ }
53022
+ };
53023
+ }
53024
+ }
53025
+ function jsonResult(value) {
53026
+ return {
53027
+ content: [{ type: "text", text: JSON.stringify(value, null, 2) }]
53028
+ };
53029
+ }
53030
+ function errorResult(message) {
53031
+ return {
53032
+ content: [{ type: "text", text: message }],
53033
+ isError: true
53034
+ };
53035
+ }
53036
+ async function httpErrorResult(response, context) {
53037
+ if (response.ok)
53038
+ return null;
53039
+ let body = "";
53040
+ try {
53041
+ body = await response.text();
53042
+ } catch {}
53043
+ let message = body;
53044
+ if (body) {
53045
+ try {
53046
+ const parsed = JSON.parse(body);
53047
+ const candidate = typeof parsed?.message === "string" && parsed.message || typeof parsed?.error === "string" && parsed.error || typeof parsed?.error?.message === "string" && parsed.error.message || typeof parsed?.detail === "string" && parsed.detail || "";
53048
+ message = candidate || body;
53049
+ } catch {}
53050
+ }
53051
+ const detail = message ? ` ${message.slice(0, 400)}` : "";
53052
+ const auth = response.status === 401 || response.status === 403 ? " Check that the bearer token / credentials are valid and not expired." : "";
53053
+ return errorResult(`${context} failed (HTTP ${response.status} ${response.statusText}).${detail}${auth}`);
53054
+ }
53055
+ async function readValidated(response, schema) {
53056
+ const text = await response.text();
53057
+ if (!text) {
53058
+ return { ok: false, result: errorResult("Empty response from server") };
53059
+ }
53060
+ let json;
53061
+ try {
53062
+ json = JSON.parse(text);
53063
+ } catch (e) {
53064
+ return {
53065
+ ok: false,
53066
+ result: errorResult(`Failed to parse response as JSON: ${e.message}` + `
53067
+
53068
+ Raw body:
53069
+ ${text.slice(0, 500)}`)
53070
+ };
53071
+ }
53072
+ const parsed = schema.safeParse(json);
53073
+ if (!parsed.success) {
53074
+ return {
53075
+ ok: false,
53076
+ result: errorResult(`Unexpected response shape:
53077
+ ${prettifyError(parsed.error)}`)
53078
+ };
53079
+ }
53080
+ return { ok: true, value: parsed.data };
53081
+ }
53082
+ async function resolveSecurity2(client) {
53083
+ const sec = client._options.security;
53084
+ if (typeof sec === "function") {
53085
+ return await sec();
53086
+ }
53087
+ return sec;
53088
+ }
53089
+ async function decodeBearer(client) {
53090
+ const sec = await resolveSecurity2(client);
53091
+ const token = sec?.bearerAuth;
53092
+ if (!token)
53093
+ return null;
53094
+ const parts = token.split(".");
53095
+ const claims = parts[1];
53096
+ if (!claims)
53097
+ return null;
53098
+ try {
53099
+ const padded = claims + "=".repeat((4 - claims.length % 4) % 4);
53100
+ const json = Buffer.from(padded.replace(/-/g, "+").replace(/_/g, "/"), "base64").toString("utf8");
53101
+ return JSON.parse(json);
53102
+ } catch {
53103
+ return null;
53104
+ }
53105
+ }
53106
+ function trimConversation(conv) {
53107
+ const messages = Array.isArray(conv?.messages) ? conv.messages : [];
53108
+ const lastBot = [...messages].reverse().find((m) => m?.messageType === "bot_response");
53109
+ return {
53110
+ conversationId: conv?._id,
53111
+ title: conv?.title,
53112
+ status: conv?.status,
53113
+ answer: lastBot?.content ?? null,
53114
+ confidence: lastBot?.confidence ?? null,
53115
+ citations: trimCitations(lastBot?.citations),
53116
+ followUpQuestions: lastBot?.followUpQuestions?.map((q) => typeof q === "string" ? q : q?.question).filter(Boolean) ?? [],
53117
+ messageCount: messages.length
53118
+ };
53119
+ }
53120
+ function trimCitations(citations) {
53121
+ if (!Array.isArray(citations))
53122
+ return [];
53123
+ return citations.map((c) => {
53124
+ const md = c?.metadata ?? {};
53125
+ return {
53126
+ recordId: md.recordId ?? c?.recordId,
53127
+ recordName: md.recordName ?? c?.recordName,
53128
+ snippet: typeof c?.content === "string" ? c.content.slice(0, 280) : md.blockText ?? null,
53129
+ mimeType: md.mimeType,
53130
+ webUrl: md.webUrl,
53131
+ pageNum: md.pageNum,
53132
+ chunkIndex: c?.chunkIndex ?? md.chunkIndex
53133
+ };
53134
+ });
53135
+ }
53136
+ async function* iterateSSE(response) {
53137
+ if (!response.body)
53138
+ return;
53139
+ const reader = response.body.getReader();
53140
+ const decoder = new TextDecoder("utf-8");
53141
+ let buf = "";
53142
+ let event = "message";
53143
+ let dataLines = [];
53144
+ const flush = () => {
53145
+ if (dataLines.length === 0) {
53146
+ event = "message";
52569
53147
  return null;
52570
53148
  }
52571
53149
  const raw = dataLines.join(`
@@ -52639,6 +53217,63 @@ async function* iterateSSE(response) {
52639
53217
  } catch {}
52640
53218
  }
52641
53219
  }
53220
+ function trimAgent(a) {
53221
+ return {
53222
+ agentId: a._key,
53223
+ name: a.name,
53224
+ description: a.description ?? null,
53225
+ systemPrompt: a.systemPrompt ?? null,
53226
+ startMessage: a.startMessage ?? null,
53227
+ tags: a.tags,
53228
+ webSearch: !!a.webSearch,
53229
+ isActive: a.isActive,
53230
+ toolsets: a.toolsets.map((ts) => ({
53231
+ name: ts.name,
53232
+ tools: ts.tools.map((t) => t.fullName ?? t.name).filter((id) => typeof id === "string")
53233
+ })),
53234
+ knowledge: a.knowledge.map((k) => ({
53235
+ name: k.name ?? k.displayName,
53236
+ type: k.type
53237
+ }))
53238
+ };
53239
+ }
53240
+ async function listAllAgents(client, opts = {}) {
53241
+ const PAGE_SIZE = 200;
53242
+ const maxPages = opts.maxPages ?? 25;
53243
+ const reqOptions = opts.signal ? { fetchOptions: { signal: opts.signal } } : {};
53244
+ const all = [];
53245
+ let total = 0;
53246
+ for (let page = 1;page <= maxPages; page++) {
53247
+ const [r] = await agentsListAgents(client, {
53248
+ page,
53249
+ limit: PAGE_SIZE,
53250
+ search: opts.search
53251
+ }, reqOptions).$inspect();
53252
+ if (!r.ok)
53253
+ return { ok: false, result: errorResult(r.error.message) };
53254
+ const httpErr = await httpErrorResult(r.value, "Agent list request");
53255
+ if (httpErr)
53256
+ return { ok: false, result: httpErr };
53257
+ const parsed = await readValidated(r.value, AgentListEnvelope$zodSchema);
53258
+ if (!parsed.ok)
53259
+ return { ok: false, result: parsed.result };
53260
+ if (parsed.value.success === false) {
53261
+ return {
53262
+ ok: false,
53263
+ result: errorResult("Agent list request returned success: false")
53264
+ };
53265
+ }
53266
+ const agents = parsed.value.agents;
53267
+ all.push(...agents);
53268
+ const pg = parsed.value.pagination;
53269
+ total = pg?.totalItems ?? pg?.total ?? all.length;
53270
+ const hasNext = pg?.hasNext ?? pg?.hasNextPage ?? agents.length >= PAGE_SIZE;
53271
+ if (!hasNext || agents.length === 0) {
53272
+ return { ok: true, agents: all, total, truncated: false };
53273
+ }
53274
+ }
53275
+ return { ok: true, agents: all, total: total || all.length, truncated: true };
53276
+ }
52642
53277
  function trimSearchHit(hit) {
52643
53278
  const md = hit?.metadata ?? {};
52644
53279
  return {
@@ -52653,6 +53288,11 @@ function trimSearchHit(hit) {
52653
53288
  pageNum: md.pageNum
52654
53289
  };
52655
53290
  }
53291
+ var init__helpers = __esm(() => {
53292
+ init_zod();
53293
+ init_agentsListAgents();
53294
+ init_agentops();
53295
+ });
52656
53296
 
52657
53297
  // src/mcp-server/tools/pipeshubChat.ts
52658
53298
  var FiltersShape, args, tool$pipeshubChat;
@@ -52660,6 +53300,9 @@ var init_pipeshubChat = __esm(() => {
52660
53300
  init_zod();
52661
53301
  init_conversationsStreamConversation();
52662
53302
  init_conversationsStreamMessage();
53303
+ init_agentsStreamConversation();
53304
+ init_agentsStreamMessage();
53305
+ init__helpers();
52663
53306
  FiltersShape = object({
52664
53307
  apps: array(string2()).optional().describe("Source-scoping ids. Mix connector instance UUIDs with the synthetic " + "`knowledgeBase_<orgId>` id (use pipeshub_sources to discover them). " + "Empty / omitted means no app-side restriction."),
52665
53308
  kb: array(string2()).optional().describe("Legacy / unused. Leave empty.")
@@ -52671,7 +53314,16 @@ var init_pipeshubChat = __esm(() => {
52671
53314
  modelKey: string2().optional().describe("Model id to use (from `pipeshub_sources` `models[*].modelKey`). " + "Defaults to the org's default LLM."),
52672
53315
  modelName: string2().optional(),
52673
53316
  modelFriendlyName: string2().optional(),
52674
- chatMode: _enum(["web_search", "internal_search"]).optional().describe("Controls retrieval source. " + "`internal_search` (default) searches the org's indexed knowledge " + "bases (Drive, Confluence, Slack, Gmail, Jira, Box, etc.) and returns " + "citations. Use this for questions about internal docs, policies, or " + "company data. " + "`web_search` searches the public web instead of internal sources. " + "Use only when the user explicitly asks about current events, public " + "information, or anything not expected to be in the org's KB. " + "Omit this field (or pass `internal_search`) for all normal queries.")
53317
+ agentId: string2().optional().describe("Optional PipesHub agent to converse with — the `agentId` from " + "`pipeshub_agents`. When set, this turn runs against that agent's " + "configuration (prompt, tools, knowledge). On follow-up turns pass the " + "SAME `agentId` together with the `conversationId` returned by the " + "previous call. Omit for a plain (non-agent) conversation. If unsure " + "which agent to use, call `pipeshub_agents` first to see the options."),
53318
+ chatMode: _enum([
53319
+ "internal_search",
53320
+ "web_search",
53321
+ "auto",
53322
+ "quick",
53323
+ "verification",
53324
+ "deep"
53325
+ ]).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): `auto` (let the agent decide; default), " + "`quick`, `verification`, or `deep`.")
52675
53327
  };
52676
53328
  tool$pipeshubChat = {
52677
53329
  name: "pipeshub_chat",
@@ -52682,6 +53334,9 @@ the user asks about their documents, files, knowledge base, company policies,
52682
53334
  or anything that could plausibly be answered by content in their PipesHub-indexed
52683
53335
  sources (Drive, Box, Confluence, Slack, Gmail, Jira, the org's KB, ...).
52684
53336
  Grounds the answer in the user's actual data and returns citations.
53337
+ Answers come from a few retrieved passages, not whole documents — for
53338
+ any task needing a document's full content, use
53339
+ \`pipeshub_get_record_content\` instead.
52685
53340
 
52686
53341
  **Web search** (\`chatMode: "web_search"\`): Use when the user asks about
52687
53342
  current events, public information, or anything unlikely to be in the org's
@@ -52689,8 +53344,11 @@ internal knowledge base. Pass \`chatMode: "web_search"\` and this tool will
52689
53344
  search the public web instead.
52690
53345
 
52691
53346
  **When to pick this over other tools:**
52692
- - "What does <document> say about X?" \`pipeshub_chat\` (internal_search)
52693
- - "Summarize <topic / doc>." \`pipeshub_chat\` (internal_search)
53347
+ - "Summarize <doc>" / "key points of <doc>" / "what does <document> say
53348
+ about X?" NOT this tool. Use \`pipeshub_search\`
53349
+ \`pipeshub_get_record_content\`: answering for a specific document
53350
+ requires its full content, and chat only sees a few retrieved
53351
+ passages, never the whole document.
52694
53352
  - "What's our policy on Y?" → \`pipeshub_chat\` (internal_search)
52695
53353
  - "What's in the news about Z?" → \`pipeshub_chat\` (web_search)
52696
53354
  - "What is the latest version of <library>?" → \`pipeshub_chat\` (web_search)
@@ -52724,7 +53382,40 @@ cited document, take \`citations[*].recordId\` and call
52724
53382
  tool: async (client, args2, ctx) => {
52725
53383
  const fetchOptions = { signal: ctx.signal };
52726
53384
  let response;
52727
- if (args2.conversationId) {
53385
+ if (args2.agentId) {
53386
+ const agentChatMode = args2.chatMode ?? "auto";
53387
+ if (args2.conversationId) {
53388
+ const [result] = await agentsStreamMessage(client, {
53389
+ agentKey: args2.agentId,
53390
+ conversationId: args2.conversationId,
53391
+ body: {
53392
+ query: args2.query,
53393
+ modelKey: args2.modelKey,
53394
+ modelName: args2.modelName,
53395
+ modelFriendlyName: args2.modelFriendlyName,
53396
+ chatMode: agentChatMode
53397
+ }
53398
+ }, { fetchOptions }).$inspect();
53399
+ if (!result.ok)
53400
+ return errorResult(result.error.message);
53401
+ response = result.value;
53402
+ } else {
53403
+ const [result] = await agentsStreamConversation(client, {
53404
+ agentKey: args2.agentId,
53405
+ body: {
53406
+ query: args2.query,
53407
+ filters: args2.filters,
53408
+ modelKey: args2.modelKey,
53409
+ modelName: args2.modelName,
53410
+ modelFriendlyName: args2.modelFriendlyName,
53411
+ chatMode: agentChatMode
53412
+ }
53413
+ }, { fetchOptions }).$inspect();
53414
+ if (!result.ok)
53415
+ return errorResult(result.error.message);
53416
+ response = result.value;
53417
+ }
53418
+ } else if (args2.conversationId) {
52728
53419
  const [result] = await conversationsStreamMessage(client, {
52729
53420
  conversationId: args2.conversationId,
52730
53421
  body: {
@@ -52732,7 +53423,7 @@ cited document, take \`citations[*].recordId\` and call
52732
53423
  modelKey: args2.modelKey,
52733
53424
  modelName: args2.modelName,
52734
53425
  modelFriendlyName: args2.modelFriendlyName,
52735
- chatMode: args2.chatMode
53426
+ chatMode: args2.chatMode ?? "internal_search"
52736
53427
  }
52737
53428
  }, { fetchOptions }).$inspect();
52738
53429
  if (!result.ok)
@@ -52745,12 +53436,15 @@ cited document, take \`citations[*].recordId\` and call
52745
53436
  modelKey: args2.modelKey,
52746
53437
  modelName: args2.modelName,
52747
53438
  modelFriendlyName: args2.modelFriendlyName,
52748
- chatMode: args2.chatMode
53439
+ chatMode: args2.chatMode ?? "internal_search"
52749
53440
  }, { fetchOptions }).$inspect();
52750
53441
  if (!result.ok)
52751
53442
  return errorResult(result.error.message);
52752
53443
  response = result.value;
52753
53444
  }
53445
+ const httpErr = await httpErrorResult(response, "PipesHub chat request");
53446
+ if (httpErr)
53447
+ return httpErr;
52754
53448
  let finalConversation = null;
52755
53449
  let recordsUsed;
52756
53450
  let lastAccumulated = null;
@@ -52874,9 +53568,9 @@ knowledge base, department, module, or record type. See
52874
53568
 
52875
53569
  // src/funcs/semanticSearchSearch.ts
52876
53570
  function semanticSearchSearch(client$, request, options) {
52877
- return new APIPromise($do3(client$, request, options));
53571
+ return new APIPromise($do6(client$, request, options));
52878
53572
  }
52879
- async function $do3(client$, request, options) {
53573
+ async function $do6(client$, request, options) {
52880
53574
  const parsed$ = safeParse4(request, (value$) => SemanticSearchRequest$zodSchema.parse(value$), "Input validation failed");
52881
53575
  if (!parsed$.ok) {
52882
53576
  return [parsed$, { status: "invalid" }];
@@ -52950,6 +53644,7 @@ var args2, tool$pipeshubSearch;
52950
53644
  var init_pipeshubSearch = __esm(() => {
52951
53645
  init_zod();
52952
53646
  init_semanticSearchSearch();
53647
+ init__helpers();
52953
53648
  args2 = {
52954
53649
  query: string2().min(1).describe("Natural language query. Vector search across the org's indexed records."),
52955
53650
  limit: number2().int().min(1).max(100).optional().describe("Max number of result chunks. Default 10. Use a small value (5–10) " + "when the goal is to resolve a filename / topic into a recordId."),
@@ -52959,12 +53654,16 @@ var init_pipeshubSearch = __esm(() => {
52959
53654
  name: "pipeshub_search",
52960
53655
  description: `Vector / semantic search across the org's indexed documents.
52961
53656
 
52962
- **Use this only when the user wants to LOCATE a document** — by name,
52963
- topic, or a phrase to grep for. For "what does the document say about
52964
- X?" or any open-ended question, use \`pipeshub_chat\` instead, which
52965
- does the retrieval internally and grounds the answer in citations.
53657
+ **Use this when the user wants to LOCATE a document** — by name, topic,
53658
+ or a phrase to grep for and to resolve it to a \`recordId\`. For
53659
+ open-ended questions across many documents, use \`pipeshub_chat\`
53660
+ instead, which does the retrieval internally and grounds the answer in
53661
+ citations.
52966
53662
 
52967
53663
  Typical uses:
53664
+ - Resolve a doc name / topic into a \`recordId\` for
53665
+ \`pipeshub_get_record_content\` — step 1 of any full-document task
53666
+ (summarize, extract, review, "what does the doc say?").
52968
53667
  - Resolve a filename / phrase into a \`recordId\` for
52969
53668
  \`pipeshub_download_record\`.
52970
53669
  - Show the user a ranked list of matching files when they ask "find /
@@ -53054,9 +53753,9 @@ on this record's knowledge base.
53054
53753
 
53055
53754
  // src/funcs/recordsStreamRecordBuffer.ts
53056
53755
  function recordsStreamRecordBuffer(client$, request, options) {
53057
- return new APIPromise($do4(client$, request, options));
53756
+ return new APIPromise($do7(client$, request, options));
53058
53757
  }
53059
- async function $do4(client$, request, options) {
53758
+ async function $do7(client$, request, options) {
53060
53759
  const parsed$ = safeParse4(request, (value$) => StreamRecordBufferRequest$zodSchema.parse(value$), "Input validation failed");
53061
53760
  if (!parsed$.ok) {
53062
53761
  return [parsed$, { status: "invalid" }];
@@ -53140,6 +53839,7 @@ var init_pipeshubDownloadRecord = __esm(() => {
53140
53839
  init_zod();
53141
53840
  init_recordsStreamRecordBuffer();
53142
53841
  init_tools();
53842
+ init__helpers();
53143
53843
  args3 = {
53144
53844
  recordId: string2().min(1).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."),
53145
53845
  convertTo: string2().optional().describe("Optional server-side format conversion target (e.g. `pdf`). When " + "omitted, the original file bytes are returned.")
@@ -53179,6 +53879,154 @@ returned base64-encoded; text content is returned inline.`,
53179
53879
  };
53180
53880
  });
53181
53881
 
53882
+ // src/models/getrecordcontentop.ts
53883
+ var GetRecordContentRequest$zodSchema;
53884
+ var init_getrecordcontentop = __esm(() => {
53885
+ init_zod();
53886
+ GetRecordContentRequest$zodSchema = object({
53887
+ recordId: string2().describe("Record ID to fetch. Obtain it from a `pipeshub_search` result (`hits[*].recordId`) or a chat citation (`citations[*].recordId`).")
53888
+ });
53889
+ });
53890
+
53891
+ // src/funcs/connectorGetRecordContent.ts
53892
+ function connectorGetRecordContent(client$, request, options) {
53893
+ return new APIPromise($do8(client$, request, options));
53894
+ }
53895
+ async function $do8(client$, request, options) {
53896
+ const parsed$ = safeParse4(request, (value$) => GetRecordContentRequest$zodSchema.parse(value$), "Input validation failed");
53897
+ if (!parsed$.ok) {
53898
+ return [parsed$, { status: "invalid" }];
53899
+ }
53900
+ const payload$ = parsed$.value;
53901
+ const body$ = null;
53902
+ const pathParams$ = {
53903
+ recordId: encodeSimple("recordId", payload$.recordId, {
53904
+ explode: false,
53905
+ charEncoding: "percent"
53906
+ })
53907
+ };
53908
+ const path$ = pathToFunc("/connectors/record/{recordId}/content")(pathParams$);
53909
+ const headers$ = new Headers(compactMap({
53910
+ Accept: "application/json"
53911
+ }));
53912
+ const securityInput = await extractSecurity(client$._options.security);
53913
+ const requestSecurity = resolveGlobalSecurity(securityInput);
53914
+ const context = {
53915
+ options: client$._options,
53916
+ baseURL: options?.serverURL ?? client$._baseURL ?? "",
53917
+ operationID: "getRecordContent",
53918
+ oAuth2Scopes: ["connector:read"],
53919
+ resolvedSecurity: requestSecurity,
53920
+ securitySource: client$._options.security,
53921
+ retryConfig: options?.retries || client$._options.retryConfig || { strategy: "none" },
53922
+ retryCodes: options?.retryCodes || [
53923
+ "429",
53924
+ "500",
53925
+ "502",
53926
+ "503",
53927
+ "504"
53928
+ ]
53929
+ };
53930
+ const requestRes = client$._createRequest(context, {
53931
+ security: requestSecurity,
53932
+ method: "GET",
53933
+ baseURL: options?.serverURL,
53934
+ path: path$,
53935
+ headers: headers$,
53936
+ body: body$,
53937
+ userAgent: client$._options.userAgent,
53938
+ timeoutMs: options?.timeoutMs || client$._options.timeoutMs || -1
53939
+ }, options);
53940
+ if (!requestRes.ok) {
53941
+ return [requestRes, { status: "invalid" }];
53942
+ }
53943
+ const req$ = requestRes.value;
53944
+ const doResult = await client$._do(req$, {
53945
+ context,
53946
+ errorCodes: [],
53947
+ retryConfig: context.retryConfig,
53948
+ retryCodes: context.retryCodes
53949
+ });
53950
+ if (!doResult.ok) {
53951
+ return [doResult, { status: "request-error", request: req$ }];
53952
+ }
53953
+ return [doResult, {
53954
+ status: "complete",
53955
+ request: req$,
53956
+ response: doResult.value
53957
+ }];
53958
+ }
53959
+ var init_connectorGetRecordContent = __esm(() => {
53960
+ init_encodings();
53961
+ init_primitives();
53962
+ init_schemas4();
53963
+ init_security2();
53964
+ init_url();
53965
+ init_getrecordcontentop();
53966
+ init_async();
53967
+ });
53968
+
53969
+ // src/mcp-server/tools/pipeshubGetRecordContent.ts
53970
+ var args4, tool$pipeshubGetRecordContent;
53971
+ var init_pipeshubGetRecordContent = __esm(() => {
53972
+ init_zod();
53973
+ init_connectorGetRecordContent();
53974
+ init__helpers();
53975
+ args4 = {
53976
+ recordId: string2().min(1).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.")
53977
+ };
53978
+ tool$pipeshubGetRecordContent = {
53979
+ name: "pipeshub_get_record_content",
53980
+ description: `Read a record's full parsed content by \`recordId\` — the only way to
53981
+ see a document's COMPLETE text.
53982
+
53983
+ Use it whenever the answer depends on a document's full content — any
53984
+ task where missing a part could make the answer wrong: summarize / key
53985
+ points / action items; extract or list ALL of something; check whether
53986
+ or where the doc mentions X; translate, rewrite, outline, or review the
53987
+ doc; compare named docs (fetch each); any question scoped to one named
53988
+ document. \`pipeshub_chat\` cannot do these — it only sees a few
53989
+ retrieved passages, never the whole document. Get the \`recordId\` from
53990
+ a \`pipeshub_search\` top hit or a chat citation.
53991
+
53992
+ Judge by the user's INTENT, not their keywords: they need not say
53993
+ "summarize", "key points", or "extract". Reason about what a good
53994
+ answer requires — if it would need the whole document (e.g. "what's
53995
+ this doc about?", "walk me through the report", "anything in here
53996
+ about Y?"), that is a full-content task, so call this tool.
53997
+
53998
+ Returns a single \`content\` string: a short metadata header (title,
53999
+ source, key fields, and a pre-generated summary) followed by the
54000
+ record's full parsed text — paragraphs, tables, and lists in reading
54001
+ order. For a record with no extractable content, \`content\` is the
54002
+ literal \`No record found\`. Use \`pipeshub_download_record\` only when
54003
+ you need the original file bytes.`,
54004
+ scopes: ["read"],
54005
+ annotations: {
54006
+ title: "Get a record's full parsed content",
54007
+ destructiveHint: false,
54008
+ idempotentHint: true,
54009
+ openWorldHint: false,
54010
+ readOnlyHint: true
54011
+ },
54012
+ args: args4,
54013
+ tool: async (client, args5, ctx) => {
54014
+ const [result] = await connectorGetRecordContent(client, {
54015
+ recordId: args5.recordId
54016
+ }, { fetchOptions: { signal: ctx.signal } }).$inspect();
54017
+ if (!result.ok)
54018
+ return errorResult(result.error.message);
54019
+ const httpErr = await httpErrorResult(result.value, "Get record content");
54020
+ if (httpErr)
54021
+ return httpErr;
54022
+ const parsed = await readJson(result.value);
54023
+ if (!parsed.ok)
54024
+ return parsed.result;
54025
+ return { content: [{ type: "text", text: parsed.value.content ?? "" }] };
54026
+ }
54027
+ };
54028
+ });
54029
+
53182
54030
  // src/models/getallusersop.ts
53183
54031
  var GetAllUsersRequest$zodSchema;
53184
54032
  var init_getallusersop = __esm(() => {
@@ -53192,9 +54040,9 @@ var init_getallusersop = __esm(() => {
53192
54040
 
53193
54041
  // src/funcs/usersGetAllUsers.ts
53194
54042
  function usersGetAllUsers(client$, request, options) {
53195
- return new APIPromise($do5(client$, request, options));
54043
+ return new APIPromise($do9(client$, request, options));
53196
54044
  }
53197
- async function $do5(client$, request, options) {
54045
+ async function $do9(client$, request, options) {
53198
54046
  const parsed$ = safeParse4(request, (value$) => GetAllUsersRequest$zodSchema.optional().parse(value$), "Input validation failed");
53199
54047
  if (!parsed$.ok) {
53200
54048
  return [parsed$, { status: "invalid" }];
@@ -53279,9 +54127,9 @@ var init_getuserbyidop = __esm(() => {
53279
54127
 
53280
54128
  // src/funcs/usersGetUserById.ts
53281
54129
  function usersGetUserById(client$, request, options) {
53282
- return new APIPromise($do6(client$, request, options));
54130
+ return new APIPromise($do10(client$, request, options));
53283
54131
  }
53284
- async function $do6(client$, request, options) {
54132
+ async function $do10(client$, request, options) {
53285
54133
  const parsed$ = safeParse4(request, (value$) => GetUserByIdRequest$zodSchema.parse(value$), "Input validation failed");
53286
54134
  if (!parsed$.ok) {
53287
54135
  return [parsed$, { status: "invalid" }];
@@ -53368,9 +54216,9 @@ var init_getallusergroupsop = __esm(() => {
53368
54216
 
53369
54217
  // src/funcs/userGroupsGetAllUserGroups.ts
53370
54218
  function userGroupsGetAllUserGroups(client$, request, options) {
53371
- return new APIPromise($do7(client$, request, options));
54219
+ return new APIPromise($do11(client$, request, options));
53372
54220
  }
53373
- async function $do7(client$, request, options) {
54221
+ async function $do11(client$, request, options) {
53374
54222
  const parsed$ = safeParse4(request, (value$) => GetAllUserGroupsRequest$zodSchema.optional().parse(value$), "Input validation failed");
53375
54223
  if (!parsed$.ok) {
53376
54224
  return [parsed$, { status: "invalid" }];
@@ -53392,7 +54240,7 @@ async function $do7(client$, request, options) {
53392
54240
  options: client$._options,
53393
54241
  baseURL: options?.serverURL ?? client$._baseURL ?? "",
53394
54242
  operationID: "getAllUserGroups",
53395
- oAuth2Scopes: [],
54243
+ oAuth2Scopes: ["usergroup:read"],
53396
54244
  resolvedSecurity: requestSecurity,
53397
54245
  securitySource: client$._options.security,
53398
54246
  retryConfig: options?.retries || client$._options.retryConfig || { strategy: "none" },
@@ -53460,9 +54308,9 @@ var init_getuserteamsop = __esm(() => {
53460
54308
 
53461
54309
  // src/funcs/teamsGetUserTeams.ts
53462
54310
  function teamsGetUserTeams(client$, request, options) {
53463
- return new APIPromise($do8(client$, request, options));
54311
+ return new APIPromise($do12(client$, request, options));
53464
54312
  }
53465
- async function $do8(client$, request, options) {
54313
+ async function $do12(client$, request, options) {
53466
54314
  const parsed$ = safeParse4(request, (value$) => GetUserTeamsRequest$zodSchema.optional().parse(value$), "Input validation failed");
53467
54315
  if (!parsed$.ok) {
53468
54316
  return [parsed$, { status: "invalid" }];
@@ -53540,14 +54388,15 @@ var init_teamsGetUserTeams = __esm(() => {
53540
54388
  });
53541
54389
 
53542
54390
  // src/mcp-server/tools/pipeshubDirectory.ts
53543
- var args4, tool$pipeshubDirectory;
54391
+ var args5, tool$pipeshubDirectory;
53544
54392
  var init_pipeshubDirectory = __esm(() => {
53545
54393
  init_zod();
53546
54394
  init_usersGetAllUsers();
53547
54395
  init_usersGetUserById();
53548
54396
  init_userGroupsGetAllUserGroups();
53549
54397
  init_teamsGetUserTeams();
53550
- args4 = {
54398
+ init__helpers();
54399
+ args5 = {
53551
54400
  action: _enum([
53552
54401
  "whoami",
53553
54402
  "list_users",
@@ -53585,10 +54434,10 @@ Output shape varies by action; see each action's docs above.`,
53585
54434
  openWorldHint: false,
53586
54435
  readOnlyHint: true
53587
54436
  },
53588
- args: args4,
53589
- tool: async (client, args5, ctx) => {
54437
+ args: args5,
54438
+ tool: async (client, args6, ctx) => {
53590
54439
  const fetchOptions = { signal: ctx.signal };
53591
- switch (args5.action) {
54440
+ switch (args6.action) {
53592
54441
  case "whoami": {
53593
54442
  const claims = await decodeBearer(client);
53594
54443
  if (!claims) {
@@ -53605,9 +54454,9 @@ Output shape varies by action; see each action's docs above.`,
53605
54454
  }
53606
54455
  case "list_users": {
53607
54456
  const [result] = await usersGetAllUsers(client, {
53608
- page: args5.page,
53609
- limit: args5.limit,
53610
- search: args5.search
54457
+ page: args6.page,
54458
+ limit: args6.limit,
54459
+ search: args6.search
53611
54460
  }, { fetchOptions }).$inspect();
53612
54461
  if (!result.ok)
53613
54462
  return errorResult(result.error.message);
@@ -53617,11 +54466,11 @@ Output shape varies by action; see each action's docs above.`,
53617
54466
  return jsonResult(parsed.value);
53618
54467
  }
53619
54468
  case "get_user": {
53620
- if (!args5.userId) {
54469
+ if (!args6.userId) {
53621
54470
  return errorResult("`userId` is required when `action` is `get_user`. " + "Use `whoami` to find your own id, or `list_users` " + "to look up by name / email.");
53622
54471
  }
53623
54472
  const [result] = await usersGetUserById(client, {
53624
- id: args5.userId
54473
+ id: args6.userId
53625
54474
  }, { fetchOptions }).$inspect();
53626
54475
  if (!result.ok)
53627
54476
  return errorResult(result.error.message);
@@ -53632,9 +54481,9 @@ Output shape varies by action; see each action's docs above.`,
53632
54481
  }
53633
54482
  case "list_groups": {
53634
54483
  const [result] = await userGroupsGetAllUserGroups(client, {
53635
- page: args5.page,
53636
- limit: args5.limit,
53637
- search: args5.search
54484
+ page: args6.page,
54485
+ limit: args6.limit,
54486
+ search: args6.search
53638
54487
  }, { fetchOptions }).$inspect();
53639
54488
  if (!result.ok)
53640
54489
  return errorResult(result.error.message);
@@ -53645,9 +54494,9 @@ Output shape varies by action; see each action's docs above.`,
53645
54494
  }
53646
54495
  case "list_my_teams": {
53647
54496
  const [result] = await teamsGetUserTeams(client, {
53648
- page: args5.page,
53649
- limit: args5.limit,
53650
- search: args5.search
54497
+ page: args6.page,
54498
+ limit: args6.limit,
54499
+ search: args6.search
53651
54500
  }, { fetchOptions }).$inspect();
53652
54501
  if (!result.ok)
53653
54502
  return errorResult(result.error.message);
@@ -53691,9 +54540,9 @@ var init_getknowledgehubrootnodesop = __esm(() => {
53691
54540
 
53692
54541
  // src/funcs/knowledgeHubGetKnowledgeHubRootNodes.ts
53693
54542
  function knowledgeHubGetKnowledgeHubRootNodes(client$, request, options) {
53694
- return new APIPromise($do9(client$, request, options));
54543
+ return new APIPromise($do13(client$, request, options));
53695
54544
  }
53696
- async function $do9(client$, request, options) {
54545
+ async function $do13(client$, request, options) {
53697
54546
  const parsed$ = safeParse4(request, (value$) => GetKnowledgeHubRootNodesRequest$zodSchema.optional().parse(value$), "Input validation failed");
53698
54547
  if (!parsed$.ok) {
53699
54548
  return [parsed$, { status: "invalid" }];
@@ -53809,9 +54658,9 @@ var init_getavailablemodelsbytypeop = __esm(() => {
53809
54658
 
53810
54659
  // src/funcs/aiModelsProvidersGetAvailableModelsByType.ts
53811
54660
  function aiModelsProvidersGetAvailableModelsByType(client$, request, options) {
53812
- return new APIPromise($do10(client$, request, options));
54661
+ return new APIPromise($do14(client$, request, options));
53813
54662
  }
53814
- async function $do10(client$, request, options) {
54663
+ async function $do14(client$, request, options) {
53815
54664
  const parsed$ = safeParse4(request, (value$) => GetAvailableModelsByTypeRequest$zodSchema.parse(value$), "Input validation failed");
53816
54665
  if (!parsed$.ok) {
53817
54666
  return [parsed$, { status: "invalid" }];
@@ -53886,12 +54735,13 @@ var init_aiModelsProvidersGetAvailableModelsByType = __esm(() => {
53886
54735
  });
53887
54736
 
53888
54737
  // src/mcp-server/tools/pipeshubSources.ts
53889
- var args5, tool$pipeshubSources;
54738
+ var args6, tool$pipeshubSources;
53890
54739
  var init_pipeshubSources = __esm(() => {
53891
54740
  init_zod();
53892
54741
  init_knowledgeHubGetKnowledgeHubRootNodes();
53893
54742
  init_aiModelsProvidersGetAvailableModelsByType();
53894
- args5 = {
54743
+ init__helpers();
54744
+ args6 = {
53895
54745
  include: array(_enum(["sources", "llmModels", "embeddingModels"])).optional().describe('Which sections to fetch. Default: `["sources", "llmModels"]`. ' + "Add `embeddingModels` if the user is configuring re-embedding.")
53896
54746
  };
53897
54747
  tool$pipeshubSources = {
@@ -53922,10 +54772,10 @@ are returned by default; pass \`include\` to override.`,
53922
54772
  openWorldHint: false,
53923
54773
  readOnlyHint: true
53924
54774
  },
53925
- args: args5,
53926
- tool: async (client, args6, ctx) => {
54775
+ args: args6,
54776
+ tool: async (client, args7, ctx) => {
53927
54777
  const fetchOptions = { signal: ctx.signal };
53928
- const include = args6.include ?? ["sources", "llmModels"];
54778
+ const include = args7.include ?? ["sources", "llmModels"];
53929
54779
  const want = (s) => include.includes(s);
53930
54780
  const result = {};
53931
54781
  if (want("sources")) {
@@ -53974,6 +54824,99 @@ are returned by default; pass \`include\` to override.`,
53974
54824
  };
53975
54825
  });
53976
54826
 
54827
+ // src/mcp-server/tools/pipeshubAgents.ts
54828
+ var args7, tool$pipeshubAgents;
54829
+ var init_pipeshubAgents = __esm(() => {
54830
+ init_zod();
54831
+ init__helpers();
54832
+ args7 = {
54833
+ search: string2().optional().describe("Optional case-insensitive substring match across agent name, " + "description, and tags. Omit to return every agent.")
54834
+ };
54835
+ tool$pipeshubAgents = {
54836
+ name: "pipeshub_agents",
54837
+ description: `List the PipesHub **agents** configured for this org, each with its
54838
+ capabilities.
54839
+
54840
+ Agents are specialized assistants (custom system prompt, tools, knowledge
54841
+ scope). To converse with one, take its \`agentId\` and pass it to
54842
+ \`pipeshub_chat\`'s \`agentId\` argument.
54843
+
54844
+ Each agent is returned as:
54845
+ \`{ agentId, name, description, systemPrompt, startMessage, tags, webSearch,
54846
+ isActive, toolsets, knowledge }\`.
54847
+ - \`toolsets\` — what the agent can DO: each \`{ name, tools }\` where \`name\`
54848
+ is the connector (e.g. \`jira\`, \`gmail\`) and \`tools\` are the runnable
54849
+ tool ids (e.g. \`jira.create_issue\`, \`gmail.send_email\`).
54850
+ - \`knowledge\` — what the agent can READ: each \`{ name, type }\` (e.g.
54851
+ \`Confluence-2\` / \`Confluence\`).
54852
+
54853
+ **Route on \`toolsets\`/\`knowledge\`, not the name** — names and descriptions
54854
+ are often generic or misleading. Match the request to the agent whose tools can
54855
+ actually perform it (e.g. "create a Jira ticket" → the agent whose toolset is
54856
+ \`jira\` and whose tools include \`jira.create_issue\`). If NO agent has a tool
54857
+ for the requested action, say so — don't force an unrelated agent.
54858
+
54859
+ The list **may be empty** (no agents configured). For plain Q&A when no
54860
+ specific agent is needed, use \`pipeshub_chat\` WITHOUT \`agentId\` and pick a
54861
+ \`chatMode\`: \`internal_search\` (org's indexed knowledge) or \`web_search\`
54862
+ (live web). Use \`agentId\` everywhere an agent is referenced.`,
54863
+ scopes: ["read"],
54864
+ annotations: {
54865
+ title: "List PipesHub agents (with toolsets & knowledge)",
54866
+ destructiveHint: false,
54867
+ idempotentHint: true,
54868
+ openWorldHint: false,
54869
+ readOnlyHint: true
54870
+ },
54871
+ args: args7,
54872
+ tool: async (client, args8, ctx) => {
54873
+ const all = await listAllAgents(client, {
54874
+ search: args8.search,
54875
+ signal: ctx.signal
54876
+ });
54877
+ if (!all.ok)
54878
+ return all.result;
54879
+ return jsonResult({
54880
+ agents: all.agents.map(trimAgent),
54881
+ total: all.total,
54882
+ ...all.truncated ? { truncated: true } : {}
54883
+ });
54884
+ }
54885
+ };
54886
+ });
54887
+
54888
+ // src/mcp-server/prompts/pipeshubAssistant.ts
54889
+ var args8, prompt$pipeshubAssistant;
54890
+ var init_pipeshubAssistant = __esm(() => {
54891
+ init_zod();
54892
+ args8 = {
54893
+ query: string2().optional().describe("Optional. The user's request to route. Provide it to have the guidance " + "applied to a concrete request; omit it to just load the routing " + "guidance as a seed system prompt at the start of a session.")
54894
+ };
54895
+ prompt$pipeshubAssistant = {
54896
+ name: "pipeshub-assistant",
54897
+ description: "Load PipesHub tool-routing guidance so the assistant picks the correct " + "tool (pipeshub_chat / search / agents / directory) and lists agents " + "with pipeshub_agents when unsure which route fits the query.",
54898
+ scopes: ["read"],
54899
+ args: args8,
54900
+ prompt: (_client, args9, _extra) => {
54901
+ const text = args9.query ? `${PIPESHUB_INSTRUCTIONS}
54902
+
54903
+ ---
54904
+
54905
+ Follow the routing rules above to ` + `handle this request, picking the right tool (and listing agents via ` + `\`pipeshub_agents\` if unsure which route fits):
54906
+
54907
+ ${args9.query}` : PIPESHUB_INSTRUCTIONS;
54908
+ return {
54909
+ messages: [
54910
+ {
54911
+ role: "user",
54912
+ content: { type: "text", text }
54913
+ }
54914
+ ]
54915
+ };
54916
+ }
54917
+ };
54918
+ });
54919
+
53977
54920
  // src/mcp-server/server.ts
53978
54921
  function createMCPServer(deps) {
53979
54922
  const server = new McpServer({
@@ -53982,17 +54925,21 @@ function createMCPServer(deps) {
53982
54925
  }, {
53983
54926
  instructions: PIPESHUB_INSTRUCTIONS
53984
54927
  });
53985
- const getClient = deps.getSDK || (() => new PipeshubCore({
54928
+ const resolveClient = deps.getSDK || (() => new PipeshubCore({
53986
54929
  security: deps.security,
53987
54930
  serverURL: deps.serverURL,
53988
54931
  serverIdx: deps.serverIdx,
53989
54932
  instance_url: deps.instance_url,
53990
54933
  debugLogger: deps.logger.level === "debug" ? {
53991
- log: (...args6) => console.log(...args6),
53992
- group: (...args6) => console.group(...args6),
53993
- groupEnd: (...args6) => console.groupEnd(...args6)
54934
+ log: (...args9) => console.log(...args9),
54935
+ group: (...args9) => console.group(...args9),
54936
+ groupEnd: (...args9) => console.groupEnd(...args9)
53994
54937
  } : undefined
53995
54938
  }));
54939
+ const getClient = () => {
54940
+ bindNewRequestId();
54941
+ return resolveClient();
54942
+ };
53996
54943
  const scopes = new Set(deps.scopes);
53997
54944
  const allowedTools = deps.allowedTools && new Set(deps.allowedTools);
53998
54945
  const [tool, tools, toolMap] = createRegisterTool(deps.logger, server, getClient, scopes, allowedTools, deps.dynamic);
@@ -54004,74 +54951,29 @@ function createMCPServer(deps) {
54004
54951
  tool(tool$pipeshubChat);
54005
54952
  tool(tool$pipeshubSearch);
54006
54953
  tool(tool$pipeshubDownloadRecord);
54954
+ tool(tool$pipeshubGetRecordContent);
54007
54955
  tool(tool$pipeshubDirectory);
54956
+ tool(tool$pipeshubAgents);
54957
+ prompt(prompt$pipeshubAssistant);
54008
54958
  if (deps.dynamic) {
54009
54959
  registerDynamicTools(deps.logger, server, getClient, toolMap, scopes);
54010
54960
  }
54011
54961
  return { server, tools };
54012
54962
  }
54013
- var PIPESHUB_INSTRUCTIONS = `# PipesHub MCP — instructions for the LLM
54014
-
54015
- PipesHub is the user's workplace AI platform. It indexes their documents,
54016
- knowledge base content, and connector sources (Drive, Box, Confluence,
54017
- Slack, Jira, Gmail, ...). When in doubt, the answer is in PipesHub.
54018
-
54019
- ## Default tool: \`pipeshub_chat\`
54020
-
54021
- **Use \`pipeshub_chat\` for any question that could plausibly be answered
54022
- by the user's PipesHub-indexed data.** That includes:
54023
-
54024
- - Anything about a specific document, file, report, ticket, message, or
54025
- page (e.g. "what's in the Q4 sales report?", "summarize the langchain
54026
- doc", "what did Aashil say about onboarding?").
54027
- - Anything about company / org policies, processes, decisions, or
54028
- history (e.g. "what's our vacation policy?", "who owns the auth
54029
- service?").
54030
- - Anything explicitly mentioning PipesHub itself, or its sources
54031
- (Drive / Box / Confluence / Slack / Gmail / Jira / etc.) when the
54032
- user has those connected.
54033
- - Open-ended "what do we know about X" questions where the answer
54034
- likely lives in the org's documents.
54035
-
54036
- Do NOT answer those from your own knowledge — \`pipeshub_chat\` grounds
54037
- the answer in the user's actual indexed content and returns citations
54038
- the user can verify.
54039
-
54040
- ## When to use the other tools
54041
-
54042
- - \`pipeshub_search\` — only when the user asks specifically to **find /
54043
- locate** a document by name or topic (so you can hand them a list, or
54044
- resolve a filename to a \`recordId\` for download). For "what does
54045
- the doc say?" use \`pipeshub_chat\` instead — it does the retrieval
54046
- internally.
54047
- - \`pipeshub_download_record\` — when the user wants the actual file
54048
- bytes (download, attach, open). Get the \`recordId\` either from
54049
- citations on a prior \`pipeshub_chat\` response or from
54050
- \`pipeshub_search\`.
54051
- - \`pipeshub_directory\` — people, groups, teams, and \`whoami\` lookups.
54052
- Not for documents.
54053
- - \`pipeshub_sources\` — call once at the start of a session to discover
54054
- which connectors / KB / models are available, then cache the result.
54055
-
54056
- ## Conversation lifecycle
54057
-
54058
- \`pipeshub_chat\` is a single tool that handles both starting and
54059
- continuing conversations. On the first turn omit \`conversationId\`; on
54060
- every subsequent turn pass back the \`conversationId\` returned by the
54061
- previous call. Server-side context is preserved — do NOT replay prior
54062
- messages. Only start a fresh conversation when the user explicitly
54063
- asks to clear context.
54064
- `;
54065
54963
  var init_server2 = __esm(() => {
54066
54964
  init_mcp();
54067
54965
  init_core3();
54966
+ init_request_context();
54068
54967
  init_resources();
54069
54968
  init_tools();
54070
54969
  init_pipeshubChat();
54071
54970
  init_pipeshubSearch();
54072
54971
  init_pipeshubDownloadRecord();
54972
+ init_pipeshubGetRecordContent();
54073
54973
  init_pipeshubDirectory();
54074
54974
  init_pipeshubSources();
54975
+ init_pipeshubAgents();
54976
+ init_pipeshubAssistant();
54075
54977
  });
54076
54978
 
54077
54979
  // src/tool-names.ts
@@ -54091,6 +54993,9 @@ the user asks about their documents, files, knowledge base, company policies,
54091
54993
  or anything that could plausibly be answered by content in their PipesHub-indexed
54092
54994
  sources (Drive, Box, Confluence, Slack, Gmail, Jira, the org's KB, ...).
54093
54995
  Grounds the answer in the user's actual data and returns citations.
54996
+ Answers come from a few retrieved passages, not whole documents — for
54997
+ any task needing a document's full content, use
54998
+ \`pipeshub_get_record_content\` instead.
54094
54999
 
54095
55000
  **Web search** (\`chatMode: "web_search"\`): Use when the user asks about
54096
55001
  current events, public information, or anything unlikely to be in the org's
@@ -54098,8 +55003,11 @@ internal knowledge base. Pass \`chatMode: "web_search"\` and this tool will
54098
55003
  search the public web instead.
54099
55004
 
54100
55005
  **When to pick this over other tools:**
54101
- - "What does <document> say about X?" \`pipeshub_chat\` (internal_search)
54102
- - "Summarize <topic / doc>." \`pipeshub_chat\` (internal_search)
55006
+ - "Summarize <doc>" / "key points of <doc>" / "what does <document> say
55007
+ about X?" NOT this tool. Use \`pipeshub_search\`
55008
+ \`pipeshub_get_record_content\`: answering for a specific document
55009
+ requires its full content, and chat only sees a few retrieved
55010
+ passages, never the whole document.
54103
55011
  - "What's our policy on Y?" → \`pipeshub_chat\` (internal_search)
54104
55012
  - "What's in the news about Z?" → \`pipeshub_chat\` (web_search)
54105
55013
  - "What is the latest version of <library>?" → \`pipeshub_chat\` (web_search)
@@ -54126,12 +55034,16 @@ cited document, take \`citations[*].recordId\` and call
54126
55034
  name: "pipeshub_search",
54127
55035
  description: `Vector / semantic search across the org's indexed documents.
54128
55036
 
54129
- **Use this only when the user wants to LOCATE a document** — by name,
54130
- topic, or a phrase to grep for. For "what does the document say about
54131
- X?" or any open-ended question, use \`pipeshub_chat\` instead, which
54132
- does the retrieval internally and grounds the answer in citations.
55037
+ **Use this when the user wants to LOCATE a document** — by name, topic,
55038
+ or a phrase to grep for and to resolve it to a \`recordId\`. For
55039
+ open-ended questions across many documents, use \`pipeshub_chat\`
55040
+ instead, which does the retrieval internally and grounds the answer in
55041
+ citations.
54133
55042
 
54134
55043
  Typical uses:
55044
+ - Resolve a doc name / topic into a \`recordId\` for
55045
+ \`pipeshub_get_record_content\` — step 1 of any full-document task
55046
+ (summarize, extract, review, "what does the doc say?").
54135
55047
  - Resolve a filename / phrase into a \`recordId\` for
54136
55048
  \`pipeshub_download_record\`.
54137
55049
  - Show the user a ranked list of matching files when they ask "find /
@@ -54146,9 +55058,40 @@ Highest \`score\` first; multiple hits may share the same \`recordId\`
54146
55058
  name: "pipeshub_download_record",
54147
55059
  description: "Stream the binary content of a single record from PipesHub.\n\nTypical sources for the `recordId`:\n- A chat citation:\n `pipeshub_chat` response → `citations[*].recordId`.\n- A search result:\n `pipeshub_search` response → `hits[*].recordId` /\n `uniqueRecords[*].recordId`.\n\nResponse `Content-Type` is forwarded from the upstream service —\n`application/pdf`, `application/octet-stream`, etc. Binary content is\nreturned base64-encoded; text content is returned inline."
54148
55060
  },
55061
+ {
55062
+ name: "pipeshub_get_record_content",
55063
+ description: `Read a record's full parsed content by \`recordId\` — the only way to
55064
+ see a document's COMPLETE text.
55065
+
55066
+ Use it whenever the answer depends on a document's full content — any
55067
+ task where missing a part could make the answer wrong: summarize / key
55068
+ points / action items; extract or list ALL of something; check whether
55069
+ or where the doc mentions X; translate, rewrite, outline, or review the
55070
+ doc; compare named docs (fetch each); any question scoped to one named
55071
+ document. \`pipeshub_chat\` cannot do these — it only sees a few
55072
+ retrieved passages, never the whole document. Get the \`recordId\` from
55073
+ a \`pipeshub_search\` top hit or a chat citation.
55074
+
55075
+ Judge by the user's INTENT, not their keywords: they need not say
55076
+ "summarize", "key points", or "extract". Reason about what a good
55077
+ answer requires — if it would need the whole document (e.g. "what's
55078
+ this doc about?", "walk me through the report", "anything in here
55079
+ about Y?"), that is a full-content task, so call this tool.
55080
+
55081
+ Returns a single \`content\` string: a short metadata header (title,
55082
+ source, key fields, and a pre-generated summary) followed by the
55083
+ record's full parsed text — paragraphs, tables, and lists in reading
55084
+ order. For a record with no extractable content, \`content\` is the
55085
+ literal \`No record found\`. Use \`pipeshub_download_record\` only when
55086
+ you need the original file bytes.`
55087
+ },
54149
55088
  {
54150
55089
  name: "pipeshub_directory",
54151
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."
55091
+ },
55092
+ {
55093
+ name: "pipeshub_agents",
55094
+ description: 'List the PipesHub **agents** configured for this org, each with its\ncapabilities.\n\nAgents are specialized assistants (custom system prompt, tools, knowledge\nscope). To converse with one, take its `agentId` and pass it to\n`pipeshub_chat`\'s `agentId` argument.\n\nEach agent is returned as:\n`{ agentId, name, description, systemPrompt, startMessage, tags, webSearch,\nisActive, toolsets, knowledge }`.\n- `toolsets` — what the agent can DO: each `{ name, tools }` where `name`\n is the connector (e.g. `jira`, `gmail`) and `tools` are the runnable\n tool ids (e.g. `jira.create_issue`, `gmail.send_email`).\n- `knowledge` — what the agent can READ: each `{ name, type }` (e.g.\n `Confluence-2` / `Confluence`).\n\n**Route on `toolsets`/`knowledge`, not the name** — names and descriptions\nare often generic or misleading. Match the request to the agent whose tools can\nactually perform it (e.g. "create a Jira ticket" → the agent whose toolset is\n`jira` and whose tools include `jira.create_issue`). If NO agent has a tool\nfor the requested action, say so — don\'t force an unrelated agent.\n\nThe list **may be empty** (no agents configured). For plain Q&A when no\nspecific agent is needed, use `pipeshub_chat` WITHOUT `agentId` and pick a\n`chatMode`: `internal_search` (org\'s indexed knowledge) or `web_search`\n(live web). Use `agentId` everywhere an agent is referenced.'
54152
55095
  }
54153
55096
  ];
54154
55097
  });
@@ -57777,5 +58720,5 @@ export {
57777
58720
  app
57778
58721
  };
57779
58722
 
57780
- //# debugId=4F54178F9A67222964756E2164756E21
58723
+ //# debugId=59975E6F38134B6C64756E2164756E21
57781
58724
  //# sourceMappingURL=mcp-server.js.map