@pipeshub-ai/mcp 2.3.3 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/bin/mcp-server.js +328 -210
- package/bin/mcp-server.js.map +12 -12
- package/bin/pipeshub.js +16 -8
- package/bin/pipeshub.js.map +4 -4
- package/esm/cli/commands.d.ts +1 -1
- package/esm/cli/commands.d.ts.map +1 -1
- package/esm/cli/commands.js +4 -1
- package/esm/cli/commands.js.map +1 -1
- package/esm/cli/pipeshub.js +13 -6
- package/esm/cli/pipeshub.js.map +1 -1
- package/esm/mcp-server/instructions.d.ts +1 -1
- package/esm/mcp-server/instructions.d.ts.map +1 -1
- package/esm/mcp-server/instructions.js +9 -6
- package/esm/mcp-server/instructions.js.map +1 -1
- package/esm/mcp-server/tools/_helpers.d.ts +76 -0
- package/esm/mcp-server/tools/_helpers.d.ts.map +1 -1
- package/esm/mcp-server/tools/_helpers.js +151 -0
- package/esm/mcp-server/tools/_helpers.js.map +1 -1
- package/esm/mcp-server/tools/pipeshubChat.d.ts.map +1 -1
- package/esm/mcp-server/tools/pipeshubChat.js +25 -11
- package/esm/mcp-server/tools/pipeshubChat.js.map +1 -1
- package/esm/mcp-server/tools/pipeshubDownloadRecord.d.ts.map +1 -1
- package/esm/mcp-server/tools/pipeshubDownloadRecord.js +15 -12
- package/esm/mcp-server/tools/pipeshubDownloadRecord.js.map +1 -1
- package/esm/mcp-server/tools/pipeshubSearch.d.ts +1 -0
- package/esm/mcp-server/tools/pipeshubSearch.d.ts.map +1 -1
- package/esm/mcp-server/tools/pipeshubSearch.js +22 -13
- 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 +15 -27
- package/esm/mcp-server/tools/pipeshubSources.js.map +1 -1
- package/esm/tool-names.js +3 -3
- package/esm/tool-names.js.map +1 -1
- package/package.json +1 -1
- package/qm/sandbox/Dockerfile +1 -1
- package/qm/sandbox/skills/pipeshub/SKILL.md +1 -0
- package/src/cli/commands.ts +3 -0
- package/src/cli/pipeshub.ts +12 -6
- package/src/mcp-server/instructions.ts +9 -6
- package/src/mcp-server/tools/_helpers.ts +233 -0
- package/src/mcp-server/tools/pipeshubChat.ts +31 -10
- package/src/mcp-server/tools/pipeshubDownloadRecord.ts +15 -12
- package/src/mcp-server/tools/pipeshubSearch.ts +38 -13
- package/src/mcp-server/tools/pipeshubSources.ts +18 -25
- package/src/tool-names.ts +3 -3
|
@@ -6,23 +6,26 @@ const args = {
|
|
|
6
6
|
recordId: z.string().min(1).describe("Record identifier — usually a UUID for connector-sourced records or "
|
|
7
7
|
+ "a 24-character ObjectId for uploaded records. Get it from a chat "
|
|
8
8
|
+ "citation (`citations[*].recordId`) or from a `pipeshub_search` hit."),
|
|
9
|
-
convertTo: z.string().optional().describe("
|
|
10
|
-
+ "
|
|
9
|
+
convertTo: z.string().optional().describe("The only conversion target connectors honour is `application/pdf` "
|
|
10
|
+
+ "(the MIME type, not `pdf`). A bare `pdf` is ignored and the "
|
|
11
|
+
+ "original file is returned with no error. Omit for the file as "
|
|
12
|
+
+ "stored. Does not parse the document — use "
|
|
13
|
+
+ "`pipeshub_get_record_content` `mode:\"content\"` for that."),
|
|
11
14
|
};
|
|
12
15
|
export const tool$pipeshubDownloadRecord = {
|
|
13
16
|
name: "pipeshub_download_record",
|
|
14
|
-
description: `
|
|
17
|
+
description: `Download the file as stored for one record — not PipesHub's parsed
|
|
18
|
+
content, metadata header, or summary.
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
\`pipeshub_chat\` response → \`citations[*].recordId\`.
|
|
19
|
-
- A search result:
|
|
20
|
-
\`pipeshub_search\` response → \`hits[*].recordId\` /
|
|
21
|
-
\`uniqueRecords[*].recordId\`.
|
|
20
|
+
Use this when the user wants the file itself (download, attach, open).
|
|
21
|
+
Get \`recordId\` from a chat citation or a \`pipeshub_search\` hit.
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
Do not use this to read, summarize, or answer "what does this doc
|
|
24
|
+
say?" regardless of format. That is \`pipeshub_get_record_content\`
|
|
25
|
+
\`mode:"content"\`. Text formats come back inline; images, audio, and
|
|
26
|
+
binary as base64.
|
|
27
|
+
|
|
28
|
+
\`convertTo\` accepts only \`application/pdf\`; anything else is ignored.`,
|
|
26
29
|
scopes: ["read"],
|
|
27
30
|
annotations: {
|
|
28
31
|
title: "Download a document by record id",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeshubDownloadRecord.js","sourceRoot":"","sources":["../../../src/mcp-server/tools/pipeshubDownloadRecord.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAE,yBAAyB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,EAAE,YAAY,EAAkB,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,IAAI,GAAG;IACX,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAClC,sEAAsE;UAClE,mEAAmE;UACnE,qEAAqE,CAC1E;IACD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACvC,
|
|
1
|
+
{"version":3,"file":"pipeshubDownloadRecord.js","sourceRoot":"","sources":["../../../src/mcp-server/tools/pipeshubDownloadRecord.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAE,yBAAyB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,EAAE,YAAY,EAAkB,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,IAAI,GAAG;IACX,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAClC,sEAAsE;UAClE,mEAAmE;UACnE,qEAAqE,CAC1E;IACD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACvC,oEAAoE;UAChE,8DAA8D;UAC9D,gEAAgE;UAChE,4CAA4C;UAC5C,4DAA4D,CACjE;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAgC;IACtE,IAAI,EAAE,0BAA0B;IAChC,WAAW,EACT;;;;;;;;;;;0EAWsE;IACxE,MAAM,EAAE,CAAC,MAAM,CAAC;IAChB,WAAW,EAAE;QACX,KAAK,EAAE,kCAAkC;QACzC,eAAe,EAAE,KAAK;QACtB,cAAc,EAAE,IAAI;QACpB,aAAa,EAAE,KAAK;QACpB,YAAY,EAAE,IAAI;KACnB;IACD,IAAI;IACJ,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QAChC,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,yBAAyB,CAAC,MAAM,EAAE;YACvD,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,EAAE,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;QACxD,IAAI,CAAC,MAAM,CAAC,EAAE;YAAE,OAAO,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAEzD,OAAO,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;CACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeshubSearch.d.ts","sourceRoot":"","sources":["../../../src/mcp-server/tools/pipeshubSearch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"pipeshubSearch.d.ts","sourceRoot":"","sources":["../../../src/mcp-server/tools/pipeshubSearch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAa7C,QAAA,MAAM,IAAI;;;;;CAiBT,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,cAAc,CAAC,OAAO,IAAI,CAwF3D,CAAC"}
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
2
|
import { semanticSearchSearch } from "../../funcs/semanticSearchSearch.js";
|
|
3
|
-
import { errorResult, jsonResult, readJson, trimSearchHit } from "./_helpers.js";
|
|
3
|
+
import { errorResult, jsonResult, readJson, resolveSourceScope, searchFilters, trimSearchHit, } from "./_helpers.js";
|
|
4
|
+
/** Matches the SDK request default (`src/models/semanticsearchrequest.ts`). */
|
|
5
|
+
const DEFAULT_LIMIT = 10;
|
|
4
6
|
const args = {
|
|
5
7
|
query: z.string().min(1).describe("Natural language query. Vector search across the org's indexed records."),
|
|
6
|
-
limit: z.number().int().min(1).max(100).optional().describe("
|
|
7
|
-
+ "
|
|
8
|
-
apps: z.array(z.string()).optional().describe("
|
|
9
|
-
+ "
|
|
8
|
+
limit: z.number().int().min(1).max(100).optional().describe("Number of results. Default 10. Use 5–10 when you only need a "
|
|
9
|
+
+ "`recordId`."),
|
|
10
|
+
apps: z.array(z.string()).optional().describe("Connector ids to search (for example a Jira or Google Drive connection). "
|
|
11
|
+
+ "Get them from `pipeshub_sources`, where `kind` is \"connector\". "
|
|
12
|
+
+ "Collection ids go in `kb`, not here."),
|
|
13
|
+
kb: z.array(z.string()).optional().describe("Collection (knowledge base) ids to search. Get them from "
|
|
14
|
+
+ "`pipeshub_sources`, where `kind` is \"knowledgeBase\"."),
|
|
10
15
|
};
|
|
11
16
|
export const tool$pipeshubSearch = {
|
|
12
17
|
name: "pipeshub_search",
|
|
@@ -37,13 +42,12 @@ not every record that matches. Never count them to answer "how many" /
|
|
|
37
42
|
"all" / "every"; navigate the record group instead, which reports its
|
|
38
43
|
real total.
|
|
39
44
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
Highest \`score\` first; multiple hits may share the same \`recordId\`
|
|
43
|
-
(different blocks of the same record).
|
|
45
|
+
By default it searches everything. To search only some sources, pass
|
|
46
|
+
connector ids in \`apps\` and collection ids in \`kb\`.
|
|
44
47
|
|
|
45
|
-
|
|
46
|
-
\`webUrl
|
|
48
|
+
Each hit is one matching passage, best match first:
|
|
49
|
+
\`{ recordId, recordName, score, snippet, mimeType, webUrl, ... }\`.
|
|
50
|
+
One record can appear in several hits. Link a record by its \`webUrl\`.`,
|
|
47
51
|
scopes: ["read"],
|
|
48
52
|
annotations: {
|
|
49
53
|
title: "Semantic search",
|
|
@@ -54,10 +58,14 @@ When presenting results to the user, link each record using its
|
|
|
54
58
|
},
|
|
55
59
|
args,
|
|
56
60
|
tool: async (client, args, ctx) => {
|
|
61
|
+
const limit = args.limit ?? DEFAULT_LIMIT;
|
|
62
|
+
// Each id is sent in the list the backend reads it from: a collection id
|
|
63
|
+
// in `apps` or a connector id in `kb` is dropped by the backend.
|
|
64
|
+
const { scope, notes } = await resolveSourceScope(client, args.apps, args.kb, { signal: ctx.signal });
|
|
57
65
|
const [result] = await semanticSearchSearch(client, {
|
|
58
66
|
query: args.query,
|
|
59
|
-
limit
|
|
60
|
-
filters:
|
|
67
|
+
limit,
|
|
68
|
+
filters: searchFilters(scope),
|
|
61
69
|
}, { fetchOptions: { signal: ctx.signal } }).$inspect();
|
|
62
70
|
if (!result.ok)
|
|
63
71
|
return errorResult(result.error.message);
|
|
@@ -75,6 +83,7 @@ When presenting results to the user, link each record using its
|
|
|
75
83
|
mimeType: r.mimeType,
|
|
76
84
|
webUrl: r.webUrl,
|
|
77
85
|
})),
|
|
86
|
+
...(notes.length > 0 ? { notes } : {}),
|
|
78
87
|
});
|
|
79
88
|
},
|
|
80
89
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeshubSearch.js","sourceRoot":"","sources":["../../../src/mcp-server/tools/pipeshubSearch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAE3E,OAAO,
|
|
1
|
+
{"version":3,"file":"pipeshubSearch.js","sourceRoot":"","sources":["../../../src/mcp-server/tools/pipeshubSearch.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeshubSources.d.ts","sourceRoot":"","sources":["../../../src/mcp-server/tools/pipeshubSources.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"pipeshubSources.d.ts","sourceRoot":"","sources":["../../../src/mcp-server/tools/pipeshubSources.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAQ7C,QAAA,MAAM,IAAI;;;;;;CAOT,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,cAAc,CAAC,OAAO,IAAI,CAqE5D,CAAC"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
|
-
import { knowledgeHubGetKnowledgeHubRootNodes } from "../../funcs/knowledgeHubGetKnowledgeHubRootNodes.js";
|
|
3
2
|
import { aiModelsProvidersGetAvailableModelsByType } from "../../funcs/aiModelsProvidersGetAvailableModelsByType.js";
|
|
4
|
-
import { errorResult, jsonResult, readJson } from "./_helpers.js";
|
|
3
|
+
import { errorResult, jsonResult, listAllSources, readJson, } from "./_helpers.js";
|
|
5
4
|
const args = {
|
|
6
5
|
include: z.array(z.enum(["sources", "llmModels", "embeddingModels"]))
|
|
7
6
|
.optional()
|
|
@@ -14,20 +13,19 @@ export const tool$pipeshubSources = {
|
|
|
14
13
|
|
|
15
14
|
Returns up to three sections:
|
|
16
15
|
|
|
17
|
-
- \`sources\` —
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
\`
|
|
16
|
+
- \`sources\` — connectors (\`kind: "connector"\`) and collections
|
|
17
|
+
(\`kind: "knowledgeBase"\`). For \`pipeshub_search\` and
|
|
18
|
+
\`pipeshub_chat\`, put a connector \`id\` in \`apps\` and a collection
|
|
19
|
+
\`id\` in \`kb\`. \`sourcesTruncated: true\` means the list stopped at
|
|
20
|
+
1,000 sources.
|
|
21
21
|
- \`llmModels\` — chat / generation models. Each item's \`modelKey\`
|
|
22
|
-
is the value to pass on \`pipeshub_chat\`
|
|
23
|
-
\`
|
|
24
|
-
specific model.
|
|
22
|
+
is the value to pass on \`pipeshub_chat\` as \`modelKey\`. Pick
|
|
23
|
+
\`isDefault: true\` unless the user asks for a specific model.
|
|
25
24
|
- \`embeddingModels\` — vector embedding models (only fetched when
|
|
26
25
|
explicitly requested via \`include\`).
|
|
27
26
|
|
|
28
27
|
Call this once at the start of a session and cache the result —
|
|
29
|
-
sources and models change infrequently
|
|
30
|
-
are returned by default; pass \`include\` to override.`,
|
|
28
|
+
sources and models change infrequently.`,
|
|
31
29
|
scopes: ["read"],
|
|
32
30
|
annotations: {
|
|
33
31
|
title: "List PipesHub sources and AI models",
|
|
@@ -44,22 +42,12 @@ are returned by default; pass \`include\` to override.`,
|
|
|
44
42
|
const want = (s) => include.includes(s);
|
|
45
43
|
const result = {};
|
|
46
44
|
if (want("sources")) {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (
|
|
52
|
-
|
|
53
|
-
const parsed = await readJson(r.value, "Knowledge base listing");
|
|
54
|
-
if (!parsed.ok)
|
|
55
|
-
return parsed.result;
|
|
56
|
-
result["sources"] = (parsed.value.items ?? []).map((n) => ({
|
|
57
|
-
id: n.id,
|
|
58
|
-
name: n.name,
|
|
59
|
-
kind: n.connector === "KB" ? "knowledgeBase" : "connector",
|
|
60
|
-
connector: n.connector,
|
|
61
|
-
hasChildren: n.hasChildren,
|
|
62
|
-
}));
|
|
45
|
+
const listed = await listAllSources(client, { signal: ctx.signal });
|
|
46
|
+
if (!listed.ok)
|
|
47
|
+
return listed.result;
|
|
48
|
+
result["sources"] = listed.sources;
|
|
49
|
+
if (listed.truncated)
|
|
50
|
+
result["sourcesTruncated"] = true;
|
|
63
51
|
}
|
|
64
52
|
for (const [key, modelType] of [
|
|
65
53
|
["llmModels", "llm"],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeshubSources.js","sourceRoot":"","sources":["../../../src/mcp-server/tools/pipeshubSources.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"pipeshubSources.js","sourceRoot":"","sources":["../../../src/mcp-server/tools/pipeshubSources.ts"],"names":[],"mappings":"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"}
|
package/esm/tool-names.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export const toolNames = [
|
|
3
3
|
{
|
|
4
4
|
"name": "pipeshub_sources",
|
|
5
|
-
"description": "Discover available chat sources and AI models in one call.\n\nReturns up to three sections:\n\n- `sources` —
|
|
5
|
+
"description": "Discover available chat sources and AI models in one call.\n\nReturns up to three sections:\n\n- `sources` — connectors (`kind: \"connector\"`) and collections\n (`kind: \"knowledgeBase\"`). For `pipeshub_search` and\n `pipeshub_chat`, put a connector `id` in `apps` and a collection\n `id` in `kb`. `sourcesTruncated: true` means the list stopped at\n 1,000 sources.\n- `llmModels` — chat / generation models. Each item's `modelKey`\n is the value to pass on `pipeshub_chat` as `modelKey`. Pick\n `isDefault: true` unless the user asks for a specific model.\n- `embeddingModels` — vector embedding models (only fetched when\n explicitly requested via `include`).\n\nCall this once at the start of a session and cache the result —\nsources and models change infrequently."
|
|
6
6
|
},
|
|
7
7
|
{
|
|
8
8
|
"name": "pipeshub_chat",
|
|
@@ -10,11 +10,11 @@ export const toolNames = [
|
|
|
10
10
|
},
|
|
11
11
|
{
|
|
12
12
|
"name": "pipeshub_search",
|
|
13
|
-
"description": "Vector / semantic search across the org's indexed documents.\n\n**Use this when the user wants to LOCATE a document** — by name, topic,\nor a phrase to grep for — and to resolve it to a `recordId`. For\nopen-ended questions across many documents, use `pipeshub_chat`\ninstead, which does the retrieval internally and grounds the answer in\ncitations.\n\nTypical uses:\n- Resolve a doc name / topic into a `recordId` for\n `pipeshub_get_record_content` — step 1 of any full-document task\n (summarize, extract, review, \"what does the doc say?\").\n- Resolve a filename / phrase into a `recordId` for\n `pipeshub_download_record`.\n- Show the user a ranked list of matching files when they ask \"find /\n search for X\".\n\nNot for structural questions — what is under this epic, which pages are\nin this space, what links to this ticket. Ranking by content cannot show\nhow records relate; use `pipeshub_get_record_content` `mode:\"navigate\"`.\n\n**A ranked sample, never a complete list.** Hits are the top-scoring\nblocks from the best-matching records — not all blocks of any record, and\nnot every record that matches. Never count them to answer \"how many\" /\n\"all\" / \"every\"; navigate the record group instead, which reports its\nreal total.\n\
|
|
13
|
+
"description": "Vector / semantic search across the org's indexed documents.\n\n**Use this when the user wants to LOCATE a document** — by name, topic,\nor a phrase to grep for — and to resolve it to a `recordId`. For\nopen-ended questions across many documents, use `pipeshub_chat`\ninstead, which does the retrieval internally and grounds the answer in\ncitations.\n\nTypical uses:\n- Resolve a doc name / topic into a `recordId` for\n `pipeshub_get_record_content` — step 1 of any full-document task\n (summarize, extract, review, \"what does the doc say?\").\n- Resolve a filename / phrase into a `recordId` for\n `pipeshub_download_record`.\n- Show the user a ranked list of matching files when they ask \"find /\n search for X\".\n\nNot for structural questions — what is under this epic, which pages are\nin this space, what links to this ticket. Ranking by content cannot show\nhow records relate; use `pipeshub_get_record_content` `mode:\"navigate\"`.\n\n**A ranked sample, never a complete list.** Hits are the top-scoring\nblocks from the best-matching records — not all blocks of any record, and\nnot every record that matches. Never count them to answer \"how many\" /\n\"all\" / \"every\"; navigate the record group instead, which reports its\nreal total.\n\nBy default it searches everything. To search only some sources, pass\nconnector ids in `apps` and collection ids in `kb`.\n\nEach hit is one matching passage, best match first:\n`{ recordId, recordName, score, snippet, mimeType, webUrl, ... }`.\nOne record can appear in several hits. Link a record by its `webUrl`."
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
"name": "pipeshub_download_record",
|
|
17
|
-
"description": "
|
|
17
|
+
"description": "Download the file as stored for one record — not PipesHub's parsed\ncontent, metadata header, or summary.\n\nUse this when the user wants the file itself (download, attach, open).\nGet `recordId` from a chat citation or a `pipeshub_search` hit.\n\nDo not use this to read, summarize, or answer \"what does this doc\nsay?\" regardless of format. That is `pipeshub_get_record_content`\n`mode:\"content\"`. Text formats come back inline; images, audio, and\nbinary as base64.\n\n`convertTo` accepts only `application/pdf`; anything else is ignored."
|
|
18
18
|
},
|
|
19
19
|
{
|
|
20
20
|
"name": "pipeshub_get_record_content",
|
package/esm/tool-names.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-names.js","sourceRoot":"","sources":["../src/tool-names.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,MAAM,CAAC,MAAM,SAAS,GAAgD;IACpE;QACE,MAAM,EAAE,kBAAkB;QAC1B,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"tool-names.js","sourceRoot":"","sources":["../src/tool-names.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,MAAM,CAAC,MAAM,SAAS,GAAgD;IACpE;QACE,MAAM,EAAE,kBAAkB;QAC1B,aAAa,EAAE,4wBAA4wB;KAC5xB;IACD;QACE,MAAM,EAAE,eAAe;QACvB,aAAa,EAAE,w+EAAw+E;KACx/E;IACD;QACE,MAAM,EAAE,iBAAiB;QACzB,aAAa,EAAE,0iDAA0iD;KAC1jD;IACD;QACE,MAAM,EAAE,0BAA0B;QAClC,aAAa,EAAE,miBAAmiB;KACnjB;IACD;QACE,MAAM,EAAE,6BAA6B;QACrC,aAAa,EAAE,06HAA06H;KAC17H;IACD;QACE,MAAM,EAAE,oBAAoB;QAC5B,aAAa,EAAE,uqBAAuqB;KACvrB;IACD;QACE,MAAM,EAAE,iBAAiB;QACzB,aAAa,EAAE,82CAA82C;KAC93C;CACF,CAAC"}
|
package/package.json
CHANGED
package/qm/sandbox/Dockerfile
CHANGED
|
@@ -13,7 +13,7 @@ FROM ghcr.io/yc-software/qm/sandbox-base
|
|
|
13
13
|
# separate package. Pin the exact version: the sandbox image and the PipesHub
|
|
14
14
|
# instance's MCP tool surface need to stay compatible, and an unpinned install
|
|
15
15
|
# turns a remote release into a silent change in agent behaviour.
|
|
16
|
-
ARG PIPESHUB_CLI_VERSION=2.
|
|
16
|
+
ARG PIPESHUB_CLI_VERSION=2.4.1
|
|
17
17
|
RUN npm install -g "@pipeshub-ai/mcp@${PIPESHUB_CLI_VERSION}" \
|
|
18
18
|
&& pipeshub --help >/dev/null
|
|
19
19
|
|
|
@@ -35,6 +35,7 @@ fresh sandbox before the install.
|
|
|
35
35
|
| "Find the file called security-review.pdf" | `pipeshub search "security-review"` |
|
|
36
36
|
| "Download that file" | `pipeshub get <recordId> --out <path>` |
|
|
37
37
|
| First call of a session | `pipeshub sources` (cache the ids) |
|
|
38
|
+
| "Search only the <X> collection / connector" | `pipeshub sources`, then `pipeshub search "..." --kb <id>` for `kind: knowledgeBase`, or `--app <id>` for `kind: connector` |
|
|
38
39
|
|
|
39
40
|
`ask` sees a few retrieved passages, not whole documents. For anything that
|
|
40
41
|
needs a document's full text — summarizing it, quoting it exactly — locate it
|
package/src/cli/commands.ts
CHANGED
|
@@ -191,9 +191,11 @@ export async function search(
|
|
|
191
191
|
query: string,
|
|
192
192
|
limit: number,
|
|
193
193
|
apps: string[],
|
|
194
|
+
kb: string[],
|
|
194
195
|
): Promise<Outcome> {
|
|
195
196
|
const args: Record<string, unknown> = { query, limit };
|
|
196
197
|
if (apps.length > 0) args["apps"] = apps;
|
|
198
|
+
if (kb.length > 0) args["kb"] = kb;
|
|
197
199
|
const raw = decodeToolJson(await callTool(ctx, "pipeshub_search", args));
|
|
198
200
|
const obj = asRecord(raw);
|
|
199
201
|
|
|
@@ -229,6 +231,7 @@ export async function search(
|
|
|
229
231
|
query,
|
|
230
232
|
contentWarning: CONTENT_WARNING,
|
|
231
233
|
hitCount: hits.length,
|
|
234
|
+
notes: arr(obj["notes"]).filter((n): n is string => typeof n === "string"),
|
|
232
235
|
hits,
|
|
233
236
|
records,
|
|
234
237
|
},
|
package/src/cli/pipeshub.ts
CHANGED
|
@@ -38,7 +38,7 @@ COMMANDS
|
|
|
38
38
|
auth status show connection, user, org, scopes, expiry
|
|
39
39
|
auth connect-help print the keychain setup steps
|
|
40
40
|
init-qm <dir> scaffold the QM deployment-layer bundle (admin)
|
|
41
|
-
sources list searchable sources (ids for --app)
|
|
41
|
+
sources list searchable sources (ids for --app / --kb)
|
|
42
42
|
search <query> locate records
|
|
43
43
|
ask <question> ask a grounded question; returns citations
|
|
44
44
|
get <recordId> fetch a record's content
|
|
@@ -47,8 +47,9 @@ COMMANDS
|
|
|
47
47
|
OPTIONS
|
|
48
48
|
--json JSON output (default)
|
|
49
49
|
--text human-readable output where available
|
|
50
|
-
--limit <n> search:
|
|
51
|
-
--app <id> search: restrict to a
|
|
50
|
+
--limit <n> search: result limit, 1-100 (default 10)
|
|
51
|
+
--app <id> search: restrict to a connector id (repeatable)
|
|
52
|
+
--kb <id> search: restrict to a collection id (repeatable)
|
|
52
53
|
--conversation <id> ask: continue an existing conversation
|
|
53
54
|
--mode <internal|web> ask: retrieval strategy (default internal)
|
|
54
55
|
--as <format> get: server-side conversion, e.g. pdf
|
|
@@ -73,6 +74,7 @@ interface Flags {
|
|
|
73
74
|
json: boolean;
|
|
74
75
|
limit: number;
|
|
75
76
|
apps: string[];
|
|
77
|
+
kb: string[];
|
|
76
78
|
conversation: string | null;
|
|
77
79
|
mode: string;
|
|
78
80
|
as: string | null;
|
|
@@ -87,6 +89,7 @@ function parseFlags(argv: string[]): { positional: string[]; flags: Flags } {
|
|
|
87
89
|
json: true,
|
|
88
90
|
limit: 10,
|
|
89
91
|
apps: [],
|
|
92
|
+
kb: [],
|
|
90
93
|
conversation: null,
|
|
91
94
|
mode: "internal",
|
|
92
95
|
as: null,
|
|
@@ -114,6 +117,7 @@ function parseFlags(argv: string[]): { positional: string[]; flags: Flags } {
|
|
|
114
117
|
case "--force": flags.force = true; break;
|
|
115
118
|
case "--limit": flags.limit = Number(needValue(a, argv[++i])); break;
|
|
116
119
|
case "--app": flags.apps.push(needValue(a, argv[++i])); break;
|
|
120
|
+
case "--kb": flags.kb.push(needValue(a, argv[++i])); break;
|
|
117
121
|
case "--conversation": flags.conversation = needValue(a, argv[++i]); break;
|
|
118
122
|
case "--mode": flags.mode = needValue(a, argv[++i]); break;
|
|
119
123
|
case "--as": flags.as = needValue(a, argv[++i]); break;
|
|
@@ -127,8 +131,10 @@ function parseFlags(argv: string[]): { positional: string[]; flags: Flags } {
|
|
|
127
131
|
positional.push(a);
|
|
128
132
|
}
|
|
129
133
|
}
|
|
130
|
-
|
|
131
|
-
|
|
134
|
+
// The tool rejects anything outside 1-100; catching it here makes it a usage
|
|
135
|
+
// error (exit 2) instead of a generic tool failure.
|
|
136
|
+
if (!Number.isInteger(flags.limit) || flags.limit < 1 || flags.limit > 100) {
|
|
137
|
+
throw new CliError("--limit must be a whole number from 1 to 100", EXIT.USAGE);
|
|
132
138
|
}
|
|
133
139
|
if (!Number.isFinite(flags.maxChars) || flags.maxChars <= 0) {
|
|
134
140
|
throw new CliError("--max-chars must be a positive number", EXIT.USAGE);
|
|
@@ -290,7 +296,7 @@ async function run(argv: string[]): Promise<number> {
|
|
|
290
296
|
case "search": {
|
|
291
297
|
const query = positional.slice(1).join(" ").trim();
|
|
292
298
|
if (query === "") throw new CliError("search requires a query", EXIT.USAGE);
|
|
293
|
-
outcome = await search(ctx, query, flags.limit, flags.apps);
|
|
299
|
+
outcome = await search(ctx, query, flags.limit, flags.apps, flags.kb);
|
|
294
300
|
break;
|
|
295
301
|
}
|
|
296
302
|
case "ask": {
|
|
@@ -56,10 +56,12 @@ the user can verify.
|
|
|
56
56
|
- \`pipeshub_search\` — locate a document by name or topic and resolve it
|
|
57
57
|
to a \`recordId\`. To read or summarize one specific document, search,
|
|
58
58
|
then pass the top hit's \`recordId\` to \`pipeshub_get_record_content\`.
|
|
59
|
-
- \`pipeshub_download_record\` — when the user wants the
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
\`
|
|
59
|
+
- \`pipeshub_download_record\` — when the user wants the file as stored
|
|
60
|
+
(download, attach, open). Never to read or summarize — that is
|
|
61
|
+
\`pipeshub_get_record_content\` \`mode:"content"\`, which returns
|
|
62
|
+
parsed text with a metadata header. Get the \`recordId\` from a chat
|
|
63
|
+
citation or from \`pipeshub_search\`. \`convertTo\` is only
|
|
64
|
+
\`application/pdf\`.
|
|
63
65
|
- \`pipeshub_get_record_content\` — when you need a record's full parsed
|
|
64
66
|
content (returned as a single \`content\` string: metadata header plus
|
|
65
67
|
the document's text) without downloading the original file. Prefer this
|
|
@@ -97,8 +99,9 @@ external ID → \`mode:"lookup"\` FIRST. It returns that record's metadata (for
|
|
|
97
99
|
ticket: status, assignee, priority, dates) plus its \`recordId\`, which often
|
|
98
100
|
answers the question outright. Never guess a \`recordId\`.
|
|
99
101
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
+
For search, pass a connector id from \`pipeshub_sources\` as \`apps: ["<id>"]\`
|
|
103
|
+
and a collection id (\`kind: "knowledgeBase"\`) as \`kb: ["<id>"]\`. Any source
|
|
104
|
+
id works as \`nodeId\` to navigate. Navigate and lookup end in a \`Next:\` line
|
|
102
105
|
naming the exact follow-up call — follow it.
|
|
103
106
|
|
|
104
107
|
## Agents
|