genexus-mcp 3.10.0 → 3.11.0
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 +13 -2
- package/cli/commands/axi.js +18 -12
- package/cli/lib/config.js +61 -2
- package/cli/run.test.js +168 -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 +12 -12
- package/publish/gxmcp-manifest.json +12 -12
- package/publish/gxmcp-sbom.json +4 -4
- package/publish/nexus-ide.vsix +0 -0
- package/publish/tool_definitions.json +4 -4
- package/publish/worker/GxMcp.Worker.exe +0 -0
package/README.md
CHANGED
|
@@ -66,7 +66,9 @@ recognized. Classic DAT KB roots are identified from their legacy markers
|
|
|
66
66
|
|
|
67
67
|
`init` also reads the KB `.gxw` major and the selected `GeneXus.exe` metadata.
|
|
68
68
|
It aborts before writing `config.json` when the majors conflict or an automatic
|
|
69
|
-
selection cannot be verified.
|
|
69
|
+
selection cannot be verified. When several installs share the KB major, the
|
|
70
|
+
automatic selection prefers the one whose update matches the `.gxw` version
|
|
71
|
+
(e.g. U7 for an `18.0.7.x` KB) over the newest one. `genexus-mcp doctor` exposes the same result as
|
|
70
72
|
the `kb_sdk_compatibility` check. For a disposable fixture, the
|
|
71
73
|
[live-KB harness](docs/live-kb-test-harness.md) includes a catalog-driven matrix
|
|
72
74
|
that checks every supported major against one published artifact.
|
|
@@ -455,6 +457,15 @@ declared indexes are reported only when they can be resolved without Specify.
|
|
|
455
457
|
typed public SDK elements and never exposes the internal collection type names
|
|
456
458
|
produced by `DataSelectorStructurePart.ToString()` on U16.
|
|
457
459
|
|
|
460
|
+
To change a Data Selector's conditions use `genexus_edit type=DataSelector part=Conditions
|
|
461
|
+
mode=full` with one condition per line (`genexus_read parts=["conditions"]` also returns
|
|
462
|
+
that text as `source`). The list is replaced as a whole, parameters/orders/Defined By are
|
|
463
|
+
left untouched, and the saved conditions are re-read and verified. A Data Selector whose
|
|
464
|
+
conditions sit inside a nested AND/OR group is refused with
|
|
465
|
+
`DataSelectorConditionsNestedGroupsUnsupported` and nothing is saved: the one-per-line form
|
|
466
|
+
carries no grouping, so replacing the list would silently flatten it. Flatten those levels
|
|
467
|
+
in GeneXus first.
|
|
468
|
+
|
|
458
469
|
**Editing**
|
|
459
470
|
- `genexus_edit` — edit any object part; modes `full` / `patch` / `ops`
|
|
460
471
|
- `genexus_edit_and_build` — edit + optional specification + rebuild callers in one call, with compensating rollback on validation failure
|
|
@@ -500,7 +511,7 @@ produced by `DataSelectorStructurePart.ToString()` on U16.
|
|
|
500
511
|
- `genexus_kb_version` — model version/branch management (Create/Activate/Revert)
|
|
501
512
|
- `genexus_versioning` — versioning umbrella (git-style history over the KB)
|
|
502
513
|
- `genexus_gxserver` — GXserver / Team Development sync, incl. `pipeline_*` (CI pipelines via `IContinuousIntegrationService`)
|
|
503
|
-
- `genexus_transfer` — real XPZ export/import (`IKnowledgeManagerService`, dependency-aware): `export` / `inspect` / `import`
|
|
514
|
+
- `genexus_transfer` — real XPZ export/import (`IKnowledgeManagerService`, dependency-aware): `export` / `inspect` / `import` (`import` previews by default: pass `dryRun:false` and `confirm:true` to actually import)
|
|
504
515
|
- `genexus_memory` — per-KB fact store for the agent
|
|
505
516
|
|
|
506
517
|
**Security provisioning, IO & meta**
|
package/cli/commands/axi.js
CHANGED
|
@@ -23,7 +23,7 @@ const {
|
|
|
23
23
|
readGeneXusKbIdentity,
|
|
24
24
|
compareGeneXusKbAndInstallation,
|
|
25
25
|
getGeneXusVersionCatalog,
|
|
26
|
-
|
|
26
|
+
discoverGeneXusInstallationForKb,
|
|
27
27
|
discoverKnowledgeBase,
|
|
28
28
|
discoverKnowledgeBases,
|
|
29
29
|
readKbCatalog,
|
|
@@ -149,7 +149,7 @@ function operationalErrorEnvelope(message, exitCode, help = [], code = 'operatio
|
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
function buildStatusData(cwd) {
|
|
152
|
-
const configPath = resolveConfigPathNoMutate(cwd);
|
|
152
|
+
const configPath = resolveConfigPathNoMutate(cwd, { allowUserProfile: true });
|
|
153
153
|
const gatewayExePath = getGatewayExePath();
|
|
154
154
|
const gatewayExeFound = fs.existsSync(gatewayExePath);
|
|
155
155
|
const configFound = !!(configPath && fs.existsSync(configPath));
|
|
@@ -165,7 +165,7 @@ function buildStatusData(cwd) {
|
|
|
165
165
|
if (process.env.GX_CONFIG_PATH) {
|
|
166
166
|
configSource = 'env';
|
|
167
167
|
} else if (configFound) {
|
|
168
|
-
configSource = 'cwd';
|
|
168
|
+
configSource = path.resolve(configPath) === path.resolve(cwd, 'config.json') ? 'cwd' : 'neutral';
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
if (configFound) {
|
|
@@ -404,7 +404,7 @@ async function probeGatewaySpawn({ configPath = null } = {}) {
|
|
|
404
404
|
}
|
|
405
405
|
|
|
406
406
|
function resolveMcpSmokeTarget(cwd) {
|
|
407
|
-
const configPath = resolveConfigPathNoMutate(cwd);
|
|
407
|
+
const configPath = resolveConfigPathNoMutate(cwd, { allowUserProfile: true });
|
|
408
408
|
const fallback = 'http://127.0.0.1:5000/mcp';
|
|
409
409
|
if (!configPath) {
|
|
410
410
|
return { applicable: true, status: null, detail: null, baseUrl: fallback };
|
|
@@ -1125,7 +1125,7 @@ async function handleDoctor(options, ctx) {
|
|
|
1125
1125
|
const gxEnvCheck = process.env.GX_CONFIG_PATH
|
|
1126
1126
|
? { status: 'pass', detail: 'GX_CONFIG_PATH env var is set.' }
|
|
1127
1127
|
: data.configFound
|
|
1128
|
-
? { status: 'not_applicable', detail: `GX_CONFIG_PATH is not set; using ${data.configPath} from the current directory.` }
|
|
1128
|
+
? { status: 'not_applicable', detail: `GX_CONFIG_PATH is not set; using ${data.configPath} ${data.configSource === 'neutral' ? 'from the user profile' : 'from the current directory'}.` }
|
|
1129
1129
|
: { status: 'warn', detail: 'GX_CONFIG_PATH env var is not set and no config file was found.' };
|
|
1130
1130
|
const kbCatalogEntries = Object.entries(data.kbCatalog?.kbs || {});
|
|
1131
1131
|
const missingCatalogKbs = kbCatalogEntries.filter(([, declaredPath]) => !fs.existsSync(declaredPath));
|
|
@@ -1439,9 +1439,12 @@ async function handleConfigCreate(options, ctx) {
|
|
|
1439
1439
|
}
|
|
1440
1440
|
|
|
1441
1441
|
async function handleConfigMigrate(options, ctx) {
|
|
1442
|
+
// No `allowUserProfile`: `--from` defaults to the config this command then reads,
|
|
1443
|
+
// so resolving the shared user profile here would silently migrate it from any
|
|
1444
|
+
// folder. `--from` stays the way to name it explicitly.
|
|
1442
1445
|
const sourcePath = options.fromPath || resolveConfigPathNoMutate(ctx.cwd);
|
|
1443
1446
|
if (!sourcePath) {
|
|
1444
|
-
return { exitCode: ctx.EXIT_CODES.USAGE, envelope: usageEnvelope('config migrate requires --from <legacy-config
|
|
1447
|
+
return { exitCode: ctx.EXIT_CODES.USAGE, envelope: usageEnvelope('config migrate requires --from <legacy-config>, GX_CONFIG_PATH, or a config.json in the current directory.', ctx.EXIT_CODES.USAGE) };
|
|
1445
1448
|
}
|
|
1446
1449
|
const targetPath = options.output || `${sourcePath}.neutral.json`;
|
|
1447
1450
|
if (path.resolve(sourcePath) === path.resolve(targetPath)) {
|
|
@@ -1484,7 +1487,7 @@ async function handleConfigMigrate(options, ctx) {
|
|
|
1484
1487
|
}
|
|
1485
1488
|
|
|
1486
1489
|
async function handleConfigShow(options, ctx) {
|
|
1487
|
-
const configPath = resolveConfigPathNoMutate(ctx.cwd);
|
|
1490
|
+
const configPath = resolveConfigPathNoMutate(ctx.cwd, { allowUserProfile: true });
|
|
1488
1491
|
if (!configPath) {
|
|
1489
1492
|
return {
|
|
1490
1493
|
exitCode: ctx.EXIT_CODES.ERROR,
|
|
@@ -1795,7 +1798,7 @@ async function runInteractiveInit(ctx) {
|
|
|
1795
1798
|
}
|
|
1796
1799
|
|
|
1797
1800
|
const kbIdentity = readGeneXusKbIdentity(finalKb);
|
|
1798
|
-
const defaultGx =
|
|
1801
|
+
const defaultGx = discoverGeneXusInstallationForKb(kbIdentity)
|
|
1799
1802
|
|| primary?.defaultInstallPath
|
|
1800
1803
|
|| catalog.supportedMajors[0]?.defaultInstallPath
|
|
1801
1804
|
|| '';
|
|
@@ -1821,7 +1824,7 @@ async function runInteractiveInit(ctx) {
|
|
|
1821
1824
|
const gxExecutable = finalGx && ['genexus.exe', 'gx.exe', 'gxw32.exe']
|
|
1822
1825
|
.find((name) => fs.existsSync(path.join(finalGx, name)));
|
|
1823
1826
|
if (!gxExecutable) {
|
|
1824
|
-
const suggested =
|
|
1827
|
+
const suggested = discoverGeneXusInstallationForKb(kbIdentity);
|
|
1825
1828
|
const help = [`Path checked: ${finalGx}`];
|
|
1826
1829
|
if (suggested && suggested.toLowerCase() !== finalGx.toLowerCase()) {
|
|
1827
1830
|
help.push(`Detected a matching GeneXus${kbIdentity.major ? ` ${kbIdentity.major}` : ''} install at: ${suggested}`);
|
|
@@ -1999,7 +2002,7 @@ async function handleInit(options, ctx) {
|
|
|
1999
2002
|
: { version: null, major: null, source: 'unavailable', reason: 'missing-kb-path' };
|
|
2000
2003
|
|
|
2001
2004
|
if (!resolution.gx.value) {
|
|
2002
|
-
const fromDisco =
|
|
2005
|
+
const fromDisco = discoverGeneXusInstallationForKb(discoveredKbIdentity);
|
|
2003
2006
|
if (fromDisco) {
|
|
2004
2007
|
resolution.gx.value = fromDisco;
|
|
2005
2008
|
resolution.gx.source = 'auto-discovery';
|
|
@@ -2047,7 +2050,7 @@ async function handleInit(options, ctx) {
|
|
|
2047
2050
|
`Source: --${resolution.gx.source === 'flag' ? 'gx flag' : resolution.gx.source}`
|
|
2048
2051
|
];
|
|
2049
2052
|
const suggested = resolution.gx.source === 'flag'
|
|
2050
|
-
?
|
|
2053
|
+
? discoverGeneXusInstallationForKb(discoveredKbIdentity)
|
|
2051
2054
|
: null;
|
|
2052
2055
|
if (suggested && suggested.toLowerCase() !== resolution.gx.value.toLowerCase()) {
|
|
2053
2056
|
help.push(`Detected a working GeneXus install at: ${suggested}`);
|
|
@@ -2618,12 +2621,15 @@ async function handleClients(subcommand, options, ctx) {
|
|
|
2618
2621
|
}
|
|
2619
2622
|
|
|
2620
2623
|
if (sub === 'add') {
|
|
2624
|
+
// No `allowUserProfile`: the resolved path is patched in place, so falling
|
|
2625
|
+
// back to the shared user config would let `clients add` rewrite it from any
|
|
2626
|
+
// folder. Point the client at the user config with GX_CONFIG_PATH instead.
|
|
2621
2627
|
const configPath = resolveConfigPathNoMutate(ctx.cwd);
|
|
2622
2628
|
if (!configPath) {
|
|
2623
2629
|
return {
|
|
2624
2630
|
exitCode: ctx.EXIT_CODES.ERROR,
|
|
2625
2631
|
envelope: operationalErrorEnvelope(
|
|
2626
|
-
'No config.json found to point the clients at. Run `genexus-mcp init` first
|
|
2632
|
+
'No config.json found to point the clients at. Run `genexus-mcp init` first, run from a KB folder, or set GX_CONFIG_PATH to the config to register.',
|
|
2627
2633
|
ctx.EXIT_CODES.ERROR
|
|
2628
2634
|
)
|
|
2629
2635
|
};
|
package/cli/lib/config.js
CHANGED
|
@@ -280,6 +280,50 @@ function discoverGeneXusInstallation(preferredMajor = null) {
|
|
|
280
280
|
return null;
|
|
281
281
|
}
|
|
282
282
|
|
|
283
|
+
// Same-major discovery returns the first install the registry or folder scan
|
|
284
|
+
// finds, usually the newest update, and opening a KB with a newer update
|
|
285
|
+
// converts it. When the KB's exact build is known, prefer an install of the
|
|
286
|
+
// same major.minor.update (sibling of the discovered one or under the standard
|
|
287
|
+
// GeneXus roots); otherwise keep the same-major result.
|
|
288
|
+
function discoverGeneXusInstallationForKb(kbIdentity) {
|
|
289
|
+
const major = kbIdentity ? kbIdentity.major : null;
|
|
290
|
+
const fallback = discoverGeneXusInstallation(major);
|
|
291
|
+
const wanted = geneXusUpdateKey(kbIdentity && kbIdentity.version);
|
|
292
|
+
if (!wanted) return fallback;
|
|
293
|
+
if (fallback && geneXusUpdateKey(readGeneXusInstallationIdentity(fallback).version) === wanted) return fallback;
|
|
294
|
+
|
|
295
|
+
const roots = [];
|
|
296
|
+
if (fallback) roots.push(path.dirname(fallback));
|
|
297
|
+
for (const base of [process.env['ProgramFiles(x86)'], process.env.ProgramFiles]) {
|
|
298
|
+
if (!base) continue;
|
|
299
|
+
roots.push(path.join(base, 'GeneXus'), path.join(base, 'Artech', 'GeneXus'));
|
|
300
|
+
}
|
|
301
|
+
const seen = new Set();
|
|
302
|
+
for (const root of roots) {
|
|
303
|
+
const key = root.toLowerCase();
|
|
304
|
+
if (seen.has(key)) continue;
|
|
305
|
+
seen.add(key);
|
|
306
|
+
let entries;
|
|
307
|
+
try {
|
|
308
|
+
entries = fs.readdirSync(root);
|
|
309
|
+
} catch {
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
for (const entry of entries) {
|
|
313
|
+
if (!/^GeneXus/i.test(entry)) continue;
|
|
314
|
+
const candidate = path.join(root, entry);
|
|
315
|
+
if (!hasGeneXusExecutable(candidate)) continue;
|
|
316
|
+
if (geneXusUpdateKey(readGeneXusInstallationIdentity(candidate).version) === wanted) return candidate;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return fallback;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function geneXusUpdateKey(version) {
|
|
323
|
+
const match = String(version || '').trim().match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
324
|
+
return match ? `${match[1]}.${match[2]}.${match[3]}` : null;
|
|
325
|
+
}
|
|
326
|
+
|
|
283
327
|
function discoverGeneXusFromPath(preferredMajor = null) {
|
|
284
328
|
if (process.platform !== 'win32') return null;
|
|
285
329
|
try {
|
|
@@ -628,7 +672,7 @@ function migrateLegacyConfig(sourcePath, targetPath, { rejectNonMigratable = fal
|
|
|
628
672
|
}
|
|
629
673
|
}
|
|
630
674
|
|
|
631
|
-
function resolveConfigPathNoMutate(cwd) {
|
|
675
|
+
function resolveConfigPathNoMutate(cwd, options) {
|
|
632
676
|
const cwdConfigPath = path.join(cwd, 'config.json');
|
|
633
677
|
// Match the Gateway: an explicit GX_CONFIG_PATH is authoritative even when
|
|
634
678
|
// the file is missing, so diagnostics do not silently inspect an unrelated
|
|
@@ -639,6 +683,20 @@ function resolveConfigPathNoMutate(cwd) {
|
|
|
639
683
|
if (fs.existsSync(cwdConfigPath)) {
|
|
640
684
|
return cwdConfigPath;
|
|
641
685
|
}
|
|
686
|
+
// The neutral user config is the last fallback, matching the Gateway and the
|
|
687
|
+
// zero-config launcher outside a KB folder. It is opt-in because this resolver
|
|
688
|
+
// is also reached from commands that WRITE to the resolved path (`clients add`
|
|
689
|
+
// patches it, `config migrate` reads it as `--from`). Falling back silently there
|
|
690
|
+
// would let a command run from any folder rewrite the shared user profile, so
|
|
691
|
+
// only the read-only diagnostics opt in and a mutating caller keeps resolving to
|
|
692
|
+
// the explicit path or the cwd config.
|
|
693
|
+
if (!options || options.allowUserProfile !== true) {
|
|
694
|
+
return null;
|
|
695
|
+
}
|
|
696
|
+
const userConfigPath = path.join(os.homedir(), '.genexus-mcp', 'config.json');
|
|
697
|
+
if (!directoryLooksLikeKnowledgeBase(cwd) && fs.existsSync(userConfigPath)) {
|
|
698
|
+
return userConfigPath;
|
|
699
|
+
}
|
|
642
700
|
return null;
|
|
643
701
|
}
|
|
644
702
|
|
|
@@ -2308,7 +2366,7 @@ function applyLauncherConfigOrExit({ cwd, stderr, quiet }) {
|
|
|
2308
2366
|
return { ok: false };
|
|
2309
2367
|
}
|
|
2310
2368
|
|
|
2311
|
-
const foundGxPath =
|
|
2369
|
+
const foundGxPath = discoverGeneXusInstallationForKb(kbIdentity);
|
|
2312
2370
|
if (!foundGxPath) {
|
|
2313
2371
|
log('[genexus-mcp] ERROR: No GeneXus installation matching the KB major was auto-discovered.');
|
|
2314
2372
|
log(`[genexus-mcp] KB major: ${kbIdentity.major}`);
|
|
@@ -2347,6 +2405,7 @@ module.exports = {
|
|
|
2347
2405
|
getGeneXusVersionCatalog,
|
|
2348
2406
|
getGeneXusCatalogEntries,
|
|
2349
2407
|
discoverGeneXusInstallation,
|
|
2408
|
+
discoverGeneXusInstallationForKb,
|
|
2350
2409
|
discoverGeneXusFromRegistry,
|
|
2351
2410
|
discoverKnowledgeBase,
|
|
2352
2411
|
discoverKnowledgeBases,
|
package/cli/run.test.js
CHANGED
|
@@ -917,6 +917,94 @@ test('classic gxi identity does not invent a GX8/GX9 mismatch before provider op
|
|
|
917
917
|
}
|
|
918
918
|
});
|
|
919
919
|
|
|
920
|
+
test('init prefers the GeneXus install of the KB update over a newer same-major one', () => {
|
|
921
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-kb-update-'));
|
|
922
|
+
const kbDir = path.join(tempRoot, 'kb');
|
|
923
|
+
const newerGx = path.join(tempRoot, 'GeneXus18_u14');
|
|
924
|
+
const kbGx = path.join(tempRoot, 'GeneXus18_u7');
|
|
925
|
+
fs.mkdirSync(kbDir, { recursive: true });
|
|
926
|
+
fs.writeFileSync(
|
|
927
|
+
path.join(kbDir, 'KnowledgeBase.gxw'),
|
|
928
|
+
'<KnowledgeBase><VersionNumber>18.0.7.179127</VersionNumber></KnowledgeBase>'
|
|
929
|
+
);
|
|
930
|
+
for (const [dir, version] of [[newerGx, '18.0.14.187794'], [kbGx, '18.0.7.179127']]) {
|
|
931
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
932
|
+
fs.writeFileSync(path.join(dir, 'GeneXus.exe'), 'not-a-real-executable');
|
|
933
|
+
fs.writeFileSync(path.join(dir, 'version.txt'), version);
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
try {
|
|
937
|
+
// Empty Program Files roots: the install scan walks them, so without this the
|
|
938
|
+
// assertion depends on what the host happens to have installed under a matching
|
|
939
|
+
// update. GENEXUS_HOME stands in for the registry, which points at the newest update.
|
|
940
|
+
const emptyPf86 = path.join(tempRoot, 'empty-pf86');
|
|
941
|
+
const emptyPf = path.join(tempRoot, 'empty-pf');
|
|
942
|
+
fs.mkdirSync(emptyPf86, { recursive: true });
|
|
943
|
+
fs.mkdirSync(emptyPf, { recursive: true });
|
|
944
|
+
const result = runCli(
|
|
945
|
+
['init', '--kb', kbDir, '--no-smoke', '--no-write-clients', '--format', 'json'],
|
|
946
|
+
{
|
|
947
|
+
env: {
|
|
948
|
+
...testGatewayEnv,
|
|
949
|
+
GENEXUS_HOME: newerGx,
|
|
950
|
+
'ProgramFiles(x86)': emptyPf86,
|
|
951
|
+
ProgramFiles: emptyPf
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
);
|
|
955
|
+
assert.equal(result.status, 0, result.stdout + result.stderr);
|
|
956
|
+
const parsed = JSON.parse(result.stdout);
|
|
957
|
+
assert.equal(parsed.ok.resolved.gx.path, kbGx);
|
|
958
|
+
const written = JSON.parse(fs.readFileSync(path.join(kbDir, 'config.json'), 'utf8'));
|
|
959
|
+
assert.equal(written.GeneXus.InstallationPath, kbGx);
|
|
960
|
+
} finally {
|
|
961
|
+
removeTempPath(tempRoot, { recursive: true, force: true });
|
|
962
|
+
}
|
|
963
|
+
});
|
|
964
|
+
|
|
965
|
+
test('init keeps the same-major install when no GeneXus matches the KB update', () => {
|
|
966
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'gxmcp-kb-update-nomatch-'));
|
|
967
|
+
const kbDir = path.join(tempRoot, 'kb');
|
|
968
|
+
const newerGx = path.join(tempRoot, 'GeneXus18_u14');
|
|
969
|
+
fs.mkdirSync(kbDir, { recursive: true });
|
|
970
|
+
// The KB names an update that is installed nowhere.
|
|
971
|
+
fs.writeFileSync(
|
|
972
|
+
path.join(kbDir, 'KnowledgeBase.gxw'),
|
|
973
|
+
'<KnowledgeBase><VersionNumber>18.0.3.111111</VersionNumber></KnowledgeBase>'
|
|
974
|
+
);
|
|
975
|
+
fs.mkdirSync(newerGx, { recursive: true });
|
|
976
|
+
fs.writeFileSync(path.join(newerGx, 'GeneXus.exe'), 'not-a-real-executable');
|
|
977
|
+
fs.writeFileSync(path.join(newerGx, 'version.txt'), '18.0.14.187794');
|
|
978
|
+
|
|
979
|
+
try {
|
|
980
|
+
const emptyPf86 = path.join(tempRoot, 'empty-pf86');
|
|
981
|
+
const emptyPf = path.join(tempRoot, 'empty-pf');
|
|
982
|
+
fs.mkdirSync(emptyPf86, { recursive: true });
|
|
983
|
+
fs.mkdirSync(emptyPf, { recursive: true });
|
|
984
|
+
const result = runCli(
|
|
985
|
+
['init', '--kb', kbDir, '--no-smoke', '--no-write-clients', '--format', 'json'],
|
|
986
|
+
{
|
|
987
|
+
env: {
|
|
988
|
+
...testGatewayEnv,
|
|
989
|
+
GENEXUS_HOME: newerGx,
|
|
990
|
+
'ProgramFiles(x86)': emptyPf86,
|
|
991
|
+
ProgramFiles: emptyPf
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
);
|
|
995
|
+
assert.equal(result.status, 0, result.stdout + result.stderr);
|
|
996
|
+
const parsed = JSON.parse(result.stdout);
|
|
997
|
+
// No exact match anywhere: the same-major install is kept rather than resolving
|
|
998
|
+
// to nothing. This is the branch that decides what happens to a KB whose update
|
|
999
|
+
// is genuinely missing, so the choice is pinned instead of implied.
|
|
1000
|
+
assert.equal(parsed.ok.resolved.gx.path, newerGx);
|
|
1001
|
+
const written = JSON.parse(fs.readFileSync(path.join(kbDir, 'config.json'), 'utf8'));
|
|
1002
|
+
assert.equal(written.GeneXus.InstallationPath, newerGx);
|
|
1003
|
+
} finally {
|
|
1004
|
+
removeTempPath(tempRoot, { recursive: true, force: true });
|
|
1005
|
+
}
|
|
1006
|
+
});
|
|
1007
|
+
|
|
920
1008
|
test('init rejects a known KB and SDK major mismatch before writing config', () => {
|
|
921
1009
|
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-mismatch-'));
|
|
922
1010
|
const kbDir = path.join(tempRoot, 'kb17');
|
|
@@ -1387,6 +1475,86 @@ test('doctor fails closed when GX_CONFIG_PATH points at a missing file', () => {
|
|
|
1387
1475
|
}
|
|
1388
1476
|
});
|
|
1389
1477
|
|
|
1478
|
+
test('doctor resolves the neutral user config outside a KB folder, like the Gateway', () => {
|
|
1479
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-doctor-user-config-'));
|
|
1480
|
+
try {
|
|
1481
|
+
const home = path.join(tempRoot, 'home');
|
|
1482
|
+
const cwd = path.join(tempRoot, 'project');
|
|
1483
|
+
const userConfig = path.join(home, '.genexus-mcp', 'config.json');
|
|
1484
|
+
fs.mkdirSync(path.dirname(userConfig), { recursive: true });
|
|
1485
|
+
fs.mkdirSync(cwd, { recursive: true });
|
|
1486
|
+
fs.writeFileSync(userConfig, JSON.stringify({ Environment: { ResolutionPolicy: 'strict' } }));
|
|
1487
|
+
|
|
1488
|
+
const result = runCli(['doctor', '--format', 'json'], {
|
|
1489
|
+
cwd,
|
|
1490
|
+
env: { ...sandboxHomeEnv(home), GENEXUS_MCP_GATEWAY_EXE: process.execPath }
|
|
1491
|
+
});
|
|
1492
|
+
assert.equal(result.status, 0);
|
|
1493
|
+
const configCheck = JSON.parse(result.stdout).ok.checks.find((c) => c.id === 'config_file');
|
|
1494
|
+
assert.ok(configCheck);
|
|
1495
|
+
assert.equal(configCheck.status, 'pass', configCheck.detail);
|
|
1496
|
+
assert.ok(configCheck.detail.includes(userConfig), configCheck.detail);
|
|
1497
|
+
assert.ok(configCheck.detail.includes('(source: neutral)'), configCheck.detail);
|
|
1498
|
+
const envCheck = JSON.parse(result.stdout).ok.checks.find((c) => c.id === 'gx_env');
|
|
1499
|
+
assert.ok(envCheck);
|
|
1500
|
+
assert.match(envCheck.detail, /from the user profile/);
|
|
1501
|
+
} finally {
|
|
1502
|
+
removeTempPath(tempRoot, { recursive: true, force: true });
|
|
1503
|
+
}
|
|
1504
|
+
});
|
|
1505
|
+
|
|
1506
|
+
// The diagnostics fall back to the shared user profile, but the commands that WRITE to
|
|
1507
|
+
// the resolved path must not: `clients add` patches it in place and `config migrate`
|
|
1508
|
+
// reads it as `--from`. Without the opt-in, both would silently rewrite
|
|
1509
|
+
// `~/.genexus-mcp/config.json` when run from any folder that is not a KB.
|
|
1510
|
+
test('clients add refuses to fall back to the shared user profile config', () => {
|
|
1511
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'gxmcp-clients-add-user-cfg-'));
|
|
1512
|
+
try {
|
|
1513
|
+
const home = path.join(tempRoot, 'home');
|
|
1514
|
+
const cwd = path.join(tempRoot, 'project');
|
|
1515
|
+
const userConfig = path.join(home, '.genexus-mcp', 'config.json');
|
|
1516
|
+
fs.mkdirSync(path.dirname(userConfig), { recursive: true });
|
|
1517
|
+
fs.mkdirSync(cwd, { recursive: true });
|
|
1518
|
+
const original = JSON.stringify({ Environment: { ResolutionPolicy: 'strict' } }, null, 2);
|
|
1519
|
+
fs.writeFileSync(userConfig, original);
|
|
1520
|
+
|
|
1521
|
+
const result = runCli(['clients', 'add', '--clients', 'opencode', '--format', 'json'], {
|
|
1522
|
+
cwd,
|
|
1523
|
+
env: { ...sandboxHomeEnv(home), GENEXUS_MCP_GATEWAY_EXE: process.execPath }
|
|
1524
|
+
});
|
|
1525
|
+
|
|
1526
|
+
assert.notEqual(result.status, 0, result.stdout + result.stderr);
|
|
1527
|
+
// The shared config is untouched.
|
|
1528
|
+
assert.equal(fs.readFileSync(userConfig, 'utf8'), original);
|
|
1529
|
+
} finally {
|
|
1530
|
+
removeTempPath(tempRoot, { recursive: true, force: true });
|
|
1531
|
+
}
|
|
1532
|
+
});
|
|
1533
|
+
|
|
1534
|
+
test('config migrate requires an explicit source instead of defaulting to the user profile', () => {
|
|
1535
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'gxmcp-config-migrate-user-cfg-'));
|
|
1536
|
+
try {
|
|
1537
|
+
const home = path.join(tempRoot, 'home');
|
|
1538
|
+
const cwd = path.join(tempRoot, 'project');
|
|
1539
|
+
const userConfig = path.join(home, '.genexus-mcp', 'config.json');
|
|
1540
|
+
fs.mkdirSync(path.dirname(userConfig), { recursive: true });
|
|
1541
|
+
fs.mkdirSync(cwd, { recursive: true });
|
|
1542
|
+
fs.writeFileSync(userConfig, JSON.stringify({ Environment: { KBPath: 'C:/KBs/One' } }));
|
|
1543
|
+
|
|
1544
|
+
const result = runCli(['config', 'migrate', '--output', path.join(tempRoot, 'out.json')], {
|
|
1545
|
+
cwd,
|
|
1546
|
+
env: { ...sandboxHomeEnv(home) }
|
|
1547
|
+
});
|
|
1548
|
+
|
|
1549
|
+
assert.notEqual(result.status, 0, result.stdout + result.stderr);
|
|
1550
|
+
// No neutral config was written next to the user profile.
|
|
1551
|
+
assert.equal(fs.existsSync(`${userConfig}.neutral.json`), false);
|
|
1552
|
+
assert.equal(fs.existsSync(path.join(tempRoot, 'out.json')), false);
|
|
1553
|
+
} finally {
|
|
1554
|
+
removeTempPath(tempRoot, { recursive: true, force: true });
|
|
1555
|
+
}
|
|
1556
|
+
});
|
|
1557
|
+
|
|
1390
1558
|
test('doctor rejects malformed tool definitions instead of reporting only file presence', () => {
|
|
1391
1559
|
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-doctor-tool-defs-'));
|
|
1392
1560
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genexus-mcp",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.11.0",
|
|
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.
|
|
10
|
+
"GxMcp.Gateway/3.11.0": {
|
|
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.
|
|
69
|
+
"GxMcp.Gateway/3.11.0": {
|
|
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
|
-
"
|
|
3
|
-
|
|
4
|
-
"
|
|
5
|
-
"
|
|
2
|
+
"Server": {
|
|
3
|
+
"HttpPort": 0,
|
|
4
|
+
"SessionIdleTimeoutMinutes": 10,
|
|
5
|
+
"EmitStructuredContent": false,
|
|
6
|
+
"TerseResponses": true,
|
|
7
|
+
"McpStdio": true,
|
|
8
|
+
"WorkerIdleTimeoutMinutes": 5
|
|
6
9
|
},
|
|
10
|
+
"GatewayMode": "stdio-isolated",
|
|
7
11
|
"Environment": {
|
|
8
12
|
"ResolutionPolicy": "strict"
|
|
9
13
|
},
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"WorkerIdleTimeoutMinutes": 5,
|
|
14
|
-
"EmitStructuredContent": false,
|
|
15
|
-
"SessionIdleTimeoutMinutes": 10,
|
|
16
|
-
"McpStdio": true
|
|
14
|
+
"GeneXus": {
|
|
15
|
+
"WorkerExecutable": "worker\\\\GxMcp.Worker.exe",
|
|
16
|
+
"InstallationPath": "C:\\Program Files (x86)\\GeneXus\\GeneXus18"
|
|
17
17
|
},
|
|
18
|
-
"
|
|
18
|
+
"ConfigSchemaVersion": 2
|
|
19
19
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "gxmcp-release-manifest/1",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"sourceCommit": "
|
|
3
|
+
"version": "3.11.0",
|
|
4
|
+
"sourceCommit": "2f880601c2bbbe4a252af2f9c01e62a7cda44a8f",
|
|
5
5
|
"sourceCommitPolicy": "exact-tag",
|
|
6
|
-
"generatedAtUtc": "2026-10-
|
|
6
|
+
"generatedAtUtc": "2026-10-04T15:25:20.8904296Z",
|
|
7
7
|
"runtime": {
|
|
8
8
|
"gateway": "net10.0-windows",
|
|
9
9
|
"worker": "net48-x86",
|
|
@@ -15,33 +15,33 @@
|
|
|
15
15
|
"2026-07-28"
|
|
16
16
|
],
|
|
17
17
|
"schema": "tool_definitions.json",
|
|
18
|
-
"schemaSha256": "
|
|
18
|
+
"schemaSha256": "bfe199e15a442c9e90b8d77a4e5e1d845498d423cfb3d92c4ee7357030040c1d",
|
|
19
19
|
"provenance": "gxmcp-sbom.json",
|
|
20
20
|
"artifacts": [
|
|
21
21
|
{
|
|
22
22
|
"path": "gxmcp-sbom.json",
|
|
23
23
|
"size": 591,
|
|
24
|
-
"sha256": "
|
|
24
|
+
"sha256": "a0cd00d9a6603ca8d6ac438b798f112ffb2eb63a38fafaf085d1664cb5b6f850"
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
"path": "GxMcp.Gateway.exe",
|
|
28
28
|
"size": 162304,
|
|
29
|
-
"sha256": "
|
|
29
|
+
"sha256": "e22835cc33a2bcff02908c6248344f3d7c299f961fb6b821592de432afab430b"
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
"path": "nexus-ide.vsix",
|
|
33
|
-
"size":
|
|
34
|
-
"sha256": "
|
|
33
|
+
"size": 1319957,
|
|
34
|
+
"sha256": "2e37e5f1d8f541e0fb6d342ceb34ccbdcbbf226a9c541ea500287f59925f3360"
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
"path": "tool_definitions.json",
|
|
38
|
-
"size":
|
|
39
|
-
"sha256": "
|
|
38
|
+
"size": 137678,
|
|
39
|
+
"sha256": "bfe199e15a442c9e90b8d77a4e5e1d845498d423cfb3d92c4ee7357030040c1d"
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
"path": "worker/GxMcp.Worker.exe",
|
|
43
|
-
"size":
|
|
44
|
-
"sha256": "
|
|
43
|
+
"size": 3980800,
|
|
44
|
+
"sha256": "431fbe4bf05fb254ce429cb5721587748160ba5ccb32bb57d6e25816b576779f"
|
|
45
45
|
}
|
|
46
46
|
]
|
|
47
47
|
}
|
package/publish/gxmcp-sbom.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "gxmcp-provenance/1",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"sourceCommit": "
|
|
3
|
+
"version": "3.11.0",
|
|
4
|
+
"sourceCommit": "2f880601c2bbbe4a252af2f9c01e62a7cda44a8f",
|
|
5
5
|
"sourceCommitPolicy": "exact-tag",
|
|
6
6
|
"components": [
|
|
7
7
|
{
|
|
8
8
|
"name": "genexus-mcp",
|
|
9
9
|
"lockfile": "package-lock.json",
|
|
10
10
|
"size": 38806,
|
|
11
|
-
"sha256": "
|
|
11
|
+
"sha256": "937fa26608eab4b5433d97ab9df2ad24cf7899eef93f74c78dc4331497285121"
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
14
|
"name": "nexus-ide",
|
|
15
15
|
"lockfile": "src/nexus-ide/package-lock.json",
|
|
16
16
|
"size": 267538,
|
|
17
|
-
"sha256": "
|
|
17
|
+
"sha256": "d9b2ee76cb5f77e317c4ec8747d77cc503cd12d417a98100981fb0af125a2c75"
|
|
18
18
|
}
|
|
19
19
|
]
|
|
20
20
|
}
|
package/publish/nexus-ide.vsix
CHANGED
|
Binary file
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
{"name":"genexus_query","description":"Search objects in active KB. Prefixes: name:, type:, usedby:, parent:, parentPath:, description:. name:\"X\" (or bare quoted \"X\") demands exact-name match — use it when you know the object's name. Compact by default. Pass kbs:[...] to run the same read-only search across an explicit set of already-open KBs in one bounded, per-KB-reported call. See genexus://kb/tool-help/genexus_query. Requires the KB index to be Ready — check genexus_lifecycle action=status if results look empty.","inputSchema":{"type":"object","properties":{"query":{"type":"string"},"typeFilter":{"type":"string"},"domainFilter":{"type":"string"},"limit":{"type":"integer"},"inline_read_top":{"type":"integer","description":"0-3. Inline reads of top N."},"sort":{"type":"string","enum":["relevance","lastUpdate"],"description":"relevance (default) or lastUpdate (newest first; bypasses score ranking)."},"since":{"type":"string","description":"ISO-8601 UTC. Only items with lastUpdate >= since."},"modifiedBefore":{"type":"string","description":"ISO-8601 UTC. Only items with lastUpdate < modifiedBefore."},"cursor":{"type":"string","description":"Opaque token from prior nextCursor. Use with sort=lastUpdate for stable paging."},"kb":{"type":"string","description":"KB alias."},"kbs":{"type":"array","items":{"type":"string"},"description":"Federated read-only discovery over an explicit KB set (max 16). Uses only already-open KBs and never opens one (the Worker pool can evict a KB you are working in). Results are grouped per KB with per-KB status and complete flags plus a coverage summary; a not-open/warming/slow/failing KB is reported individually, never as zero matches. Mutually exclusive with kb."},"cursors":{"type":"object","additionalProperties":{"type":"string"},"description":"Per-KB continuation: map each alias in kbs to that KB's nextCursor. An alias outside kbs is rejected, not dropped."},"maxConcurrency":{"type":"integer","description":"Federation only: KBs searched in parallel (default 4, max 8)."},"maxTotalResults":{"type":"integer","description":"Federation only: total results across all KBs (default 500, max 5000). Overflow marks the affected KB incomplete with its nextCursor intact."},"perKbTimeoutMs":{"type":"integer","description":"Federation only: per-KB deadline in ms (default 30000, max 120000)."},"axiCompact":{"type":"boolean","description":"Compact projection (default true).","default":true},"exactMatch":{"type":"boolean","description":"Require an exact object-name match."}},"required":["query"],"examples":[{"query":"type:Transaction parent:Customers"},{"query":"\"Customer\"","limit":5},{"query":"name:\"Customer\"","kbs":["KbAlpha","KbBeta"]}]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},
|
|
6
6
|
{"name":"genexus_list_objects","description":"List objects with pagination. Feed nextOffset until hasMore=false. Every item exposes its persisted GUID and path; verbose=true also exposes the typed EntityKey when available.","inputSchema":{"type":"object","properties":{"filter":{"type":"string","description":"Legacy: name OR description. Prefer nameFilter/descriptionFilter."},"nameFilter":{"type":"string","description":"Substring on name."},"descriptionFilter":{"type":"string","description":"Substring on description."},"pathPrefix":{"type":"string","description":"Folder prefix, e.g. 'Root Module/X/'."},"limit":{"type":"integer"},"offset":{"type":"integer"},"parent":{"type":"string"},"parentPath":{"type":"string"},"typeFilter":{"type":"string"},"verbose":{"type":"boolean","description":"Full item shape."},"sort":{"type":"string","enum":["name","lastUpdate"],"description":"name (default, type-bucketed) or lastUpdate (newest first)."},"since":{"type":"string","description":"ISO-8601 UTC. Only items with lastUpdate >= since."},"modifiedBefore":{"type":"string","description":"ISO-8601 UTC. Only items with lastUpdate < modifiedBefore."},"cursor":{"type":"string","description":"Opaque token from prior nextCursor. Use with sort=lastUpdate for stable paging."},"inline_read_top":{"type":"integer","description":"0-3. Inline reads of top N."},"kb":{"type":"string","description":"KB alias."},"axiCompact":{"type":"boolean","description":"Compact projection (default true).","default":true},"projection":{"type":"string","enum":["minimal","standard","verbose"],"description":"minimal=name+type+lastUpdate; standard=default compact; verbose=all fields. Overrides axiCompact when set."}},"examples":[{"limit":25},{"typeFilter":"Transaction","limit":10}]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},
|
|
7
7
|
{"name":"genexus_read","description":"Read object code and metadata. Omitting 'part' (RECOMMENDED) returns the COMPLETE object in 1 call (rules with parm, source/events, variables, structure, called signatures) tailored to the object type. Resolve modular objects by name/type, persisted GUID, EntityKey, or path. Pass 'part' only for targeted single-part reads. Response carries versionToken for safe writes. A single-part response also carries contentToken: echo it back as ifUnchangedSince to re-read the same representation without retransmitting an unchanged body. See genexus://kb/tool-help/genexus_read.","inputSchema":{"type":"object","properties":{"name":{"type":"string"},"targets":{"type":"array","items":{"type":"string"}},"guid":{"type":"string","description":"Persisted object GUID from genexus_list_objects."},"entityKey":{"type":"string","description":"Typed GeneXus EntityKey from genexus_list_objects verbose output."},"path":{"type":"string","description":"Module/folder-qualified object path from genexus_list_objects."},"part":{"type":"string","description":"DataSelector: parameters|conditions|orders|projection|definedBy|baseTransaction|baseTable|joins|structure."},"parts":{"type":"array","items":{"type":"string"},"description":"Selected parts; unavailable DataSelector parts appear in unsupportedParts. Mutually exclusive with part/offset/limit."},"offset":{"type":"integer"},"limit":{"type":"integer"},"ifUnchangedSince":{"type":"string","description":"Opaque contentToken from a previous single-part read of the SAME object/part/offset/limit. Provably unchanged -> notModified:true with identity and freshness metadata and no source; otherwise the full body plus a new contentToken and conditional.reason. Single-part reads only (rejected with ConditionalReadUnsupportedForm on targets[]/parts[]/full-object forms). Omit to keep the unconditional behavior."},"type":{"type":"string"},"kb":{"type":"string","description":"KB alias."}},"examples":[{"name":"Customer"},{"name":"Customer","type":"Procedure","guid":"<guid-from-list>"},{"name":"Customer","path":"Operations/Customer","type":"Procedure"},{"name":"Customer","part":"Source"},{"name":"Customer","part":"Source","limit":0,"ifUnchangedSince":"<contentToken-from-previous-read>"}]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},
|
|
8
|
-
{"name":"genexus_edit","description":"Edit object part. name or targets (exclusive). mode: full|patch|ops. dryRun first. async=true returns an operationId for lifecycle polling. Text payloads for Source/Rules/Events/Code must contain real line breaks; literal backslash sequences \\r\\n, \\n, or \\r are rejected before persistence with LiteralLineBreaksDetected. For WWP edit host's PatternInstance NOT the parent WebForm (gets overwritten on reapply). Uncertain about a property/method/event? → resources/read uri=genexus://kb/skills/navigation (or gam-integrated-security / sd-panel-mobile / webpanel-events) first.","inputSchema":{"type":"object","properties":{"name":{"type":"string"},"part":{"type":"string"},"parts":{"type":"array","description":"Multi-part edit on a single object. Each item: {part, content, mode?}. Saves the object once atomically. Text content must use real line breaks; literal backslash sequences \\r\\n, \\n, or \\r are rejected before persistence.","items":{"type":"object","properties":{"part":{"type":"string"},"content":{"type":"string"},"mode":{"type":"string"}},"required":["part","content"]}},"mode":{"type":"string","enum":["full","patch","ops"]},"content":{"type":"string"},"ops":{"type":"array","description":"GeneXus semantic ops (NOT RFC 6902 JSON-Patch). Each item: {op, args}. Supported ops: set_attribute, add_attribute, remove_attribute (Transaction); add_rule, remove_rule (Transaction/Procedure/WebPanel); set_property (any kind). Use mode=patch for textual find/replace.","items":{"type":"object","properties":{"op":{"type":"string","enum":["set_attribute","add_attribute","remove_attribute","add_rule","remove_rule","set_property"]},"args":{"type":"object","description":"Op-specific args. set_attribute: {name, type?, description?}. add_attribute: {name, type, ...}. add_rule: {rule}. set_property: {name, value}."}},"required":["op"]}},"patch":{"type":"object","additionalProperties":true,"description":"Shorthand for {find,replace}
|
|
8
|
+
{"name":"genexus_edit","description":"Edit object part. name or targets (exclusive). mode: full|patch|ops. dryRun first. async=true returns an operationId for lifecycle polling. Text payloads for Source/Rules/Events/Code must contain real line breaks; literal backslash sequences \\r\\n, \\n, or \\r are rejected before persistence with LiteralLineBreaksDetected. For WWP edit host's PatternInstance NOT the parent WebForm (gets overwritten on reapply). Uncertain about a property/method/event? → resources/read uri=genexus://kb/skills/navigation (or gam-integrated-security / sd-panel-mobile / webpanel-events) first.","inputSchema":{"type":"object","properties":{"name":{"type":"string"},"part":{"type":"string"},"parts":{"type":"array","description":"Multi-part edit on a single object. Each item: {part, content, mode?}. Saves the object once atomically. Text content must use real line breaks; literal backslash sequences \\r\\n, \\n, or \\r are rejected before persistence.","items":{"type":"object","properties":{"part":{"type":"string"},"content":{"type":"string"},"mode":{"type":"string"}},"required":["part","content"]}},"mode":{"type":"string","enum":["full","patch","ops"]},"content":{"type":"string"},"ops":{"type":"array","description":"GeneXus semantic ops (NOT RFC 6902 JSON-Patch). Each item: {op, args}. Supported ops: set_attribute, add_attribute, remove_attribute (Transaction); add_rule, remove_rule (Transaction/Procedure/WebPanel); set_property (any kind). Use mode=patch for textual find/replace.","items":{"type":"object","properties":{"op":{"type":"string","enum":["set_attribute","add_attribute","remove_attribute","add_rule","remove_rule","set_property"]},"args":{"type":"object","description":"Op-specific args. set_attribute: {name, type?, description?}. add_attribute: {name, type, ...}. add_rule: {rule}. set_property: {name, value}."}},"required":["op"]}},"patch":{"type":"object","additionalProperties":true,"description":"Shorthand for {find,replace}; implies mode=patch when mode is omitted, and is a usage_error with mode=full|ops: find is the exact existing text, replace is inserted literally (no auto-indentation). Optional opt-in protections: scope bounds the search region, indentation validates the replacement's base indent. Both apply ONLY to this shape — never with operation, mode=ops, targets[], parts[], Insert_After or Append.","properties":{"find":{"type":"string","description":"Exact existing text to find. Real line breaks; tabs/spaces must match the part."},"replace":{"type":"string","description":"Replacement text, inserted literally."},"scope":{"type":"object","required":["start"],"description":"Region delimited by complete-line anchors: editable starts after scope.start's last line and ends before scope.end's first line (EOF when end is omitted). Anchors stay outside the region, are compared with only CRLF/LF normalized, and must each be unique. Errors: ScopeStartRequired, ScopeAnchorNotFound, ScopeAnchorAmbiguous, ScopeAnchorNotComparable. The response reports editableStartLine, editableEndLineExclusive and scopeEndsAtEof.","properties":{"start":{"type":"string","description":"Required. Unique complete-line anchor ending immediately before the editable region."},"end":{"type":"string","description":"Optional. Unique complete-line anchor starting immediately after the editable region. Omitted = region runs to EOF."}}},"indentation":{"type":"object","required":["mode"],"description":"Validates the base indentation of the located match against the first line of replace before persisting; tabs and spaces are distinct and nothing is reformatted. With replaceAll=true every match is validated. Errors: IndentationMismatch, IndentationNotComparable.","properties":{"mode":{"type":"string","enum":["validate"],"description":"validate: block the write when the replacement's base indentation differs from the matched line's."}}}}},"scope":{"type":"object","description":"patch.scope may also be passed at the top level. Honored ONLY by the abbreviated patch={find,replace} form; combined with operation, mode=ops, targets[], parts[], Insert_After or Append the call is rejected with ScopeUnsupportedPatchForm and nothing is written."},"indentation":{"type":"object","description":"patch.indentation may also be passed at the top level. Honored ONLY by the abbreviated patch={find,replace} form; combined with operation, mode=ops, targets[], parts[], Insert_After or Append the call is rejected with IndentationUnsupportedPatchForm and nothing is written."},"context":{"type":"string","description":"Exact existing text to find (Replace) or anchor after (Insert_After). Required for both. For text parts, send real line breaks; literal backslash sequences \\r\\n, \\n, or \\r are rejected before persistence."},"operation":{"type":"string","enum":["Replace","Insert_After","Append"]},"expectedCount":{"type":"integer"},"replaceAll":{"type":"boolean","description":"patch mode only. Apply to ALL occurrences instead of requiring expectedCount to match exactly."},"dryRun":{"type":"boolean"},"async":{"type":"boolean","description":"Run as a background job. Result returns operationId/job_id for genexus_lifecycle polling."},"estimated_seconds":{"type":"integer","description":"When async=true, expected runtime used for progress/job metadata (default 30)."},"verifyRollback":{"type":"boolean"},"targets":{"type":"array","description":"Multi-target Source/Rules writes. Each target may include expectedVersion/baseVersion; all versions are checked before the first write.","items":{"type":"object","properties":{"name":{"type":"string"},"part":{"type":"string"},"content":{"type":"string"},"expectedVersion":{"type":"string"},"baseVersion":{"type":"string"}},"required":["name","content"]}},"type":{"type":"string"},"return_post_state":{"type":"boolean","description":"Omit post_state.diff (default true)."},"includePersistedText":{"type":"boolean","description":"Full text; default false."},"verbose":{"type":"boolean","description":"Add ±15-line slices to post_state."},"validate":{"type":"string","enum":["strict","best-effort","only"],"description":"strict (default) aborts on first error and post-write-verifies visual/PatternInstance writes (re-reads + diffs the persisted XML). best-effort applies what compiles and SKIPS the post-write XML re-read/diff (faster on large WebForm/PatternInstance writes; build to confirm). only runs in-memory, no persist."},"validationMode":{"type":"string","enum":["specify"],"description":"Issue #60: run the inline Specify pass (Spec+Gen, no Compile) against the edited object right after the write, returning structured spc*/gen* diagnostics in the same call. Combines with rollbackOnFailure."},"rollbackOnFailure":{"type":"boolean","description":"Explicit rollback only. Full Source verification failure reports AtomicRollbackUnavailable without a restore write until atomic conditional restore is supported. Other paths require a valid snapshot. No rollback when false or omitted."},"requireObjectSave":{"type":"boolean","default":false,"description":"Full Source requires transactional object save. Events patch: dryRun available; real writes blocked by ObjectSaveIsolationUnverified until SDK/pattern save-event isolation is established. No override; baseVersion required."},"forceWrite":{"type":"boolean","default":false,"description":"WebForm only: persist despite SDK WebForm validation errors; response includes validationOverridden=true."},"verifyMode":{"type":"string","enum":["semantic","normalized","exact"],"default":"normalized","description":"Post-save text comparison. Full exact compares public-read text verbatim; patch exact retains logical CRLF/LF equivalence. normalized ignores EOL, BOM, trailing whitespace and blank lines; semantic also tolerates casing/spacing. Fresh reread always required. sdkSaveCompleted/saved report physical save; persistedStateKnown and postSaveVerification report read evidence. Mismatch never retries automatically."},"visualVerify":{"type":"boolean","default":false,"description":"Post-edit headless screenshot + pixel-diff vs baseline. See tool-help."},"baseVersion":{"type":"string","description":"Optimistic concurrency: pass the versionToken from the genexus_read this edit is based on. If the object changed since (e.g. edited in the IDE), the write is refused with VersionConflict instead of overwriting the newer version. Omit to skip the check."},"expectedVersion":{"type":"string","description":"Alias of baseVersion. The write is refused when the current version no longer matches."},"concurrencyPolicy":{"type":"string","enum":["warn","fail_if_open"],"default":"warn","description":"warn (default) or fail_if_open if open in GeneXus IDE."},"autoDeclareVariables":{"type":"boolean","default":false,"description":"When true, scans updated source for newly referenced &Variable tokens and auto-declares them in VariablesPart."},"kb":{"type":"string","description":"KB alias."},"changeSet":{"type":"object","required":["action","changes"],"properties":{"action":{"type":"string","enum":["preview","validate","apply"]},"changes":{"type":"array","items":{"type":"object","required":["name","content"],"properties":{"name":{"type":"string"},"part":{"type":"string","enum":["Source","Rules","Variables"]},"content":{"type":"string"},"expectedVersion":{"type":"string"}}}},"changeSetId":{"type":"string"},"baseRevision":{"type":"string"}}},"module":{"type":"string","description":"mode=ops: Transaction module for modular objects."}},"examples":[{"name":"Customer","mode":"patch","part":"Source","patch":{"find":"old","replace":"new"}},{"name":"Customer","mode":"patch","part":"Rules","patch":{"find":"error(","replace":"msg("},"dryRun":true},{"name":"Customer","mode":"patch","part":"Source","patch":{"find":"old","replace":"new","scope":{"start":"// Banco B","end":"// Proximo banco"}}}]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false}},
|
|
9
9
|
{"name":"genexus_inspect","description":"Use this for a compact object snapshot: metadata, variables, structure, signature and navigation context. Modular objects accept persisted GUID, EntityKey, or path in addition to name/type. Don't use it when you need full Source or exact part bytes; use genexus_read for that. runtimeIds needs a prior build.","inputSchema":{"type":"object","properties":{"name":{"type":"string"},"guid":{"type":"string","description":"Persisted object GUID from genexus_list_objects."},"entityKey":{"type":"string","description":"Typed GeneXus EntityKey from genexus_list_objects verbose output."},"path":{"type":"string","description":"Module/folder-qualified object path from genexus_list_objects."},"include":{"type":"array","items":{"type":"string","enum":["metadata","variables","signature","structure","parts","controls","events_repertoire","callers","runtimeIds"]}},"projection":{"type":"string","enum":["minimal","standard","verbose"],"description":"Token budget. minimal=name/type/lastUpdate; standard=default (vars≤40 name+type, source heads 1200c); verbose=full vars + 8000c heads."},"type":{"type":"string"},"kb":{"type":"string","description":"KB alias."},"verbose":{"type":"boolean","description":"Include verbose diagnostic fields."}},"examples":[{"name":"Customer"},{"name":"Customer","type":"Procedure","path":"Operations/Customer"},{"name":"Customer","include":["variables","signature"]}]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},
|
|
10
|
-
{"name":"genexus_analyze","description":"Use this for cross-object semantic analysis. mode=context (alias deep_context) returns 360° task context in 1 call (object + called procedures' parm signatures + referenced tables' schemas/PKs + SDTs + callers). Other modes: impact, callers, hierarchy, navigation, linter, summary, explain. mode=theme_classes lists the KB's theme classes (name + objectGuid) so you can pick a class by name; objectGuid is the class object's GUID and is NOT the value a layout class attribute takes, so never invent that value. mode=explain is compatibility-only: it preserves the legacy response envelope and returns NotImplemented; use mode=summary for a concise overview, mode=context for 360° task context, or genexus_read for source. Requires Ready index for impact/callers.","inputSchema":{"type":"object","properties":{"name":{"type":"string"},"mode":{"type":"string","enum":["context","deep_context","linter","navigation","hierarchy","impact","cross_platform_impact","callers","event_flow","data_context","ui_context","pattern_metadata","summary","dependency_heatmap","code_metrics","kb_stats","table_relations","theme_classes","explain"]},"code":{"type":"string","description":"mode=explain: legacy code snippet carried through the compatibility-only envelope; the result is NotImplemented. Use mode=summary, mode=context, or genexus_read for supported analysis."},"cursor":{"type":"string","description":"mode=context:
|
|
10
|
+
{"name":"genexus_analyze","description":"Use this for cross-object semantic analysis. mode=context (alias deep_context) returns 360° task context in 1 call (object + called procedures' parm signatures + referenced tables' schemas/PKs + SDTs + callers). Other modes: impact, callers, hierarchy, navigation, linter, summary, explain. mode=theme_classes lists the KB's theme classes (name + objectGuid) so you can pick a class by name; objectGuid is the class object's GUID and is NOT the value a layout class attribute takes, so never invent that value. mode=explain is compatibility-only: it preserves the legacy response envelope and returns NotImplemented; use mode=summary for a concise overview, mode=context for 360° task context, or genexus_read for source. Requires Ready index for impact/callers.","inputSchema":{"type":"object","properties":{"name":{"type":"string"},"mode":{"type":"string","enum":["context","deep_context","linter","navigation","hierarchy","impact","cross_platform_impact","callers","event_flow","data_context","ui_context","pattern_metadata","summary","dependency_heatmap","code_metrics","kb_stats","table_relations","theme_classes","explain"]},"code":{"type":"string","description":"mode=explain: legacy code snippet carried through the compatibility-only envelope; the result is NotImplemented. Use mode=summary, mode=context, or genexus_read for supported analysis."},"cursor":{"type":"string","description":"Continuation cursor from a budgeted page. mode=context: scan.nextCursor. mode=callers: the integer scan.nextCursor (resume offset into the caller list)."},"maxCallers":{"type":"integer","description":"mode=callers: callers to scan in this page (default 50)."},"maxSourceBytes":{"type":"integer","description":"mode=callers: UTF-8 bytes of caller source per page (default 4194304). A caller larger than this is listed in scan.skippedCallers."},"format":{"type":"string","enum":["json","ascii"],"description":"mode=dependency_heatmap: ascii adds rendered bar chart."},"kb":{"type":"string","description":"KB alias."},"maxBytes":{"type":"integer","description":"mode=context: maximum UTF-8 bytes for the returned context bundle (bounded by the server)."},"waitForIndex":{"type":"boolean","description":"mode=impact: block up to 30s for Ready index (default true).","default":true},"dryRun":{"type":"boolean","description":"mode=linter: with fix=true, reject the unsupported combination before any SDK read; with fix=false, lint remains read-only."},"fix":{"type":"boolean","description":"mode=linter: apply automatic fixes to the KB."},"top":{"type":"integer","description":"mode=code_metrics: maximum results (default 25)."},"waitTimeoutMs":{"type":"integer","description":"mode=impact: maximum index wait in milliseconds."}},"required":["mode"],"examples":[{"name":"Customer","mode":"impact"},{"name":"Customer","mode":"summary"}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},
|
|
11
11
|
{"name":"genexus_lifecycle","description":"Build, validate, index, or poll the KB. action=build_all runs the native incremental Build All for the entire selected KB (ForceRebuild=false); it rejects target, refuses silent reorganization, and returns completion evidence. action=rebuild remains the forced Rebuild All path. action=specify runs Spec+Gen only. action=build with mode=compile_check checks targets plus transitive callers without KB-wide DeveloperMenu regeneration. Long operations are async with operationId. dryRun=true previews without executing. Build results carry generateEvidence and effective_status. See genexus://kb/tool-help/genexus_lifecycle for actions and target formats.","inputSchema":{"type":"object","properties":{"action":{"type":"string","enum":["build","build_all","cancel","specify","rebuild","reorg","reorg_preview","validate","validate-kb","sync","index","status","result","snapshots-list","snapshots-restore","inspect","reconcile"],"description":"Lifecycle action to perform."},"mode":{"type":"string","enum":["compile_check"],"description":"With action=build: compile_check spec+gen+compiles target(s) plus their transitive callers and SKIPS the KB-wide DeveloperMenu regen (the dominant build-all cost). Fast 'did my edit break the build?' check; requires target."},"target":{"type":"string","description":"Object/task ID/op:<id>. compile_check accepts unique name, Type:Name, GUID; no paths. build_all rejects target."},"job_id":{"type":"string","description":"Gateway operation id or Worker task id for status/result/cancel; the op: prefix is optional."},"jobId":{"type":"string","description":"Legacy alias for job_id."},"code":{"type":"string","description":"validate: in-memory code to check without persisting."},"limit":{"type":"integer","description":"validate-kb: maximum number of objects/conditions to validate."},"snapshotPath":{"type":"string","description":"snapshots-restore: path to pattern snapshot to restore."},"estimated_seconds":{"type":"integer","description":"Build: <20 sync, >=20 async (default 60)."},"wait_seconds":{"type":"integer","description":"Status/build long-poll cap, 0-600s."},"wait_until_done":{"type":"boolean","description":"Build/build_all/rebuild: block in one turn until terminal (up to wait_seconds, default 600)."},"until":{"type":"string","enum":["change","terminal"],"description":"Status wait stop condition: change (default for polling) or terminal (default when wait_until_done=true)."},"wait":{"type":"integer","description":"Status block, 0-600s. With a build taskId (or since): event-driven, returns on change. On index status with no since: blocks until index is Ready."},"since":{"type":"string","description":"Status: prior _meta.snapshot for chained waits."},"freshness":{"type":"string","enum":["current","stale","refreshing"],"description":"Status: freshness target for the wait. With wait and no since, the call blocks until the index status is Ready AND freshness matches, then reports waitSatisfied. Use freshness=current to wait for a warm-start delta refresh to finish (a snapshot restored from the warm cache is Ready but stale, so a status-only wait returns immediately)."},"compact":{"type":"boolean","description":"Status: counts + top-10 errors (default true)."},"force":{"type":"boolean","description":"Index: full SDK rescan (clears snapshot)."},"dryRun":{"type":"boolean","default":false,"description":"build/build_all/rebuild/index: returns the plan without executing."},"environment":{"type":"string","description":"Build: target environment name/folder. Switches active environment before building."},"includeCallees":{"type":"string","enum":["none","direct","transitive"],"description":"Build: expand call graph so callees compile first (default transitive)."},"callers":{"type":"boolean","description":"compile_check: expand transitive callers of the target (default true). Set false for a target-only check when the target is a base transaction/BC with a huge caller closure."},"callerCap":{"type":"integer","description":"compile_check: max callers to pull into the check (default 40). Closure beyond this is truncated and flagged."},"deploy":{"type":"boolean","description":"Build: force the full deploy (Theme/Image/Style/Module copy to web/bin + WebAppConfig) so the built object is runnable, not just compiled. Default false (fast compile-only path). Slower; use when you need to run/preview the object."},"buildPlanCap":{"type":"integer","description":"Build: max nodes before BuildPlanTooLarge (default 200)."},"kb":{"type":"string","description":"KB alias."},"part":{"type":"string","description":"validate: specific object part to check (e.g. Source, Rules)."},"page":{"type":"integer","description":"status/result: 1-based page number for paginated results."},"pageSize":{"type":"integer","description":"status/result: page size for paginated results (default 50)."},"page_size":{"type":"integer","description":"status/result: snake_case alias for pageSize."},"notifyOnFailure":{"type":"string","description":"build: Slack/Discord webhook URL to notify on terminal build failure."},"skipFullDeploy":{"type":"boolean","description":"build: skip full deployment stage to speed up compile pass."},"fastIncremental":{"type":"boolean","description":"build: experimental fast incremental build opt-in."},"operationKey":{"type":"string","description":"inspect/reconcile: original idempotency key; journal lookup is hash-scoped to the resolved KB."},"operationTool":{"type":"string","description":"inspect/reconcile: canonical mutating tool that owns the idempotency key, e.g. genexus_edit."},"confirmed":{"type":"boolean","description":"reconcile: must be true after independently reading the affected target; this never authorizes a retry with the same key."},"verification":{"type":"string","description":"reconcile: short operator/model verification statement. Only a hash is persisted; source and KB content are never journaled."},"observedTargetIds":{"type":"array","items":{"type":"string"},"description":"reconcile: target names observed by an independent read; send one name as a single-item array. Must match the durable target fence."},"observedRevision":{"type":"string","description":"reconcile: revision/version observed by an independent read; must match the durable revision fence."}},"required":["action"],"examples":[{"action":"build"},{"action":"build_all"},{"action":"status","target":"op:abc123"},{"action":"build","mode":"compile_check","target":"MyObject"},{"action":"inspect","operationTool":"genexus_edit","operationKey":"edit_20260905_01"}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"outputSchema":{"type":"object","description":"Structured lifecycle result. Action-specific fields remain additive; text content is preserved for legacy clients.","properties":{"status":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"error":{"type":"string"},"operationId":{"type":"string"},"job_id":{"type":"string"},"pollTarget":{"type":"string"},"isError":{"type":"boolean"}},"additionalProperties":true}},
|
|
12
12
|
{"name":"genexus_test","description":"Execute native GeneXus tests (GXtest).","inputSchema":{"type":"object","properties":{"name":{"type":"string"},"kb":{"type":"string","description":"KB alias."}},"required":["name"],"examples":[{"name":"MyTestProc"}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":true}},
|
|
13
13
|
{"name":"genexus_sdk_probe","description":"Read the GeneXus SDK surface. mode=surface dumps types/methods/props to docs/sdk-probe/; mode=capabilities returns an in-memory capability matrix with honest signature-probe status.","inputSchema":{"type":"object","properties":{"mode":{"type":"string","enum":["surface","capabilities"],"description":"surface (default) writes the diagnostic probe; capabilities is read-only and returns status/evidence."},"outputDir":{"type":"string","description":"Absolute path for mode=surface. Default <repo>/docs/sdk-probe/."},"kb":{"type":"string","description":"KB alias."}},"examples":[{},{"mode":"capabilities"}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},
|
|
@@ -41,11 +41,11 @@
|
|
|
41
41
|
{"name":"genexus_db","description":"Database umbrella. Actions: drift_check|drift_report; optimize_analyze|optimize_suggest|optimize_report; sql_ddl|sql_navigation; sample_data; records_query|records_insert|records_update (typed Transaction rows; query read-only; writes dryRun; no business rules); types_list|types_describe|types_validate; reorg_impact; reorg_preview (non-mutating; deep uses ImpactDatabase); translations_import.","inputSchema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["drift_check","drift_report","optimize_analyze","optimize_suggest","optimize_report","sql_ddl","sql_navigation","sample_data","records_query","records_insert","records_update","types_list","types_describe","types_validate","translations_import","reorg_impact","reorg_preview"],"description":"Database operation. records_query is read-only; records_insert/records_update default to dryRun=true and require the matching single-use v2 preview token for persistence."},"deep":{"type":"boolean","description":"reorg_impact/reorg_preview only: run ISpecifierService.ImpactDatabase (specification, build-heavy) for the authoritative AnalysisResult. Default false (cheap timestamp heuristic)."},"name":{"type":"string","description":"Object/transaction/type name."},"trn":{"type":"string","description":"sample_data: Transaction name."},"transaction":{"type":"string","description":"records_*: root-level Transaction name."},"dataStore":{"type":"string","description":"records_*: existing active-environment datastore; defaults to the SDK default."},"dataStoreAlias":{"type":"string","description":"records_query: profile alias; no credentials."},"where":{"type":"object","description":"records_query/update: equality filters only; update requires a filter."},"values":{"type":"object","description":"records_insert/update: typed attribute values."},"fields":{"type":"array","items":{"type":"string"},"description":"records_query: optional root-attribute projection."},"databaseManagedFields":{"type":"array","items":{"type":"string"},"description":"records_*: reviewed trigger-maintained fields; excludes keys and supplied values. Included in the preview token."},"limit":{"type":"integer","description":"records_query: 1-1000; default 100."},"expectedCount":{"type":"integer","description":"records_update: defaults to exactly one matched record."},"expectedVersion":{"type":"string","description":"records_*: v2 token from the matching write dry-run; query/v1 tokens cannot authorize writes."},"versionToken":{"type":"string","description":"records_*: alias of expectedVersion."},"dryRun":{"type":"boolean","default":true,"description":"records_insert/update: validate and reread the plan without writing."},"rollbackOnFailure":{"type":"boolean","default":true,"description":"records_*: default true; validation failures roll back before commit. Post-commit compensation is refused to preserve concurrent writers."},"timeoutSeconds":{"type":"integer","description":"records_*: command timeout, 1-60 seconds."},"rows":{"type":"integer","description":"sample_data: 1-1000; default 5."},"includeSubordinated":{"type":"boolean","description":"sql_ddl only."},"levelNumber":{"type":"integer","description":"sql_navigation only."},"includeExecutionPlan":{"type":"boolean","description":"sql_navigation."},"includeIndexAdvisor":{"type":"boolean","description":"sql_navigation."},"format":{"type":"string","enum":["json","markdown"],"description":"optimize_report only."},"kind":{"type":"string","enum":["domain","sdt","all"],"description":"types_list filter."},"value":{"type":"string","description":"types_validate."},"type":{"type":"string","description":"types_validate / disambiguator."},"inputPath":{"type":"string","description":"translations_import: CSV path."},"kb":{"type":"string","description":"KB alias."}},"examples":[{"action":"drift_check"},{"action":"sql_ddl","name":"Customer"},{"action":"records_query","dataStoreAlias":"production","transaction":"Order","where":{"OrderId":1},"limit":20,"timeoutSeconds":20}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},
|
|
42
42
|
{"name":"genexus_versioning","description":"Versioning umbrella. action: history_list|history_get|history_save|history_restore (snapshot store; restore+discard=true is IDE 'Discard changes' parity) | undo (revert last N edits) | time_travel (recover bytes from a past git commit) | blame (git blame an object part) | diff (text: mode=textVsText|currentVsText) | diff_generated (against=last-build|git-head). Long version-store reads (history_get/history_list/diff/diff_generated/blame) accept async=true: the reply returns {operationId, pollTarget} before the read starts and the result stays readable via genexus_lifecycle action=status/result.","inputSchema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["history_list","history_get","history_save","history_restore","undo","time_travel","blame","diff","diff_generated"],"description":"History, diff, time-travel, or rollback operation to perform."},"name":{"type":"string","description":"Object name for history, diff, time_travel, or blame."},"part":{"type":"string","description":"Object part name, e.g. Source, Rules, Events."},"partName":{"type":"string","description":"Legacy alias for part on history actions."},"versionId":{"type":"integer","description":"history_get/history_restore: numerical version ID."},"snapshot":{"type":"string","description":"history_restore: snapshot label or path to restore."},"discard":{"type":"boolean","description":"history_restore: true for IDE 'Discard changes' parity."},"dryRun":{"type":"boolean","description":"history_restore/undo: preview without mutating the KB."},"async":{"type":"boolean","description":"history_get/history_list/diff/diff_generated/blame only: return {operationId, job_id, pollTarget:'op:<id>', status:'running'} before the read starts and run it in the background, so the result is still readable with genexus_lifecycle action=status/result if this call's window expires. Never applies to the mutating actions."},"estimated_seconds":{"type":"integer","description":"async=true: expected duration used as the poll cadence hint in the accepted envelope."},"last":{"type":"integer","description":"undo: default 1, max 20."},"at":{"type":"string","description":"time_travel: ISO-8601 or commit sha."},"line":{"type":"integer","description":"blame: 1-based line number to annotate."},"filePath":{"type":"string","description":"blame: absolute or KB-relative file path."},"context":{"type":"integer","description":"blame: surrounding lines of context."},"mode":{"type":"string","enum":["textVsText","currentVsText"],"description":"diff."},"left":{"type":"string","description":"diff: left-side text or snapshot label."},"right":{"type":"string","description":"diff: right-side text or snapshot label."},"against":{"type":"string","enum":["last-build","git-head"],"description":"diff_generated."},"kb":{"type":"string","description":"KB alias."}},"examples":[{"action":"history_list","name":"Customer"},{"action":"time_travel","name":"Customer","at":"2026-05-20T10:00:00Z"}]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false}},
|
|
43
43
|
{"name":"genexus_io","description":"IO umbrella for assets, Object Text exchange, screenshots, OCR. action: asset_find|asset_read|asset_write | read_blob | export_part|import_part (single part) | export_kb_to_text|import_text_to_kb|validate_kb_text_files|delete_kb_objects (official GeneXus for Agents Object Text parity) | export_unified|screenshot_publish|ocr.","inputSchema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["asset_find","asset_read","asset_write","read_blob","export_part","import_part","export_kb_to_text","import_text_to_kb","validate_kb_text_files","validate_text_in_memory","list_text_files","text_mirror_start","text_mirror_stop","text_mirror_status","text_mirror_catchup","text_mirror_set_references","delete_kb_objects","export_unified","screenshot_publish","ocr"],"description":"Asset, single-part, SDK text-tree, batch Object Text, screenshot, or OCR operation."},"path":{"type":"string","description":"asset/screenshot_publish/ocr: file path; Object Text import/validate may use a manifest directory."},"name":{"type":"string","description":"single object name or comma-separated selector; export_unified uses one object."},"targets":{"type":"array","items":{},"description":"Object Text selector array. Items may be names or {name,type} objects. Omit for export_kb_to_text to export the full indexed KB."},"outputPath":{"type":"string","description":"path"},"inputPath":{"type":"string","description":"import_part: source file; import_text_to_kb/validate_kb_text_files: manifest or directory."},"part":{"type":"string","description":"Object Text or part-exchange part name (e.g. Source, Rules, WebForm). For native format, part=all serializes authored textual parts into one sectioned .gx document."},"parts":{"type":"array","items":{"type":"string"},"description":"native export: explicit authored parts to include in one sectioned .gx document; part=all uses the safe default part set."},"format":{"type":"string","enum":["legacy","native"],"description":"Object Text export/import format. legacy preserves .gxtext compatibility; native creates the SDK text tree under src/ and ref/ without GX4A DLLs."},"mode":{"type":"string","enum":["all","newAndModified","newOnly"],"description":"native export mode. all writes every selected object; newAndModified uses the SDK/index version token; newOnly keeps existing files."},"includeDependencies":{"type":"boolean","description":"native export/import: include Calls/Tables dependency closure under ref/."},"includeReferences":{"type":"boolean","description":"Alias of includeDependencies for native src/ref exchange."},"includeVisualParts":{"type":"boolean","description":"native export/import: include WebForm/Layout companions (.web.xml or .report.xml)."},"includeModuleMetadata":{"type":"boolean","default":true,"description":"native export: emit deterministic module.toml metadata for modules represented in src/ref; no package DLL is loaded."},"includeModulePackages":{"type":"boolean","description":"native export: copy matching official .opc reference packages from the selected GeneXus installation into ref/; defaults to includeDependencies and never copies DLLs."},"includeTableProjections":{"type":"boolean","description":"native export: emit official SDK Table structures under src/#tables for selected Transactions; opt-in because tables may be shared/derived."},"includeChildren":{"type":"boolean","default":true,"description":"filesystem parity: recurse into child directories or expand Module/Folder selectors recursively; default true."},"listOnly":{"type":"boolean","description":"filesystem parity: return the resolved plan without reading the SDK, writing files or mutating the KB."},"stopOnError":{"type":"boolean","description":"filesystem parity: stop after the first item-level error and report remaining work for a safe resume."},"skip":{"type":"integer","minimum":0,"description":"filesystem parity: skip this many deterministic planned items before processing; useful for resuming a large batch."},"indentString":{"type":"string","description":"native export: optional prefix applied to non-empty source lines inside the object body; omitted preserves source indentation."},"forceSave":{"type":"boolean","description":"text import: force the official WriteService persistence path even when the content is unchanged."},"rollbackOnFailure":{"type":"boolean","default":true,"description":"native multi-part import: restore parts already written when a later SDK part write fails; reports reconciliationRequired if a prior snapshot cannot be read or restored."},"importMissingReferences":{"type":"boolean","description":"native import: include reference/dependency files when importing a tree."},"ignore":{"type":"array","items":{"type":"string"},"description":"list_text_files/validate_text_in_memory: relative file or directory prefixes to ignore; batch KB actions also accept object selectors."},"intervalMs":{"type":"integer","minimum":250,"description":"text_mirror_start: debounce/poll interval in milliseconds (250-600000)."},"initialSync":{"type":"boolean","description":"text_mirror_start: schedule a full catch-up immediately after start."},"full":{"type":"boolean","description":"text_mirror_catchup: reconcile the complete indexed KB instead of only queued changes."},"enabled":{"type":"boolean","description":"text_mirror_set_references: enable/disable reference export."},"type":{"type":"string","description":"Object type disambiguator/filter."},"module":{"type":"string","description":"Object Text module filter."},"pathPrefix":{"type":"string","description":"Object Text KB object-path prefix filter."},"overwrite":{"type":"boolean","description":"replace file"},"confirm":{"type":"boolean","description":"delete_kb_objects: required for a real delete; dryRun remains non-mutating."},"dryRun":{"type":"boolean","description":"Object Text import/delete preview without persisting changes."},"async":{"type":"boolean","description":"Run a batch Object Text operation as a cancellable background job when supported."},"pattern":{"type":"string","description":"asset_find: glob pattern."},"relativeRoot":{"type":"string","description":"asset_find: root for relative paths."},"limit":{"type":"integer","description":"asset_find/Object Text: max results."},"includeContent":{"type":"boolean","description":"asset_find: inline file content."},"maxBytes":{"type":"integer","description":"inline limit"},"includeBase64":{"type":"boolean","description":"include Base64 response"},"contentBase64":{"type":"string","description":"asset_write: base64-encoded file content."},"includePersistedText":{"type":"boolean","description":"Full text; default false."},"kb":{"type":"string","description":"KB alias."}},"examples":[{"action":"export_kb_to_text","outputPath":"C:\\tmp\\customer-text","targets":[{"name":"Customer","type":"Transaction"}]},{"action":"validate_kb_text_files","inputPath":"C:\\tmp\\customer-text"},{"action":"delete_kb_objects","targets":["Procedure:OldProc"],"dryRun":true}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},
|
|
44
|
-
{"name":"genexus_variable","description":"Variables CRUD. add accepts varName or variables[] batch; modify changes type atomically. basedOn binds a Domain; basedOnAttribute (or typeName Attribute:<name>) binds an Attribute by native SDK identity preserving picture/semantics. objectType=BusinessComponent with objectName+module binds a modular BC by EntityKey/GUID and verifies it after save. length/decimals override size; collection=true declares a collection; dimensions=1|2 plus dimensionSizes declares a fixed-size vector/matrix (not a collection); untyped add inherits a same-named attribute with its binding. modify refuses to silently drop an Attribute binding (AttributeBindingWouldBeLost); reads surface basedOn. dryRun validates and previews without mutation; async returns an operationId.","inputSchema":{"type":"object","required":["action","name"],"properties":{"action":{"type":"string","enum":["add","delete","modify"],"description":"Variable-part operation to add, delete, or modify a variable."},"name":{"type":"string"},"varName":{"type":"string","description":"Single-variable form (add/delete/modify). For batch add use variables[] instead."},"variables":{"type":"array","description":"Batch add only: one object per variable — {varName, typeName?, basedOn?, basedOnAttribute?, length?, decimals?, collection?, dimensions?, dimensionSizes?}. Added before a single save.","items":{"type":"object","required":["varName"],"properties":{"varName":{"type":"string"},"typeName":{"type":"string"},"length":{"type":"integer"},"decimals":{"type":"integer"},"collection":{"type":"boolean"},"dimensions":{"type":"integer","minimum":1,"maximum":2,"description":"Fixed-size vector/matrix rank; requires dimensionSizes and conflicts with collection."},"dimensionSizes":{"type":"array","minItems":1,"maxItems":2,"items":{"type":"integer","minimum":1},"description":"Positive sizes in row/column order; length must equal dimensions."},"basedOn":{"type":"string","description":"Domain name; native SDK reference."},"basedOnAttribute":{"type":"string","description":"Attribute name (or Attribute:<name>); preserves picture/semantics."}}}},"typeName":{"type":"string","description":"Primitive (Character/Numeric/VarChar/Date/...), SDT/BC/Domain name, Attribute:<name>, or WebSession. VarChar keeps VARCHAR semantics."},"newTypeName":{"type":"string","description":"modify alias for the replacement type; accepted alongside typeName."},"dataType":{"type":"string","description":"modify alias for the replacement type; accepted alongside typeName."},"objectType":{"type":"string","enum":["BusinessComponent"],"description":"add/modify: resolve an object-backed variable natively instead of interpreting typeName as a Domain."},"objectName":{"type":"string","description":"Business Component Transaction name, without module when module is passed separately."},"module":{"type":"string","description":"Module owning objectName. Required to disambiguate modular Business Components."},"expectedVersion":{"type":"string","description":"Optimistic-concurrency token for an object-backed add/modify. Stale state returns VersionConflict before mutation."},"length":{"type":"integer","description":"add/modify optional: overrides the length parsed from typeName."},"decimals":{"type":"integer","description":"add/modify optional: overrides decimals parsed from typeName."},"collection":{"type":"boolean","description":"add/modify optional: declare the variable as a collection."},"dimensions":{"type":"integer","minimum":1,"maximum":2,"description":"add/modify optional: fixed-size vector/matrix rank; requires dimensionSizes and conflicts with collection."},"dimensionSizes":{"type":"array","minItems":1,"maxItems":2,"items":{"type":"integer","minimum":1},"description":"add/modify optional: positive sizes in row/column order; length must equal dimensions."},"basedOn":{"type":"string","description":"Domain name, or Attribute:<name> for an attribute binding (prefer basedOnAttribute)."},"basedOnAttribute":{"type":"string","description":"Attribute name (or Attribute:<name>) to bind; preserves picture/semantics."},"dryRun":{"type":"boolean","default":false,"description":"Validate and return the typed diff without changing any object, Attribute, hash, or version."},"validationMode":{"type":"string","enum":["specify"],"description":"Explicitly run the inline Specify pass after a legacy variable write. Never runs unless requested."},"rollbackOnFailure":{"type":"boolean","default":true,"description":"Object-backed variables always snapshot the complete owner and restore it on save/re-read divergence."},"async":{"type":"boolean","description":"Run as a background job. Result returns operationId/job_id for genexus_lifecycle polling."},"estimated_seconds":{"type":"integer","description":"When async=true, expected runtime used for progress/job metadata (default 30)."},"includePersistedText":{"type":"boolean","description":"Full text; default false."},"kb":{"type":"string","description":"KB alias."}},"examples":[{"action":"add","name":"MyPanel","varName":"&Choice","typeName":"Numeric"},{"action":"add","name":"MyProc","varName":"&OrderRecord","objectType":"BusinessComponent","objectName":"OrderRecord","module":"Operations","dryRun":true},{"action":"add","name":"MyProc","variables":[{"varName":"&ApiKey","typeName":"VarChar","length":80},{"varName":"&CmdNro","typeName":"Numeric","length":9}]},{"action":"delete","name":"MyPanel","varName":"&OldVar"}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},
|
|
44
|
+
{"name":"genexus_variable","description":"Variables CRUD. add accepts varName or variables[] batch; modify changes type atomically, or only the description when typeName is omitted (the type is kept). basedOn binds a Domain; basedOnAttribute (or typeName Attribute:<name>) binds an Attribute by native SDK identity preserving picture/semantics. objectType=BusinessComponent with objectName+module binds a modular BC by EntityKey/GUID and verifies it after save. length/decimals override size; collection=true declares a collection; dimensions=1|2 plus dimensionSizes declares a fixed-size vector/matrix (not a collection); untyped add inherits a same-named attribute with its binding. modify refuses to silently drop an Attribute binding (AttributeBindingWouldBeLost); reads surface basedOn. dryRun validates and previews without mutation; async returns an operationId.","inputSchema":{"type":"object","required":["action","name"],"properties":{"action":{"type":"string","enum":["add","delete","modify"],"description":"Variable-part operation to add, delete, or modify a variable."},"name":{"type":"string"},"varName":{"type":"string","description":"Single-variable form (add/delete/modify). For batch add use variables[] instead."},"variables":{"type":"array","description":"Batch add only: one object per variable — {varName, typeName?, basedOn?, basedOnAttribute?, length?, decimals?, collection?, dimensions?, dimensionSizes?}. Added before a single save.","items":{"type":"object","required":["varName"],"properties":{"varName":{"type":"string"},"typeName":{"type":"string"},"length":{"type":"integer"},"decimals":{"type":"integer"},"collection":{"type":"boolean"},"dimensions":{"type":"integer","minimum":1,"maximum":2,"description":"Fixed-size vector/matrix rank; requires dimensionSizes and conflicts with collection."},"dimensionSizes":{"type":"array","minItems":1,"maxItems":2,"items":{"type":"integer","minimum":1},"description":"Positive sizes in row/column order; length must equal dimensions."},"basedOn":{"type":"string","description":"Domain name; native SDK reference."},"basedOnAttribute":{"type":"string","description":"Attribute name (or Attribute:<name>); preserves picture/semantics."}}}},"typeName":{"type":"string","description":"Primitive (Character/Numeric/VarChar/Date/...), SDT/BC/Domain name, Attribute:<name>, or WebSession. VarChar keeps VARCHAR semantics."},"newTypeName":{"type":"string","description":"modify alias for the replacement type; accepted alongside typeName."},"dataType":{"type":"string","description":"modify alias for the replacement type; accepted alongside typeName."},"description":{"type":"string","description":"modify: new variable Description (empty string clears it). Without typeName the type is kept and only the description changes."},"objectType":{"type":"string","enum":["BusinessComponent"],"description":"add/modify: resolve an object-backed variable natively instead of interpreting typeName as a Domain."},"objectName":{"type":"string","description":"Business Component Transaction name, without module when module is passed separately."},"module":{"type":"string","description":"Module owning objectName. Required to disambiguate modular Business Components."},"expectedVersion":{"type":"string","description":"Optimistic-concurrency token for an object-backed add/modify. Stale state returns VersionConflict before mutation."},"length":{"type":"integer","description":"add/modify optional: overrides the length parsed from typeName."},"decimals":{"type":"integer","description":"add/modify optional: overrides decimals parsed from typeName."},"collection":{"type":"boolean","description":"add/modify optional: declare the variable as a collection."},"dimensions":{"type":"integer","minimum":1,"maximum":2,"description":"add/modify optional: fixed-size vector/matrix rank; requires dimensionSizes and conflicts with collection."},"dimensionSizes":{"type":"array","minItems":1,"maxItems":2,"items":{"type":"integer","minimum":1},"description":"add/modify optional: positive sizes in row/column order; length must equal dimensions."},"basedOn":{"type":"string","description":"Domain name, or Attribute:<name> for an attribute binding (prefer basedOnAttribute)."},"basedOnAttribute":{"type":"string","description":"Attribute name (or Attribute:<name>) to bind; preserves picture/semantics."},"dryRun":{"type":"boolean","default":false,"description":"Validate and return the typed diff without changing any object, Attribute, hash, or version."},"validationMode":{"type":"string","enum":["specify"],"description":"Explicitly run the inline Specify pass after a legacy variable write. Never runs unless requested."},"rollbackOnFailure":{"type":"boolean","default":true,"description":"Object-backed variables always snapshot the complete owner and restore it on save/re-read divergence."},"async":{"type":"boolean","description":"Run as a background job. Result returns operationId/job_id for genexus_lifecycle polling."},"estimated_seconds":{"type":"integer","description":"When async=true, expected runtime used for progress/job metadata (default 30)."},"includePersistedText":{"type":"boolean","description":"Full text; default false."},"kb":{"type":"string","description":"KB alias."}},"examples":[{"action":"add","name":"MyPanel","varName":"&Choice","typeName":"Numeric"},{"action":"add","name":"MyProc","varName":"&OrderRecord","objectType":"BusinessComponent","objectName":"OrderRecord","module":"Operations","dryRun":true},{"action":"add","name":"MyProc","variables":[{"varName":"&ApiKey","typeName":"VarChar","length":80},{"varName":"&CmdNro","typeName":"Numeric","length":9}]},{"action":"delete","name":"MyPanel","varName":"&OldVar"}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},
|
|
45
45
|
{"name":"genexus_telemetry","description":"Observability umbrella. action: executions (recent invocations) | watch_event (ops mentioning an event) | friction_append|friction_tail (.gx/friction.jsonl) | learning_report (aggregate friction) | logs (worker_debug.log tail) | profile_analyze|profile_hotspots|profile_correlate (GeneXus profiler XML).","inputSchema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["executions","watch_event","friction_append","friction_tail","learning_report","logs","profile_analyze","profile_hotspots","profile_correlate"],"description":"Telemetry, profiling, or friction-log operation to perform."},"target":{"type":"string","description":"executions/watch_event: object name to filter."},"event":{"type":"string","description":"watch_event: event name to match in operation payload."},"last":{"type":"integer","description":"executions/watch_event: max results."},"tool":{"type":"string","description":"friction_append: tool name that produced the friction entry."},"message":{"type":"string","description":"friction_append: description of the friction encountered."},"severity":{"type":"string","enum":["info","warn","error","critical"],"description":"friction_append: severity level."},"n":{"type":"integer","description":"friction_tail: number of recent lines to return."},"since":{"type":"string","description":"learning_report/logs: ISO-8601 start time filter."},"until":{"type":"string","description":"learning_report: ISO-8601 end time filter."},"tail":{"type":"integer","description":"logs: number of tail lines from worker_debug.log."},"filterCorrelation":{"type":"string","description":"logs: filter by correlation/operation ID."},"grep":{"type":"string","description":"logs: substring filter on log lines."},"path":{"type":"string","description":"profile_*: path to the GeneXus profiler XML file."},"top":{"type":"integer","description":"profile_hotspots: top-N hottest procedures to return."},"kb":{"type":"string","description":"KB alias."}},"examples":[{"action":"executions"},{"action":"friction_tail","n":20}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},
|
|
46
46
|
{"name":"genexus_create","description":"Creation. action: object (Transaction/Procedure/WebPanel/SDT/API/Domain/Dashboard/Folder/Module; type='API' scaffolds a REST API object with one HTTP-verb block per object; type='Folder'/'Module' create containers; folder/module places the new object there; SDT and Transaction take optional firstItem/firstItemType; Domain takes dataType+length or enumValues; NOT WWP — use genexus_apply_pattern) | popup (popup WebPanel with Form type='layout' body) | sd_panel_create|sd_panel_inspect|sd_panel_edit | save_as (clone parts) | scaffold|translate|sample (forge) | template (kpi_header|empty_state|confirm_dialog) | object_atomic (issue #62: all-or-nothing create/update of an object with variables[], rules[], parms[], properties{} and source in ONE validated call — pre-validates every field before the first save, composes the SDK write primitives, compensates on failure, dryRun previews, validate=true runs the inline Specify pass, update mode guards concurrent writes via expectedVersion). | curl_procedure imports a REST-consumer Procedure from a curl command through the GeneXus SDK.","inputSchema":{"type":"object","required":[],"properties":{"action":{"type":"string","enum":["object","object_atomic","popup","sd_panel_create","sd_panel_inspect","sd_panel_edit","save_as","scaffold","translate","sample","template","curl_procedure"],"description":"Object-creation or scaffold operation to perform."},"curl":{"type":"string","description":"curl_procedure: the curl command to import as a Procedure."},"type":{"type":"string","description":"Object type to create (Transaction, Procedure, WebPanel, SDT, API, Domain, Dashboard, Folder, Module)."},"objectType":{"type":"string","description":"Legacy alias for type when creating an object."},"name":{"type":"string","description":"Name of the object to create, clone, or update."},"newName":{"type":"string","description":"save_as."},"description":{"type":"string","description":"Human-readable description / title of the object."},"dataType":{"type":"string","description":"object Domain."},"length":{"type":"integer","description":"object Domain."},"decimals":{"type":"integer","description":"object Domain."},"signed":{"type":"boolean","description":"object Domain."},"basedOn":{"type":"string","description":"object Domain."},"enumValues":{"type":"array","items":{"type":"object"},"description":"object Domain enum."},"firstItem":{"type":"string","description":"object SDT/Transaction optional: name of the initial structure item/key attribute to seed (SDK requires >=1). Defaults to <ObjectName>Id for Transaction and Item1 for SDT."},"firstItemType":{"type":"string","description":"object SDT/Transaction optional: type of the seeded first item/key attribute (Character/Numeric/VarChar/…). Defaults to Numeric(4) for Transaction and VarChar for SDT."},"folder":{"type":"string","description":"object: Folder destination (created in Root, then moved+verified)."},"module":{"type":"string","description":"object: Module destination (created in Root, then moved+verified)."},"parentPath":{"type":"string","description":"object: folder/module destination (fallback when folder/module absent)."},"mode":{"type":"string","enum":["create","update","auto"],"description":"object_atomic: create (fail if exists), update (fail if missing), auto (default — create or update by existence)."},"variables":{"type":"array","items":{"type":"object","required":["varName"],"properties":{"varName":{"type":"string"},"typeName":{"type":"string"},"length":{"type":"integer"},"decimals":{"type":"integer"},"collection":{"type":"boolean"},"name":{"type":"string"},"basedOn":{"type":"string"},"basedOnAttribute":{"type":"string"}}},"description":"object_atomic: one object per variable — {varName, typeName?, length?, decimals?, collection?}. Validated before any save; errors are attributed to variables[N]."},"rules":{"type":"array","items":{"type":"string"},"description":"object_atomic: rule lines (e.g. \"Parm(in:&Id);\"). Send actual line breaks; literal backslash sequences \\r\\n, \\n, or \\r are rejected before the first save."},"parms":{"type":"array","items":{"type":"string"},"description":"object_atomic: parameter entries rendered into a Parm rule — bare names (\"&Id\") or prefixed (\"out:&Msg\")."},"source":{"type":"string","description":"object_atomic: Source part text. Send actual line breaks; literal backslash sequences \\r\\n, \\n, or \\r are rejected before the first save."},"properties":{"type":"object","description":"object_atomic: object-level properties applied via the genexus_properties path (propertyName → value)."},"expectedVersion":{"type":"string","description":"object_atomic update: optimistic concurrency token returned as `version` by a prior atomic create/update/read; a mismatch fails with ConcurrentModification instead of overwriting concurrent changes."},"validate":{"type":"boolean","description":"object_atomic: run the inline Specify pass (Spec+Gen) before confirming success. On failure with rollbackOnFailure=true, a freshly-created object is deleted so the operation stays all-or-nothing."},"validationMode":{"type":"string","enum":["specify"],"description":"Issue #60: with action=object, run the inline Specify pass (Spec+Gen, no Compile) after creation, returning structured spc*/gen* diagnostics in the same call. Combines with rollbackOnFailure."},"rollbackOnFailure":{"type":"boolean","description":"Issue #60: with action=object and validationMode=specify, roll back the created object when the specify pass reports errors. A fresh object has no pre-write snapshot, so rollback reports rolledBack=false — delete it via genexus_delete_object if spec fails."},"spec":{"type":"object","description":"popup."},"part":{"type":"string","description":"sd_panel_edit/template."},"content":{"type":"string","description":"sd_panel_edit/scaffold/translate."},"includePatternInstance":{"type":"boolean","description":"save_as."},"overwrite":{"type":"boolean","description":"save_as."},"dryRun":{"type":"boolean","description":"popup/save_as/template/object."},"template":{"type":"string","enum":["kpi_header","empty_state","confirm_dialog"],"description":"template."},"args":{"type":"object","description":"template."},"kb":{"type":"string","description":"KB alias."},"baseVersion":{"type":"string","description":"Optimistic concurrency versionToken for atomic create/update."},"updateExisting":{"type":"boolean","default":false,"description":"object_atomic: allow updating existing object if it already exists."}},"examples":[{"action":"object","name":"NewPanel","type":"WebPanel"},{"action":"object","name":"CustomerApi","type":"API"},{"action":"popup","name":"MyPopup","spec":{"host":"Customer"}}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},
|
|
47
47
|
{"name":"genexus_memory","description":"Per-KB fact store. action: save (fact required; optional target/type/tags; dedups on identical fact+object, bumping a hit count) | recall (filter by target/type/tags — ANY match; no filter returns all) | list (all, newest first) | forget (tombstone by id) | promote (lift a friction-log message into a memory, tagged 'friction') | consolidate (dreaming — merge redundant/overlapping facts within scope; dryRun=true previews, dryRun=false compacts memory.jsonl). Persisted to .gx/memory/memory.jsonl.","inputSchema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["save","recall","list","forget","promote","consolidate"],"description":"Persistent agent-memory operation to perform."},"fact":{"type":"string","description":"save: the fact to remember."},"target":{"type":"string","description":"object name this memory is about."},"type":{"type":"string","description":"object type this memory is about."},"tags":{"type":"array","items":{"type":"string"},"description":"labels for filtering."},"id":{"type":"string","description":"forget: memory id to tombstone."},"message":{"type":"string","description":"promote: friction text to promote into a memory."},"dryRun":{"type":"boolean","description":"consolidate: true previews proposed merges without writing; false (default) applies and compacts memory.jsonl."},"kb":{"type":"string","description":"KB alias."}},"additionalProperties":false,"examples":[{"action":"save","fact":"Customer.Email must be unique","target":"Customer","type":"Transaction","tags":["validation"]},{"action":"recall","target":"Customer"},{"action":"consolidate","dryRun":true}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},
|
|
48
|
-
{"name":"genexus_transfer","description":"Real XPZ export/import over the SDK's IKnowledgeManagerService — dependency-aware, IDE Export/Import parity (NOT the filesystem copy genexus_io/kb_import do). action=export (targets[]+outputFile; includeDependencies=true exports transitive closure) | inspect (explore an .xpz, read-only) | import (apply into KB; dryRun defaults true=preview via ExploreExport; dryRun=false
|
|
48
|
+
{"name":"genexus_transfer","description":"Real XPZ export/import over the SDK's IKnowledgeManagerService — dependency-aware, IDE Export/Import parity (NOT the filesystem copy genexus_io/kb_import do). action=export (targets[]+outputFile; includeDependencies=true exports transitive closure) | inspect (explore an .xpz, read-only) | import (apply into KB; dryRun defaults true=preview via ExploreExport; to actually import pass dryRun=false AND confirm=true; confirm=true alone only previews).","inputSchema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["export","inspect","import"],"description":"XPZ export, inspection, or import operation to perform."},"targets":{"type":"array","items":{"type":"string"},"description":"export: object names to export."},"outputFile":{"type":"string","description":"export: absolute .xpz output path."},"includeDependencies":{"type":"boolean","description":"export: compute transitive dependency closure (Calls, Tables) and export all referenced objects.","default":false},"file":{"type":"string","description":"inspect/import: absolute .xpz path."},"type":{"type":"string","description":"export: disambiguate object type."},"dryRun":{"type":"boolean","description":"import: true (default) previews and imports NOTHING; pass false (with confirm=true) to actually apply. confirm=true alone does not import."},"confirm":{"type":"boolean","description":"import with dryRun=false: required."},"kb":{"type":"string","description":"KB alias."}},"examples":[{"action":"export","targets":["Customer"],"outputFile":"C:\\tmp\\cust.xpz"},{"action":"export","targets":["Customer"],"outputFile":"C:\\tmp\\cust_full.xpz","includeDependencies":true},{"action":"inspect","file":"C:\\tmp\\cust.xpz"}]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false}},
|
|
49
49
|
{"name":"genexus_deploy","description":"Deploy application over the SDK. action=list_targets (read-only, default) enumerates deployment target types (IDeploymentTargetService); action=deploy (destructive, confirm=true) runs IDeploymentService.Deploy(model).","inputSchema":{"type":"object","properties":{"action":{"type":"string","enum":["list_targets","deploy"],"description":"Deployment-target or deployment execution operation to perform."},"confirm":{"type":"boolean","description":"deploy: required (builds + ships the app)."},"kb":{"type":"string","description":"KB alias."}},"examples":[{"action":"list_targets"},{"action":"deploy","confirm":true}]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false}},
|
|
50
50
|
{"name":"genexus_generator_reference","description":"Native typed .NET generator references used by GxExternalReference. list and dry-run actions are read-only. add/remove validate a managed assembly when a path is supplied, require optimistic baseVersion for changes, save only the native GeneratorsPart, reread it, and restore the complete generator-property snapshot on verification failure. No lifecycle action runs implicitly.","inputSchema":{"type":"object","additionalProperties":false,"required":["action","environment","generator"],"properties":{"action":{"type":"string","enum":["list","dry_run_add","add","dry_run_remove","remove"],"description":"Typed .NET generator-reference operation to perform."},"environment":{"type":"string","description":"Active GeneXus Environment name; the tool never switches environments."},"generator":{"type":"string","description":"Generator display name, e.g. Default (.NET)."},"assembly":{"type":"string","description":"Assembly file name for add/remove, e.g. SpreadsheetLibrary.dll."},"assemblyPath":{"type":"string","description":"Absolute path or KB-relative path used to validate a managed assembly. Required for add unless found in a standard model/bin location."},"baseVersion":{"type":"string","description":"Optimistic token returned by list or a dry-run. Required for a real state change."},"dryRun":{"type":"boolean","default":false,"description":"Force add/remove to remain read-only."},"rollbackOnFailure":{"type":"boolean","default":true,"description":"Restore and verify the complete prior generator-property snapshot if save/reread diverges."},"kb":{"type":"string","description":"KB alias."}},"examples":[{"action":"list","environment":".Net Environment","generator":"Default (.NET)"},{"action":"dry_run_add","environment":".Net Environment","generator":"Default (.NET)","assembly":"SpreadsheetLibrary.dll","assemblyPath":"C:\\KBs\\Sample\\CSharpModel\\web\\bin\\SpreadsheetLibrary.dll"},{"action":"add","environment":".Net Environment","generator":"Default (.NET)","assembly":"SpreadsheetLibrary.dll","assemblyPath":"C:\\KBs\\Sample\\CSharpModel\\web\\bin\\SpreadsheetLibrary.dll","baseVersion":"sha256:<token>","rollbackOnFailure":true}]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":true,"openWorldHint":false}},
|
|
51
51
|
{"name":"genexus_wwp","description":"Typed WorkWithPlus action, form-level action, tab, grid, native table-type, and structural edits with dryRun, optimistic concurrency, exact snapshots, post-save reread, projection verification, and rollback. set_table_type mutates only an existing table type through the native PatternInstance SDK and preserves children, bindings, events, names, classes, defaultType, and childrenOrderedList. No lifecycle operation is implicit. Settings: embedded and separate WWP templates, paged reads and exact table-class dryRun; saves remain blocked.","inputSchema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["list","add_action","add_user_action","update_action","move_action","remove_action","add_tab","move_tab","remove_tab","set_table_type","add_grid_attribute","move_grid_column","add_grid_variable","replace_web_component_with_user_action","settings_templates","settings_read","settings_edit"],"description":"WorkWithPlus action-group, tab, grid-attribute, or explicit native structural operation to perform."},"name":{"type":"string","description":"Transaction, WebPanel, or WorkWithPlus<Object> host."},"group":{"type":"string","description":"Action group name. add_action creates it when absent; update/remove use it as a filter."},"containerName":{"type":"string","description":"add_user_action: form-level action container, usually TableActions."},"actionName":{"type":"string","description":"Action name. add_user_action derives the GeneXus event Do<actionName>."},"attribute":{"type":"string","description":"add_grid_attribute/move_grid_column: GeneXus Attribute name or grid-column reference."},"variable":{"type":"string","description":"add_grid_variable: presentation variable name; pair with variableReference for identity-safe writes."},"variableReference":{"type":"string","description":"Verified SDK variable identity in GUID-Name form; required for add_grid_variable."},"gridPath":{"type":"string","description":"move_grid_column/add_grid_variable: explicit grid path when the instance has multiple grids."},"before":{"type":"string","description":"move_grid_column/add_grid_variable: place before this existing column."},"caption":{"type":"string","description":"Action caption or add_grid_variable label."},"basicType":{"type":"string","description":"add_grid_variable: Character or VarChar presentation type."},"length":{"type":"integer","minimum":1,"description":"add_grid_variable: Character/VarChar length."},"procedure":{"type":"string","description":"add/update: associated Procedure; existence is validated against the KB."},"selection":{"type":"string","enum":["single","multiple"],"description":"add/update: execution scope for grid actions."},"enabledWhen":{"type":"string","description":"Availability condition stored verbatim; expression semantics are not validated."},"icon":{"type":"string","description":"add/update: button icon."},"description":{"type":"string","description":"add/update: tooltip or description."},"confirm":{"type":"boolean","description":"Confirmation prompt; required to delete unless dryRun."},"buttonClass":{"type":"string","description":"add/update: theme button class."},"position":{"type":"integer","minimum":0,"description":"Zero-based action or tab index."},"toGroup":{"type":"string","description":"move_action: destination group (created when absent)."},"fromGroup":{"type":"string","description":"move_action: source group (optional; searched across groups when omitted)."},"dryRun":{"type":"boolean","description":"Return a typed diff and versionToken without mutation."},"rollbackOnFailure":{"type":"boolean","default":true,"description":"On a failed write or post-save verification, restore the original PatternInstance when possible."},"controlName":{"type":"string","description":"Tab ControlName."},"title":{"type":"string","description":"add_tab: tab title."},"children":{"type":"array","description":"add_tab controls; flat children are wrapped in a responsive table. Nested table children accept the same control shape.","items":{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["variable","userAction","table"]},"name":{"type":"string"},"caption":{"type":"string"},"description":{"type":"string"},"basicType":{"type":"string"},"length":{"type":"integer","minimum":1},"decimals":{"type":"integer","minimum":0},"controlType":{"type":"string"},"controlValues":{"type":"string"},"controlEmptyItem":{"type":"boolean"},"controlEmptyItemText":{"type":"string"},"columns":{"type":"integer","minimum":1},"themeClass":{"type":"string"},"children":{"type":"array","items":{"type":"object"}}},"additionalProperties":false}},"sourceName":{"type":"string","description":"replace_web_component_with_user_action: existing WebComponent name."},"userActionName":{"type":"string","description":"replace_web_component_with_user_action: resulting UserAction name; defaults to sourceName."},"tablePath":{"type":"string","description":"set_table_type: existing table breadcrumb by names or indexed table segments; replace_web_component_with_user_action: full breadcrumb including the source node, for example TableHeader > TableUserRole > EmpresaSelector."},"tableType":{"type":"string","enum":["Regular","Responsive"],"description":"set_table_type: requested native WWP table type. Only the existing table @type changes; defaultType and all child identity/metadata remain guarded."},"gxobject":{"type":"string","description":"replace_web_component_with_user_action: existing WebComponent Gxobject to retain; it must match the current node."},"controlType":{"type":"string","enum":["DropDownComponent"],"description":"replace_web_component_with_user_action: resulting UserAction ControlType."},"webComponentLoad":{"type":"string","enum":["On Web Panel load","On first click","On every click"],"description":"DropDownComponent load timing."},"trigger":{"type":"string","enum":["Click","Hover"],"description":"DropDownComponent trigger."},"baseVersion":{"type":"string","description":"Optimistic-concurrency token returned by dryRun/read."},"expectedVersion":{"type":"string","description":"Alias for baseVersion."},"versionToken":{"type":"string","description":"Backward-compatible alias for baseVersion."},"kb":{"type":"string","description":"KB alias."},"template":{"description":"Settings catalog path, wwp:<template-guid>, or unique template name.","type":"string"},"limit":{"type":"integer","minimum":0,"description":"Settings nodes per page; offset=0, limit=0 includes full separate-template XML."},"guid":{"type":"string","description":"Pattern Settings object GUID for settings_* actions."},"nodePath":{"description":"Settings node path returned by settings_read.","type":"string"},"entityKey":{"type":"string"},"value":{"type":"string"},"property":{"description":"Exact SDK property name.","type":"string"},"offset":{"minimum":0,"type":"integer"}},"examples":[{"action":"list","name":"SampleOrderWW"},{"action":"add_action","name":"SampleOrderWW","group":"Operations","actionName":"Retry","procedure":"RetrySampleOrder","selection":"multiple","dryRun":true},{"action":"add_tab","name":"SamplePanel","controlName":"Details","title":"Details","children":[{"type":"variable","name":"Status","basicType":"VarChar","length":40},{"type":"userAction","name":"Refresh","caption":"Refresh"}],"dryRun":true},{"action":"add_grid_attribute","name":"SampleOrderWW","attribute":"SampleOrderStatus","caption":"Status","dryRun":true},{"action":"replace_web_component_with_user_action","name":"WorkWithPlusWorkWithPlusMasterPage","sourceName":"EmpresaSelector","userActionName":"EmpresaSelector","tablePath":"TableHeader > TableUserRole > EmpresaSelector","gxobject":"WWP_MasterPageEmpresaSelectorWC","controlType":"DropDownComponent","caption":"&Context.EmpresaDescricao","webComponentLoad":"On every click","trigger":"Click","dryRun":true},{"action":"set_table_type","name":"SamplePanel","tablePath":"TableMain > TableContent > TableLogin","tableType":"Responsive","dryRun":true},{"action":"add_user_action","name":"WorkWithPlusImpressaoConfiguracao","containerName":"TableActions","actionName":"BaixarConfiguracao","caption":"Baixar Configuração","dryRun":true,"rollbackOnFailure":true}]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false}},
|
|
Binary file
|