@pipeshub-ai/mcp 2.3.0 → 2.3.2
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 +1 -1
- package/bin/mcp-server.js +56 -15
- package/bin/mcp-server.js.map +7 -7
- package/bin/pipeshub.js +185 -24
- package/bin/pipeshub.js.map +7 -7
- package/esm/cli/client.d.ts.map +1 -1
- package/esm/cli/client.js +6 -1
- package/esm/cli/client.js.map +1 -1
- package/esm/cli/commands.d.ts.map +1 -1
- package/esm/cli/commands.js +22 -16
- package/esm/cli/commands.js.map +1 -1
- package/esm/cli/config.d.ts +2 -2
- package/esm/cli/config.js +2 -2
- package/esm/cli/init-qm.d.ts +51 -1
- package/esm/cli/init-qm.d.ts.map +1 -1
- package/esm/cli/init-qm.js +209 -16
- package/esm/cli/init-qm.js.map +1 -1
- package/esm/cli/pipeshub.js +4 -3
- package/esm/cli/pipeshub.js.map +1 -1
- package/esm/mcp-server/tools/_helpers.d.ts +20 -3
- package/esm/mcp-server/tools/_helpers.d.ts.map +1 -1
- package/esm/mcp-server/tools/_helpers.js +41 -4
- package/esm/mcp-server/tools/_helpers.js.map +1 -1
- package/esm/mcp-server/tools/pipeshubDirectory.d.ts.map +1 -1
- package/esm/mcp-server/tools/pipeshubDirectory.js +62 -8
- package/esm/mcp-server/tools/pipeshubDirectory.js.map +1 -1
- package/esm/mcp-server/tools/pipeshubGetRecordContent.d.ts +1 -1
- package/esm/mcp-server/tools/pipeshubSearch.js +1 -1
- package/esm/mcp-server/tools/pipeshubSearch.js.map +1 -1
- package/esm/mcp-server/tools/pipeshubSources.js +2 -2
- package/esm/mcp-server/tools/pipeshubSources.js.map +1 -1
- package/esm/models/availablemodelsresponse.d.ts +1 -1
- package/esm/models/conversation.d.ts +1 -1
- package/esm/models/userteamsresponse.d.ts +1 -1
- package/esm/tool-names.js +1 -1
- package/esm/tool-names.js.map +1 -1
- package/package.json +1 -1
- package/qm/README.md +84 -71
- package/qm/SECURITY.md +7 -5
- package/qm/TROUBLESHOOTING.md +34 -29
- package/qm/qm.config.fragment.jsonc +12 -33
- package/qm/sandbox/Dockerfile +1 -1
- package/qm/sandbox/skills/pipeshub/SKILL.md +27 -7
- package/qm/sandbox/tools/pipeshub/tool.json +1 -1
- package/src/cli/client.ts +8 -1
- package/src/cli/commands.ts +22 -16
- package/src/cli/config.ts +2 -2
- package/src/cli/init-qm.ts +206 -17
- package/src/cli/pipeshub.ts +4 -3
- package/src/mcp-server/tools/_helpers.ts +42 -2
- package/src/mcp-server/tools/pipeshubDirectory.ts +65 -7
- package/src/mcp-server/tools/pipeshubSearch.ts +1 -1
- package/src/mcp-server/tools/pipeshubSources.ts +2 -2
- package/src/tool-names.ts +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ PipesHub exposes a remote MCP endpoint over **Streamable HTTP** at `/mcp`.MCP Cl
|
|
|
6
6
|
|
|
7
7
|
> **Looking for the tool reference?** See [TOOLS.md](./TOOLS.md) for descriptions, arguments, and a decision guide for each tool the MCP server exposes (`pipeshub_chat`, `pipeshub_search`, `pipeshub_download_record`, `pipeshub_directory`, `pipeshub_sources`).
|
|
8
8
|
|
|
9
|
-
> **Using QM?** QM cannot attach a third-party MCP endpoint — it is an MCP *server* to its own harness, not a client.
|
|
9
|
+
> **Using QM?** QM cannot attach a third-party MCP endpoint — it is an MCP *server* to its own harness, not a client. Follow [Use PipesHub with QM](./qm/docs/use-with-qm.md). The deployment-layer bundle in [`qm/`](./qm/) gives agents a `pipeshub` command inside their sandbox; this package ships that command as a second bin.
|
|
10
10
|
|
|
11
11
|
## Prerequisites
|
|
12
12
|
|
package/bin/mcp-server.js
CHANGED
|
@@ -53098,7 +53098,10 @@ var init_agentsListAgents = __esm(() => {
|
|
|
53098
53098
|
});
|
|
53099
53099
|
|
|
53100
53100
|
// src/mcp-server/tools/_helpers.ts
|
|
53101
|
-
async function readJson(response) {
|
|
53101
|
+
async function readJson(response, context = "PipesHub request") {
|
|
53102
|
+
const httpErr = await httpErrorResult(response, context);
|
|
53103
|
+
if (httpErr)
|
|
53104
|
+
return { ok: false, result: httpErr };
|
|
53102
53105
|
const text = await response.text();
|
|
53103
53106
|
if (!text) {
|
|
53104
53107
|
return {
|
|
@@ -53127,6 +53130,13 @@ ${text.slice(0, 500)}`
|
|
|
53127
53130
|
};
|
|
53128
53131
|
}
|
|
53129
53132
|
}
|
|
53133
|
+
function expiredTokenError(exp) {
|
|
53134
|
+
if (typeof exp !== "number" || !Number.isFinite(exp))
|
|
53135
|
+
return null;
|
|
53136
|
+
if (exp * 1000 > Date.now())
|
|
53137
|
+
return null;
|
|
53138
|
+
return errorResult(`The access token expired on ${new Date(exp * 1000).toISOString()}. ` + "Mint a new personal access token in PipesHub under " + "Developer Settings → Personal Access Tokens.");
|
|
53139
|
+
}
|
|
53130
53140
|
function jsonResult(value) {
|
|
53131
53141
|
return {
|
|
53132
53142
|
content: [{ type: "text", text: JSON.stringify(value, null, 2) }]
|
|
@@ -53153,11 +53163,15 @@ async function httpErrorResult(response, context) {
|
|
|
53153
53163
|
message = candidate || body;
|
|
53154
53164
|
} catch {}
|
|
53155
53165
|
}
|
|
53156
|
-
const
|
|
53166
|
+
const reason = message.slice(0, 400).trim();
|
|
53167
|
+
const detail = reason ? ` ${/[.!?]$/.test(reason) ? reason : `${reason}.`}` : "";
|
|
53157
53168
|
const auth = response.status === 401 || response.status === 403 ? " Check that the bearer token / credentials are valid and not expired." : "";
|
|
53158
53169
|
return errorResult(`${context} failed (HTTP ${response.status} ${response.statusText}).${detail}${auth}`);
|
|
53159
53170
|
}
|
|
53160
|
-
async function readValidated(response, schema) {
|
|
53171
|
+
async function readValidated(response, schema, context = "PipesHub request") {
|
|
53172
|
+
const httpErr = await httpErrorResult(response, context);
|
|
53173
|
+
if (httpErr)
|
|
53174
|
+
return { ok: false, result: httpErr };
|
|
53161
53175
|
const text = await response.text();
|
|
53162
53176
|
if (!text) {
|
|
53163
53177
|
return { ok: false, result: errorResult("Empty response from server") };
|
|
@@ -53791,7 +53805,7 @@ When presenting results to the user, link each record using its
|
|
|
53791
53805
|
}, { fetchOptions: { signal: ctx.signal } }).$inspect();
|
|
53792
53806
|
if (!result.ok)
|
|
53793
53807
|
return errorResult(result.error.message);
|
|
53794
|
-
const parsed = await readJson(result.value);
|
|
53808
|
+
const parsed = await readJson(result.value, "PipesHub search");
|
|
53795
53809
|
if (!parsed.ok)
|
|
53796
53810
|
return parsed.result;
|
|
53797
53811
|
const sr = parsed.value.searchResponse ?? {};
|
|
@@ -54806,7 +54820,7 @@ var init_pipeshubDirectory = __esm(() => {
|
|
|
54806
54820
|
"list_groups",
|
|
54807
54821
|
"list_my_teams"
|
|
54808
54822
|
]).describe(`What to do:
|
|
54809
|
-
` + "- `whoami` — return the authenticated user's identity
|
|
54823
|
+
` + "- `whoami` — return the authenticated user's identity, confirmed " + `against the server. No other args needed.
|
|
54810
54824
|
` + "- `list_users` — paginated list of org users. Optional `page`, " + "`limit`, `search` (substring match against name or email).\n" + "- `get_user` — full profile for one user. Required `userId`. " + "Use `whoami` to find your own id first if needed.\n" + "- `list_groups` — paginated list of user groups (with `userCount`).\n" + "- `list_my_teams` — teams the authenticated user belongs to, with " + "capability flags."),
|
|
54811
54825
|
userId: string2().optional().describe("Required when `action` is `get_user`. 24-character ObjectId."),
|
|
54812
54826
|
page: number2().int().min(1).optional().describe("Pagination — 1-based page number. Used by list_* actions."),
|
|
@@ -54820,7 +54834,8 @@ actions — pick the right \`action\`:
|
|
|
54820
54834
|
|
|
54821
54835
|
- \`whoami\` — who is the caller? Use this whenever you need the
|
|
54822
54836
|
authenticated user's own id, email, or full name (e.g. before
|
|
54823
|
-
\`get_user\` on themselves).
|
|
54837
|
+
\`get_user\` on themselves). Errors if the credential is expired
|
|
54838
|
+
or revoked.
|
|
54824
54839
|
- \`list_users\` — search / page through org users.
|
|
54825
54840
|
- \`get_user\` — full \`User\` document for one user (requires \`userId\`).
|
|
54826
54841
|
- \`list_groups\` — list user groups with \`userCount\`.
|
|
@@ -54845,13 +54860,39 @@ Output shape varies by action; see each action's docs above.`,
|
|
|
54845
54860
|
if (!claims) {
|
|
54846
54861
|
return errorResult("No bearer token configured on the SDK client, so `whoami` " + "cannot resolve the caller's identity. Ask the user for " + "their email and use `list_users` with `search`.");
|
|
54847
54862
|
}
|
|
54863
|
+
const exp = claims["exp"];
|
|
54864
|
+
const expired = expiredTokenError(exp);
|
|
54865
|
+
if (expired)
|
|
54866
|
+
return expired;
|
|
54867
|
+
const tokenExpiresAt = typeof exp === "number" ? new Date(exp * 1000).toISOString() : undefined;
|
|
54868
|
+
const userId = claims["userId"];
|
|
54869
|
+
let verified = "unchecked";
|
|
54870
|
+
let unverifiedReason = "No userId claim in the token, so the identity could not be " + "confirmed with the server.";
|
|
54871
|
+
if (typeof userId === "string" && userId) {
|
|
54872
|
+
const [probe] = await usersGetUserById(client, { id: userId }, {
|
|
54873
|
+
fetchOptions
|
|
54874
|
+
}).$inspect();
|
|
54875
|
+
if (!probe.ok) {
|
|
54876
|
+
unverifiedReason = `Could not reach PipesHub to confirm the ` + `identity (${probe.error.message}). The details below come ` + `from the token itself.`;
|
|
54877
|
+
} else if (probe.value.status === 401) {
|
|
54878
|
+
return errorResult("PipesHub rejected this access token (HTTP 401 Unauthorized), " + "so the identity in it is no longer valid — it has most " + "likely been revoked. Mint a new personal access token " + "under Developer Settings → Personal Access Tokens.");
|
|
54879
|
+
} else if (probe.value.ok) {
|
|
54880
|
+
verified = true;
|
|
54881
|
+
unverifiedReason = undefined;
|
|
54882
|
+
} else {
|
|
54883
|
+
unverifiedReason = `PipesHub returned HTTP ${probe.value.status} ` + `when confirming the identity, so it could not be checked. ` + `The details below come from the token itself.`;
|
|
54884
|
+
}
|
|
54885
|
+
}
|
|
54848
54886
|
return jsonResult({
|
|
54849
54887
|
userId: claims["userId"],
|
|
54850
54888
|
orgId: claims["orgId"],
|
|
54851
54889
|
email: claims["email"],
|
|
54852
54890
|
fullName: claims["fullName"],
|
|
54853
54891
|
mobile: claims["mobile"],
|
|
54854
|
-
userSlug: claims["userSlug"]
|
|
54892
|
+
userSlug: claims["userSlug"],
|
|
54893
|
+
tokenExpiresAt,
|
|
54894
|
+
identityVerified: verified,
|
|
54895
|
+
note: unverifiedReason
|
|
54855
54896
|
});
|
|
54856
54897
|
}
|
|
54857
54898
|
case "list_users": {
|
|
@@ -54862,7 +54903,7 @@ Output shape varies by action; see each action's docs above.`,
|
|
|
54862
54903
|
}, { fetchOptions }).$inspect();
|
|
54863
54904
|
if (!result.ok)
|
|
54864
54905
|
return errorResult(result.error.message);
|
|
54865
|
-
const parsed = await readJson(result.value);
|
|
54906
|
+
const parsed = await readJson(result.value, "User listing");
|
|
54866
54907
|
if (!parsed.ok)
|
|
54867
54908
|
return parsed.result;
|
|
54868
54909
|
return jsonResult(parsed.value);
|
|
@@ -54876,7 +54917,7 @@ Output shape varies by action; see each action's docs above.`,
|
|
|
54876
54917
|
}, { fetchOptions }).$inspect();
|
|
54877
54918
|
if (!result.ok)
|
|
54878
54919
|
return errorResult(result.error.message);
|
|
54879
|
-
const parsed = await readJson(result.value);
|
|
54920
|
+
const parsed = await readJson(result.value, "User lookup");
|
|
54880
54921
|
if (!parsed.ok)
|
|
54881
54922
|
return parsed.result;
|
|
54882
54923
|
return jsonResult(parsed.value);
|
|
@@ -54889,7 +54930,7 @@ Output shape varies by action; see each action's docs above.`,
|
|
|
54889
54930
|
}, { fetchOptions }).$inspect();
|
|
54890
54931
|
if (!result.ok)
|
|
54891
54932
|
return errorResult(result.error.message);
|
|
54892
|
-
const parsed = await readJson(result.value);
|
|
54933
|
+
const parsed = await readJson(result.value, "Group listing");
|
|
54893
54934
|
if (!parsed.ok)
|
|
54894
54935
|
return parsed.result;
|
|
54895
54936
|
return jsonResult(parsed.value);
|
|
@@ -54902,7 +54943,7 @@ Output shape varies by action; see each action's docs above.`,
|
|
|
54902
54943
|
}, { fetchOptions }).$inspect();
|
|
54903
54944
|
if (!result.ok)
|
|
54904
54945
|
return errorResult(result.error.message);
|
|
54905
|
-
const parsed = await readJson(result.value);
|
|
54946
|
+
const parsed = await readJson(result.value, "Team listing");
|
|
54906
54947
|
if (!parsed.ok)
|
|
54907
54948
|
return parsed.result;
|
|
54908
54949
|
return jsonResult(parsed.value);
|
|
@@ -55187,7 +55228,7 @@ are returned by default; pass \`include\` to override.`,
|
|
|
55187
55228
|
}, { fetchOptions }).$inspect();
|
|
55188
55229
|
if (!r.ok)
|
|
55189
55230
|
return errorResult(`sources: ${r.error.message}`);
|
|
55190
|
-
const parsed = await readJson(r.value);
|
|
55231
|
+
const parsed = await readJson(r.value, "Knowledge base listing");
|
|
55191
55232
|
if (!parsed.ok)
|
|
55192
55233
|
return parsed.result;
|
|
55193
55234
|
result["sources"] = (parsed.value.items ?? []).map((n) => ({
|
|
@@ -55209,7 +55250,7 @@ are returned by default; pass \`include\` to override.`,
|
|
|
55209
55250
|
}, { fetchOptions }).$inspect();
|
|
55210
55251
|
if (!r.ok)
|
|
55211
55252
|
return errorResult(`${key}: ${r.error.message}`);
|
|
55212
|
-
const parsed = await readJson(r.value);
|
|
55253
|
+
const parsed = await readJson(r.value, "Model listing");
|
|
55213
55254
|
if (!parsed.ok)
|
|
55214
55255
|
return parsed.result;
|
|
55215
55256
|
result[key] = (parsed.value.models ?? []).map((m) => ({
|
|
@@ -55560,7 +55601,7 @@ it using the \`Web URL\` from its metadata header (when present).`
|
|
|
55560
55601
|
},
|
|
55561
55602
|
{
|
|
55562
55603
|
name: "pipeshub_directory",
|
|
55563
|
-
description: "Look up people, groups, and teams in PipesHub. One tool with five\nactions — pick the right `action`:\n\n- `whoami` — who is the caller? Use this whenever you need the\n authenticated user's own id, email, or full name (e.g. before\n `get_user` on themselves).\n- `list_users` — search / page through org users.\n- `get_user` — full `User` document for one user (requires `userId`).\n- `list_groups` — list user groups with `userCount`.\n- `list_my_teams` — teams the caller belongs to, with capability flags\n (`canEdit` / `canDelete` / `canManageMembers`).\n\nOutput shape varies by action; see each action's docs above."
|
|
55604
|
+
description: "Look up people, groups, and teams in PipesHub. One tool with five\nactions — pick the right `action`:\n\n- `whoami` — who is the caller? Use this whenever you need the\n authenticated user's own id, email, or full name (e.g. before\n `get_user` on themselves). Errors if the credential is expired\n or revoked.\n- `list_users` — search / page through org users.\n- `get_user` — full `User` document for one user (requires `userId`).\n- `list_groups` — list user groups with `userCount`.\n- `list_my_teams` — teams the caller belongs to, with capability flags\n (`canEdit` / `canDelete` / `canManageMembers`).\n\nOutput shape varies by action; see each action's docs above."
|
|
55564
55605
|
},
|
|
55565
55606
|
{
|
|
55566
55607
|
name: "pipeshub_agents",
|
|
@@ -59193,5 +59234,5 @@ export {
|
|
|
59193
59234
|
app
|
|
59194
59235
|
};
|
|
59195
59236
|
|
|
59196
|
-
//# debugId=
|
|
59237
|
+
//# debugId=B3EADAB5212D24DD64756E2164756E21
|
|
59197
59238
|
//# sourceMappingURL=mcp-server.js.map
|