@pipeshub-ai/mcp 2.3.0 → 2.3.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.
@@ -6,7 +6,7 @@ import { usersGetAllUsers } from "../../funcs/usersGetAllUsers.js";
6
6
  import { usersGetUserById } from "../../funcs/usersGetUserById.js";
7
7
  import { userGroupsGetAllUserGroups } from "../../funcs/userGroupsGetAllUserGroups.js";
8
8
  import { teamsGetUserTeams } from "../../funcs/teamsGetUserTeams.js";
9
- import { decodeBearer, errorResult, jsonResult, readJson, } from "./_helpers.js";
9
+ import { decodeBearer, errorResult, jsonResult, expiredTokenError, readJson, } from "./_helpers.js";
10
10
  const args = {
11
11
  action: z.enum([
12
12
  "whoami",
@@ -15,8 +15,8 @@ const args = {
15
15
  "list_groups",
16
16
  "list_my_teams",
17
17
  ]).describe("What to do:\n"
18
- + "- `whoami` — return the authenticated user's identity (decoded from "
19
- + "the bearer JWT). No other args needed.\n"
18
+ + "- `whoami` — return the authenticated user's identity, confirmed "
19
+ + "against the server. No other args needed.\n"
20
20
  + "- `list_users` — paginated list of org users. Optional `page`, "
21
21
  + "`limit`, `search` (substring match against name or email).\n"
22
22
  + "- `get_user` — full profile for one user. Required `userId`. "
@@ -36,7 +36,8 @@ actions — pick the right \`action\`:
36
36
 
37
37
  - \`whoami\` — who is the caller? Use this whenever you need the
38
38
  authenticated user's own id, email, or full name (e.g. before
39
- \`get_user\` on themselves).
39
+ \`get_user\` on themselves). Errors if the credential is expired
40
+ or revoked.
40
41
  - \`list_users\` — search / page through org users.
41
42
  - \`get_user\` — full \`User\` document for one user (requires \`userId\`).
42
43
  - \`list_groups\` — list user groups with \`userCount\`.
@@ -63,6 +64,53 @@ Output shape varies by action; see each action's docs above.`,
63
64
  + "cannot resolve the caller's identity. Ask the user for "
64
65
  + "their email and use `list_users` with `search`.");
65
66
  }
67
+ // The claims come out of the local token, which proves nothing about
68
+ // whether the server still accepts it — a revoked token carries a
69
+ // perfectly good name and org. Since whoami is the command people run
70
+ // to check "is my login working?", answering from the token alone
71
+ // gives a confident yes in exactly the case that matters.
72
+ //
73
+ // Expiry is checkable offline, so check it first: it is the common
74
+ // case and costs no round-trip.
75
+ const exp = claims["exp"];
76
+ const expired = expiredTokenError(exp);
77
+ if (expired)
78
+ return expired;
79
+ const tokenExpiresAt = typeof exp === "number"
80
+ ? new Date(exp * 1000).toISOString()
81
+ : undefined;
82
+ // Revocation can only be established by asking the server. get_user on
83
+ // the caller's own id needs `user:read`, which whoami's callers already
84
+ // hold, and returns 401 for a rejected credential.
85
+ const userId = claims["userId"];
86
+ let verified = "unchecked";
87
+ let unverifiedReason = "No userId claim in the token, so the identity could not be "
88
+ + "confirmed with the server.";
89
+ if (typeof userId === "string" && userId) {
90
+ const [probe] = await usersGetUserById(client, { id: userId }, {
91
+ fetchOptions,
92
+ }).$inspect();
93
+ if (!probe.ok) {
94
+ unverifiedReason = `Could not reach PipesHub to confirm the `
95
+ + `identity (${probe.error.message}). The details below come `
96
+ + `from the token itself.`;
97
+ }
98
+ else if (probe.value.status === 401) {
99
+ return errorResult("PipesHub rejected this access token (HTTP 401 Unauthorized), "
100
+ + "so the identity in it is no longer valid — it has most "
101
+ + "likely been revoked. Mint a new personal access token "
102
+ + "under Developer Settings → Personal Access Tokens.");
103
+ }
104
+ else if (probe.value.ok) {
105
+ verified = true;
106
+ unverifiedReason = undefined;
107
+ }
108
+ else {
109
+ unverifiedReason = `PipesHub returned HTTP ${probe.value.status} `
110
+ + `when confirming the identity, so it could not be checked. `
111
+ + `The details below come from the token itself.`;
112
+ }
113
+ }
66
114
  return jsonResult({
67
115
  userId: claims["userId"],
68
116
  orgId: claims["orgId"],
@@ -70,6 +118,12 @@ Output shape varies by action; see each action's docs above.`,
70
118
  fullName: claims["fullName"],
71
119
  mobile: claims["mobile"],
72
120
  userSlug: claims["userSlug"],
121
+ tokenExpiresAt,
122
+ // Never `false`: that reads as "the server rejected this identity",
123
+ // which is a different and much more alarming claim than "this was
124
+ // not checked". A rejection returns an error above instead.
125
+ identityVerified: verified,
126
+ note: unverifiedReason,
73
127
  });
74
128
  }
75
129
  case "list_users": {
@@ -80,7 +134,7 @@ Output shape varies by action; see each action's docs above.`,
80
134
  }, { fetchOptions }).$inspect();
81
135
  if (!result.ok)
82
136
  return errorResult(result.error.message);
83
- const parsed = await readJson(result.value);
137
+ const parsed = await readJson(result.value, "User listing");
84
138
  if (!parsed.ok)
85
139
  return parsed.result;
86
140
  return jsonResult(parsed.value);
@@ -96,7 +150,7 @@ Output shape varies by action; see each action's docs above.`,
96
150
  }, { fetchOptions }).$inspect();
97
151
  if (!result.ok)
98
152
  return errorResult(result.error.message);
99
- const parsed = await readJson(result.value);
153
+ const parsed = await readJson(result.value, "User lookup");
100
154
  if (!parsed.ok)
101
155
  return parsed.result;
102
156
  return jsonResult(parsed.value);
@@ -109,7 +163,7 @@ Output shape varies by action; see each action's docs above.`,
109
163
  }, { fetchOptions }).$inspect();
110
164
  if (!result.ok)
111
165
  return errorResult(result.error.message);
112
- const parsed = await readJson(result.value);
166
+ const parsed = await readJson(result.value, "Group listing");
113
167
  if (!parsed.ok)
114
168
  return parsed.result;
115
169
  return jsonResult(parsed.value);
@@ -122,7 +176,7 @@ Output shape varies by action; see each action's docs above.`,
122
176
  }, { fetchOptions }).$inspect();
123
177
  if (!result.ok)
124
178
  return errorResult(result.error.message);
125
- const parsed = await readJson(result.value);
179
+ const parsed = await readJson(result.value, "Team listing");
126
180
  if (!parsed.ok)
127
181
  return parsed.result;
128
182
  return jsonResult(parsed.value);
@@ -1 +1 @@
1
- {"version":3,"file":"pipeshubDirectory.js","sourceRoot":"","sources":["../../../src/mcp-server/tools/pipeshubDirectory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pipeshubDirectory.js","sourceRoot":"","sources":["../../../src/mcp-server/tools/pipeshubDirectory.ts"],"names":[],"mappings":"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"}
@@ -103,8 +103,8 @@ export declare function renderedResult(response: Response): Promise<{
103
103
  }>;
104
104
  declare const args: {
105
105
  mode: z.ZodDefault<z.ZodEnum<{
106
- content: "content";
107
106
  navigate: "navigate";
107
+ content: "content";
108
108
  lookup: "lookup";
109
109
  }>>;
110
110
  recordId: z.ZodOptional<z.ZodString>;
@@ -61,7 +61,7 @@ When presenting results to the user, link each record using its
61
61
  }, { fetchOptions: { signal: ctx.signal } }).$inspect();
62
62
  if (!result.ok)
63
63
  return errorResult(result.error.message);
64
- const parsed = await readJson(result.value);
64
+ const parsed = await readJson(result.value, "PipesHub search");
65
65
  if (!parsed.ok)
66
66
  return parsed.result;
67
67
  const sr = parsed.value.searchResponse ?? {};
@@ -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,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEjF,MAAM,IAAI,GAAG;IACX,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAC/B,yEAAyE,CAC1E;IACD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACzD,oEAAoE;UAChE,iEAAiE,CACtE;IACD,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAC3C,yDAAyD;UACrD,4DAA4D,CACjE;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAgC;IAC9D,IAAI,EAAE,iBAAiB;IACvB,WAAW,EACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAiCuB;IACzB,MAAM,EAAE,CAAC,MAAM,CAAC;IAChB,WAAW,EAAE;QACX,KAAK,EAAE,iBAAiB;QACxB,eAAe,EAAE,KAAK;QACtB,cAAc,EAAE,IAAI;QACpB,aAAa,EAAE,IAAI;QACnB,YAAY,EAAE,KAAK;KACpB;IACD,IAAI;IACJ,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QAChC,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,oBAAoB,CAAC,MAAM,EAAE;YAClD,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS;SAC7D,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,MAAM,MAAM,GAAG,MAAM,QAAQ,CAQ1B,MAAM,CAAC,KAAK,CAAC,CAAC;QACjB,IAAI,CAAC,MAAM,CAAC,EAAE;YAAE,OAAO,MAAM,CAAC,MAAM,CAAC;QAErC,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,cAAc,IAAI,EAAE,CAAC;QAC7C,OAAO,UAAU,CAAC;YAChB,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ;YAC/B,IAAI,EAAE,CAAC,EAAE,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC;YACjD,aAAa,EAAE,CAAC,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;gBACjD,QAAQ,EAAE,CAAC,CAAC,IAAI;gBAChB,UAAU,EAAE,CAAC,CAAC,UAAU;gBACxB,SAAS,EAAE,CAAC,CAAC,aAAa;gBAC1B,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,MAAM,EAAE,CAAC,CAAC,MAAM;aACjB,CAAC,CAAC;SACJ,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
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,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEjF,MAAM,IAAI,GAAG;IACX,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAC/B,yEAAyE,CAC1E;IACD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACzD,oEAAoE;UAChE,iEAAiE,CACtE;IACD,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAC3C,yDAAyD;UACrD,4DAA4D,CACjE;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAgC;IAC9D,IAAI,EAAE,iBAAiB;IACvB,WAAW,EACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAiCuB;IACzB,MAAM,EAAE,CAAC,MAAM,CAAC;IAChB,WAAW,EAAE;QACX,KAAK,EAAE,iBAAiB;QACxB,eAAe,EAAE,KAAK;QACtB,cAAc,EAAE,IAAI;QACpB,aAAa,EAAE,IAAI;QACnB,YAAY,EAAE,KAAK;KACpB;IACD,IAAI;IACJ,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QAChC,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,oBAAoB,CAAC,MAAM,EAAE;YAClD,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS;SAC7D,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,MAAM,MAAM,GAAG,MAAM,QAAQ,CAQ1B,MAAM,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;QACpC,IAAI,CAAC,MAAM,CAAC,EAAE;YAAE,OAAO,MAAM,CAAC,MAAM,CAAC;QAErC,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,cAAc,IAAI,EAAE,CAAC;QAC7C,OAAO,UAAU,CAAC;YAChB,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ;YAC/B,IAAI,EAAE,CAAC,EAAE,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC;YACjD,aAAa,EAAE,CAAC,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;gBACjD,QAAQ,EAAE,CAAC,CAAC,IAAI;gBAChB,UAAU,EAAE,CAAC,CAAC,UAAU;gBACxB,SAAS,EAAE,CAAC,CAAC,aAAa;gBAC1B,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,MAAM,EAAE,CAAC,CAAC,MAAM;aACjB,CAAC,CAAC;SACJ,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
@@ -50,7 +50,7 @@ are returned by default; pass \`include\` to override.`,
50
50
  }, { fetchOptions }).$inspect();
51
51
  if (!r.ok)
52
52
  return errorResult(`sources: ${r.error.message}`);
53
- const parsed = await readJson(r.value);
53
+ const parsed = await readJson(r.value, "Knowledge base listing");
54
54
  if (!parsed.ok)
55
55
  return parsed.result;
56
56
  result["sources"] = (parsed.value.items ?? []).map((n) => ({
@@ -72,7 +72,7 @@ are returned by default; pass \`include\` to override.`,
72
72
  }, { fetchOptions }).$inspect();
73
73
  if (!r.ok)
74
74
  return errorResult(`${key}: ${r.error.message}`);
75
- const parsed = await readJson(r.value);
75
+ const parsed = await readJson(r.value, "Model listing");
76
76
  if (!parsed.ok)
77
77
  return parsed.result;
78
78
  result[key] = (parsed.value.models ?? []).map((m) => ({
@@ -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,oCAAoC,EAAE,MAAM,qDAAqD,CAAC;AAC3G,OAAO,EAAE,yCAAyC,EAAE,MAAM,0DAA0D,CAAC;AAErH,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAElE,MAAM,IAAI,GAAG;IACX,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,WAAW,EAAE,iBAAiB,CAAC,CAAC,CAAC;SAClE,QAAQ,EAAE;SACV,QAAQ,CACP,oEAAoE;UAChE,gEAAgE,CACrE;CACJ,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAgC;IAC/D,IAAI,EAAE,kBAAkB;IACxB,WAAW,EACT;;;;;;;;;;;;;;;;;uDAiBmD;IACrD,MAAM,EAAE,CAAC,MAAM,CAAC;IAChB,WAAW,EAAE;QACX,KAAK,EAAE,qCAAqC;QAC5C,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,YAAY,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO;eACtB,CAAC,SAAS,EAAE,WAAW,CAAW,CAAC;QACzC,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE,CAAE,OAA6B,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAEvE,MAAM,MAAM,GAA4B,EAAE,CAAC;QAE3C,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YACpB,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,oCAAoC,CAAC,MAAM,EAAE;gBAC7D,IAAI,EAAE,CAAC;gBACP,KAAK,EAAE,GAAG;aACX,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;YAChC,IAAI,CAAC,CAAC,CAAC,EAAE;gBAAE,OAAO,WAAW,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7D,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAoB,CAAC,CAAC,KAAK,CAAC,CAAC;YAC1D,IAAI,CAAC,MAAM,CAAC,EAAE;gBAAE,OAAO,MAAM,CAAC,MAAM,CAAC;YACrC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;gBAC9D,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,IAAI,EAAE,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,WAAW;gBAC1D,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,WAAW,EAAE,CAAC,CAAC,WAAW;aAC3B,CAAC,CAAC,CAAC;QACN,CAAC;QAED,KACE,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI;YACxB,CAAC,WAAW,EAAE,KAAK,CAAU;YAC7B,CAAC,iBAAiB,EAAE,WAAW,CAAU;SAC1C,EACD,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;gBAAE,SAAS;YACzB,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,yCAAyC,CAAC,MAAM,EAAE;gBAClE,SAAS;aACV,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;YAChC,IAAI,CAAC,CAAC,CAAC,EAAE;gBAAE,OAAO,WAAW,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5D,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAqB,CAAC,CAAC,KAAK,CAAC,CAAC;YAC3D,IAAI,CAAC,MAAM,CAAC,EAAE;gBAAE,OAAO,MAAM,CAAC,MAAM,CAAC;YACrC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;gBACzD,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,YAAY,EAAE,CAAC,CAAC,YAAY;gBAC5B,WAAW,EAAE,CAAC,CAAC,WAAW;aAC3B,CAAC,CAAC,CAAC;QACN,CAAC;QAED,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"pipeshubSources.js","sourceRoot":"","sources":["../../../src/mcp-server/tools/pipeshubSources.ts"],"names":[],"mappings":"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"}
@@ -7,8 +7,8 @@ export declare const AvailableModelsResponseStatus: {
7
7
  };
8
8
  export type AvailableModelsResponseStatus = ClosedEnum<typeof AvailableModelsResponseStatus>;
9
9
  export declare const AvailableModelsResponseStatus$zodSchema: z.ZodEnum<{
10
- error: "error";
11
10
  success: "success";
11
+ error: "error";
12
12
  }>;
13
13
  /**
14
14
  * Response from `GET /configurationManager/ai-models/available/{modelType}`.
@@ -35,8 +35,8 @@ export declare const ConversationStatus: {
35
35
  */
36
36
  export type ConversationStatus = ClosedEnum<typeof ConversationStatus>;
37
37
  export declare const ConversationStatus$zodSchema: z.ZodEnum<{
38
- Complete: "Complete";
39
38
  Inprogress: "Inprogress";
39
+ Complete: "Complete";
40
40
  Failed: "Failed";
41
41
  None: "None";
42
42
  }>;
@@ -8,8 +8,8 @@ export declare const UserTeamsResponseStatus: {
8
8
  };
9
9
  export type UserTeamsResponseStatus = ClosedEnum<typeof UserTeamsResponseStatus>;
10
10
  export declare const UserTeamsResponseStatus$zodSchema: z.ZodEnum<{
11
- error: "error";
12
11
  success: "success";
12
+ error: "error";
13
13
  }>;
14
14
  /**
15
15
  * Paginated response from `GET /teams/user/teams`.
package/esm/tool-names.js CHANGED
@@ -22,7 +22,7 @@ export const toolNames = [
22
22
  },
23
23
  {
24
24
  "name": "pipeshub_directory",
25
- "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."
25
+ "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."
26
26
  },
27
27
  {
28
28
  "name": "pipeshub_agents",
@@ -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,80BAA80B;KAC91B;IACD;QACE,MAAM,EAAE,eAAe;QACvB,aAAa,EAAE,w+EAAw+E;KACx/E;IACD;QACE,MAAM,EAAE,iBAAiB;QACzB,aAAa,EAAE,uiDAAuiD;KACvjD;IACD;QACE,MAAM,EAAE,0BAA0B;QAClC,aAAa,EAAE,8dAA8d;KAC9e;IACD;QACE,MAAM,EAAE,6BAA6B;QACrC,aAAa,EAAE,06HAA06H;KAC17H;IACD;QACE,MAAM,EAAE,oBAAoB;QAC5B,aAAa,EAAE,onBAAonB;KACpoB;IACD;QACE,MAAM,EAAE,iBAAiB;QACzB,aAAa,EAAE,82CAA82C;KAC93C;CACF,CAAC"}
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,80BAA80B;KAC91B;IACD;QACE,MAAM,EAAE,eAAe;QACvB,aAAa,EAAE,w+EAAw+E;KACx/E;IACD;QACE,MAAM,EAAE,iBAAiB;QACzB,aAAa,EAAE,uiDAAuiD;KACvjD;IACD;QACE,MAAM,EAAE,0BAA0B;QAClC,aAAa,EAAE,8dAA8d;KAC9e;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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipeshub-ai/mcp",
3
- "version": "2.3.0",
3
+ "version": "2.3.1",
4
4
  "author": "Pipeshub",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -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.3.0
16
+ ARG PIPESHUB_CLI_VERSION=2.3.1
17
17
  RUN npm install -g "@pipeshub-ai/mcp@${PIPESHUB_CLI_VERSION}" \
18
18
  && pipeshub --help >/dev/null
19
19
 
package/src/cli/client.ts CHANGED
@@ -48,7 +48,14 @@ function statusToExit(status: number): number {
48
48
  export function toolErrorToExit(message: string): number {
49
49
  const m = message.match(/\(HTTP\s+(\d{3})/i);
50
50
  if (m && m[1] !== undefined) return statusToExit(Number(m[1]));
51
- if (/\b401\b|unautheni?ticated|no token provided/i.test(message)) {
51
+ // `token expired` / `been revoked` cover the credential failures that are
52
+ // established without an HTTP round-trip — whoami checks the token's own
53
+ // expiry offline, so there is no status code to key off, but "your
54
+ // credential is not valid" is exactly what exit 3 means.
55
+ if (
56
+ /\b401\b|unautheni?ticated|no token provided|token expired|been revoked/i
57
+ .test(message)
58
+ ) {
52
59
  return EXIT.UNAUTHENTICATED;
53
60
  }
54
61
  if (/\b403\b|not have permission|forbidden/i.test(message)) {
@@ -15,11 +15,23 @@ import {
15
15
 
16
16
  /**
17
17
  * Parse a fetch Response as JSON, returning a CallToolResult error when the
18
- * body is missing / malformed.
18
+ * status is not ok, or the body is missing / malformed.
19
+ *
20
+ * The status check has to happen here rather than in each caller. The SDK funcs
21
+ * are generated with `errorCodes: []`, so `result.ok` reports transport
22
+ * failures only and a 401 arrives looking exactly like a success. Parsing that
23
+ * body yields an envelope with no results in it, which every caller then
24
+ * reports as an empty corpus — a failed credential becomes "no documents
25
+ * found". Guarding at the single point where a body is turned into a value
26
+ * closes that for every present and future caller.
19
27
  */
20
28
  export async function readJson<T = unknown>(
21
29
  response: Response,
30
+ context = "PipesHub request",
22
31
  ): Promise<{ ok: true; value: T } | { ok: false; result: CallToolResult }> {
32
+ const httpErr = await httpErrorResult(response, context);
33
+ if (httpErr) return { ok: false, result: httpErr };
34
+
23
35
  const text = await response.text();
24
36
  if (!text) {
25
37
  return {
@@ -48,6 +60,24 @@ export async function readJson<T = unknown>(
48
60
  }
49
61
  }
50
62
 
63
+ /**
64
+ * Reject an access token whose own expiry has already passed.
65
+ *
66
+ * Expiry is the one part of a credential's validity that can be established
67
+ * without asking the server, so it is worth checking before spending a
68
+ * round-trip — and it still answers when the server is unreachable. Returns
69
+ * `null` when the token is unexpired or carries no usable `exp`.
70
+ */
71
+ export function expiredTokenError(exp: unknown): CallToolResult | null {
72
+ if (typeof exp !== "number" || !Number.isFinite(exp)) return null;
73
+ if (exp * 1000 > Date.now()) return null;
74
+ return errorResult(
75
+ `The access token expired on ${new Date(exp * 1000).toISOString()}. `
76
+ + "Mint a new personal access token in PipesHub under "
77
+ + "Developer Settings → Personal Access Tokens.",
78
+ );
79
+ }
80
+
51
81
  /** Return a CallToolResult holding a single JSON-stringified text block. */
52
82
  export function jsonResult(value: unknown): CallToolResult {
53
83
  return {
@@ -105,7 +135,12 @@ export async function httpErrorResult(
105
135
  }
106
136
  }
107
137
 
108
- const detail = message ? ` ${message.slice(0, 400)}` : "";
138
+ // The server's reason rarely ends in punctuation, which runs it straight
139
+ // into the hint below ("Invalid token Check that ...").
140
+ const reason = message.slice(0, 400).trim();
141
+ const detail = reason
142
+ ? ` ${/[.!?]$/.test(reason) ? reason : `${reason}.`}`
143
+ : "";
109
144
  const auth = (response.status === 401 || response.status === 403)
110
145
  ? " Check that the bearer token / credentials are valid and not expired."
111
146
  : "";
@@ -122,7 +157,12 @@ export async function httpErrorResult(
122
157
  export async function readValidated<T>(
123
158
  response: Response,
124
159
  schema: z.ZodType<T>,
160
+ context = "PipesHub request",
125
161
  ): Promise<{ ok: true; value: T } | { ok: false; result: CallToolResult }> {
162
+ // Same reasoning as readJson: never let a non-2xx body reach the parser.
163
+ const httpErr = await httpErrorResult(response, context);
164
+ if (httpErr) return { ok: false, result: httpErr };
165
+
126
166
  const text = await response.text();
127
167
  if (!text) {
128
168
  return { ok: false, result: errorResult("Empty response from server") };
@@ -12,6 +12,7 @@ import {
12
12
  decodeBearer,
13
13
  errorResult,
14
14
  jsonResult,
15
+ expiredTokenError,
15
16
  readJson,
16
17
  } from "./_helpers.js";
17
18
 
@@ -24,8 +25,8 @@ const args = {
24
25
  "list_my_teams",
25
26
  ]).describe(
26
27
  "What to do:\n"
27
- + "- `whoami` — return the authenticated user's identity (decoded from "
28
- + "the bearer JWT). No other args needed.\n"
28
+ + "- `whoami` — return the authenticated user's identity, confirmed "
29
+ + "against the server. No other args needed.\n"
29
30
  + "- `list_users` — paginated list of org users. Optional `page`, "
30
31
  + "`limit`, `search` (substring match against name or email).\n"
31
32
  + "- `get_user` — full profile for one user. Required `userId`. "
@@ -56,7 +57,8 @@ actions — pick the right \`action\`:
56
57
 
57
58
  - \`whoami\` — who is the caller? Use this whenever you need the
58
59
  authenticated user's own id, email, or full name (e.g. before
59
- \`get_user\` on themselves).
60
+ \`get_user\` on themselves). Errors if the credential is expired
61
+ or revoked.
60
62
  - \`list_users\` — search / page through org users.
61
63
  - \`get_user\` — full \`User\` document for one user (requires \`userId\`).
62
64
  - \`list_groups\` — list user groups with \`userCount\`.
@@ -86,6 +88,56 @@ Output shape varies by action; see each action's docs above.`,
86
88
  + "their email and use `list_users` with `search`.",
87
89
  );
88
90
  }
91
+ // The claims come out of the local token, which proves nothing about
92
+ // whether the server still accepts it — a revoked token carries a
93
+ // perfectly good name and org. Since whoami is the command people run
94
+ // to check "is my login working?", answering from the token alone
95
+ // gives a confident yes in exactly the case that matters.
96
+ //
97
+ // Expiry is checkable offline, so check it first: it is the common
98
+ // case and costs no round-trip.
99
+ const exp = claims["exp"];
100
+ const expired = expiredTokenError(exp);
101
+ if (expired) return expired;
102
+ const tokenExpiresAt = typeof exp === "number"
103
+ ? new Date(exp * 1000).toISOString()
104
+ : undefined;
105
+
106
+ // Revocation can only be established by asking the server. get_user on
107
+ // the caller's own id needs `user:read`, which whoami's callers already
108
+ // hold, and returns 401 for a rejected credential.
109
+ const userId = claims["userId"];
110
+ let verified: true | "unchecked" = "unchecked";
111
+ let unverifiedReason: string | undefined =
112
+ "No userId claim in the token, so the identity could not be "
113
+ + "confirmed with the server.";
114
+
115
+ if (typeof userId === "string" && userId) {
116
+ const [probe] = await usersGetUserById(client, { id: userId }, {
117
+ fetchOptions,
118
+ }).$inspect();
119
+
120
+ if (!probe.ok) {
121
+ unverifiedReason = `Could not reach PipesHub to confirm the `
122
+ + `identity (${probe.error.message}). The details below come `
123
+ + `from the token itself.`;
124
+ } else if (probe.value.status === 401) {
125
+ return errorResult(
126
+ "PipesHub rejected this access token (HTTP 401 Unauthorized), "
127
+ + "so the identity in it is no longer valid — it has most "
128
+ + "likely been revoked. Mint a new personal access token "
129
+ + "under Developer Settings → Personal Access Tokens.",
130
+ );
131
+ } else if (probe.value.ok) {
132
+ verified = true;
133
+ unverifiedReason = undefined;
134
+ } else {
135
+ unverifiedReason = `PipesHub returned HTTP ${probe.value.status} `
136
+ + `when confirming the identity, so it could not be checked. `
137
+ + `The details below come from the token itself.`;
138
+ }
139
+ }
140
+
89
141
  return jsonResult({
90
142
  userId: claims["userId"],
91
143
  orgId: claims["orgId"],
@@ -93,6 +145,12 @@ Output shape varies by action; see each action's docs above.`,
93
145
  fullName: claims["fullName"],
94
146
  mobile: claims["mobile"],
95
147
  userSlug: claims["userSlug"],
148
+ tokenExpiresAt,
149
+ // Never `false`: that reads as "the server rejected this identity",
150
+ // which is a different and much more alarming claim than "this was
151
+ // not checked". A rejection returns an error above instead.
152
+ identityVerified: verified,
153
+ note: unverifiedReason,
96
154
  });
97
155
  }
98
156
 
@@ -103,7 +161,7 @@ Output shape varies by action; see each action's docs above.`,
103
161
  search: args.search,
104
162
  }, { fetchOptions }).$inspect();
105
163
  if (!result.ok) return errorResult(result.error.message);
106
- const parsed = await readJson(result.value);
164
+ const parsed = await readJson(result.value, "User listing");
107
165
  if (!parsed.ok) return parsed.result;
108
166
  return jsonResult(parsed.value);
109
167
  }
@@ -120,7 +178,7 @@ Output shape varies by action; see each action's docs above.`,
120
178
  id: args.userId,
121
179
  }, { fetchOptions }).$inspect();
122
180
  if (!result.ok) return errorResult(result.error.message);
123
- const parsed = await readJson(result.value);
181
+ const parsed = await readJson(result.value, "User lookup");
124
182
  if (!parsed.ok) return parsed.result;
125
183
  return jsonResult(parsed.value);
126
184
  }
@@ -132,7 +190,7 @@ Output shape varies by action; see each action's docs above.`,
132
190
  search: args.search,
133
191
  }, { fetchOptions }).$inspect();
134
192
  if (!result.ok) return errorResult(result.error.message);
135
- const parsed = await readJson(result.value);
193
+ const parsed = await readJson(result.value, "Group listing");
136
194
  if (!parsed.ok) return parsed.result;
137
195
  return jsonResult(parsed.value);
138
196
  }
@@ -144,7 +202,7 @@ Output shape varies by action; see each action's docs above.`,
144
202
  search: args.search,
145
203
  }, { fetchOptions }).$inspect();
146
204
  if (!result.ok) return errorResult(result.error.message);
147
- const parsed = await readJson(result.value);
205
+ const parsed = await readJson(result.value, "Team listing");
148
206
  if (!parsed.ok) return parsed.result;
149
207
  return jsonResult(parsed.value);
150
208
  }
@@ -80,7 +80,7 @@ When presenting results to the user, link each record using its
80
80
  status?: string;
81
81
  message?: string;
82
82
  };
83
- }>(result.value);
83
+ }>(result.value, "PipesHub search");
84
84
  if (!parsed.ok) return parsed.result;
85
85
 
86
86
  const sr = parsed.value.searchResponse ?? {};
@@ -57,7 +57,7 @@ are returned by default; pass \`include\` to override.`,
57
57
  limit: 200,
58
58
  }, { fetchOptions }).$inspect();
59
59
  if (!r.ok) return errorResult(`sources: ${r.error.message}`);
60
- const parsed = await readJson<{ items?: any[] }>(r.value);
60
+ const parsed = await readJson<{ items?: any[] }>(r.value, "Knowledge base listing");
61
61
  if (!parsed.ok) return parsed.result;
62
62
  result["sources"] = (parsed.value.items ?? []).map((n: any) => ({
63
63
  id: n.id,
@@ -79,7 +79,7 @@ are returned by default; pass \`include\` to override.`,
79
79
  modelType,
80
80
  }, { fetchOptions }).$inspect();
81
81
  if (!r.ok) return errorResult(`${key}: ${r.error.message}`);
82
- const parsed = await readJson<{ models?: any[] }>(r.value);
82
+ const parsed = await readJson<{ models?: any[] }>(r.value, "Model listing");
83
83
  if (!parsed.ok) return parsed.result;
84
84
  result[key] = (parsed.value.models ?? []).map((m: any) => ({
85
85
  modelKey: m.modelKey,
package/src/tool-names.ts CHANGED
@@ -22,7 +22,7 @@ export const toolNames: Array<{ name: string; description: string }>= [
22
22
  },
23
23
  {
24
24
  "name": "pipeshub_directory",
25
- "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."
25
+ "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."
26
26
  },
27
27
  {
28
28
  "name": "pipeshub_agents",