genexus-mcp 2.8.2 → 2.8.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.
- package/README.md +20 -6
- package/cli/commands/axi.js +151 -8
- package/cli/index.js +24 -1
- package/cli/lib/config.js +395 -19
- package/cli/lib/update-check.js +241 -74
- package/cli/run.test.js +253 -1
- package/docs/llm_cli_mcp_playbook.md +1 -0
- 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 +17 -20
- package/publish/worker/GxMcp.Worker.exe +0 -0
- package/publish/GxMcp.Gateway.pdb +0 -0
- package/publish/worker/GxMcp.Worker.pdb +0 -0
package/cli/run.test.js
CHANGED
|
@@ -5,7 +5,8 @@ const path = require('node:path');
|
|
|
5
5
|
const os = require('node:os');
|
|
6
6
|
const fs = require('node:fs');
|
|
7
7
|
const { renderOutput } = require('./lib/output');
|
|
8
|
-
const { compareSemver } = require('./lib/update-check');
|
|
8
|
+
const { compareSemver, detectInstallMethod, upgradePlanFor } = require('./lib/update-check');
|
|
9
|
+
const { detectClientInstalled, readJsonFileSafe } = require('./lib/config');
|
|
9
10
|
|
|
10
11
|
const cliPath = path.join(__dirname, 'run.js');
|
|
11
12
|
|
|
@@ -599,6 +600,227 @@ test('update --help returns usage entry', () => {
|
|
|
599
600
|
assert.ok(parsed.ok.usage.includes('genexus-mcp update'));
|
|
600
601
|
});
|
|
601
602
|
|
|
603
|
+
test('detectClientInstalled flags an agent installed via marker even with no MCP config', () => {
|
|
604
|
+
// Regression for the field report where Antigravity showed "not detected":
|
|
605
|
+
// an agent whose install dir exists but which hasn't created our MCP config
|
|
606
|
+
// file yet must still be detected as installed.
|
|
607
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-detect-'));
|
|
608
|
+
const installDir = path.join(tempRoot, 'Programs', 'Antigravity');
|
|
609
|
+
fs.mkdirSync(installDir, { recursive: true });
|
|
610
|
+
|
|
611
|
+
const client = {
|
|
612
|
+
name: 'Antigravity',
|
|
613
|
+
path: path.join(tempRoot, 'never-created', 'mcp_config.json'),
|
|
614
|
+
installMarkers: [installDir]
|
|
615
|
+
};
|
|
616
|
+
|
|
617
|
+
const det = detectClientInstalled(client);
|
|
618
|
+
assert.equal(det.installed, true, 'marker dir present => installed');
|
|
619
|
+
assert.equal(det.hasConfig, false, 'config file does not exist yet');
|
|
620
|
+
assert.equal(det.markerHit, installDir);
|
|
621
|
+
|
|
622
|
+
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
623
|
+
});
|
|
624
|
+
|
|
625
|
+
test('detectClientInstalled reports not-installed and lists checked paths', () => {
|
|
626
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-detect-'));
|
|
627
|
+
const client = {
|
|
628
|
+
name: 'Antigravity',
|
|
629
|
+
path: path.join(tempRoot, 'nope.json'),
|
|
630
|
+
installMarkers: [path.join(tempRoot, 'absent-a'), path.join(tempRoot, 'absent-b')]
|
|
631
|
+
};
|
|
632
|
+
|
|
633
|
+
const det = detectClientInstalled(client);
|
|
634
|
+
assert.equal(det.installed, false);
|
|
635
|
+
assert.equal(det.markerHit, null);
|
|
636
|
+
assert.deepEqual(det.markersChecked, client.installMarkers);
|
|
637
|
+
|
|
638
|
+
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
test('detectClientInstalled treats an existing config file as installed', () => {
|
|
642
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-detect-'));
|
|
643
|
+
const cfg = path.join(tempRoot, 'settings.json');
|
|
644
|
+
fs.writeFileSync(cfg, '{}');
|
|
645
|
+
const client = { name: 'Gemini CLI', path: cfg, installMarkers: [] };
|
|
646
|
+
|
|
647
|
+
const det = detectClientInstalled(client);
|
|
648
|
+
assert.equal(det.installed, true);
|
|
649
|
+
assert.equal(det.hasConfig, true);
|
|
650
|
+
|
|
651
|
+
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
// Build a throwaway HOME so client-config writes never touch the real machine.
|
|
655
|
+
function sandboxHomeEnv(root) {
|
|
656
|
+
return {
|
|
657
|
+
HOME: root,
|
|
658
|
+
USERPROFILE: root,
|
|
659
|
+
APPDATA: path.join(root, 'AppData', 'Roaming'),
|
|
660
|
+
LOCALAPPDATA: path.join(root, 'AppData', 'Local'),
|
|
661
|
+
XDG_CONFIG_HOME: path.join(root, '.config')
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
test('clients list returns structured status with summary', () => {
|
|
666
|
+
const result = runCli(['clients', '--format', 'json']);
|
|
667
|
+
assert.equal(result.status, 0);
|
|
668
|
+
const parsed = JSON.parse(result.stdout);
|
|
669
|
+
assert.equal(parsed.meta.command, 'clients.list');
|
|
670
|
+
assert.ok(Array.isArray(parsed.ok.clients));
|
|
671
|
+
assert.ok(parsed.ok.clients.length >= 8);
|
|
672
|
+
assert.equal(typeof parsed.ok.summary.installed, 'number');
|
|
673
|
+
assert.equal(typeof parsed.ok.summary.registered, 'number');
|
|
674
|
+
const row = parsed.ok.clients.find((c) => c.id === 'antigravity');
|
|
675
|
+
assert.ok(row, 'antigravity should be listed');
|
|
676
|
+
assert.equal(typeof row.installed, 'boolean');
|
|
677
|
+
assert.equal(typeof row.registered, 'boolean');
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
test('clients add registers a client into a sandbox home with backup + atomic write', () => {
|
|
681
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-clients-'));
|
|
682
|
+
const env = sandboxHomeEnv(tempRoot);
|
|
683
|
+
const cfgPath = path.join(tempRoot, 'config.json');
|
|
684
|
+
fs.writeFileSync(cfgPath, JSON.stringify({ Environment: { KBPath: tempRoot } }));
|
|
685
|
+
|
|
686
|
+
// Pre-existing cursor config so we can assert a backup is taken.
|
|
687
|
+
const cursorCfg = path.join(tempRoot, '.cursor', 'mcp.json');
|
|
688
|
+
fs.mkdirSync(path.dirname(cursorCfg), { recursive: true });
|
|
689
|
+
fs.writeFileSync(cursorCfg, JSON.stringify({ mcpServers: { other: { command: 'x' } } }, null, 2));
|
|
690
|
+
|
|
691
|
+
const res = runCli(['clients', 'add', '--clients', 'cursor', '--format', 'json'], {
|
|
692
|
+
env: { ...env, GX_CONFIG_PATH: cfgPath }
|
|
693
|
+
});
|
|
694
|
+
assert.equal(res.status, 0);
|
|
695
|
+
const parsed = JSON.parse(res.stdout);
|
|
696
|
+
assert.equal(parsed.meta.command, 'clients.add');
|
|
697
|
+
assert.ok(parsed.ok.patchedClients.includes('Cursor'));
|
|
698
|
+
|
|
699
|
+
const written = JSON.parse(fs.readFileSync(cursorCfg, 'utf8'));
|
|
700
|
+
assert.ok(written.mcpServers.genexus, 'genexus entry should be written');
|
|
701
|
+
assert.ok(written.mcpServers.other, 'pre-existing entries preserved');
|
|
702
|
+
|
|
703
|
+
const baks = fs.readdirSync(path.dirname(cursorCfg)).filter((f) => f.includes('.bak'));
|
|
704
|
+
assert.ok(baks.length >= 1, 'a .bak backup should be created before mutating');
|
|
705
|
+
|
|
706
|
+
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
707
|
+
});
|
|
708
|
+
|
|
709
|
+
test('clients add tolerates a JSONC (commented) VS Code mcp.json', () => {
|
|
710
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-jsonc-'));
|
|
711
|
+
const env = sandboxHomeEnv(tempRoot);
|
|
712
|
+
const cfgPath = path.join(tempRoot, 'config.json');
|
|
713
|
+
fs.writeFileSync(cfgPath, JSON.stringify({ Environment: { KBPath: tempRoot } }));
|
|
714
|
+
|
|
715
|
+
const vscodeCfg = path.join(env.APPDATA, 'Code', 'User', 'mcp.json');
|
|
716
|
+
fs.mkdirSync(path.dirname(vscodeCfg), { recursive: true });
|
|
717
|
+
fs.writeFileSync(vscodeCfg, '{\n // user comment\n "servers": {\n "foo": { "command": "bar" },\n }\n}\n');
|
|
718
|
+
|
|
719
|
+
const res = runCli(['clients', 'add', '--clients', 'vscode', '--format', 'json'], {
|
|
720
|
+
env: { ...env, GX_CONFIG_PATH: cfgPath }
|
|
721
|
+
});
|
|
722
|
+
assert.equal(res.status, 0);
|
|
723
|
+
const parsed = JSON.parse(res.stdout);
|
|
724
|
+
assert.ok(parsed.ok.patchedClients.includes('VS Code'), 'VS Code should be patched despite comments');
|
|
725
|
+
|
|
726
|
+
const written = JSON.parse(fs.readFileSync(vscodeCfg, 'utf8'));
|
|
727
|
+
assert.ok(written.servers.genexus, 'genexus server entry written');
|
|
728
|
+
assert.ok(written.servers.foo, 'pre-existing server preserved');
|
|
729
|
+
|
|
730
|
+
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
731
|
+
});
|
|
732
|
+
|
|
733
|
+
test('clients add replaces a legacy genexus18 entry instead of duplicating it', () => {
|
|
734
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-legacy-'));
|
|
735
|
+
const env = sandboxHomeEnv(tempRoot);
|
|
736
|
+
const cfgPath = path.join(tempRoot, 'config.json');
|
|
737
|
+
fs.writeFileSync(cfgPath, JSON.stringify({ Environment: { KBPath: tempRoot } }));
|
|
738
|
+
|
|
739
|
+
const cursorCfg = path.join(tempRoot, '.cursor', 'mcp.json');
|
|
740
|
+
fs.mkdirSync(path.dirname(cursorCfg), { recursive: true });
|
|
741
|
+
fs.writeFileSync(cursorCfg, JSON.stringify({ mcpServers: { genexus18: { command: 'C:\\old\\start_mcp.bat' } } }, null, 2));
|
|
742
|
+
|
|
743
|
+
const res = runCli(['clients', 'add', '--clients', 'cursor', '--format', 'json'], {
|
|
744
|
+
env: { ...env, GX_CONFIG_PATH: cfgPath }
|
|
745
|
+
});
|
|
746
|
+
assert.equal(res.status, 0);
|
|
747
|
+
|
|
748
|
+
const written = JSON.parse(fs.readFileSync(cursorCfg, 'utf8'));
|
|
749
|
+
assert.ok(written.mcpServers.genexus, 'new genexus entry present');
|
|
750
|
+
assert.equal(written.mcpServers.genexus18, undefined, 'legacy genexus18 removed (no duplicate)');
|
|
751
|
+
|
|
752
|
+
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
753
|
+
});
|
|
754
|
+
|
|
755
|
+
test('clients list flags a registered command pointing at a missing launcher as stale (.bat too)', () => {
|
|
756
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-stale-'));
|
|
757
|
+
const env = sandboxHomeEnv(tempRoot);
|
|
758
|
+
const cursorCfg = path.join(tempRoot, '.cursor', 'mcp.json');
|
|
759
|
+
fs.mkdirSync(path.dirname(cursorCfg), { recursive: true });
|
|
760
|
+
// A non-.exe launcher (.bat) that no longer exists must also be flagged stale.
|
|
761
|
+
const missing = path.join(tempRoot, 'gone', 'start_mcp.bat');
|
|
762
|
+
fs.writeFileSync(cursorCfg, JSON.stringify({ mcpServers: { genexus: { command: missing, args: [] } } }, null, 2));
|
|
763
|
+
|
|
764
|
+
const res = runCli(['clients', '--format', 'json'], { env });
|
|
765
|
+
assert.equal(res.status, 0);
|
|
766
|
+
const parsed = JSON.parse(res.stdout);
|
|
767
|
+
const cursor = parsed.ok.clients.find((c) => c.id === 'cursor');
|
|
768
|
+
assert.ok(cursor.registered, 'cursor should read as registered');
|
|
769
|
+
assert.equal(cursor.commandStale, true, 'missing launcher => stale');
|
|
770
|
+
assert.ok(parsed.help.some((h) => h.includes('missing gateway exe')), 'help should call out the stale client');
|
|
771
|
+
|
|
772
|
+
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
773
|
+
});
|
|
774
|
+
|
|
775
|
+
test('readJsonFileSafe parses JSONC without corrupting string values containing commas', () => {
|
|
776
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-jsonc2-'));
|
|
777
|
+
const f = path.join(tempRoot, 'mcp.json');
|
|
778
|
+
// Leading comment forces the JSONC fallback; the string value contains ", ]"
|
|
779
|
+
// and the object has a legitimate trailing comma that SHOULD be stripped.
|
|
780
|
+
fs.writeFileSync(f, '{\n // comment\n "servers": { "x": { "command": "a, ]b", "args": ["c,]"] } },\n}\n');
|
|
781
|
+
const parsed = readJsonFileSafe(f);
|
|
782
|
+
assert.ok(parsed, 'should parse');
|
|
783
|
+
assert.equal(parsed.servers.x.command, 'a, ]b', 'comma inside string value preserved');
|
|
784
|
+
assert.deepEqual(parsed.servers.x.args, ['c,]'], 'comma inside array string preserved');
|
|
785
|
+
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
786
|
+
});
|
|
787
|
+
|
|
788
|
+
test('readJsonFileSafe strips a genuine trailing comma', () => {
|
|
789
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-jsonc3-'));
|
|
790
|
+
const f = path.join(tempRoot, 'mcp.json');
|
|
791
|
+
fs.writeFileSync(f, '{\n // c\n "a": [1, 2, 3,],\n "b": { "x": 1, },\n}\n');
|
|
792
|
+
const parsed = readJsonFileSafe(f);
|
|
793
|
+
assert.deepEqual(parsed.a, [1, 2, 3]);
|
|
794
|
+
assert.deepEqual(parsed.b, { x: 1 });
|
|
795
|
+
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
796
|
+
});
|
|
797
|
+
|
|
798
|
+
test('clients add without --clients is a usage error', () => {
|
|
799
|
+
const res = runCli(['clients', 'add', '--format', 'json']);
|
|
800
|
+
assert.equal(res.status, 2);
|
|
801
|
+
const parsed = JSON.parse(res.stdout);
|
|
802
|
+
assert.equal(parsed.error.code, 'usage_error');
|
|
803
|
+
});
|
|
804
|
+
|
|
805
|
+
test('clients remove drops the genexus entry (sandbox home)', () => {
|
|
806
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-rm-'));
|
|
807
|
+
const env = sandboxHomeEnv(tempRoot);
|
|
808
|
+
const cursorCfg = path.join(tempRoot, '.cursor', 'mcp.json');
|
|
809
|
+
fs.mkdirSync(path.dirname(cursorCfg), { recursive: true });
|
|
810
|
+
fs.writeFileSync(cursorCfg, JSON.stringify({ mcpServers: { genexus: { command: 'npx' }, genexus18: { command: 'old' } } }, null, 2));
|
|
811
|
+
|
|
812
|
+
const res = runCli(['clients', 'remove', '--clients', 'cursor', '--format', 'json'], { env });
|
|
813
|
+
assert.equal(res.status, 0);
|
|
814
|
+
const parsed = JSON.parse(res.stdout);
|
|
815
|
+
assert.ok(parsed.ok.removedClients.includes('Cursor'));
|
|
816
|
+
|
|
817
|
+
const written = JSON.parse(fs.readFileSync(cursorCfg, 'utf8'));
|
|
818
|
+
assert.equal(written.mcpServers.genexus, undefined, 'genexus removed');
|
|
819
|
+
assert.equal(written.mcpServers.genexus18, undefined, 'legacy genexus18 also removed');
|
|
820
|
+
|
|
821
|
+
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
822
|
+
});
|
|
823
|
+
|
|
602
824
|
test('compareSemver detects newer, older, equal versions', () => {
|
|
603
825
|
assert.equal(compareSemver('1.3.1', '1.3.0'), 1);
|
|
604
826
|
assert.equal(compareSemver('v1.4.0', '1.3.9'), 1);
|
|
@@ -607,6 +829,36 @@ test('compareSemver detects newer, older, equal versions', () => {
|
|
|
607
829
|
assert.equal(compareSemver('garbage', '1.0.0'), 0);
|
|
608
830
|
});
|
|
609
831
|
|
|
832
|
+
test('detectInstallMethod returns fixed-path when GENEXUS_MCP_GATEWAY_EXE is set', () => {
|
|
833
|
+
const prev = process.env.GENEXUS_MCP_GATEWAY_EXE;
|
|
834
|
+
process.env.GENEXUS_MCP_GATEWAY_EXE = 'C:\\Tools\\GenexusMCP\\GxMcp.Gateway.exe';
|
|
835
|
+
try {
|
|
836
|
+
const r = detectInstallMethod();
|
|
837
|
+
assert.equal(r.method, 'fixed-path');
|
|
838
|
+
assert.equal(r.detail, 'C:\\Tools\\GenexusMCP\\GxMcp.Gateway.exe');
|
|
839
|
+
} finally {
|
|
840
|
+
if (prev === undefined) delete process.env.GENEXUS_MCP_GATEWAY_EXE;
|
|
841
|
+
else process.env.GENEXUS_MCP_GATEWAY_EXE = prev;
|
|
842
|
+
}
|
|
843
|
+
});
|
|
844
|
+
|
|
845
|
+
test('upgradePlanFor encodes the per-method upgrade strategy', () => {
|
|
846
|
+
const npx = upgradePlanFor('npx-latest', 'latest');
|
|
847
|
+
assert.equal(npx.auto, true, 'npx@latest auto-updates on restart');
|
|
848
|
+
assert.ok(npx.steps.join(' ').toLowerCase().includes('restart'));
|
|
849
|
+
|
|
850
|
+
const npm = upgradePlanFor('npm-global', 'latest');
|
|
851
|
+
assert.equal(npm.auto, false);
|
|
852
|
+
assert.deepEqual(npm.applyCommand.args, ['install', '-g', 'genexus-mcp@latest']);
|
|
853
|
+
|
|
854
|
+
const npmNext = upgradePlanFor('npm-global', 'next');
|
|
855
|
+
assert.deepEqual(npmNext.applyCommand.args, ['install', '-g', 'genexus-mcp@next']);
|
|
856
|
+
|
|
857
|
+
const fixed = upgradePlanFor('fixed-path', 'latest');
|
|
858
|
+
assert.equal(fixed.auto, false);
|
|
859
|
+
assert.equal(fixed.applyCommand, null, 'fixed-path has no npm apply; uses the installer');
|
|
860
|
+
});
|
|
861
|
+
|
|
610
862
|
test('gateway passthrough remains intact when no AXI subcommand is used', () => {
|
|
611
863
|
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-test-'));
|
|
612
864
|
const fakeGateway = path.join(tempRoot, 'fake-gateway.js');
|
|
@@ -27,6 +27,7 @@ Entry points:
|
|
|
27
27
|
- `genexus-mcp llm help`
|
|
28
28
|
- `genexus-mcp status`
|
|
29
29
|
- `genexus-mcp doctor --mcp-smoke`
|
|
30
|
+
- `genexus-mcp clients` (which AI agents are installed/registered; `clients add|remove --clients <csv>`)
|
|
30
31
|
- `genexus-mcp tools list`
|
|
31
32
|
- `genexus-mcp config show`
|
|
32
33
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genexus-mcp",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.4",
|
|
4
4
|
"mcpName": "io.github.lennix1337/genexus",
|
|
5
5
|
"description": "GeneXus 18 MCP server — read, edit, and analyze GeneXus knowledge base objects (transactions, web panels, procedures, SDTs) 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=v8.0": {},
|
|
9
9
|
".NETCoreApp,Version=v8.0/win-x64": {
|
|
10
|
-
"GxMcp.Gateway/2.8.
|
|
10
|
+
"GxMcp.Gateway/2.8.4": {
|
|
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/2.8.
|
|
69
|
+
"GxMcp.Gateway/2.8.4": {
|
|
70
70
|
"type": "project",
|
|
71
71
|
"serviceable": false,
|
|
72
72
|
"sha512": ""
|
|
Binary file
|
|
Binary file
|
package/publish/config.json
CHANGED
|
@@ -1,20 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"DefaultKb": "academicohomolog1"
|
|
19
|
-
}
|
|
20
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"GeneXus": {
|
|
3
|
+
"WorkerExecutable": "C:\\Projetos\\Genexus18MCP\\publish\\\\worker\\\\GxMcp.Worker.exe",
|
|
4
|
+
"InstallationPath": "C:\\\\Program Files (x86)\\\\GeneXus\\\\GeneXus18"
|
|
5
|
+
},
|
|
6
|
+
"Server": {
|
|
7
|
+
"HttpPort": 5000,
|
|
8
|
+
"McpStdio": true
|
|
9
|
+
},
|
|
10
|
+
"Logging": {
|
|
11
|
+
"Path": "logs",
|
|
12
|
+
"Level": "Debug"
|
|
13
|
+
},
|
|
14
|
+
"Environment": {
|
|
15
|
+
"KBPath": "C:\\\\KBs\\\\YourKB"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|