@egain/egain-mcp-server 1.0.6 → 1.0.11
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 +22 -0
- package/bin/mcp-server.js +191 -171
- package/bin/mcp-server.js.map +9 -9
- package/esm/src/funcs/getPortals.d.ts +48 -7
- package/esm/src/funcs/getPortals.d.ts.map +1 -1
- package/esm/src/funcs/getPortals.js +48 -7
- package/esm/src/funcs/getPortals.js.map +1 -1
- package/esm/src/hooks/auth-hook.d.ts +6 -1
- package/esm/src/hooks/auth-hook.d.ts.map +1 -1
- package/esm/src/hooks/auth-hook.js +174 -197
- package/esm/src/hooks/auth-hook.js.map +1 -1
- package/esm/src/hooks/tooltip-images.d.ts +10 -0
- package/esm/src/hooks/tooltip-images.d.ts.map +1 -0
- package/esm/src/hooks/tooltip-images.js +12 -0
- package/esm/src/hooks/tooltip-images.js.map +1 -0
- package/esm/src/lib/config.d.ts +2 -2
- package/esm/src/lib/config.js +2 -2
- package/esm/src/lib/config.js.map +1 -1
- package/esm/src/mcp-server/mcp-server.js +1 -1
- package/esm/src/mcp-server/mcp-server.js.map +1 -1
- package/esm/src/mcp-server/server.js +1 -1
- package/esm/src/mcp-server/server.js.map +1 -1
- package/esm/src/mcp-server/tools/getPortals.d.ts.map +1 -1
- package/esm/src/mcp-server/tools/getPortals.js +48 -7
- package/esm/src/mcp-server/tools/getPortals.js.map +1 -1
- package/esm/src/models/getmyportalsop.d.ts +1 -1
- package/esm/src/models/getmyportalsop.d.ts.map +1 -1
- package/manifest.json +2 -2
- package/package.json +1 -1
- package/src/funcs/getPortals.ts +48 -7
- package/src/hooks/auth-hook.ts +185 -224
- package/src/lib/config.ts +2 -2
- package/src/mcp-server/mcp-server.ts +1 -1
- package/src/mcp-server/server.ts +1 -1
- package/src/mcp-server/tools/getPortals.ts +48 -7
- package/src/models/getmyportalsop.ts +1 -1
package/README.md
CHANGED
|
@@ -23,6 +23,7 @@ Learn more about the tools and usage of the MCP in the [eGain MCP guide](https:/
|
|
|
23
23
|
<!-- No Table of Contents [toc] -->
|
|
24
24
|
|
|
25
25
|
### Prerequisites
|
|
26
|
+
- **Node.js** (includes npm and npx) - Required for running the MCP server. Download from [nodejs.org](https://nodejs.org/)
|
|
26
27
|
- eGain platform version 21.22 or newer.
|
|
27
28
|
- Access mirrors the user's permissions: MCP only sees content that user can see (portal/article visibility).
|
|
28
29
|
- AI Services must be enabled for your tenant and the target portal, or AI tools will not run.
|
|
@@ -116,6 +117,27 @@ You'll need to enter your authentication configuration values in the browser for
|
|
|
116
117
|
- **Configuration problems?** → [FAQ: Configuration Issues](./help/faq.md#configuration-issues)
|
|
117
118
|
- **Tool/Query problems?** → [FAQ: MCP Tool Issues](./help/faq.md#mcp-tool-issues)
|
|
118
119
|
|
|
120
|
+
### Token Issues (Expired/Stuck Tokens)
|
|
121
|
+
|
|
122
|
+
If you're experiencing issues with expired tokens or authentication failures:
|
|
123
|
+
|
|
124
|
+
When using `npx`, token files (`.bearer_token` and `.bearer_token_metadata`) are stored in the directory where you run `npx` from (or where `package.json` exists). To find them:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# Search your home directory
|
|
128
|
+
find ~ -name ".bearer_token" -o -name ".bearer_token_metadata" 2>/dev/null
|
|
129
|
+
|
|
130
|
+
# Or search from your current directory
|
|
131
|
+
find . -name ".bearer_token" -o -name ".bearer_token_metadata" 2>/dev/null
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Once found, delete them:
|
|
135
|
+
```bash
|
|
136
|
+
rm /path/to/.bearer_token
|
|
137
|
+
rm /path/to/.bearer_token_metadata
|
|
138
|
+
```
|
|
139
|
+
This will search common locations and show you exactly where your token files are.
|
|
140
|
+
|
|
119
141
|
### Common Setup Hurdles
|
|
120
142
|
- **Can't find API Domain?** → [FAQ: Finding API Domain](./help/faq.md#q-i-cant-find-my-api-domain-or-scope-prefix-where-is-it)
|
|
121
143
|
- **Browser didn't open?** → [FAQ: No auth popup](./help/faq.md#no-auth-popup-appears)
|
package/bin/mcp-server.js
CHANGED
|
@@ -4046,9 +4046,9 @@ var init_config = __esm(() => {
|
|
|
4046
4046
|
SDK_METADATA = {
|
|
4047
4047
|
language: "typescript",
|
|
4048
4048
|
openapiDocVersion: "1.0.0",
|
|
4049
|
-
sdkVersion: "1.0.
|
|
4049
|
+
sdkVersion: "1.0.11",
|
|
4050
4050
|
genVersion: "2.723.8",
|
|
4051
|
-
userAgent: "speakeasy-sdk/mcp-typescript 1.0.
|
|
4051
|
+
userAgent: "speakeasy-sdk/mcp-typescript 1.0.11 2.723.8 1.0.0 @egain/egain-mcp-server"
|
|
4052
4052
|
};
|
|
4053
4053
|
});
|
|
4054
4054
|
|
|
@@ -40991,119 +40991,6 @@ class AuthenticationHook {
|
|
|
40991
40991
|
const fullUrl = `${baseUrl}?${existingParams.toString()}`;
|
|
40992
40992
|
return fullUrl;
|
|
40993
40993
|
}
|
|
40994
|
-
async monitorBrowserForAuthCode() {
|
|
40995
|
-
const platform = process.platform;
|
|
40996
|
-
const timeout = 120;
|
|
40997
|
-
const startTime = Date.now();
|
|
40998
|
-
if (platform === "darwin") {
|
|
40999
|
-
console.error(`\uD83D\uDD0D Monitoring ${this.detectedBrowser} for authorization code...`);
|
|
41000
|
-
let lastUrl = "";
|
|
41001
|
-
while (Date.now() - startTime < timeout * 1000) {
|
|
41002
|
-
try {
|
|
41003
|
-
const script = `
|
|
41004
|
-
tell application "${this.detectedBrowser}"
|
|
41005
|
-
try
|
|
41006
|
-
set currentURL to URL of active tab of front window
|
|
41007
|
-
return currentURL
|
|
41008
|
-
on error
|
|
41009
|
-
return ""
|
|
41010
|
-
end try
|
|
41011
|
-
end tell
|
|
41012
|
-
`;
|
|
41013
|
-
const { stdout } = await execAsync(`osascript -e '${script}'`);
|
|
41014
|
-
const currentUrl = stdout.trim();
|
|
41015
|
-
if (currentUrl && currentUrl !== lastUrl) {
|
|
41016
|
-
lastUrl = currentUrl;
|
|
41017
|
-
console.error(`\uD83D\uDD0D Current URL: ${currentUrl}`);
|
|
41018
|
-
}
|
|
41019
|
-
if (currentUrl && currentUrl.includes("code=")) {
|
|
41020
|
-
console.error("✅ Found authorization code in URL!");
|
|
41021
|
-
const codeMatch = currentUrl.match(/[?&]code=([^&]+)/);
|
|
41022
|
-
if (codeMatch && codeMatch[1]) {
|
|
41023
|
-
const code = decodeURIComponent(codeMatch[1]);
|
|
41024
|
-
console.error(`\uD83D\uDD11 Extracted authorization code (first 20 chars): ${code.substring(0, 20)}...`);
|
|
41025
|
-
console.error(` Code length: ${code.length} characters`);
|
|
41026
|
-
setImmediate(async () => {
|
|
41027
|
-
try {
|
|
41028
|
-
await execAsync(`osascript -e 'tell application "${this.detectedBrowser}" to close front window'`);
|
|
41029
|
-
console.error("✅ Browser window closed");
|
|
41030
|
-
} catch (closeError) {
|
|
41031
|
-
console.error("⚠️ Could not close browser window:", closeError);
|
|
41032
|
-
}
|
|
41033
|
-
});
|
|
41034
|
-
return code;
|
|
41035
|
-
}
|
|
41036
|
-
}
|
|
41037
|
-
if (currentUrl && currentUrl.includes("error=")) {
|
|
41038
|
-
const errorMatch = currentUrl.match(/[?&]error=([^&]+)/);
|
|
41039
|
-
const errorDescMatch = currentUrl.match(/error_description=([^&]+)/);
|
|
41040
|
-
const error = errorMatch && errorMatch[1] ? decodeURIComponent(errorMatch[1]) : "unknown_error";
|
|
41041
|
-
const errorDesc = errorDescMatch && errorDescMatch[1] ? decodeURIComponent(errorDescMatch[1]) : "No description";
|
|
41042
|
-
throw new Error(`OAuth error: ${error} - ${errorDesc}`);
|
|
41043
|
-
}
|
|
41044
|
-
} catch (error) {
|
|
41045
|
-
if (error instanceof Error && error.message.includes("OAuth error:")) {
|
|
41046
|
-
throw error;
|
|
41047
|
-
}
|
|
41048
|
-
}
|
|
41049
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
41050
|
-
}
|
|
41051
|
-
throw new Error("Authentication timeout. Please try again.");
|
|
41052
|
-
} else if (platform === "win32") {
|
|
41053
|
-
console.error(`\uD83D\uDD0D Monitoring ${this.detectedBrowser} for authorization code...`);
|
|
41054
|
-
let lastTitle = "";
|
|
41055
|
-
while (Date.now() - startTime < timeout * 1000) {
|
|
41056
|
-
try {
|
|
41057
|
-
const browserProcessName = this.detectedBrowser.replace(".exe", "");
|
|
41058
|
-
const psScript = `
|
|
41059
|
-
$process = Get-Process -Name "${browserProcessName}" -ErrorAction SilentlyContinue |
|
|
41060
|
-
Where-Object { $_.MainWindowHandle -ne 0 } |
|
|
41061
|
-
Select-Object -First 1
|
|
41062
|
-
if ($process) {
|
|
41063
|
-
$process.MainWindowTitle
|
|
41064
|
-
}
|
|
41065
|
-
`.replace(/\n\s+/g, " ");
|
|
41066
|
-
const { stdout } = await execAsync(`powershell -Command "${psScript}"`);
|
|
41067
|
-
const windowTitle = stdout.trim();
|
|
41068
|
-
if (windowTitle && windowTitle !== lastTitle) {
|
|
41069
|
-
lastTitle = windowTitle;
|
|
41070
|
-
console.error(`\uD83D\uDD0D Browser window: ${windowTitle.substring(0, 100)}...`);
|
|
41071
|
-
if (windowTitle.includes("code=") || windowTitle.includes("localhost:3333")) {
|
|
41072
|
-
console.error("✅ Detected OAuth callback!");
|
|
41073
|
-
const codeMatch = windowTitle.match(/code=([^&\s]+)/);
|
|
41074
|
-
if (codeMatch && codeMatch[1]) {
|
|
41075
|
-
const code = decodeURIComponent(codeMatch[1]);
|
|
41076
|
-
console.error(`\uD83D\uDD11 Extracted authorization code (first 20 chars): ${code.substring(0, 20)}...`);
|
|
41077
|
-
console.error(` Code length: ${code.length} characters`);
|
|
41078
|
-
setImmediate(async () => {
|
|
41079
|
-
try {
|
|
41080
|
-
await execAsync(`powershell -Command "Stop-Process -Name '${browserProcessName}' -Force"`);
|
|
41081
|
-
console.error("✅ Browser window closed");
|
|
41082
|
-
} catch (closeError) {
|
|
41083
|
-
console.error("⚠️ Could not close browser window:", closeError);
|
|
41084
|
-
}
|
|
41085
|
-
});
|
|
41086
|
-
return code;
|
|
41087
|
-
}
|
|
41088
|
-
}
|
|
41089
|
-
if (windowTitle.includes("error=")) {
|
|
41090
|
-
const errorMatch = windowTitle.match(/error=([^&\s]+)/);
|
|
41091
|
-
const error = errorMatch && errorMatch[1] ? decodeURIComponent(errorMatch[1]) : "unknown_error";
|
|
41092
|
-
throw new Error(`OAuth error: ${error}`);
|
|
41093
|
-
}
|
|
41094
|
-
}
|
|
41095
|
-
} catch (error) {
|
|
41096
|
-
if (error instanceof Error && error.message.includes("OAuth error:")) {
|
|
41097
|
-
throw error;
|
|
41098
|
-
}
|
|
41099
|
-
}
|
|
41100
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
41101
|
-
}
|
|
41102
|
-
throw new Error("Authentication timeout. The browser window title did not show the authorization code. Please ensure your redirect URL is http://localhost:3333/callback for automatic detection on Windows.");
|
|
41103
|
-
} else {
|
|
41104
|
-
throw new Error("Linux is not supported. Use macOS or Windows for automatic authentication.");
|
|
41105
|
-
}
|
|
41106
|
-
}
|
|
41107
40994
|
async getUserAccessToken(code) {
|
|
41108
40995
|
const { clientId, clientSecret, redirectUri, accessUrl } = this.authConfig;
|
|
41109
40996
|
console.error("\uD83D\uDD04 Starting token exchange...");
|
|
@@ -41237,6 +41124,20 @@ class AuthenticationHook {
|
|
|
41237
41124
|
return true;
|
|
41238
41125
|
} else {
|
|
41239
41126
|
console.error(`⏰ AUTH: Token expires in ${Math.round(timeUntilExpiry / 1000)} seconds - treating as expired`);
|
|
41127
|
+
const projectRoot2 = getProjectRoot();
|
|
41128
|
+
const tokenPath = path.join(projectRoot2, ".bearer_token");
|
|
41129
|
+
try {
|
|
41130
|
+
if (fs.existsSync(tokenPath)) {
|
|
41131
|
+
fs.unlinkSync(tokenPath);
|
|
41132
|
+
console.error("\uD83D\uDDD1️ Deleted expired bearer token file");
|
|
41133
|
+
}
|
|
41134
|
+
if (fs.existsSync(metadataPath)) {
|
|
41135
|
+
fs.unlinkSync(metadataPath);
|
|
41136
|
+
console.error("\uD83D\uDDD1️ Deleted expired bearer token metadata file");
|
|
41137
|
+
}
|
|
41138
|
+
} catch (error) {
|
|
41139
|
+
console.error("⚠️ Failed to delete expired token files:", error);
|
|
41140
|
+
}
|
|
41240
41141
|
return false;
|
|
41241
41142
|
}
|
|
41242
41143
|
}
|
|
@@ -41362,26 +41263,7 @@ class AuthenticationHook {
|
|
|
41362
41263
|
}));
|
|
41363
41264
|
console.error("\uD83D\uDD0D Starting browser URL monitoring for authorization code...");
|
|
41364
41265
|
setImmediate(async () => {
|
|
41365
|
-
|
|
41366
|
-
const code = await this.monitorBrowserForAuthCode();
|
|
41367
|
-
console.error("✅ Authorization code detected:", code.substring(0, 10) + "...");
|
|
41368
|
-
const accessToken = await this.getUserAccessToken(code);
|
|
41369
|
-
console.error("✅ Access token received");
|
|
41370
|
-
this.token = accessToken;
|
|
41371
|
-
if (this.portalCacheHook) {
|
|
41372
|
-
try {
|
|
41373
|
-
const fakeRequest = new Request(this.authConfig.environmentUrl, {
|
|
41374
|
-
headers: { Authorization: `Bearer ${accessToken}` }
|
|
41375
|
-
});
|
|
41376
|
-
await this.portalCacheHook.ensureCacheInitialized(fakeRequest);
|
|
41377
|
-
} catch (error) {}
|
|
41378
|
-
}
|
|
41379
|
-
console.error("\uD83C\uDF89 Authentication complete! Stopping config server...");
|
|
41380
|
-
this.stopConfigServer();
|
|
41381
|
-
} catch (authError) {
|
|
41382
|
-
console.error("❌ Authentication monitoring error:", authError);
|
|
41383
|
-
this.stopConfigServer();
|
|
41384
|
-
}
|
|
41266
|
+
await this.monitorBrowserWithRetry();
|
|
41385
41267
|
});
|
|
41386
41268
|
} catch (error) {
|
|
41387
41269
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
@@ -41459,30 +41341,7 @@ class AuthenticationHook {
|
|
|
41459
41341
|
}));
|
|
41460
41342
|
console.error("\uD83D\uDD0D Starting browser URL monitoring for authorization code...");
|
|
41461
41343
|
setImmediate(async () => {
|
|
41462
|
-
|
|
41463
|
-
const code = await this.monitorBrowserForAuthCode();
|
|
41464
|
-
console.error("✅ Authorization code detected:", code.substring(0, 10) + "...");
|
|
41465
|
-
const accessToken = await this.getUserAccessToken(code);
|
|
41466
|
-
console.error("✅ Access token received");
|
|
41467
|
-
this.token = accessToken;
|
|
41468
|
-
if (this.portalCacheHook) {
|
|
41469
|
-
console.error("\uD83D\uDD04 Triggering cache initialization...");
|
|
41470
|
-
try {
|
|
41471
|
-
const fakeRequest = new Request(this.authConfig.environmentUrl, {
|
|
41472
|
-
headers: { Authorization: `Bearer ${accessToken}` }
|
|
41473
|
-
});
|
|
41474
|
-
await this.portalCacheHook.ensureCacheInitialized(fakeRequest);
|
|
41475
|
-
console.error("✅ Cache initialization completed");
|
|
41476
|
-
} catch (error) {
|
|
41477
|
-
console.error("⚠️ Cache initialization failed:", error);
|
|
41478
|
-
}
|
|
41479
|
-
}
|
|
41480
|
-
console.error("\uD83C\uDF89 Authentication complete! Stopping config server...");
|
|
41481
|
-
this.stopConfigServer();
|
|
41482
|
-
} catch (authError) {
|
|
41483
|
-
console.error("❌ Authentication monitoring error:", authError);
|
|
41484
|
-
this.stopConfigServer();
|
|
41485
|
-
}
|
|
41344
|
+
await this.monitorBrowserWithRetry();
|
|
41486
41345
|
});
|
|
41487
41346
|
} catch (error) {
|
|
41488
41347
|
console.error("❌ Error processing authentication request:", error);
|
|
@@ -41539,8 +41398,14 @@ class AuthenticationHook {
|
|
|
41539
41398
|
console.error("\uD83C\uDF89 Authentication complete! Stopping config server...");
|
|
41540
41399
|
this.stopConfigServer();
|
|
41541
41400
|
} catch (authError) {
|
|
41542
|
-
|
|
41543
|
-
|
|
41401
|
+
const isOAuthError = authError instanceof Error && authError.message.includes("OAuth error:");
|
|
41402
|
+
if (isOAuthError) {
|
|
41403
|
+
console.error("❌ OAuth authentication error:", authError.message);
|
|
41404
|
+
console.error("\uD83D\uDCA1 The configuration server will remain running. Please try again with correct credentials.");
|
|
41405
|
+
} else {
|
|
41406
|
+
console.error("❌ Token exchange error:", authError);
|
|
41407
|
+
this.stopConfigServer();
|
|
41408
|
+
}
|
|
41544
41409
|
}
|
|
41545
41410
|
});
|
|
41546
41411
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
@@ -41607,6 +41472,120 @@ class AuthenticationHook {
|
|
|
41607
41472
|
});
|
|
41608
41473
|
});
|
|
41609
41474
|
}
|
|
41475
|
+
async monitorBrowserWithRetry() {
|
|
41476
|
+
const platform = process.platform;
|
|
41477
|
+
const timeout = 120;
|
|
41478
|
+
const startTime = Date.now();
|
|
41479
|
+
let oAuthErrorLogged = false;
|
|
41480
|
+
let lastUrl = "";
|
|
41481
|
+
let lastErrorUrl = null;
|
|
41482
|
+
if (platform === "darwin") {
|
|
41483
|
+
console.error(`\uD83D\uDD0D Monitoring ${this.detectedBrowser} for authorization code...`);
|
|
41484
|
+
} else if (platform === "win32") {
|
|
41485
|
+
console.error(`\uD83D\uDD0D Monitoring ${this.detectedBrowser} for authorization code...`);
|
|
41486
|
+
}
|
|
41487
|
+
while (true) {
|
|
41488
|
+
try {
|
|
41489
|
+
if (Date.now() - startTime >= timeout * 1000) {
|
|
41490
|
+
throw new Error("Authentication timeout. Please try again.");
|
|
41491
|
+
}
|
|
41492
|
+
let currentUrl = "";
|
|
41493
|
+
if (platform === "darwin") {
|
|
41494
|
+
const script = `
|
|
41495
|
+
tell application "${this.detectedBrowser}"
|
|
41496
|
+
try
|
|
41497
|
+
set currentURL to URL of active tab of front window
|
|
41498
|
+
return currentURL
|
|
41499
|
+
on error
|
|
41500
|
+
return ""
|
|
41501
|
+
end try
|
|
41502
|
+
end tell
|
|
41503
|
+
`;
|
|
41504
|
+
const { stdout } = await execAsync(`osascript -e '${script}'`);
|
|
41505
|
+
currentUrl = stdout.trim();
|
|
41506
|
+
} else if (platform === "win32") {
|
|
41507
|
+
const browserProcessName = this.detectedBrowser.replace(".exe", "");
|
|
41508
|
+
const psScript = `
|
|
41509
|
+
$process = Get-Process -Name "${browserProcessName}" -ErrorAction SilentlyContinue |
|
|
41510
|
+
Where-Object { $_.MainWindowHandle -ne 0 } |
|
|
41511
|
+
Select-Object -First 1
|
|
41512
|
+
if ($process) {
|
|
41513
|
+
$process.MainWindowTitle
|
|
41514
|
+
}
|
|
41515
|
+
`.replace(/\n\s+/g, " ");
|
|
41516
|
+
const { stdout } = await execAsync(`powershell -Command "${psScript}"`);
|
|
41517
|
+
currentUrl = stdout.trim();
|
|
41518
|
+
}
|
|
41519
|
+
if (currentUrl && currentUrl !== lastUrl) {
|
|
41520
|
+
lastUrl = currentUrl;
|
|
41521
|
+
console.error(`\uD83D\uDD0D Current URL: ${currentUrl}`);
|
|
41522
|
+
}
|
|
41523
|
+
if (currentUrl && currentUrl.includes("code=")) {
|
|
41524
|
+
const codeMatch = currentUrl.match(/[?&]code=([^&]+)/);
|
|
41525
|
+
if (codeMatch && codeMatch[1]) {
|
|
41526
|
+
const code = decodeURIComponent(codeMatch[1]);
|
|
41527
|
+
console.error("✅ Found authorization code in URL!");
|
|
41528
|
+
console.error(`\uD83D\uDD11 Extracted authorization code (first 20 chars): ${code.substring(0, 20)}...`);
|
|
41529
|
+
setImmediate(async () => {
|
|
41530
|
+
try {
|
|
41531
|
+
if (platform === "darwin") {
|
|
41532
|
+
await execAsync(`osascript -e 'tell application "${this.detectedBrowser}" to close front window'`);
|
|
41533
|
+
} else if (platform === "win32") {
|
|
41534
|
+
const browserProcessName = this.detectedBrowser.replace(".exe", "");
|
|
41535
|
+
await execAsync(`powershell -Command "Stop-Process -Name '${browserProcessName}' -Force"`);
|
|
41536
|
+
}
|
|
41537
|
+
} catch (closeError) {}
|
|
41538
|
+
});
|
|
41539
|
+
console.error("✅ Authorization code detected:", code.substring(0, 10) + "...");
|
|
41540
|
+
const accessToken = await this.getUserAccessToken(code);
|
|
41541
|
+
console.error("✅ Access token received");
|
|
41542
|
+
this.token = accessToken;
|
|
41543
|
+
if (this.portalCacheHook) {
|
|
41544
|
+
try {
|
|
41545
|
+
const fakeRequest = new Request(this.authConfig.environmentUrl, {
|
|
41546
|
+
headers: { Authorization: `Bearer ${accessToken}` }
|
|
41547
|
+
});
|
|
41548
|
+
await this.portalCacheHook.ensureCacheInitialized(fakeRequest);
|
|
41549
|
+
console.error("✅ Cache initialization completed");
|
|
41550
|
+
} catch (error) {
|
|
41551
|
+
console.error("⚠️ Cache initialization failed:", error);
|
|
41552
|
+
}
|
|
41553
|
+
}
|
|
41554
|
+
console.error("\uD83C\uDF89 Authentication complete! Stopping config server...");
|
|
41555
|
+
this.stopConfigServer();
|
|
41556
|
+
return;
|
|
41557
|
+
}
|
|
41558
|
+
}
|
|
41559
|
+
if (currentUrl && currentUrl.includes("error=")) {
|
|
41560
|
+
if (currentUrl !== lastErrorUrl) {
|
|
41561
|
+
lastErrorUrl = currentUrl;
|
|
41562
|
+
const errorMatch = currentUrl.match(/[?&]error=([^&]+)/);
|
|
41563
|
+
const errorDescMatch = currentUrl.match(/error_description=([^&]+)/);
|
|
41564
|
+
const error = errorMatch && errorMatch[1] ? decodeURIComponent(errorMatch[1]) : "unknown_error";
|
|
41565
|
+
const errorDesc = errorDescMatch && errorDescMatch[1] ? decodeURIComponent(errorDescMatch[1]) : "No description";
|
|
41566
|
+
if (!oAuthErrorLogged) {
|
|
41567
|
+
console.error("❌ OAuth authentication error:", `${error} - ${errorDesc}`);
|
|
41568
|
+
console.error("\uD83D\uDCA1 The configuration server will remain running. Please try again with correct credentials.");
|
|
41569
|
+
console.error("\uD83D\uDD0D Continuing to monitor browser for authorization code...");
|
|
41570
|
+
oAuthErrorLogged = true;
|
|
41571
|
+
}
|
|
41572
|
+
}
|
|
41573
|
+
} else {
|
|
41574
|
+
if (lastErrorUrl !== null) {
|
|
41575
|
+
lastErrorUrl = null;
|
|
41576
|
+
oAuthErrorLogged = false;
|
|
41577
|
+
}
|
|
41578
|
+
}
|
|
41579
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
41580
|
+
} catch (error) {
|
|
41581
|
+
if (!(error instanceof Error && error.message.includes("OAuth error:"))) {
|
|
41582
|
+
console.error("❌ Authentication monitoring error:", error);
|
|
41583
|
+
this.stopConfigServer();
|
|
41584
|
+
return;
|
|
41585
|
+
}
|
|
41586
|
+
}
|
|
41587
|
+
}
|
|
41588
|
+
}
|
|
41610
41589
|
stopConfigServer() {
|
|
41611
41590
|
if (this.configServer) {
|
|
41612
41591
|
console.error("\uD83D\uDEAA Stopping configuration server...");
|
|
@@ -46810,14 +46789,55 @@ var init_getPortals2 = __esm(() => {
|
|
|
46810
46789
|
name: "get-portals",
|
|
46811
46790
|
description: `Get All Portals Accessible To User
|
|
46812
46791
|
|
|
46792
|
+
Get All Portals Accessible to User
|
|
46793
|
+
|
|
46813
46794
|
## Overview
|
|
46814
|
-
|
|
46815
|
-
|
|
46816
|
-
|
|
46817
|
-
|
|
46818
|
-
|
|
46819
|
-
|
|
46820
|
-
|
|
46795
|
+
The Get All Portals Accessible to User API allows a user to fetch all portals accessible to the user across all departments.
|
|
46796
|
+
- If no access tags are specified for a portal, any user can access the portal.
|
|
46797
|
+
- 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.
|
|
46798
|
+
- Global users (partition) cannot be assigned user profiles; their access is limited to portals without access restrictions.
|
|
46799
|
+
- The only articles returned are associated to an Article type when the parameter “Include in browse on portals” is set to "Yes".
|
|
46800
|
+
- 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.
|
|
46801
|
+
|
|
46802
|
+
## Pagination behavior (CRITICAL for AI assistants)
|
|
46803
|
+
|
|
46804
|
+
**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.
|
|
46805
|
+
|
|
46806
|
+
### Automatic pagination is REQUIRED when:
|
|
46807
|
+
- User asks to find a portal by name (e.g., "business portal", "Master portal")
|
|
46808
|
+
- User requests to list or see all portals
|
|
46809
|
+
- You need to resolve a natural portal name to its ID
|
|
46810
|
+
|
|
46811
|
+
### How to detect more pages exist:
|
|
46812
|
+
The response includes \`paginationInfo\` with:
|
|
46813
|
+
- \`count\`: Total number of items across all pages
|
|
46814
|
+
- \`pagenum\`: Current page number
|
|
46815
|
+
- \`pagesize\`: Items per page (default: 25)
|
|
46816
|
+
|
|
46817
|
+
**Check for more pages if ANY of these are true:**
|
|
46818
|
+
1. The number of portals returned equals \`pagesize\` (e.g., exactly 25 portals returned)
|
|
46819
|
+
2. \`paginationInfo.count > (pagenum * pagesize)\` - there are more items beyond this page
|
|
46820
|
+
3. The response includes a \`link\` array with a \`next\` relation
|
|
46821
|
+
|
|
46822
|
+
### Required pagination workflow:
|
|
46823
|
+
1. Start with \`$pagenum=1\` and \`$pagesize=25\` (default)
|
|
46824
|
+
2. After receiving the response, check \`paginationInfo\`
|
|
46825
|
+
3. **If more pages exist** (using the checks above), automatically call this endpoint again with \`$pagenum=2\`, then \`$pagenum=3\`, etc.
|
|
46826
|
+
4. Continue incrementing \`$pagenum\` until:
|
|
46827
|
+
- A page returns fewer portals than \`pagesize\` (indicating the last page)
|
|
46828
|
+
- A page returns zero portals
|
|
46829
|
+
- \`pagenum * pagesize >= paginationInfo.count\` (if count represents total items)
|
|
46830
|
+
5. Merge all portals from all pages by unique portal ID
|
|
46831
|
+
6. Only then search through the complete merged list or report results to the user
|
|
46832
|
+
|
|
46833
|
+
### Example scenario:
|
|
46834
|
+
If you search for "business portal" and the first page returns 25 portals but none match:
|
|
46835
|
+
- DO NOT immediately tell the user the portal doesn't exist
|
|
46836
|
+
- Check \`paginationInfo.count\` - if it's > 25, automatically fetch page 2
|
|
46837
|
+
- Continue fetching until all pages are retrieved
|
|
46838
|
+
- Search the complete merged list before concluding the portal doesn't exist
|
|
46839
|
+
|
|
46840
|
+
This ensures reliable portal name-to-ID resolution and prevents false "not found" errors.
|
|
46821
46841
|
`,
|
|
46822
46842
|
annotations: {
|
|
46823
46843
|
destructiveHint: false,
|
|
@@ -47817,7 +47837,7 @@ The Search API is a hybrid search service that combines semantic understanding w
|
|
|
47817
47837
|
function createMCPServer(deps) {
|
|
47818
47838
|
const server = new McpServer({
|
|
47819
47839
|
name: "EgainMcp",
|
|
47820
|
-
version: "1.0.
|
|
47840
|
+
version: "1.0.11"
|
|
47821
47841
|
});
|
|
47822
47842
|
const getClient = deps.getSDK || (() => new EgainMcpCore({
|
|
47823
47843
|
security: deps.security,
|
|
@@ -49064,7 +49084,7 @@ var routes = ln({
|
|
|
49064
49084
|
var app = _e(routes, {
|
|
49065
49085
|
name: "mcp",
|
|
49066
49086
|
versionInfo: {
|
|
49067
|
-
currentVersion: "1.0.
|
|
49087
|
+
currentVersion: "1.0.11"
|
|
49068
49088
|
}
|
|
49069
49089
|
});
|
|
49070
49090
|
Yt(app, process3.argv.slice(2), buildContext(process3));
|
|
@@ -49072,5 +49092,5 @@ export {
|
|
|
49072
49092
|
app
|
|
49073
49093
|
};
|
|
49074
49094
|
|
|
49075
|
-
//# debugId=
|
|
49095
|
+
//# debugId=2754684247616B6C64756E2164756E21
|
|
49076
49096
|
//# sourceMappingURL=mcp-server.js.map
|