@egain/egain-mcp-server 1.0.1 → 1.0.4

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.
@@ -3,6 +3,7 @@ import { AuthenticationHook } from "./auth-hook.js";
3
3
  import { PortalCacheHook } from "./portal-cache-hook.js";
4
4
  import { PortalLookupHook } from "./portal-lookup-hook.js";
5
5
  import { ServerRoutingHook } from "./server-routing-hook.js";
6
+ import { VersionCheckHook } from "./version-check-hook.js";
6
7
 
7
8
  /*
8
9
  * This file is only ever generated once on the first generation and then is free to be modified.
@@ -13,6 +14,12 @@ import { ServerRoutingHook } from "./server-routing-hook.js";
13
14
  export function initHooks(hooks: Hooks) {
14
15
  console.error('🚀 Initializing eGain MCP hooks...');
15
16
 
17
+ // 0. Version Check Hook - checks for updates from npm
18
+ // Register this FIRST so users see update notifications early
19
+ const versionCheckHook = new VersionCheckHook();
20
+ hooks.registerSDKInitHook(versionCheckHook);
21
+ console.error('✅ VERSION: Registered version check hook for SDK init');
22
+
16
23
  // 1. Server Routing Hook - routes operations to correct API server
17
24
  // Register this FIRST before request creation so URLs are correct from the start
18
25
  const serverRoutingHook = new ServerRoutingHook();
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Version Check Hook for eGain MCP Server
3
+ * Checks for updates by comparing local version with latest version on npm
4
+ */
5
+
6
+ import { SDKInitHook } from "./types.js";
7
+ import { SDKOptions } from "../lib/config.js";
8
+ import * as fs from "fs";
9
+ import * as path from "path";
10
+ import { fileURLToPath } from 'url';
11
+
12
+ // ES module __dirname equivalent
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = path.dirname(__filename);
15
+
16
+ // Get the project root directory by finding package.json
17
+ const getProjectRoot = (): string => {
18
+ // Start from current directory and walk up until we find package.json
19
+ let currentDir = __dirname;
20
+ while (currentDir !== path.dirname(currentDir)) { // Stop at filesystem root
21
+ if (fs.existsSync(path.join(currentDir, 'package.json'))) {
22
+ return currentDir;
23
+ }
24
+ currentDir = path.dirname(currentDir);
25
+ }
26
+ // If package.json not found, use current working directory as fallback
27
+ return process.cwd();
28
+ };
29
+
30
+ /**
31
+ * Compare two semantic version strings
32
+ * Returns: 1 if v1 > v2, -1 if v1 < v2, 0 if equal
33
+ */
34
+ function compareVersions(v1: string, v2: string): number {
35
+ const parts1 = v1.split('.').map(Number);
36
+ const parts2 = v2.split('.').map(Number);
37
+
38
+ for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
39
+ const part1 = parts1[i] || 0;
40
+ const part2 = parts2[i] || 0;
41
+
42
+ if (part1 > part2) return 1;
43
+ if (part1 < part2) return -1;
44
+ }
45
+
46
+ return 0;
47
+ }
48
+
49
+ /**
50
+ * Check if we're running from a git repository
51
+ */
52
+ function isGitRepo(projectRoot: string): boolean {
53
+ try {
54
+ const gitDir = path.join(projectRoot, '.git');
55
+ return fs.existsSync(gitDir) || fs.existsSync(path.join(projectRoot, '.git', 'HEAD'));
56
+ } catch {
57
+ return false;
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Get local version from package.json
63
+ */
64
+ function getLocalVersion(): string | null {
65
+ try {
66
+ const projectRoot = getProjectRoot();
67
+ const packageJsonPath = path.join(projectRoot, 'package.json');
68
+
69
+ if (fs.existsSync(packageJsonPath)) {
70
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
71
+ return packageJson.version || null;
72
+ }
73
+ } catch (error) {
74
+ console.error('⚠️ Could not read local version:', error);
75
+ }
76
+
77
+ return null;
78
+ }
79
+
80
+ /**
81
+ * Fetch latest version from npm registry
82
+ */
83
+ async function getLatestVersion(): Promise<string | null> {
84
+ try {
85
+ const packageName = '@egain/egain-mcp-server';
86
+ const registryUrl = `https://registry.npmjs.org/${packageName}`;
87
+
88
+ const response = await fetch(registryUrl, {
89
+ headers: {
90
+ 'Accept': 'application/json',
91
+ },
92
+ });
93
+
94
+ if (!response.ok) {
95
+ throw new Error(`npm registry returned ${response.status}`);
96
+ }
97
+
98
+ const data = await response.json() as { 'dist-tags'?: { latest?: string } };
99
+ return data['dist-tags']?.latest || null;
100
+ } catch (error) {
101
+ // Silently fail - network issues shouldn't block initialization
102
+ return null;
103
+ }
104
+ }
105
+
106
+ export class VersionCheckHook implements SDKInitHook {
107
+ private checkPerformed = false;
108
+
109
+ sdkInit(opts: SDKOptions): SDKOptions {
110
+ // Only check once per SDK initialization
111
+ if (this.checkPerformed) {
112
+ return opts;
113
+ }
114
+
115
+ this.checkPerformed = true;
116
+
117
+ // Perform version check asynchronously (non-blocking)
118
+ setImmediate(async () => {
119
+ try {
120
+ const localVersion = getLocalVersion();
121
+
122
+ if (!localVersion) {
123
+ console.error('⚠️ Could not determine local version');
124
+ return;
125
+ }
126
+
127
+ console.error(`📦 Checking for updates (current version: ${localVersion})...`);
128
+
129
+ const latestVersion = await getLatestVersion();
130
+
131
+ if (!latestVersion) {
132
+ // Silently fail - network issues shouldn't be noisy
133
+ return;
134
+ }
135
+
136
+ if (compareVersions(latestVersion, localVersion) > 0) {
137
+ const projectRoot = getProjectRoot();
138
+ const isGit = isGitRepo(projectRoot);
139
+
140
+ console.error('');
141
+ console.error('⚠️ UPDATE AVAILABLE');
142
+ console.error(` Current version: ${localVersion}`);
143
+ console.error(` Latest version: ${latestVersion}`);
144
+
145
+ if (isGit) {
146
+ console.error(` Update with: git pull && npm run build`);
147
+ console.error(` Or visit: https://github.com/eGain/egain-mcp-server`);
148
+ } else {
149
+ console.error(` Update with: npm install -g @egain/egain-mcp-server@latest`);
150
+ console.error(` Or visit: https://www.npmjs.com/package/@egain/egain-mcp-server`);
151
+ }
152
+ console.error('');
153
+ } else {
154
+ console.error(`✅ You are running the latest version (${localVersion})`);
155
+ }
156
+ } catch (error) {
157
+ // Silently fail - version check shouldn't break initialization
158
+ // Only log if it's a non-network error
159
+ if (error instanceof Error && !error.message.includes('fetch')) {
160
+ console.error('⚠️ Version check failed:', error.message);
161
+ }
162
+ }
163
+ });
164
+
165
+ return opts;
166
+ }
167
+ }
168
+
package/src/lib/config.ts CHANGED
@@ -82,8 +82,8 @@ export function serverURLFromOptions(options: SDKOptions): URL | null {
82
82
  export const SDK_METADATA = {
83
83
  language: "typescript",
84
84
  openapiDocVersion: "1.0.0",
85
- sdkVersion: "1.0.1",
85
+ sdkVersion: "1.0.4",
86
86
  genVersion: "2.723.8",
87
87
  userAgent:
88
- "speakeasy-sdk/mcp-typescript 1.0.1 2.723.8 1.0.0 @egain/egain-mcp-server",
88
+ "speakeasy-sdk/mcp-typescript 1.0.4 2.723.8 1.0.0 @egain/egain-mcp-server",
89
89
  } as const;
@@ -19,7 +19,7 @@ const routes = buildRouteMap({
19
19
  export const app = buildApplication(routes, {
20
20
  name: "mcp",
21
21
  versionInfo: {
22
- currentVersion: "1.0.1",
22
+ currentVersion: "1.0.4",
23
23
  },
24
24
  });
25
25
 
@@ -34,7 +34,7 @@ export function createMCPServer(deps: {
34
34
  }) {
35
35
  const server = new McpServer({
36
36
  name: "EgainMcp",
37
- version: "1.0.1",
37
+ version: "1.0.4",
38
38
  });
39
39
 
40
40
  const getClient = deps.getSDK || (() =>