@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
@@ -0,0 +1,10 @@
1
+ export interface RequestContextStore {
2
+ random: string;
3
+ finalId?: string;
4
+ }
5
+ /** Bind a fresh request-id context for the remainder of the current async chain. */
6
+ export declare function bindNewRequestId(): void;
7
+ export declare function getRequestContextStore(): RequestContextStore | undefined;
8
+ /** One-off id for the rare case a backend call happens with no bound tool-call context. */
9
+ export declare function newRequestId(): string;
10
+ //# sourceMappingURL=request-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/hooks/request-context.ts"],"names":[],"mappings":"AA2BA,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAID,oFAAoF;AACpF,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAED,wBAAgB,sBAAsB,IAAI,mBAAmB,GAAG,SAAS,CAExE;AAED,2FAA2F;AAC3F,wBAAgB,YAAY,IAAI,MAAM,CAErC"}
@@ -0,0 +1,38 @@
1
+ /*
2
+ * Ambient per-tool-call request-id context (AsyncLocalStorage). Mirrors the
3
+ * pipeshub-ai backend's own request-context pattern (same header name,
4
+ * `x-request-id`) so a single id traces one MCP tool/resource/prompt
5
+ * invocation across every backend HTTP call it makes.
6
+ *
7
+ * `tools.ts` / `resources.ts` / `prompts.ts` are Speakeasy-generated and
8
+ * regenerated on every build, so there is no `next()`-style wrapper point to
9
+ * bind context around a call. Instead `bindNewRequestId` is called from the
10
+ * hand-written `getClient` closure in `server.ts`, which every generated
11
+ * dispatch site calls synchronously as the first thing before invoking a
12
+ * tool/resource/prompt handler — `enterWith` binds the store for the rest of
13
+ * that handler's execution (sync remainder + everything it awaits).
14
+ *
15
+ * The final id (`mcp-<userId>-<random>` or `mcp-<random>`) can't be composed
16
+ * at bind time — `getClient` only has a `PipeshubCore`, not yet a resolved
17
+ * `Authorization` header, and resolving security may be async (OAuth2)
18
+ * while `getClient` must stay sync (generated call sites pass its return
19
+ * value straight into a handler, never await it). So only the random suffix
20
+ * is fixed here; `requestid.ts`'s hook fills in `finalId` off the first
21
+ * outbound request's `Authorization` header and every later call in the
22
+ * same tool invocation reuses that cached value.
23
+ */
24
+ import { AsyncLocalStorage } from "node:async_hooks";
25
+ import { nanoid } from "nanoid";
26
+ const storage = new AsyncLocalStorage();
27
+ /** Bind a fresh request-id context for the remainder of the current async chain. */
28
+ export function bindNewRequestId() {
29
+ storage.enterWith({ random: nanoid() });
30
+ }
31
+ export function getRequestContextStore() {
32
+ return storage.getStore();
33
+ }
34
+ /** One-off id for the rare case a backend call happens with no bound tool-call context. */
35
+ export function newRequestId() {
36
+ return `mcp-${nanoid()}`;
37
+ }
38
+ //# sourceMappingURL=request-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-context.js","sourceRoot":"","sources":["../../src/hooks/request-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAOhC,MAAM,OAAO,GAAG,IAAI,iBAAiB,EAAuB,CAAC;AAE7D,oFAAoF;AACpF,MAAM,UAAU,gBAAgB;IAC9B,OAAO,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO,OAAO,CAAC,QAAQ,EAAE,CAAC;AAC5B,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,YAAY;IAC1B,OAAO,OAAO,MAAM,EAAE,EAAE,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { BeforeRequestContext, BeforeRequestHook } from "./types.js";
2
+ export declare class RequestIDHook implements BeforeRequestHook {
3
+ beforeRequest(_hookCtx: BeforeRequestContext, request: Request): Request;
4
+ }
5
+ //# sourceMappingURL=requestid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requestid.d.ts","sourceRoot":"","sources":["../../src/hooks/requestid.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AA0BrE,qBAAa,aAAc,YAAW,iBAAiB;IACrD,aAAa,CAAC,QAAQ,EAAE,oBAAoB,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO;CAqBzE"}
@@ -0,0 +1,58 @@
1
+ /*
2
+ * Stamp an x-request-id trace header onto every outbound SDK request, reusing
3
+ * the id bound for the current MCP tool/resource/prompt call (see
4
+ * request-context.ts) so all backend calls from one invocation share it.
5
+ *
6
+ * Format mirrors the TypeScript SDK's own RequestIDHook: `mcp-<userId>-<random>`
7
+ * when the bearer JWT carries a userId claim, else `mcp-<random>`. The userId
8
+ * is only knowable once a request actually carries a resolved Authorization
9
+ * header, so it's decoded off the first outbound request of the tool call and
10
+ * cached on the bound context for every subsequent call to reuse verbatim.
11
+ */
12
+ import { getRequestContextStore, newRequestId } from "./request-context.js";
13
+ const REQUEST_ID_HEADER = "x-request-id";
14
+ /** Decodes the JWT payload without verifying the signature. */
15
+ function decodeJwtPayload(token) {
16
+ try {
17
+ const base64Url = token.split(".")[1];
18
+ if (!base64Url)
19
+ return null;
20
+ const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
21
+ const padded = base64 + "=".repeat((4 - (base64.length % 4)) % 4);
22
+ const claims = JSON.parse(Buffer.from(padded, "base64").toString("utf8"));
23
+ return typeof claims === "object" && claims !== null ? claims : null;
24
+ }
25
+ catch {
26
+ return null;
27
+ }
28
+ }
29
+ function userIdFromRequest(request) {
30
+ const auth = request.headers.get("authorization") ?? "";
31
+ if (!auth.toLowerCase().startsWith("bearer "))
32
+ return null;
33
+ const token = auth.slice(7).trim();
34
+ const claims = decodeJwtPayload(token);
35
+ return claims?.["userId"] || null;
36
+ }
37
+ export class RequestIDHook {
38
+ beforeRequest(_hookCtx, request) {
39
+ if (request.headers.get(REQUEST_ID_HEADER)) {
40
+ return request;
41
+ }
42
+ const store = getRequestContextStore();
43
+ if (!store) {
44
+ // No bound tool-call context (shouldn't happen in practice).
45
+ request.headers.set(REQUEST_ID_HEADER, newRequestId());
46
+ return request;
47
+ }
48
+ if (!store.finalId) {
49
+ const userId = userIdFromRequest(request);
50
+ store.finalId = userId
51
+ ? `mcp-${userId}-${store.random}`
52
+ : `mcp-${store.random}`;
53
+ }
54
+ request.headers.set(REQUEST_ID_HEADER, store.finalId);
55
+ return request;
56
+ }
57
+ }
58
+ //# sourceMappingURL=requestid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requestid.js","sourceRoot":"","sources":["../../src/hooks/requestid.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAG5E,MAAM,iBAAiB,GAAG,cAAc,CAAC;AAEzC,+DAA+D;AAC/D,SAAS,gBAAgB,CAAC,KAAa;IACrC,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAC;QAC5B,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC/D,MAAM,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QAC1E,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IACvE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAgB;IACzC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;IACxD,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACvC,OAAQ,MAAM,EAAE,CAAC,QAAQ,CAAY,IAAI,IAAI,CAAC;AAChD,CAAC;AAED,MAAM,OAAO,aAAa;IACxB,aAAa,CAAC,QAA8B,EAAE,OAAgB;QAC5D,IAAI,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAC3C,OAAO,OAAO,CAAC;QACjB,CAAC;QAED,MAAM,KAAK,GAAG,sBAAsB,EAAE,CAAC;QACvC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,6DAA6D;YAC7D,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,YAAY,EAAE,CAAC,CAAC;YACvD,OAAO,OAAO,CAAC;QACjB,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;YAC1C,KAAK,CAAC,OAAO,GAAG,MAAM;gBACpB,CAAC,CAAC,OAAO,MAAM,IAAI,KAAK,CAAC,MAAM,EAAE;gBACjC,CAAC,CAAC,OAAO,KAAK,CAAC,MAAM,EAAE,CAAC;QAC5B,CAAC;QACD,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QACtD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ export declare const PIPESHUB_INSTRUCTIONS = "# PipesHub MCP \u2014 instructions for the LLM\n\nPipesHub is the user's workplace AI platform. It indexes their documents,\nknowledge base content, and connector sources (Drive, Box, Confluence,\nSlack, Jira, Gmail, ...). When in doubt, the answer is in PipesHub.\n\n## Full-document tasks: `pipeshub_search` \u2192 `pipeshub_get_record_content`\n\n`pipeshub_chat` answers from a handful of retrieved passages \u2014 it never\nreads a whole document. Whenever the task depends on a document's\nCOMPLETE content, fetch the document itself:\n\n1. `pipeshub_search` with the document's name / topic.\n2. Take the top hit's `recordId`.\n3. `pipeshub_get_record_content`, and answer from the returned content.\n\nTasks that need this path \u2014 anything where missing part of the document\ncould make the answer wrong:\n\n- Summarize / TL;DR / key points / takeaways / action items of a doc.\n- Extract or list ALL of something (dates, owners, requirements, ...).\n- Check whether / where a doc mentions something.\n- Translate, rewrite, outline, review, or reformat a doc.\n- Compare named docs (fetch each `recordId`).\n- Any question explicitly scoped to ONE named document \u2014 chat retrieval\n cannot be restricted to a single record.\n\n## Default tool: `pipeshub_chat`\n\n**Use `pipeshub_chat` for any question that could plausibly be answered\nby the user's PipesHub-indexed data** and is not a full-document task:\n\n- A question that may span several documents, or where you don't yet\n know which record holds the answer (e.g. \"what did Aashil say about\n onboarding?\").\n- Anything about company / org policies, processes, decisions, or\n history (e.g. \"what's our vacation policy?\", \"who owns the auth\n service?\").\n- Anything explicitly mentioning PipesHub itself, or its sources\n (Drive / Box / Confluence / Slack / Gmail / Jira / etc.) when the\n user has those connected.\n- Open-ended \"what do we know about X\" questions where the answer\n likely lives in the org's documents.\n\nDo NOT answer those from your own knowledge \u2014 `pipeshub_chat` grounds\nthe answer in the user's actual indexed content and returns citations\nthe user can verify.\n\n## When to use the other tools\n\n- `pipeshub_search` \u2014 locate a document by name or topic and resolve it\n to a `recordId`. To read or summarize one specific document, search,\n then pass the top hit's `recordId` to `pipeshub_get_record_content`.\n- `pipeshub_download_record` \u2014 when the user wants the actual file\n bytes (download, attach, open). Get the `recordId` either from\n citations on a prior `pipeshub_chat` response or from\n `pipeshub_search`.\n- `pipeshub_get_record_content` \u2014 when you need a record's full parsed\n content (returned as a single `content` string: metadata header plus\n the document's text) without downloading the original file. Prefer this\n over download when the question is about what the record says.\n- `pipeshub_directory` \u2014 people, groups, teams, and `whoami` lookups.\n Not for documents.\n- `pipeshub_sources` \u2014 call once at the start of a session to discover\n which connectors / KB / models are available, then cache the result.\n- `pipeshub_agents` \u2014 list the org's configured **agents** (specialized\n assistants with their own prompt, tools, and knowledge scope).\n\n## Agents\n\nSome orgs configure **agents** for specific jobs (e.g. a Slack messenger, a\nJira ticket creator, a Salesforce CRM updater). To run a turn against an\nagent, call `pipeshub_chat` with its `agentId` (from `pipeshub_agents`)\n\u2014 optionally with an agent `chatMode` (`auto` by default, or `quick` /\n`verification` / `deep`). Keep passing the same `agentId` plus the\nreturned `conversationId` on follow-up turns.\n\n**When to route to an agent vs plain chat:**\n- The user names a system/action that maps to an agent (e.g. \"post to\n Slack\", \"create a Jira ticket\", \"update the Salesforce deal\") \u2192 call\n `pipeshub_agents`, pick the matching agent, and use it.\n- Plain question about the org's knowledge or the public web \u2192 just use\n `pipeshub_chat` (no `agentId`) with `internal_search` or `web_search`.\n\n**If you are unsure which agent or route fits the request**, call\n`pipeshub_agents` FIRST and read the returned names/descriptions, then\neither pick the best match or present the list to the user and let them\nchoose. Do NOT guess an agent blindly, and do NOT refuse \u2014 list the agents\nand decide from real data. The list may be empty (no agents configured),\nin which case fall back to plain `pipeshub_chat`.\n\n## Conversation lifecycle\n\n`pipeshub_chat` is a single tool that handles both starting and\ncontinuing conversations (plain or with an `agentId`). On the first turn\nomit `conversationId`; on every subsequent turn pass back the\n`conversationId` returned by the previous call (along with the same\n`agentId` if you used one). Server-side context is preserved \u2014 do NOT\nreplay prior messages. Only start a fresh conversation when the user\nexplicitly asks to clear context.\n";
2
+ //# sourceMappingURL=instructions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["../../src/mcp-server/instructions.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,qBAAqB,q+JAoGjC,CAAC"}
@@ -0,0 +1,106 @@
1
+ // Shared routing guidance for the host LLM. Surfaced two ways:
2
+ // 1. As the server `instructions` (always present at `initialize`).
3
+ // 2. As the body of the user-invokable `pipeshub-assistant` prompt.
4
+ // Keeping it in one place avoids the two copies drifting apart.
5
+ export const PIPESHUB_INSTRUCTIONS = `# PipesHub MCP — instructions for the LLM
6
+
7
+ PipesHub is the user's workplace AI platform. It indexes their documents,
8
+ knowledge base content, and connector sources (Drive, Box, Confluence,
9
+ Slack, Jira, Gmail, ...). When in doubt, the answer is in PipesHub.
10
+
11
+ ## Full-document tasks: \`pipeshub_search\` → \`pipeshub_get_record_content\`
12
+
13
+ \`pipeshub_chat\` answers from a handful of retrieved passages — it never
14
+ reads a whole document. Whenever the task depends on a document's
15
+ COMPLETE content, fetch the document itself:
16
+
17
+ 1. \`pipeshub_search\` with the document's name / topic.
18
+ 2. Take the top hit's \`recordId\`.
19
+ 3. \`pipeshub_get_record_content\`, and answer from the returned content.
20
+
21
+ Tasks that need this path — anything where missing part of the document
22
+ could make the answer wrong:
23
+
24
+ - Summarize / TL;DR / key points / takeaways / action items of a doc.
25
+ - Extract or list ALL of something (dates, owners, requirements, ...).
26
+ - Check whether / where a doc mentions something.
27
+ - Translate, rewrite, outline, review, or reformat a doc.
28
+ - Compare named docs (fetch each \`recordId\`).
29
+ - Any question explicitly scoped to ONE named document — chat retrieval
30
+ cannot be restricted to a single record.
31
+
32
+ ## Default tool: \`pipeshub_chat\`
33
+
34
+ **Use \`pipeshub_chat\` for any question that could plausibly be answered
35
+ by the user's PipesHub-indexed data** and is not a full-document task:
36
+
37
+ - A question that may span several documents, or where you don't yet
38
+ know which record holds the answer (e.g. "what did Aashil say about
39
+ onboarding?").
40
+ - Anything about company / org policies, processes, decisions, or
41
+ history (e.g. "what's our vacation policy?", "who owns the auth
42
+ service?").
43
+ - Anything explicitly mentioning PipesHub itself, or its sources
44
+ (Drive / Box / Confluence / Slack / Gmail / Jira / etc.) when the
45
+ user has those connected.
46
+ - Open-ended "what do we know about X" questions where the answer
47
+ likely lives in the org's documents.
48
+
49
+ Do NOT answer those from your own knowledge — \`pipeshub_chat\` grounds
50
+ the answer in the user's actual indexed content and returns citations
51
+ the user can verify.
52
+
53
+ ## When to use the other tools
54
+
55
+ - \`pipeshub_search\` — locate a document by name or topic and resolve it
56
+ to a \`recordId\`. To read or summarize one specific document, search,
57
+ then pass the top hit's \`recordId\` to \`pipeshub_get_record_content\`.
58
+ - \`pipeshub_download_record\` — when the user wants the actual file
59
+ bytes (download, attach, open). Get the \`recordId\` either from
60
+ citations on a prior \`pipeshub_chat\` response or from
61
+ \`pipeshub_search\`.
62
+ - \`pipeshub_get_record_content\` — when you need a record's full parsed
63
+ content (returned as a single \`content\` string: metadata header plus
64
+ the document's text) without downloading the original file. Prefer this
65
+ over download when the question is about what the record says.
66
+ - \`pipeshub_directory\` — people, groups, teams, and \`whoami\` lookups.
67
+ Not for documents.
68
+ - \`pipeshub_sources\` — call once at the start of a session to discover
69
+ which connectors / KB / models are available, then cache the result.
70
+ - \`pipeshub_agents\` — list the org's configured **agents** (specialized
71
+ assistants with their own prompt, tools, and knowledge scope).
72
+
73
+ ## Agents
74
+
75
+ Some orgs configure **agents** for specific jobs (e.g. a Slack messenger, a
76
+ Jira ticket creator, a Salesforce CRM updater). To run a turn against an
77
+ agent, call \`pipeshub_chat\` with its \`agentId\` (from \`pipeshub_agents\`)
78
+ — optionally with an agent \`chatMode\` (\`auto\` by default, or \`quick\` /
79
+ \`verification\` / \`deep\`). Keep passing the same \`agentId\` plus the
80
+ returned \`conversationId\` on follow-up turns.
81
+
82
+ **When to route to an agent vs plain chat:**
83
+ - The user names a system/action that maps to an agent (e.g. "post to
84
+ Slack", "create a Jira ticket", "update the Salesforce deal") → call
85
+ \`pipeshub_agents\`, pick the matching agent, and use it.
86
+ - Plain question about the org's knowledge or the public web → just use
87
+ \`pipeshub_chat\` (no \`agentId\`) with \`internal_search\` or \`web_search\`.
88
+
89
+ **If you are unsure which agent or route fits the request**, call
90
+ \`pipeshub_agents\` FIRST and read the returned names/descriptions, then
91
+ either pick the best match or present the list to the user and let them
92
+ choose. Do NOT guess an agent blindly, and do NOT refuse — list the agents
93
+ and decide from real data. The list may be empty (no agents configured),
94
+ in which case fall back to plain \`pipeshub_chat\`.
95
+
96
+ ## Conversation lifecycle
97
+
98
+ \`pipeshub_chat\` is a single tool that handles both starting and
99
+ continuing conversations (plain or with an \`agentId\`). On the first turn
100
+ omit \`conversationId\`; on every subsequent turn pass back the
101
+ \`conversationId\` returned by the previous call (along with the same
102
+ \`agentId\` if you used one). Server-side context is preserved — do NOT
103
+ replay prior messages. Only start a fresh conversation when the user
104
+ explicitly asks to clear context.
105
+ `;
106
+ //# sourceMappingURL=instructions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instructions.js","sourceRoot":"","sources":["../../src/mcp-server/instructions.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,sEAAsE;AACtE,sEAAsE;AACtE,gEAAgE;AAEhE,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoGpC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import * as z from "zod";
2
+ import { PromptDefinition } from "../prompts.js";
3
+ declare const args: {
4
+ query: z.ZodOptional<z.ZodString>;
5
+ };
6
+ export declare const prompt$pipeshubAssistant: PromptDefinition<typeof args>;
7
+ export {};
8
+ //# sourceMappingURL=pipeshubAssistant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeshubAssistant.d.ts","sourceRoot":"","sources":["../../../src/mcp-server/prompts/pipeshubAssistant.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGjD,QAAA,MAAM,IAAI;;CAMT,CAAC;AAEF,eAAO,MAAM,wBAAwB,EAAE,gBAAgB,CAAC,OAAO,IAAI,CAwBlE,CAAC"}
@@ -0,0 +1,31 @@
1
+ import * as z from "zod";
2
+ import { PIPESHUB_INSTRUCTIONS } from "../instructions.js";
3
+ const args = {
4
+ query: z.string().optional().describe("Optional. The user's request to route. Provide it to have the guidance "
5
+ + "applied to a concrete request; omit it to just load the routing "
6
+ + "guidance as a seed system prompt at the start of a session."),
7
+ };
8
+ export const prompt$pipeshubAssistant = {
9
+ name: "pipeshub-assistant",
10
+ description: "Load PipesHub tool-routing guidance so the assistant picks the correct "
11
+ + "tool (pipeshub_chat / search / agents / directory) and lists agents "
12
+ + "with pipeshub_agents when unsure which route fits the query.",
13
+ scopes: ["read"],
14
+ args,
15
+ prompt: (_client, args, _extra) => {
16
+ const text = args.query
17
+ ? `${PIPESHUB_INSTRUCTIONS}\n\n---\n\nFollow the routing rules above to `
18
+ + `handle this request, picking the right tool (and listing agents via `
19
+ + `\`pipeshub_agents\` if unsure which route fits):\n\n${args.query}`
20
+ : PIPESHUB_INSTRUCTIONS;
21
+ return {
22
+ messages: [
23
+ {
24
+ role: "user",
25
+ content: { type: "text", text },
26
+ },
27
+ ],
28
+ };
29
+ },
30
+ };
31
+ //# sourceMappingURL=pipeshubAssistant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeshubAssistant.js","sourceRoot":"","sources":["../../../src/mcp-server/prompts/pipeshubAssistant.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,MAAM,IAAI,GAAG;IACX,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACnC,yEAAyE;UACrE,kEAAkE;UAClE,6DAA6D,CAClE;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAkC;IACrE,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EACT,yEAAyE;UACvE,sEAAsE;UACtE,8DAA8D;IAClE,MAAM,EAAE,CAAC,MAAM,CAAC;IAChB,IAAI;IACJ,MAAM,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;QAChC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK;YACrB,CAAC,CAAC,GAAG,qBAAqB,+CAA+C;kBACrE,sEAAsE;kBACtE,uDAAuD,IAAI,CAAC,KAAK,EAAE;YACvE,CAAC,CAAC,qBAAqB,CAAC;QAE1B,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;iBAChC;aACF;SACF,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp-server/server.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA2DpE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAMzD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAQvC,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,MAAM,EAAE,aAAa,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACpC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,YAAY,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,QAAQ,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,GAAG,SAAS,CAAC;IAC9C,SAAS,CAAC,EAAE,UAAU,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC;IAChD,YAAY,CAAC,EAAE,UAAU,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;CACvD;;;;;;EAkEA"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp-server/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAMzD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAWvC,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,MAAM,EAAE,aAAa,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACpC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,YAAY,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,QAAQ,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,GAAG,SAAS,CAAC;IAC9C,SAAS,CAAC,EAAE,UAAU,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC;IAChD,YAAY,CAAC,EAAE,UAAU,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;CACvD;;;;;;EA2EA"}
@@ -1,71 +1,18 @@
1
- // Hand-written; replaces the Speakeasy-generated server.ts. Registers the
2
- // five curated PipesHub tools instead of one tool per OpenAPI operation.
3
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
- // Top-level instructions surfaced to the host LLM at server initialize.
5
- // These set defaults so the model picks `pipeshub_chat` as the natural
6
- // entry point for anything that touches the user's PipesHub data —
7
- // documents, files, knowledge base content, citations, etc.
8
- const PIPESHUB_INSTRUCTIONS = `# PipesHub MCP — instructions for the LLM
9
-
10
- PipesHub is the user's workplace AI platform. It indexes their documents,
11
- knowledge base content, and connector sources (Drive, Box, Confluence,
12
- Slack, Jira, Gmail, ...). When in doubt, the answer is in PipesHub.
13
-
14
- ## Default tool: \`pipeshub_chat\`
15
-
16
- **Use \`pipeshub_chat\` for any question that could plausibly be answered
17
- by the user's PipesHub-indexed data.** That includes:
18
-
19
- - Anything about a specific document, file, report, ticket, message, or
20
- page (e.g. "what's in the Q4 sales report?", "summarize the langchain
21
- doc", "what did Aashil say about onboarding?").
22
- - Anything about company / org policies, processes, decisions, or
23
- history (e.g. "what's our vacation policy?", "who owns the auth
24
- service?").
25
- - Anything explicitly mentioning PipesHub itself, or its sources
26
- (Drive / Box / Confluence / Slack / Gmail / Jira / etc.) when the
27
- user has those connected.
28
- - Open-ended "what do we know about X" questions where the answer
29
- likely lives in the org's documents.
30
-
31
- Do NOT answer those from your own knowledge — \`pipeshub_chat\` grounds
32
- the answer in the user's actual indexed content and returns citations
33
- the user can verify.
34
-
35
- ## When to use the other tools
36
-
37
- - \`pipeshub_search\` — only when the user asks specifically to **find /
38
- locate** a document by name or topic (so you can hand them a list, or
39
- resolve a filename to a \`recordId\` for download). For "what does
40
- the doc say?" use \`pipeshub_chat\` instead — it does the retrieval
41
- internally.
42
- - \`pipeshub_download_record\` — when the user wants the actual file
43
- bytes (download, attach, open). Get the \`recordId\` either from
44
- citations on a prior \`pipeshub_chat\` response or from
45
- \`pipeshub_search\`.
46
- - \`pipeshub_directory\` — people, groups, teams, and \`whoami\` lookups.
47
- Not for documents.
48
- - \`pipeshub_sources\` — call once at the start of a session to discover
49
- which connectors / KB / models are available, then cache the result.
50
-
51
- ## Conversation lifecycle
52
-
53
- \`pipeshub_chat\` is a single tool that handles both starting and
54
- continuing conversations. On the first turn omit \`conversationId\`; on
55
- every subsequent turn pass back the \`conversationId\` returned by the
56
- previous call. Server-side context is preserved — do NOT replay prior
57
- messages. Only start a fresh conversation when the user explicitly
58
- asks to clear context.
59
- `;
2
+ import { PIPESHUB_INSTRUCTIONS } from "./instructions.js";
60
3
  import { PipeshubCore } from "../core.js";
4
+ import { bindNewRequestId } from "../hooks/request-context.js";
61
5
  import { createRegisterPrompt } from "./prompts.js";
62
6
  import { createRegisterResource, createRegisterResourceTemplate, } from "./resources.js";
63
7
  import { createRegisterTool, registerDynamicTools } from "./tools.js";
64
8
  import { tool$pipeshubChat } from "./tools/pipeshubChat.js";
65
9
  import { tool$pipeshubSearch } from "./tools/pipeshubSearch.js";
66
10
  import { tool$pipeshubDownloadRecord } from "./tools/pipeshubDownloadRecord.js";
11
+ import { tool$pipeshubGetRecordContent } from "./tools/pipeshubGetRecordContent.js";
67
12
  import { tool$pipeshubDirectory } from "./tools/pipeshubDirectory.js";
68
13
  import { tool$pipeshubSources } from "./tools/pipeshubSources.js";
14
+ import { tool$pipeshubAgents } from "./tools/pipeshubAgents.js";
15
+ import { prompt$pipeshubAssistant } from "./prompts/pipeshubAssistant.js";
69
16
  export function createMCPServer(deps) {
70
17
  const server = new McpServer({
71
18
  name: "pipeshub-mcp",
@@ -73,7 +20,7 @@ export function createMCPServer(deps) {
73
20
  }, {
74
21
  instructions: PIPESHUB_INSTRUCTIONS,
75
22
  });
76
- const getClient = deps.getSDK || (() => new PipeshubCore({
23
+ const resolveClient = deps.getSDK || (() => new PipeshubCore({
77
24
  security: deps.security,
78
25
  serverURL: deps.serverURL,
79
26
  serverIdx: deps.serverIdx,
@@ -86,6 +33,10 @@ export function createMCPServer(deps) {
86
33
  }
87
34
  : undefined,
88
35
  }));
36
+ const getClient = () => {
37
+ bindNewRequestId();
38
+ return resolveClient();
39
+ };
89
40
  const scopes = new Set(deps.scopes);
90
41
  const allowedTools = deps.allowedTools && new Set(deps.allowedTools);
91
42
  const [tool, tools, toolMap] = createRegisterTool(deps.logger, server, getClient, scopes, allowedTools, deps.dynamic);
@@ -94,13 +45,16 @@ export function createMCPServer(deps) {
94
45
  const prompt = createRegisterPrompt(deps.logger, server, getClient, scopes);
95
46
  const register = { tool, resource, resourceTemplate, prompt };
96
47
  void register; // suppress unused warnings
97
- // Curated tool set. Five tools instead of ten one-per-op generated tools.
98
- // Order = preferred discovery order shown to the LLM.
48
+ // Curated tool set. Order = preferred discovery order shown to the LLM.
99
49
  tool(tool$pipeshubSources); // 1. discover sources + models
100
50
  tool(tool$pipeshubChat); // 2. ask questions (start + continue)
101
51
  tool(tool$pipeshubSearch); // 3. resolve filename → recordId
102
52
  tool(tool$pipeshubDownloadRecord); // 4. fetch a document by id
103
- tool(tool$pipeshubDirectory); // 5. people / groups / teams / whoami
53
+ tool(tool$pipeshubGetRecordContent); // 5. fetch a record's parsed content
54
+ tool(tool$pipeshubDirectory); // 6. people / groups / teams / whoami
55
+ tool(tool$pipeshubAgents); // 7. discover org agents
56
+ // Curated prompt: user-invokable tool-routing guidance.
57
+ prompt(prompt$pipeshubAssistant);
104
58
  if (deps.dynamic) {
105
59
  registerDynamicTools(deps.logger, server, getClient, toolMap, scopes);
106
60
  }
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp-server/server.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,yEAAyE;AAEzE,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,wEAAwE;AACxE,uEAAuE;AACvE,mEAAmE;AACnE,4DAA4D;AAC5D,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmD7B,CAAC;AAEF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EACL,sBAAsB,EACtB,8BAA8B,GAC/B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,2BAA2B,EAAE,MAAM,mCAAmC,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAElE,MAAM,UAAU,eAAe,CAAC,IAU/B;IACC,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B;QACE,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,OAAO;KACjB,EACD;QACE,YAAY,EAAE,qBAAqB;KACpC,CACF,CAAC;IAEF,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,CACrC,IAAI,YAAY,CAAC;QACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,OAAO;YACxC,CAAC,CAAC;gBACA,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;gBACtC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;gBAC1C,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;aACjD;YACD,CAAC,CAAC,SAAS;KACd,CAAC,CAAC,CAAC;IAEN,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEpC,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACrE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,GAAG,kBAAkB,CAC/C,IAAI,CAAC,MAAM,EACX,MAAM,EACN,SAAS,EACT,MAAM,EACN,YAAY,EACZ,IAAI,CAAC,OAAO,CACb,CAAC;IACF,MAAM,QAAQ,GAAG,sBAAsB,CACrC,IAAI,CAAC,MAAM,EACX,MAAM,EACN,SAAS,EACT,MAAM,CACP,CAAC;IACF,MAAM,gBAAgB,GAAG,8BAA8B,CACrD,IAAI,CAAC,MAAM,EACX,MAAM,EACN,SAAS,EACT,MAAM,CACP,CAAC;IACF,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAC5E,MAAM,QAAQ,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC9D,KAAK,QAAQ,CAAC,CAAC,2BAA2B;IAE1C,0EAA0E;IAC1E,sDAAsD;IACtD,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAU,+BAA+B;IACpE,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAa,sCAAsC;IAC3E,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAW,iCAAiC;IACtE,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAG,4BAA4B;IACjE,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAQ,sCAAsC;IAE3E,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,oBAAoB,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IACxE,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAC3B,CAAC"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp-server/server.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
+ import * as z from "zod";
1
2
  import { Security } from "../../models/security.js";
2
3
  import { PipeshubCore } from "../../core.js";
3
4
  import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
5
+ import { AgentSummary } from "../../models/agentops.js";
4
6
  /**
5
7
  * Parse a fetch Response as JSON, returning a CallToolResult error when the
6
8
  * body is missing / malformed.
@@ -16,6 +18,30 @@ export declare function readJson<T = unknown>(response: Response): Promise<{
16
18
  export declare function jsonResult(value: unknown): CallToolResult;
17
19
  /** Standard error → CallToolResult conversion. */
18
20
  export declare function errorResult(message: string): CallToolResult;
21
+ /**
22
+ * Guard a (possibly streaming) `Response` on its HTTP status. The streaming
23
+ * SDK funcs configure `errorCodes: []`, so the request layer treats ANY HTTP
24
+ * response — including 401 / 403 / 404 / 5xx — as a success and hands back the
25
+ * raw `Response`. Without this check those failures slip into the SSE drain
26
+ * and surface as the useless "stream ended without usable frames".
27
+ *
28
+ * Returns a `CallToolResult` error (status + best-effort message from the body)
29
+ * when the response is not ok, or `null` when it is ok (body left untouched so
30
+ * the caller can still stream it).
31
+ */
32
+ export declare function httpErrorResult(response: Response, context: string): Promise<CallToolResult | null>;
33
+ /**
34
+ * Read a `Response` body as JSON and validate it against a zod `schema`,
35
+ * returning the typed value or a `CallToolResult` error (empty body, invalid
36
+ * JSON, or a shape that doesn't match the schema).
37
+ */
38
+ export declare function readValidated<T>(response: Response, schema: z.ZodType<T>): Promise<{
39
+ ok: true;
40
+ value: T;
41
+ } | {
42
+ ok: false;
43
+ result: CallToolResult;
44
+ }>;
19
45
  /** Resolve `client._options.security` (which may be a function) to a value. */
20
46
  export declare function resolveSecurity(client: PipeshubCore): Promise<Security | undefined>;
21
47
  /**
@@ -85,6 +111,57 @@ export type SSEFrame = {
85
111
  * generator does not need to recheck it.
86
112
  */
87
113
  export declare function iterateSSE(response: Response): AsyncGenerator<SSEFrame, void, unknown>;
114
+ interface AgentToolsetView {
115
+ /** Integration / connector key, e.g. `jira`, `gmail`. */
116
+ name: string | null | undefined;
117
+ /** Fully-qualified tool ids the agent can run, e.g. `jira.create_issue`. */
118
+ tools: string[];
119
+ }
120
+ interface AgentKnowledgeView {
121
+ name: string | null | undefined;
122
+ type: string | null | undefined;
123
+ }
124
+ export interface EnrichedAgent {
125
+ agentId: string;
126
+ name: string;
127
+ description: string | null;
128
+ systemPrompt: string | null;
129
+ startMessage: string | null;
130
+ tags: string[];
131
+ webSearch: boolean;
132
+ isActive: boolean | null | undefined;
133
+ toolsets: AgentToolsetView[];
134
+ knowledge: AgentKnowledgeView[];
135
+ }
136
+ /**
137
+ * Trim an enriched `AgentSummary` (from `GET /agents`) to just what the LLM
138
+ * needs to pick and converse with an agent. Strips ids/revs/timestamps/perms
139
+ * and the heavy nested tool/knowledge metadata, keeping the routing-critical
140
+ * signal: each toolset's connector `name` + its tool ids (e.g.
141
+ * `jira.create_issue`), and each knowledge source's `name`/`type`.
142
+ */
143
+ export declare function trimAgent(a: AgentSummary): EnrichedAgent;
144
+ /**
145
+ * Fetch the COMPLETE agent list, auto-paginating `GET /agents` so callers
146
+ * (discovery + routing) never have to manage page numbers. Pages are fetched
147
+ * at the max page size until the backend reports no more (`hasNext` /
148
+ * `hasNextPage`, with a short-page fallback), capped by `maxPages` as a
149
+ * runaway guard. Returns the raw `AgentListItem`s plus a normalized `total`
150
+ * and a `truncated` flag (true if the cap was hit before exhausting pages).
151
+ */
152
+ export declare function listAllAgents(client: PipeshubCore, opts?: {
153
+ search?: string | undefined;
154
+ signal?: AbortSignal | undefined;
155
+ maxPages?: number | undefined;
156
+ }): Promise<{
157
+ ok: true;
158
+ agents: AgentSummary[];
159
+ total: number;
160
+ truncated: boolean;
161
+ } | {
162
+ ok: false;
163
+ result: CallToolResult;
164
+ }>;
88
165
  /** Trim a single search hit to what the LLM actually needs. */
89
166
  export declare function trimSearchHit(hit: any): {
90
167
  recordId: any;
@@ -97,4 +174,5 @@ export declare function trimSearchHit(hit: any): {
97
174
  webUrl: any;
98
175
  pageNum: any;
99
176
  };
177
+ export {};
100
178
  //# sourceMappingURL=_helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"_helpers.d.ts","sourceRoot":"","sources":["../../../src/mcp-server/tools/_helpers.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEpE;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,CAAC,GAAG,OAAO,EACxC,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,CAAC,CA2BzE;AAED,4EAA4E;AAC5E,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CAIzD;AAED,kDAAkD;AAClD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAK3D;AAED,+EAA+E;AAC/E,wBAAsB,eAAe,CACnC,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAM/B;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAoBzC;AAID;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,GAAG;;;;;;;;;;;;;;;;;EAkBzC;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,OAAO;;;;;;;;IAgB/C;AAID;;;;;;;;;;GAUG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,GAAG,CAAC;IACV,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAuB,UAAU,CAC/B,QAAQ,EAAE,QAAQ,GACjB,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CA+EzC;AAED,+DAA+D;AAC/D,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG;;;;;;;;;;EAerC"}
1
+ {"version":3,"file":"_helpers.d.ts","sourceRoot":"","sources":["../../../src/mcp-server/tools/_helpers.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEpE,OAAO,EAEL,YAAY,EACb,MAAM,0BAA0B,CAAC;AAElC;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,CAAC,GAAG,OAAO,EACxC,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,CAAC,CA2BzE;AAED,4EAA4E;AAC5E,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CAIzD;AAED,kDAAkD;AAClD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAK3D;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAmChC;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,CAAC,EACnC,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,CAAC,CA2BzE;AAED,+EAA+E;AAC/E,wBAAsB,eAAe,CACnC,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAM/B;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAoBzC;AAID;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,GAAG;;;;;;;;;;;;;;;;;EAkBzC;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,OAAO;;;;;;;;IAgB/C;AAID;;;;;;;;;;GAUG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,GAAG,CAAC;IACV,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAuB,UAAU,CAC/B,QAAQ,EAAE,QAAQ,GACjB,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CA+EzC;AAID,UAAU,gBAAgB;IACxB,yDAAyD;IACzD,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChC,4EAA4E;IAC5E,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,UAAU,kBAAkB;IAC1B,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CACjC;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;IACrC,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,SAAS,EAAE,kBAAkB,EAAE,CAAC;CACjC;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,YAAY,GAAG,aAAa,CAqBxD;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,YAAY,EACpB,IAAI,GAAE;IACJ,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B,GACL,OAAO,CACN;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,YAAY,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,GACvE;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,CACxC,CA6CA;AAED,+DAA+D;AAC/D,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG;;;;;;;;;;EAerC"}