@egain/egain-mcp-server 1.0.6 → 1.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +22 -0
  2. package/bin/mcp-server.js +201 -171
  3. package/bin/mcp-server.js.map +9 -9
  4. package/esm/src/funcs/getPortals.d.ts +48 -7
  5. package/esm/src/funcs/getPortals.d.ts.map +1 -1
  6. package/esm/src/funcs/getPortals.js +48 -7
  7. package/esm/src/funcs/getPortals.js.map +1 -1
  8. package/esm/src/hooks/auth-hook.d.ts +6 -1
  9. package/esm/src/hooks/auth-hook.d.ts.map +1 -1
  10. package/esm/src/hooks/auth-hook.js +189 -197
  11. package/esm/src/hooks/auth-hook.js.map +1 -1
  12. package/esm/src/hooks/tooltip-images.d.ts +10 -0
  13. package/esm/src/hooks/tooltip-images.d.ts.map +1 -0
  14. package/esm/src/hooks/tooltip-images.js +12 -0
  15. package/esm/src/hooks/tooltip-images.js.map +1 -0
  16. package/esm/src/lib/config.d.ts +2 -2
  17. package/esm/src/lib/config.js +2 -2
  18. package/esm/src/lib/config.js.map +1 -1
  19. package/esm/src/mcp-server/mcp-server.js +1 -1
  20. package/esm/src/mcp-server/mcp-server.js.map +1 -1
  21. package/esm/src/mcp-server/server.js +1 -1
  22. package/esm/src/mcp-server/server.js.map +1 -1
  23. package/esm/src/mcp-server/tools/getPortals.d.ts.map +1 -1
  24. package/esm/src/mcp-server/tools/getPortals.js +48 -7
  25. package/esm/src/mcp-server/tools/getPortals.js.map +1 -1
  26. package/esm/src/models/getmyportalsop.d.ts +1 -1
  27. package/esm/src/models/getmyportalsop.d.ts.map +1 -1
  28. package/manifest.json +2 -2
  29. package/package.json +1 -1
  30. package/src/funcs/getPortals.ts +48 -7
  31. package/src/hooks/auth-hook.ts +200 -224
  32. package/src/lib/config.ts +2 -2
  33. package/src/mcp-server/mcp-server.ts +1 -1
  34. package/src/mcp-server/server.ts +1 -1
  35. package/src/mcp-server/tools/getPortals.ts +48 -7
  36. package/src/models/getmyportalsop.ts +1 -1
@@ -11,14 +11,55 @@ export const tool$getPortals = {
11
11
  name: "get-portals",
12
12
  description: `Get All Portals Accessible To User
13
13
 
14
+ Get All Portals Accessible to User
15
+
14
16
  ## Overview
15
- The Get All Portals Accessible to User API allows a user to fetch all portals accessible to user across all department.
16
- * If no access tags are specified for a portal, then any user can access the portal.
17
- * If access tags are specified for a portal, users with a user profile that allows access have access to the portal. For users with multiple user profiles, the user profile that allows access does not need to be the active user profile.
18
- * All the global users(partition) cannot be assigned user profiles; their access is limited to portals without access restrictions.
19
- * The only articles returned are associated to an Article type when the parameter, “Include in browse on portals” is set to "Yes".
20
- * When the "shortUrlTemplate" query parameter is provided, the API filters accessible portals according to the specified language and template name. Portal Short URL specific to to the "shortUrlTemplate" query parameter value is returned in the response.
21
- * When there is no short URL available for a specific language, the API returns a portal object with an empty "shortURL" field.
17
+ The Get All Portals Accessible to User API allows a user to fetch all portals accessible to the user across all departments.
18
+ - If no access tags are specified for a portal, any user can access the portal.
19
+ - If access tags are specified for a portal, users with a user profile that allows access can access the portal. For users with multiple user profiles, the user profile that allows access does not need to be the active user profile.
20
+ - Global users (partition) cannot be assigned user profiles; their access is limited to portals without access restrictions.
21
+ - The only articles returned are associated to an Article type when the parameter “Include in browse on portals” is set to "Yes".
22
+ - When the \`shortUrlTemplate\` query parameter is provided, the API filters accessible portals according to the specified language and template name. A portal short URL specific to the \`shortUrlTemplate\` value is returned in the response when available. If there is no short URL for a language, the portal object returns an empty \`shortURL\` field.
23
+
24
+ ## Pagination behavior (CRITICAL for AI assistants)
25
+
26
+ **IMPORTANT**: This endpoint is paginated. When searching for a portal by name or listing portals, you MUST automatically fetch ALL pages before concluding that a portal doesn't exist.
27
+
28
+ ### Automatic pagination is REQUIRED when:
29
+ - User asks to find a portal by name (e.g., "business portal", "Master portal")
30
+ - User requests to list or see all portals
31
+ - You need to resolve a natural portal name to its ID
32
+
33
+ ### How to detect more pages exist:
34
+ The response includes \`paginationInfo\` with:
35
+ - \`count\`: Total number of items across all pages
36
+ - \`pagenum\`: Current page number
37
+ - \`pagesize\`: Items per page (default: 25)
38
+
39
+ **Check for more pages if ANY of these are true:**
40
+ 1. The number of portals returned equals \`pagesize\` (e.g., exactly 25 portals returned)
41
+ 2. \`paginationInfo.count > (pagenum * pagesize)\` - there are more items beyond this page
42
+ 3. The response includes a \`link\` array with a \`next\` relation
43
+
44
+ ### Required pagination workflow:
45
+ 1. Start with \`$pagenum=1\` and \`$pagesize=25\` (default)
46
+ 2. After receiving the response, check \`paginationInfo\`
47
+ 3. **If more pages exist** (using the checks above), automatically call this endpoint again with \`$pagenum=2\`, then \`$pagenum=3\`, etc.
48
+ 4. Continue incrementing \`$pagenum\` until:
49
+ - A page returns fewer portals than \`pagesize\` (indicating the last page)
50
+ - A page returns zero portals
51
+ - \`pagenum * pagesize >= paginationInfo.count\` (if count represents total items)
52
+ 5. Merge all portals from all pages by unique portal ID
53
+ 6. Only then search through the complete merged list or report results to the user
54
+
55
+ ### Example scenario:
56
+ If you search for "business portal" and the first page returns 25 portals but none match:
57
+ - DO NOT immediately tell the user the portal doesn't exist
58
+ - Check \`paginationInfo.count\` - if it's > 25, automatically fetch page 2
59
+ - Continue fetching until all pages are retrieved
60
+ - Search the complete merged list before concluding the portal doesn't exist
61
+
62
+ This ensures reliable portal name-to-ID resolution and prevents false "not found" errors.
22
63
  `,
23
64
  annotations: {
24
65
  "destructiveHint": false,
@@ -1 +1 @@
1
- {"version":3,"file":"getPortals.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/getPortals.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAkB,MAAM,aAAa,CAAC;AAE3D,MAAM,IAAI,GAAG;IACX,OAAO,EAAE,6BAA6B;CACvC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAgC;IAC1D,IAAI,EAAE,aAAa;IACnB,WAAW,EAAE;;;;;;;;;;CAUd;IACC,WAAW,EAAE;QACX,iBAAiB,EAAE,KAAK;QACxB,gBAAgB,EAAE,KAAK;QACvB,eAAe,EAAE,KAAK;QACtB,cAAc,EAAE,IAAI;KACrB;IACD,IAAI;IACJ,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,UAAU,CACxC,MAAM,EACN,IAAI,CAAC,OAAO,EACZ,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,CACzC,CAAC,QAAQ,EAAE,CAAC;QAEb,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;gBACvD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAE3B,OAAO,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"getPortals.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/getPortals.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAkB,MAAM,aAAa,CAAC;AAE3D,MAAM,IAAI,GAAG;IACX,OAAO,EAAE,6BAA6B;CACvC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAgC;IAC1D,IAAI,EAAE,aAAa;IACnB,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmDd;IACC,WAAW,EAAE;QACX,iBAAiB,EAAE,KAAK;QACxB,gBAAgB,EAAE,KAAK;QACvB,eAAe,EAAE,KAAK;QACtB,cAAc,EAAE,IAAI;KACrB;IACD,IAAI;IACJ,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,UAAU,CACxC,MAAM,EACN,IAAI,CAAC,OAAO,EACZ,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,CACzC,CAAC,QAAQ,EAAE,CAAC;QAEb,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;gBACvD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAE3B,OAAO,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;CACF,CAAC"}
@@ -13,8 +13,8 @@ export type GetMyPortalsRequest = {
13
13
  shortUrlTemplate?: string | undefined;
14
14
  Dollar_sort?: SortIdNameDepartment | undefined;
15
15
  Dollar_order?: Order | undefined;
16
- Dollar_pagenum?: number | undefined;
17
16
  Dollar_pagesize?: number | undefined;
17
+ Dollar_pagenum?: number | undefined;
18
18
  };
19
19
  export declare const GetMyPortalsRequest$zodSchema: z.ZodType<GetMyPortalsRequest, z.ZodTypeDef, unknown>;
20
20
  export type GetMyPortalsResponse = {
@@ -1 +1 @@
1
- {"version":3,"file":"getmyportalsop.d.ts","sourceRoot":"","sources":["../../../src/models/getmyportalsop.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAE,cAAc,EAA4B,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EACL,oBAAoB,EAErB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,+BAA+B,EAEhC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAmB,MAAM,YAAY,CAAC;AACpD,OAAO,EACL,oBAAoB,EAErB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,aAAa,EAA2B,MAAM,oBAAoB,CAAC;AAE5E,MAAM,MAAM,mBAAmB,GAAG;IAChC,cAAc,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IAC5C,WAAW,EAAE,+BAA+B,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,WAAW,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAC/C,YAAY,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;IACjC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACtC,CAAC;AAEF,eAAO,MAAM,6BAA6B,EAAE,CAAC,CAAC,OAAO,CACnD,mBAAmB,EACnB,CAAC,CAAC,UAAU,EACZ,OAAO,CAqBP,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,QAAQ,CAAC;IACtB,oBAAoB,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACxD,aAAa,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;CAC3C,CAAC;AAEF,eAAO,MAAM,8BAA8B,EAAE,CAAC,CAAC,OAAO,CACpD,oBAAoB,EACpB,CAAC,CAAC,UAAU,EACZ,OAAO,CAOP,CAAC"}
1
+ {"version":3,"file":"getmyportalsop.d.ts","sourceRoot":"","sources":["../../../src/models/getmyportalsop.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAE,cAAc,EAA4B,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EACL,oBAAoB,EAErB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,+BAA+B,EAEhC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAmB,MAAM,YAAY,CAAC;AACpD,OAAO,EACL,oBAAoB,EAErB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,aAAa,EAA2B,MAAM,oBAAoB,CAAC;AAE5E,MAAM,MAAM,mBAAmB,GAAG;IAChC,cAAc,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IAC5C,WAAW,EAAE,+BAA+B,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,WAAW,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAC/C,YAAY,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;IACjC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC,CAAC;AAEF,eAAO,MAAM,6BAA6B,EAAE,CAAC,CAAC,OAAO,CACnD,mBAAmB,EACnB,CAAC,CAAC,UAAU,EACZ,OAAO,CAqBP,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,QAAQ,CAAC;IACtB,oBAAoB,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACxD,aAAa,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;CAC3C,CAAC;AAEF,eAAO,MAAM,8BAA8B,EAAE,CAAC,CAAC,OAAO,CACpD,oBAAoB,EACpB,CAAC,CAAC,UAAU,EACZ,OAAO,CAOP,CAAC"}
package/manifest.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "dxt_version": "0.1",
3
3
  "name": "@egain/egain-mcp-server",
4
- "version": "1.0.6",
4
+ "version": "1.0.12",
5
5
  "description": "",
6
6
  "long_description": "eGain Portal, Retrieve, Search, Answers APIs: Enterprise knowledge APIs for managing portals, searching content, retrieving AI-powered answers, and accessing content chunks for custom integrations.",
7
7
  "author": {
@@ -40,7 +40,7 @@
40
40
  },
41
41
  {
42
42
  "name": "get-portals",
43
- "description": "Get All Portals Accessible To User\n\n## Overview\n The Get All Portals Accessible to User API allows a user to fetch all portals accessible to user across all department.\n * If no access tags are specified for a portal, then any user can access the portal.\n * If access tags are specified for a portal, users with a user profile that allows access have access to the portal. For users with multiple user profiles, the user profile that allows access does not need to be the active user profile.\n * All the global users(partition) cannot be assigned user profiles; their access is limited to portals without access restrictions.\n * The only articles returned are associated to an Article type when the parameter, “Include in browse on portals” is set to \"Yes\".\n * When the \"shortUrlTemplate\" query parameter is provided, the API filters accessible portals according to the specified language and template name. Portal Short URL specific to to the \"shortUrlTemplate\" query parameter value is returned in the response.\n * When there is no short URL available for a specific language, the API returns a portal object with an empty \"shortURL\" field.\n"
43
+ "description": "Get All Portals Accessible To User\n\nGet All Portals Accessible to User\n\n## Overview\nThe Get All Portals Accessible to User API allows a user to fetch all portals accessible to the user across all departments.\n- If no access tags are specified for a portal, any user can access the portal.\n- If access tags are specified for a portal, users with a user profile that allows access can access the portal. For users with multiple user profiles, the user profile that allows access does not need to be the active user profile.\n- Global users (partition) cannot be assigned user profiles; their access is limited to portals without access restrictions.\n- The only articles returned are associated to an Article type when the parameter “Include in browse on portals” is set to \"Yes\".\n- When the \\`shortUrlTemplate\\` query parameter is provided, the API filters accessible portals according to the specified language and template name. A portal short URL specific to the \\`shortUrlTemplate\\` value is returned in the response when available. If there is no short URL for a language, the portal object returns an empty \\`shortURL\\` field.\n\n## Pagination behavior (CRITICAL for AI assistants)\n\n**IMPORTANT**: This endpoint is paginated. When searching for a portal by name or listing portals, you MUST automatically fetch ALL pages before concluding that a portal doesn't exist.\n\n### Automatic pagination is REQUIRED when:\n- User asks to find a portal by name (e.g., \"business portal\", \"Master portal\")\n- User requests to list or see all portals\n- You need to resolve a natural portal name to its ID\n\n### How to detect more pages exist:\nThe response includes \\`paginationInfo\\` with:\n- \\`count\\`: Total number of items across all pages\n- \\`pagenum\\`: Current page number\n- \\`pagesize\\`: Items per page (default: 25)\n\n**Check for more pages if ANY of these are true:**\n1. The number of portals returned equals \\`pagesize\\` (e.g., exactly 25 portals returned)\n2. \\`paginationInfo.count > (pagenum * pagesize)\\` - there are more items beyond this page\n3. The response includes a \\`link\\` array with a \\`next\\` relation\n\n### Required pagination workflow:\n1. Start with \\`$pagenum=1\\` and \\`$pagesize=25\\` (default)\n2. After receiving the response, check \\`paginationInfo\\`\n3. **If more pages exist** (using the checks above), automatically call this endpoint again with \\`$pagenum=2\\`, then \\`$pagenum=3\\`, etc.\n4. Continue incrementing \\`$pagenum\\` until:\n - A page returns fewer portals than \\`pagesize\\` (indicating the last page)\n - A page returns zero portals\n - \\`pagenum * pagesize >= paginationInfo.count\\` (if count represents total items)\n5. Merge all portals from all pages by unique portal ID\n6. Only then search through the complete merged list or report results to the user\n\n### Example scenario:\nIf you search for \"business portal\" and the first page returns 25 portals but none match:\n- DO NOT immediately tell the user the portal doesn't exist\n- Check \\`paginationInfo.count\\` - if it's > 25, automatically fetch page 2\n- Continue fetching until all pages are retrieved\n- Search the complete merged list before concluding the portal doesn't exist\n\nThis ensures reliable portal name-to-ID resolution and prevents false \"not found\" errors.\n"
44
44
  },
45
45
  {
46
46
  "name": "make-suggestion",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@egain/egain-mcp-server",
3
- "version": "1.0.6",
3
+ "version": "1.0.12",
4
4
  "author": "Emily Loh - eGain Corporation",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -32,14 +32,55 @@ import { Result } from "../types/fp.js";
32
32
  * Get All Portals Accessible To User
33
33
  *
34
34
  * @remarks
35
+ * Get All Portals Accessible to User
36
+ *
35
37
  * ## Overview
36
- * The Get All Portals Accessible to User API allows a user to fetch all portals accessible to user across all department.
37
- * * If no access tags are specified for a portal, then any user can access the portal.
38
- * * If access tags are specified for a portal, users with a user profile that allows access have access to the portal. For users with multiple user profiles, the user profile that allows access does not need to be the active user profile.
39
- * * All the global users(partition) cannot be assigned user profiles; their access is limited to portals without access restrictions.
40
- * * The only articles returned are associated to an Article type when the parameter, “Include in browse on portals” is set to "Yes".
41
- * * When the "shortUrlTemplate" query parameter is provided, the API filters accessible portals according to the specified language and template name. Portal Short URL specific to to the "shortUrlTemplate" query parameter value is returned in the response.
42
- * * When there is no short URL available for a specific language, the API returns a portal object with an empty "shortURL" field.
38
+ * The Get All Portals Accessible to User API allows a user to fetch all portals accessible to the user across all departments.
39
+ * - If no access tags are specified for a portal, any user can access the portal.
40
+ * - If access tags are specified for a portal, users with a user profile that allows access can access the portal. For users with multiple user profiles, the user profile that allows access does not need to be the active user profile.
41
+ * - Global users (partition) cannot be assigned user profiles; their access is limited to portals without access restrictions.
42
+ * - The only articles returned are associated to an Article type when the parameter “Include in browse on portals” is set to "Yes".
43
+ * - When the `shortUrlTemplate` query parameter is provided, the API filters accessible portals according to the specified language and template name. A portal short URL specific to the `shortUrlTemplate` value is returned in the response when available. If there is no short URL for a language, the portal object returns an empty `shortURL` field.
44
+ *
45
+ * ## Pagination behavior (CRITICAL for AI assistants)
46
+ *
47
+ * **IMPORTANT**: This endpoint is paginated. When searching for a portal by name or listing portals, you MUST automatically fetch ALL pages before concluding that a portal doesn't exist.
48
+ *
49
+ * ### Automatic pagination is REQUIRED when:
50
+ * - User asks to find a portal by name (e.g., "business portal", "Master portal")
51
+ * - User requests to list or see all portals
52
+ * - You need to resolve a natural portal name to its ID
53
+ *
54
+ * ### How to detect more pages exist:
55
+ * The response includes `paginationInfo` with:
56
+ * - `count`: Total number of items across all pages
57
+ * - `pagenum`: Current page number
58
+ * - `pagesize`: Items per page (default: 25)
59
+ *
60
+ * **Check for more pages if ANY of these are true:**
61
+ * 1. The number of portals returned equals `pagesize` (e.g., exactly 25 portals returned)
62
+ * 2. `paginationInfo.count > (pagenum * pagesize)` - there are more items beyond this page
63
+ * 3. The response includes a `link` array with a `next` relation
64
+ *
65
+ * ### Required pagination workflow:
66
+ * 1. Start with `$pagenum=1` and `$pagesize=25` (default)
67
+ * 2. After receiving the response, check `paginationInfo`
68
+ * 3. **If more pages exist** (using the checks above), automatically call this endpoint again with `$pagenum=2`, then `$pagenum=3`, etc.
69
+ * 4. Continue incrementing `$pagenum` until:
70
+ * - A page returns fewer portals than `pagesize` (indicating the last page)
71
+ * - A page returns zero portals
72
+ * - `pagenum * pagesize >= paginationInfo.count` (if count represents total items)
73
+ * 5. Merge all portals from all pages by unique portal ID
74
+ * 6. Only then search through the complete merged list or report results to the user
75
+ *
76
+ * ### Example scenario:
77
+ * If you search for "business portal" and the first page returns 25 portals but none match:
78
+ * - DO NOT immediately tell the user the portal doesn't exist
79
+ * - Check `paginationInfo.count` - if it's > 25, automatically fetch page 2
80
+ * - Continue fetching until all pages are retrieved
81
+ * - Search the complete merged list before concluding the portal doesn't exist
82
+ *
83
+ * This ensures reliable portal name-to-ID resolution and prevents false "not found" errors.
43
84
  */
44
85
  export function getPortals(
45
86
  client$: EgainMcpCore,