@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.
- package/README.md +90 -2
- package/bin/mcp-server.js +1156 -213
- package/bin/mcp-server.js.map +30 -16
- package/esm/funcs/agentsListAgents.d.ts +10 -0
- package/esm/funcs/agentsListAgents.d.ts.map +1 -0
- package/esm/funcs/agentsListAgents.js +83 -0
- package/esm/funcs/agentsListAgents.js.map +1 -0
- package/esm/funcs/agentsStreamConversation.d.ts +10 -0
- package/esm/funcs/agentsStreamConversation.d.ts.map +1 -0
- package/esm/funcs/agentsStreamConversation.js +83 -0
- package/esm/funcs/agentsStreamConversation.js.map +1 -0
- package/esm/funcs/agentsStreamMessage.d.ts +10 -0
- package/esm/funcs/agentsStreamMessage.d.ts.map +1 -0
- package/esm/funcs/agentsStreamMessage.js +86 -0
- package/esm/funcs/agentsStreamMessage.js.map +1 -0
- package/esm/funcs/connectorGetRecordContent.d.ts +43 -0
- package/esm/funcs/connectorGetRecordContent.d.ts.map +1 -0
- package/esm/funcs/connectorGetRecordContent.js +114 -0
- package/esm/funcs/connectorGetRecordContent.js.map +1 -0
- package/esm/funcs/conversationsStreamConversation.d.ts.map +1 -1
- package/esm/funcs/conversationsStreamConversation.js +2 -4
- package/esm/funcs/conversationsStreamConversation.js.map +1 -1
- package/esm/funcs/conversationsStreamMessage.d.ts.map +1 -1
- package/esm/funcs/conversationsStreamMessage.js +0 -7
- package/esm/funcs/conversationsStreamMessage.js.map +1 -1
- package/esm/funcs/userGroupsGetAllUserGroups.js +1 -1
- package/esm/funcs/userGroupsGetAllUserGroups.js.map +1 -1
- package/esm/hooks/registration.d.ts.map +1 -1
- package/esm/hooks/registration.js +2 -1
- package/esm/hooks/registration.js.map +1 -1
- package/esm/hooks/request-context.d.ts +10 -0
- package/esm/hooks/request-context.d.ts.map +1 -0
- package/esm/hooks/request-context.js +38 -0
- package/esm/hooks/request-context.js.map +1 -0
- package/esm/hooks/requestid.d.ts +5 -0
- package/esm/hooks/requestid.d.ts.map +1 -0
- package/esm/hooks/requestid.js +58 -0
- package/esm/hooks/requestid.js.map +1 -0
- package/esm/mcp-server/instructions.d.ts +2 -0
- package/esm/mcp-server/instructions.d.ts.map +1 -0
- package/esm/mcp-server/instructions.js +106 -0
- package/esm/mcp-server/instructions.js.map +1 -0
- package/esm/mcp-server/prompts/pipeshubAssistant.d.ts +8 -0
- package/esm/mcp-server/prompts/pipeshubAssistant.d.ts.map +1 -0
- package/esm/mcp-server/prompts/pipeshubAssistant.js +31 -0
- package/esm/mcp-server/prompts/pipeshubAssistant.js.map +1 -0
- package/esm/mcp-server/server.d.ts.map +1 -1
- package/esm/mcp-server/server.js +16 -62
- package/esm/mcp-server/server.js.map +1 -1
- package/esm/mcp-server/tools/_helpers.d.ts +78 -0
- package/esm/mcp-server/tools/_helpers.d.ts.map +1 -1
- package/esm/mcp-server/tools/_helpers.js +155 -1
- package/esm/mcp-server/tools/_helpers.js.map +1 -1
- package/esm/mcp-server/tools/pipeshubAgents.d.ts +8 -0
- package/esm/mcp-server/tools/pipeshubAgents.d.ts.map +1 -0
- package/esm/mcp-server/tools/pipeshubAgents.js +62 -0
- package/esm/mcp-server/tools/pipeshubAgents.js.map +1 -0
- package/esm/mcp-server/tools/pipeshubChat.d.ts +6 -1
- package/esm/mcp-server/tools/pipeshubChat.d.ts.map +1 -1
- package/esm/mcp-server/tools/pipeshubChat.js +79 -23
- package/esm/mcp-server/tools/pipeshubChat.js.map +1 -1
- package/esm/mcp-server/tools/pipeshubDirectory.d.ts.map +1 -1
- package/esm/mcp-server/tools/pipeshubDirectory.js +0 -1
- package/esm/mcp-server/tools/pipeshubDirectory.js.map +1 -1
- package/esm/mcp-server/tools/pipeshubDownloadRecord.d.ts.map +1 -1
- package/esm/mcp-server/tools/pipeshubDownloadRecord.js +0 -3
- package/esm/mcp-server/tools/pipeshubDownloadRecord.js.map +1 -1
- package/esm/mcp-server/tools/pipeshubGetRecordContent.d.ts +8 -0
- package/esm/mcp-server/tools/pipeshubGetRecordContent.d.ts.map +1 -0
- package/esm/mcp-server/tools/pipeshubGetRecordContent.js +63 -0
- package/esm/mcp-server/tools/pipeshubGetRecordContent.js.map +1 -0
- package/esm/mcp-server/tools/pipeshubSearch.d.ts.map +1 -1
- package/esm/mcp-server/tools/pipeshubSearch.js +8 -7
- package/esm/mcp-server/tools/pipeshubSearch.js.map +1 -1
- package/esm/mcp-server/tools/pipeshubSources.d.ts.map +1 -1
- package/esm/mcp-server/tools/pipeshubSources.js +0 -4
- package/esm/mcp-server/tools/pipeshubSources.js.map +1 -1
- package/esm/mcp-server/tools.d.ts.map +1 -1
- package/esm/mcp-server/tools.js +13 -1
- package/esm/mcp-server/tools.js.map +1 -1
- package/esm/models/agentops.d.ts +119 -0
- package/esm/models/agentops.d.ts.map +1 -0
- package/esm/models/agentops.js +97 -0
- package/esm/models/agentops.js.map +1 -0
- package/esm/models/getrecordcontentop.d.ts +6 -0
- package/esm/models/getrecordcontentop.d.ts.map +1 -0
- package/esm/models/getrecordcontentop.js +5 -0
- package/esm/models/getrecordcontentop.js.map +1 -0
- package/esm/tool-names.d.ts.map +1 -1
- package/esm/tool-names.js +10 -2
- package/esm/tool-names.js.map +1 -1
- package/package.json +3 -2
- package/src/funcs/agentsListAgents.ts +141 -0
- package/src/funcs/agentsStreamConversation.ts +144 -0
- package/src/funcs/agentsStreamMessage.ts +147 -0
- package/src/funcs/connectorGetRecordContent.ts +179 -0
- package/src/funcs/conversationsStreamConversation.ts +2 -4
- package/src/funcs/conversationsStreamMessage.ts +0 -8
- package/src/funcs/userGroupsGetAllUserGroups.ts +1 -1
- package/src/hooks/registration.ts +2 -1
- package/src/hooks/request-context.ts +47 -0
- package/src/hooks/requestid.ts +62 -0
- package/src/mcp-server/instructions.ts +106 -0
- package/src/mcp-server/prompts/pipeshubAssistant.ts +37 -0
- package/src/mcp-server/server.ts +18 -64
- package/src/mcp-server/tools/_helpers.ts +216 -1
- package/src/mcp-server/tools/pipeshubAgents.ts +68 -0
- package/src/mcp-server/tools/pipeshubChat.ts +78 -23
- package/src/mcp-server/tools/pipeshubDirectory.ts +0 -1
- package/src/mcp-server/tools/pipeshubDownloadRecord.ts +0 -4
- package/src/mcp-server/tools/pipeshubGetRecordContent.ts +67 -0
- package/src/mcp-server/tools/pipeshubSearch.ts +8 -7
- package/src/mcp-server/tools/pipeshubSources.ts +0 -5
- package/src/mcp-server/tools.ts +14 -1
- package/src/models/agentops.ts +160 -0
- package/src/models/getrecordcontentop.ts +11 -0
- 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 @@
|
|
|
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":"
|
|
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"}
|
package/esm/mcp-server/server.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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.
|
|
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$
|
|
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,
|
|
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":"
|
|
1
|
+
{"version":3,"file":"_helpers.d.ts","sourceRoot":"","sources":["../../../src/mcp-server/tools/_helpers.ts"],"names":[],"mappings":"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"}
|