genexus-mcp 3.9.0 → 3.9.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/cli/commands/axi.js +19 -6
- package/cli/index.js +9 -0
- package/cli/lib/runtime-stager.js +384 -71
- package/cli/lib/runtime-stager.test.js +289 -3
- package/package.json +1 -1
- package/publish/GxMcp.Gateway.deps.json +2 -2
- package/publish/GxMcp.Gateway.dll +0 -0
- package/publish/GxMcp.Gateway.exe +0 -0
- package/publish/config.json +9 -9
- package/publish/gxmcp-manifest.json +15 -10
- package/publish/gxmcp-sbom.json +6 -6
- package/publish/nexus-ide.vsix +0 -0
- package/publish/tool_definitions.json +56 -56
- package/publish/worker/GxMcp.Worker.exe +0 -0
|
@@ -13,7 +13,8 @@ const {
|
|
|
13
13
|
ensureStagedGateway,
|
|
14
14
|
cleanOldRuntimes,
|
|
15
15
|
verifyManifest,
|
|
16
|
-
classifyProcessRuntime
|
|
16
|
+
classifyProcessRuntime,
|
|
17
|
+
getRuntimeProcessUsage
|
|
17
18
|
} = require('./runtime-stager');
|
|
18
19
|
|
|
19
20
|
function sha256(content) {
|
|
@@ -167,7 +168,8 @@ test('runtime-stager: ensureStagedGateway fails closed and cleans tmp on manifes
|
|
|
167
168
|
packageRoot: fakePkg,
|
|
168
169
|
publishDir: fakePublish,
|
|
169
170
|
runtimeRoot,
|
|
170
|
-
forceStaging: true
|
|
171
|
+
forceStaging: true,
|
|
172
|
+
getRunningProcesses: () => []
|
|
171
173
|
});
|
|
172
174
|
}, /Manifest verification failed/);
|
|
173
175
|
|
|
@@ -175,6 +177,58 @@ test('runtime-stager: ensureStagedGateway fails closed and cleans tmp on manifes
|
|
|
175
177
|
assert.equal(fs.readdirSync(runtimeRoot).length, 0);
|
|
176
178
|
});
|
|
177
179
|
|
|
180
|
+
test('runtime-stager: temporary staging cleanup retains a live process and reports the final-probe skip', (t) => {
|
|
181
|
+
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'gx-stage-live-process-'));
|
|
182
|
+
t.after(() => {
|
|
183
|
+
try { fs.rmSync(tmpRoot, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
const fakePkg = path.join(tmpRoot, 'package');
|
|
187
|
+
const fakePublish = path.join(fakePkg, 'publish');
|
|
188
|
+
const runtimeRoot = path.join(tmpRoot, 'runtime');
|
|
189
|
+
fs.mkdirSync(fakePublish, { recursive: true });
|
|
190
|
+
fs.writeFileSync(path.join(fakePkg, 'package.json'), JSON.stringify({ version: '3.9.1' }));
|
|
191
|
+
fs.writeFileSync(path.join(fakePublish, 'GxMcp.Gateway.exe'), 'partial gateway');
|
|
192
|
+
fs.writeFileSync(path.join(fakePublish, 'gxmcp-manifest.json'), JSON.stringify({
|
|
193
|
+
artifacts: [{ path: 'GxMcp.Gateway.exe', size: 9999, sha256: 'deadbeef' }]
|
|
194
|
+
}));
|
|
195
|
+
|
|
196
|
+
let probeCalls = 0;
|
|
197
|
+
let stagingError;
|
|
198
|
+
try {
|
|
199
|
+
ensureStagedGateway({
|
|
200
|
+
packageRoot: fakePkg,
|
|
201
|
+
publishDir: fakePublish,
|
|
202
|
+
runtimeRoot,
|
|
203
|
+
forceStaging: true,
|
|
204
|
+
getRunningProcesses: () => {
|
|
205
|
+
probeCalls++;
|
|
206
|
+
if (probeCalls === 1) return [];
|
|
207
|
+
const tmpName = fs.readdirSync(runtimeRoot).find((name) => name.includes('.tmp-'));
|
|
208
|
+
return [{
|
|
209
|
+
pid: 5150,
|
|
210
|
+
exePath: path.join(runtimeRoot, tmpName, 'worker', 'GxMcp.Worker.exe')
|
|
211
|
+
}];
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
} catch (err) {
|
|
215
|
+
stagingError = err;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
assert.ok(stagingError);
|
|
219
|
+
assert.match(stagingError.message, /Manifest verification failed/);
|
|
220
|
+
assert.match(stagingError.message, /Runtime cleanup skipped/);
|
|
221
|
+
assert.equal(stagingError.runtimeCleanup.processProbeAvailable, true);
|
|
222
|
+
assert.equal(stagingError.runtimeCleanup.skipped.length, 1);
|
|
223
|
+
assert.equal(stagingError.runtimeCleanup.skipped[0].reason, 'in-use-before-delete');
|
|
224
|
+
assert.deepEqual(stagingError.runtimeCleanup.skipped[0].pids, [5150]);
|
|
225
|
+
assert.equal(probeCalls, 2);
|
|
226
|
+
assert.equal(
|
|
227
|
+
fs.readdirSync(runtimeRoot).filter((name) => name.includes('.tmp-')).length,
|
|
228
|
+
1
|
|
229
|
+
);
|
|
230
|
+
});
|
|
231
|
+
|
|
178
232
|
test('runtime-stager: cleanOldRuntimes retains current version plus keepCount newest versions', (t) => {
|
|
179
233
|
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'gx-gc-test-'));
|
|
180
234
|
t.after(() => {
|
|
@@ -196,7 +250,7 @@ test('runtime-stager: cleanOldRuntimes retains current version plus keepCount ne
|
|
|
196
250
|
fs.utimesSync(v4, 4000, 4000);
|
|
197
251
|
|
|
198
252
|
// Current is v4. Keep count = 2 -> keep v4, v3, v2. v1 should be deleted.
|
|
199
|
-
cleanOldRuntimes(tmpRoot, v4, 2);
|
|
253
|
+
cleanOldRuntimes(tmpRoot, v4, 2, { getRunningProcesses: () => [] });
|
|
200
254
|
|
|
201
255
|
assert.equal(fs.existsSync(v4), true, 'current version must be kept');
|
|
202
256
|
assert.equal(fs.existsSync(v3), true, 'newest previous version must be kept');
|
|
@@ -219,3 +273,235 @@ test('runtime-stager: classifyProcessRuntime identifies staged vs npx-cache', ()
|
|
|
219
273
|
'other'
|
|
220
274
|
);
|
|
221
275
|
});
|
|
276
|
+
|
|
277
|
+
test('runtime-stager: cleanOldRuntimes retains a runtime with a live child process and reports its PID', (t) => {
|
|
278
|
+
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'gx-gc-in-use-'));
|
|
279
|
+
t.after(() => {
|
|
280
|
+
try { fs.rmSync(tmpRoot, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
const oldRuntime = path.join(tmpRoot, '3.6.0-old');
|
|
284
|
+
const currentRuntime = path.join(tmpRoot, '3.9.0-current');
|
|
285
|
+
fs.mkdirSync(oldRuntime);
|
|
286
|
+
fs.mkdirSync(currentRuntime);
|
|
287
|
+
fs.utimesSync(oldRuntime, 1000, 1000);
|
|
288
|
+
fs.utimesSync(currentRuntime, 2000, 2000);
|
|
289
|
+
|
|
290
|
+
const result = cleanOldRuntimes(tmpRoot, currentRuntime, 0, {
|
|
291
|
+
getRunningProcesses: () => [{
|
|
292
|
+
pid: 4242,
|
|
293
|
+
exePath: path.join(oldRuntime, 'worker', 'GxMcp.Worker.exe')
|
|
294
|
+
}]
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
assert.equal(fs.existsSync(oldRuntime), true);
|
|
298
|
+
assert.equal(result.skipped.length, 1);
|
|
299
|
+
assert.equal(result.skipped[0].reason, 'in-use');
|
|
300
|
+
assert.deepEqual(result.skipped[0].pids, [4242]);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
test('runtime-stager: cleanOldRuntimes renames before removal and leaves the original on rename failure', (t) => {
|
|
304
|
+
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'gx-gc-atomic-'));
|
|
305
|
+
t.after(() => {
|
|
306
|
+
try { fs.rmSync(tmpRoot, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
const oldRuntime = path.join(tmpRoot, '3.6.0-atomic');
|
|
310
|
+
const currentRuntime = path.join(tmpRoot, '3.9.0-current');
|
|
311
|
+
fs.mkdirSync(oldRuntime);
|
|
312
|
+
fs.mkdirSync(currentRuntime);
|
|
313
|
+
fs.writeFileSync(path.join(oldRuntime, 'keep.txt'), 'payload');
|
|
314
|
+
fs.utimesSync(oldRuntime, 1000, 1000);
|
|
315
|
+
fs.utimesSync(currentRuntime, 2000, 2000);
|
|
316
|
+
|
|
317
|
+
const renameCalls = [];
|
|
318
|
+
const result = cleanOldRuntimes(tmpRoot, currentRuntime, 0, {
|
|
319
|
+
getRunningProcesses: () => [],
|
|
320
|
+
renameSync: (from, to) => {
|
|
321
|
+
renameCalls.push([from, to]);
|
|
322
|
+
fs.renameSync(from, to);
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
assert.equal(renameCalls.length, 1);
|
|
327
|
+
assert.equal(fs.existsSync(oldRuntime), false);
|
|
328
|
+
assert.equal(result.deleted.length, 1);
|
|
329
|
+
|
|
330
|
+
const failedRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'gx-gc-rename-fail-'));
|
|
331
|
+
t.after(() => {
|
|
332
|
+
try { fs.rmSync(failedRoot, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
333
|
+
});
|
|
334
|
+
const failedOld = path.join(failedRoot, '3.6.0-failed');
|
|
335
|
+
const failedCurrent = path.join(failedRoot, '3.9.0-current');
|
|
336
|
+
fs.mkdirSync(failedOld);
|
|
337
|
+
fs.mkdirSync(failedCurrent);
|
|
338
|
+
fs.writeFileSync(path.join(failedOld, 'keep.txt'), 'payload');
|
|
339
|
+
|
|
340
|
+
const failed = cleanOldRuntimes(failedRoot, failedCurrent, 0, {
|
|
341
|
+
getRunningProcesses: () => [],
|
|
342
|
+
renameSync: () => { throw new Error('directory is in use'); }
|
|
343
|
+
});
|
|
344
|
+
assert.equal(fs.existsSync(failedOld), true);
|
|
345
|
+
assert.equal(failed.failed.length, 1);
|
|
346
|
+
assert.match(failed.failed[0].error, /directory is in use/);
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
test('runtime-stager: process-probe failure is fail-closed and reported', (t) => {
|
|
350
|
+
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'gx-gc-probe-fail-'));
|
|
351
|
+
t.after(() => {
|
|
352
|
+
try { fs.rmSync(tmpRoot, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
353
|
+
});
|
|
354
|
+
const oldRuntime = path.join(tmpRoot, 'old');
|
|
355
|
+
const currentRuntime = path.join(tmpRoot, 'current');
|
|
356
|
+
fs.mkdirSync(oldRuntime);
|
|
357
|
+
fs.mkdirSync(currentRuntime);
|
|
358
|
+
|
|
359
|
+
const result = cleanOldRuntimes(tmpRoot, currentRuntime, 0, {
|
|
360
|
+
getRunningProcesses: () => ({ ok: false, processes: [], error: 'access denied' })
|
|
361
|
+
});
|
|
362
|
+
assert.equal(result.processProbeAvailable, false);
|
|
363
|
+
assert.equal(fs.existsSync(oldRuntime), true);
|
|
364
|
+
assert.equal(result.skipped[0].reason, 'process-probe-unavailable');
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
test('runtime-stager: a process appearing during retirement restores the original directory name', (t) => {
|
|
368
|
+
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'gx-gc-race-'));
|
|
369
|
+
t.after(() => {
|
|
370
|
+
try { fs.rmSync(tmpRoot, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
371
|
+
});
|
|
372
|
+
const oldRuntime = path.join(tmpRoot, 'old');
|
|
373
|
+
const currentRuntime = path.join(tmpRoot, 'current');
|
|
374
|
+
fs.mkdirSync(oldRuntime);
|
|
375
|
+
fs.mkdirSync(currentRuntime);
|
|
376
|
+
fs.writeFileSync(path.join(oldRuntime, 'payload.txt'), 'keep');
|
|
377
|
+
|
|
378
|
+
let calls = 0;
|
|
379
|
+
const result = cleanOldRuntimes(tmpRoot, currentRuntime, 0, {
|
|
380
|
+
getRunningProcesses: () => {
|
|
381
|
+
calls++;
|
|
382
|
+
return calls < 3
|
|
383
|
+
? []
|
|
384
|
+
: [{ pid: 777, exePath: path.join(oldRuntime, 'GxMcp.Gateway.exe') }];
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
assert.equal(fs.existsSync(oldRuntime), true);
|
|
389
|
+
assert.equal(fs.existsSync(path.join(oldRuntime, 'payload.txt')), true);
|
|
390
|
+
assert.equal(result.skipped[0].reason, 'in-use-after-rename');
|
|
391
|
+
assert.equal(result.skipped[0].restored, true);
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
test('runtime-stager: a process appearing at the final delete probe restores the renamed runtime', (t) => {
|
|
395
|
+
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'gx-gc-final-race-'));
|
|
396
|
+
t.after(() => {
|
|
397
|
+
try { fs.rmSync(tmpRoot, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
398
|
+
});
|
|
399
|
+
const oldRuntime = path.join(tmpRoot, 'old');
|
|
400
|
+
const currentRuntime = path.join(tmpRoot, 'current');
|
|
401
|
+
fs.mkdirSync(oldRuntime);
|
|
402
|
+
fs.mkdirSync(currentRuntime);
|
|
403
|
+
fs.writeFileSync(path.join(oldRuntime, 'payload.txt'), 'keep');
|
|
404
|
+
|
|
405
|
+
let calls = 0;
|
|
406
|
+
let deletingPath = null;
|
|
407
|
+
const result = cleanOldRuntimes(tmpRoot, currentRuntime, 0, {
|
|
408
|
+
getRunningProcesses: () => {
|
|
409
|
+
calls++;
|
|
410
|
+
if (calls < 4 || !deletingPath) return [];
|
|
411
|
+
return [{ pid: 778, exePath: path.join(deletingPath, 'GxMcp.Gateway.exe') }];
|
|
412
|
+
},
|
|
413
|
+
renameSync: (from, to) => {
|
|
414
|
+
deletingPath = to;
|
|
415
|
+
fs.renameSync(from, to);
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
assert.equal(fs.existsSync(oldRuntime), true);
|
|
420
|
+
assert.equal(fs.existsSync(path.join(oldRuntime, 'payload.txt')), true);
|
|
421
|
+
assert.equal(result.skipped[0].reason, 'in-use-before-delete');
|
|
422
|
+
assert.equal(result.skipped[0].restored, true);
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
test('runtime-stager: a failed removal leaves a retryable tombstone and the next pass collects it', (t) => {
|
|
426
|
+
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'gx-gc-tombstone-'));
|
|
427
|
+
t.after(() => {
|
|
428
|
+
try { fs.rmSync(tmpRoot, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
429
|
+
});
|
|
430
|
+
const oldRuntime = path.join(tmpRoot, 'old');
|
|
431
|
+
const currentRuntime = path.join(tmpRoot, 'current');
|
|
432
|
+
fs.mkdirSync(oldRuntime);
|
|
433
|
+
fs.mkdirSync(currentRuntime);
|
|
434
|
+
fs.writeFileSync(path.join(oldRuntime, 'payload.txt'), 'keep');
|
|
435
|
+
|
|
436
|
+
const failed = cleanOldRuntimes(tmpRoot, currentRuntime, 0, {
|
|
437
|
+
getRunningProcesses: () => [],
|
|
438
|
+
rmSync: () => { throw new Error('temporary delete failure'); }
|
|
439
|
+
});
|
|
440
|
+
assert.equal(failed.failed.length, 1);
|
|
441
|
+
assert.equal(fs.existsSync(oldRuntime), false);
|
|
442
|
+
assert.equal(fs.readdirSync(tmpRoot).some((name) => name.includes('.deleting-')), true);
|
|
443
|
+
|
|
444
|
+
const retried = cleanOldRuntimes(tmpRoot, currentRuntime, 0, {
|
|
445
|
+
getRunningProcesses: () => []
|
|
446
|
+
});
|
|
447
|
+
assert.equal(retried.failed.length, 0);
|
|
448
|
+
assert.equal(fs.readdirSync(tmpRoot).some((name) => name.includes('.deleting-')), false);
|
|
449
|
+
});
|
|
450
|
+
test('runtime-stager: a failed tombstone restore is retained when the live process still reports the original path', (t) => {
|
|
451
|
+
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'gx-gc-tombstone-restore-'));
|
|
452
|
+
t.after(() => {
|
|
453
|
+
try { fs.rmSync(tmpRoot, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
454
|
+
});
|
|
455
|
+
const oldRuntime = path.join(tmpRoot, 'old');
|
|
456
|
+
const currentRuntime = path.join(tmpRoot, 'current');
|
|
457
|
+
fs.mkdirSync(oldRuntime);
|
|
458
|
+
fs.mkdirSync(currentRuntime);
|
|
459
|
+
fs.writeFileSync(path.join(oldRuntime, 'payload.txt'), 'keep');
|
|
460
|
+
|
|
461
|
+
let deletingPath = null;
|
|
462
|
+
const first = cleanOldRuntimes(tmpRoot, currentRuntime, 0, {
|
|
463
|
+
getRunningProcesses: () => deletingPath
|
|
464
|
+
? [{ pid: 779, exePath: path.join(oldRuntime, 'GxMcp.Gateway.exe') }]
|
|
465
|
+
: [],
|
|
466
|
+
renameSync: (from, to) => {
|
|
467
|
+
if (from.includes('.deleting-') && to === oldRuntime) {
|
|
468
|
+
throw new Error('restore failed while process is live');
|
|
469
|
+
}
|
|
470
|
+
deletingPath = to;
|
|
471
|
+
fs.renameSync(from, to);
|
|
472
|
+
}
|
|
473
|
+
});
|
|
474
|
+
assert.equal(first.skipped[0].restored, false);
|
|
475
|
+
assert.equal(fs.existsSync(oldRuntime), false);
|
|
476
|
+
assert.equal(fs.readdirSync(tmpRoot).some((name) => name.includes('.deleting-')), true);
|
|
477
|
+
|
|
478
|
+
const second = cleanOldRuntimes(tmpRoot, currentRuntime, 0, {
|
|
479
|
+
getRunningProcesses: () => [{ pid: 779, exePath: path.join(oldRuntime, 'GxMcp.Gateway.exe') }]
|
|
480
|
+
});
|
|
481
|
+
assert.equal(second.skipped.some((entry) => entry.reason === 'in-use'), true);
|
|
482
|
+
assert.equal(fs.readdirSync(tmpRoot).some((name) => name.includes('.deleting-')), true);
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
test('runtime-stager: getRuntimeProcessUsage maps Gateway, broker, and Worker PIDs to their runtime', (t) => {
|
|
486
|
+
const runtimeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'gx-gc-usage-'));
|
|
487
|
+
t.after(() => {
|
|
488
|
+
try { fs.rmSync(runtimeRoot, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
489
|
+
});
|
|
490
|
+
const runtimeDir = path.join(runtimeRoot, '3.8.0-old');
|
|
491
|
+
const siblingDir = path.join(runtimeRoot, '3.8.0-old-suffix');
|
|
492
|
+
fs.mkdirSync(runtimeDir);
|
|
493
|
+
fs.mkdirSync(siblingDir);
|
|
494
|
+
const gateway = path.join(runtimeDir, 'GxMcp.Gateway.exe');
|
|
495
|
+
const worker = path.join(runtimeDir, 'worker', 'GxMcp.Worker.exe');
|
|
496
|
+
const usage = getRuntimeProcessUsage(runtimeRoot, [
|
|
497
|
+
{ pid: 10, exePath: gateway },
|
|
498
|
+
{ pid: 11, exePath: worker },
|
|
499
|
+
{ pid: 12, exePath: path.join(siblingDir, 'GxMcp.Gateway.exe') }
|
|
500
|
+
]);
|
|
501
|
+
|
|
502
|
+
assert.equal(usage.length, 2);
|
|
503
|
+
const oldUsage = usage.find((entry) => entry.name === '3.8.0-old');
|
|
504
|
+
const siblingUsage = usage.find((entry) => entry.name === '3.8.0-old-suffix');
|
|
505
|
+
assert.deepEqual(oldUsage.pids, [10, 11]);
|
|
506
|
+
assert.deepEqual(siblingUsage.pids, [12]);
|
|
507
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genexus-mcp",
|
|
3
|
-
"version": "3.9.
|
|
3
|
+
"version": "3.9.2",
|
|
4
4
|
"mcpName": "io.github.lennix1337/genexus",
|
|
5
5
|
"description": "GeneXus 16, GeneXus 17, GeneXus 18 MCP server with native SDK support; basic legacy compatibility for GeneXus Evolution 3, GeneXus Evolution 2, GeneXus Evolution 1, GeneXus 15, GeneXus 9.0, GeneXus 8.0 via com-gxpublic and dotnet-reflection drivers — read, edit, and analyze Knowledge Base objects directly from Claude, Cursor, and other AI agents over the Model Context Protocol.",
|
|
6
6
|
"keywords": [
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"targets": {
|
|
8
8
|
".NETCoreApp,Version=v10.0": {},
|
|
9
9
|
".NETCoreApp,Version=v10.0/win-x64": {
|
|
10
|
-
"GxMcp.Gateway/3.9.
|
|
10
|
+
"GxMcp.Gateway/3.9.2": {
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"Newtonsoft.Json": "13.0.3",
|
|
13
13
|
"System.Management": "10.0.5",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
}
|
|
67
67
|
},
|
|
68
68
|
"libraries": {
|
|
69
|
-
"GxMcp.Gateway/3.9.
|
|
69
|
+
"GxMcp.Gateway/3.9.2": {
|
|
70
70
|
"type": "project",
|
|
71
71
|
"serviceable": false,
|
|
72
72
|
"sha512": ""
|
|
Binary file
|
|
Binary file
|
package/publish/config.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
|
+
"Environment": {
|
|
3
|
+
"ResolutionPolicy": "strict"
|
|
4
|
+
},
|
|
2
5
|
"Server": {
|
|
3
|
-
"SessionIdleTimeoutMinutes": 10,
|
|
4
|
-
"HttpPort": 0,
|
|
5
6
|
"TerseResponses": true,
|
|
6
7
|
"McpStdio": true,
|
|
7
|
-
"
|
|
8
|
-
"
|
|
8
|
+
"HttpPort": 0,
|
|
9
|
+
"SessionIdleTimeoutMinutes": 10,
|
|
10
|
+
"EmitStructuredContent": false,
|
|
11
|
+
"WorkerIdleTimeoutMinutes": 5
|
|
9
12
|
},
|
|
10
13
|
"ConfigSchemaVersion": 2,
|
|
11
|
-
"Environment": {
|
|
12
|
-
"ResolutionPolicy": "strict"
|
|
13
|
-
},
|
|
14
|
-
"GatewayMode": "stdio-isolated",
|
|
15
14
|
"GeneXus": {
|
|
16
15
|
"WorkerExecutable": "worker\\\\GxMcp.Worker.exe",
|
|
17
16
|
"InstallationPath": "C:\\Program Files (x86)\\GeneXus\\GeneXus18"
|
|
18
|
-
}
|
|
17
|
+
},
|
|
18
|
+
"GatewayMode": "stdio-isolated"
|
|
19
19
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "gxmcp-release-manifest/1",
|
|
3
|
-
"version": "3.9.
|
|
4
|
-
"sourceCommit": "
|
|
3
|
+
"version": "3.9.2",
|
|
4
|
+
"sourceCommit": "a198d035ce7c54a8563382a9bc814fc241287e85",
|
|
5
5
|
"sourceCommitPolicy": "exact-tag",
|
|
6
|
-
"generatedAtUtc": "2026-09-
|
|
6
|
+
"generatedAtUtc": "2026-09-27T23:21:16.1079775Z",
|
|
7
7
|
"runtime": {
|
|
8
8
|
"gateway": "net10.0-windows",
|
|
9
9
|
"worker": "net48-x86",
|
|
@@ -15,28 +15,33 @@
|
|
|
15
15
|
"2026-07-28"
|
|
16
16
|
],
|
|
17
17
|
"schema": "tool_definitions.json",
|
|
18
|
-
"schemaSha256": "
|
|
18
|
+
"schemaSha256": "3868e10738a997877b6350bf38e9748ddeffd2a194af77dc6fd89e1af0a32fe9",
|
|
19
19
|
"provenance": "gxmcp-sbom.json",
|
|
20
20
|
"artifacts": [
|
|
21
21
|
{
|
|
22
22
|
"path": "gxmcp-sbom.json",
|
|
23
23
|
"size": 590,
|
|
24
|
-
"sha256": "
|
|
24
|
+
"sha256": "657932e329aef821997783720744484e68d35e2b9227c0e13610010411f32155"
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
"path": "GxMcp.Gateway.exe",
|
|
28
28
|
"size": 162304,
|
|
29
|
-
"sha256": "
|
|
29
|
+
"sha256": "2309948ca38d9e8f5687b6172663c4aa83eb4b8d45eb6b4b46a1fd0ee345da21"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"path": "nexus-ide.vsix",
|
|
33
|
+
"size": 1319958,
|
|
34
|
+
"sha256": "de680984e7caaac86ca017cb2389138642a72c0f4a6879317e777b393c595750"
|
|
30
35
|
},
|
|
31
36
|
{
|
|
32
37
|
"path": "tool_definitions.json",
|
|
33
|
-
"size":
|
|
34
|
-
"sha256": "
|
|
38
|
+
"size": 132679,
|
|
39
|
+
"sha256": "3868e10738a997877b6350bf38e9748ddeffd2a194af77dc6fd89e1af0a32fe9"
|
|
35
40
|
},
|
|
36
41
|
{
|
|
37
42
|
"path": "worker/GxMcp.Worker.exe",
|
|
38
|
-
"size":
|
|
39
|
-
"sha256": "
|
|
43
|
+
"size": 3846144,
|
|
44
|
+
"sha256": "3d19cfc9e8e40d830303fcfd7414f885331fcce4f43b5429686435a82cdfe614"
|
|
40
45
|
}
|
|
41
46
|
]
|
|
42
47
|
}
|
package/publish/gxmcp-sbom.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "gxmcp-provenance/1",
|
|
3
|
-
"version": "3.9.
|
|
4
|
-
"sourceCommit": "
|
|
3
|
+
"version": "3.9.2",
|
|
4
|
+
"sourceCommit": "a198d035ce7c54a8563382a9bc814fc241287e85",
|
|
5
5
|
"sourceCommitPolicy": "exact-tag",
|
|
6
6
|
"components": [
|
|
7
7
|
{
|
|
8
8
|
"name": "genexus-mcp",
|
|
9
9
|
"lockfile": "package-lock.json",
|
|
10
|
-
"size":
|
|
11
|
-
"sha256": "
|
|
10
|
+
"size": 38804,
|
|
11
|
+
"sha256": "02dde3331f502f0856ecdf807cde097d2db71b83128f3ecfc6561430b09de33c"
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
14
|
"name": "nexus-ide",
|
|
15
15
|
"lockfile": "src/nexus-ide/package-lock.json",
|
|
16
|
-
"size":
|
|
17
|
-
"sha256": "
|
|
16
|
+
"size": 267536,
|
|
17
|
+
"sha256": "64db440edd7ea7c9f51b6ab4f087b8265c03a722e5f9146f12efec7c8138a082"
|
|
18
18
|
}
|
|
19
19
|
]
|
|
20
20
|
}
|
|
Binary file
|