genexus-mcp 3.5.2 → 3.5.3

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.
@@ -36,6 +36,7 @@ const {
36
36
  DEFAULT_MCP_SERVER_NAME
37
37
  } = require('../lib/config');
38
38
  const { getStdioErrorLogPath } = require('../lib/stdio-diagnostics');
39
+ const { getPackageVersion } = require('../lib/update-check');
39
40
 
40
41
  function resolveClientIds(options) {
41
42
  if (!options || !options.clients) return null;
@@ -2483,6 +2484,13 @@ function commandHelpMap() {
2483
2484
  'genexus-mcp update --channel next # check the @next dist-tag'
2484
2485
  ]
2485
2486
  },
2487
+ version: {
2488
+ usage: 'genexus-mcp --version | -v | version [--format toon|json|text]',
2489
+ examples: [
2490
+ 'genexus-mcp --version # prints the bare version (scripts/CI)',
2491
+ 'genexus-mcp -v --format json # axi-cli/1 envelope with ok.version'
2492
+ ]
2493
+ },
2486
2494
  layout: {
2487
2495
  usage: 'genexus-mcp layout status [--title "GeneXus"] [--format ...] OR genexus-mcp layout run --action <focus|activate-layout|activate-tab|send-keys|type-text|click> [--tab "Layout"] [--keys "..."] [--text "..."] [--x N --y N] [--title "..."] [--format ...] OR genexus-mcp layout inspect [--tab "Layout"] [--limit N] [--full] [--title "..."] [--format ...]',
2488
2496
  examples: ['genexus-mcp layout status --format json', 'genexus-mcp layout run --action activate-tab --tab "Layout" --format json', 'genexus-mcp layout inspect --tab Layout --format json']
@@ -2518,6 +2526,34 @@ async function handleHome(_options, ctx) {
2518
2526
  };
2519
2527
  }
2520
2528
 
2529
+ // Issue #207: `genexus-mcp --version` / `-v` / `version` used to fall through to the
2530
+ // gateway passthrough (which never answers that token) and exit 0 with no output — a
2531
+ // silent false positive for install checks. The package version is read from the same
2532
+ // helper the update flow uses.
2533
+ // `deps` is an injection seam so the unreadable-package.json path is testable.
2534
+ async function handleVersion(_options, ctx, deps = {}) {
2535
+ const readVersion = deps.getPackageVersion || getPackageVersion;
2536
+ const version = readVersion();
2537
+ if (!version) {
2538
+ return {
2539
+ exitCode: ctx.EXIT_CODES.ERROR,
2540
+ envelope: operationalErrorEnvelope(
2541
+ 'Could not read the genexus-mcp package version (package.json missing or unreadable).',
2542
+ ctx.EXIT_CODES.ERROR,
2543
+ ['Reinstall the CLI (`genexus-mcp update`) so package.json can be read.'],
2544
+ 'version_unavailable'
2545
+ )
2546
+ };
2547
+ }
2548
+ return {
2549
+ exitCode: ctx.EXIT_CODES.OK,
2550
+ envelope: {
2551
+ ok: { version },
2552
+ help: []
2553
+ }
2554
+ };
2555
+ }
2556
+
2521
2557
  async function handleHelp(targetCommand, ctx) {
2522
2558
  const binPath = collapseHome(process.argv[1] || process.execPath);
2523
2559
  const map = commandHelpMap();
@@ -2547,7 +2583,7 @@ async function handleHelp(targetCommand, ctx) {
2547
2583
  bin: binPath,
2548
2584
  command: 'genexus-mcp',
2549
2585
  description: 'GeneXus MCP launcher and AXI-oriented utility CLI',
2550
- commands: ['home', 'axi home', 'status', 'doctor', 'tools list', 'config show', 'config create', 'layout status', 'layout run', 'layout inspect', 'init', 'whoami', 'uninstall', 'kb list', 'kb add', 'kb remove', 'kb switch', 'llm help', 'update', 'help'],
2586
+ commands: ['home', 'axi home', 'status', 'doctor', 'tools list', 'config show', 'config create', 'layout status', 'layout run', 'layout inspect', 'init', 'whoami', 'uninstall', 'kb list', 'kb add', 'kb remove', 'kb switch', 'llm help', 'update', 'version', 'help'],
2551
2587
  defaults: { format: 'toon', limit: 100 }
2552
2588
  },
2553
2589
  help: [
@@ -2660,6 +2696,7 @@ module.exports = {
2660
2696
  handleLlmHelp,
2661
2697
  handleLayout,
2662
2698
  handleHelp,
2699
+ handleVersion,
2663
2700
  usageEnvelope,
2664
2701
  operationalErrorEnvelope,
2665
2702
  resolveMcpSmokeTarget,
package/cli/index.js CHANGED
@@ -26,6 +26,7 @@ const {
26
26
  handleLlmHelp,
27
27
  handleLayout,
28
28
  handleHelp,
29
+ handleVersion,
29
30
  usageEnvelope,
30
31
  commandHelpMap
31
32
  } = require('./commands/axi');
@@ -63,7 +64,19 @@ const GLOBAL_DEFAULTS = {
63
64
  help: false
64
65
  };
65
66
 
66
- const KNOWN_COMMANDS = new Set(['status', 'doctor', 'tools', 'config', 'init', 'setup', 'whoami', 'uninstall', 'kb', 'clients', 'help', 'home', 'axi', 'llm', 'layout', 'update']);
67
+ // Single source of truth for command routing: cli/run.js imports both sets so the
68
+ // AXI-vs-passthrough decision (stdout vs stderr for unhandled errors) cannot drift
69
+ // from the parser again — issue #207 was caused by two hand-synced copies.
70
+ const KNOWN_COMMANDS = new Set(['status', 'doctor', 'tools', 'config', 'init', 'setup', 'whoami', 'uninstall', 'kb', 'clients', 'help', 'home', 'axi', 'llm', 'layout', 'update', 'version']);
71
+
72
+ // Version query aliases. `-v` deliberately is NOT an alias of `--help`/`-h`: those
73
+ // return immediately, while the version aliases are command tokens so that remaining
74
+ // flags (`-v --format json`) are still parsed and honored (issue #207).
75
+ const VERSION_ALIASES = new Set(['version', '-v', '--version']);
76
+
77
+ function isKnownCommandToken(token) {
78
+ return KNOWN_COMMANDS.has(token) || VERSION_ALIASES.has(token);
79
+ }
67
80
 
68
81
  function parseArgs(argv) {
69
82
  const result = {
@@ -79,7 +92,8 @@ function parseArgs(argv) {
79
92
  if (tokens.length === 0) return result;
80
93
 
81
94
  const first = tokens[0];
82
- if (!KNOWN_COMMANDS.has(first) && !first.startsWith('--')) {
95
+ const versionIntent = VERSION_ALIASES.has(first);
96
+ if (!versionIntent && !KNOWN_COMMANDS.has(first) && !first.startsWith('--')) {
83
97
  return result;
84
98
  }
85
99
 
@@ -89,7 +103,13 @@ function parseArgs(argv) {
89
103
  return result;
90
104
  }
91
105
 
92
- if (KNOWN_COMMANDS.has(first)) {
106
+ if (versionIntent) {
107
+ // Treat the alias as a consumed command token and keep parsing the remaining
108
+ // flags, so `version --format json`, `-v --format json` and `--version --format json`
109
+ // all reach the format validation instead of falling through to passthrough.
110
+ result.command = 'version';
111
+ tokens.shift();
112
+ } else if (KNOWN_COMMANDS.has(first)) {
93
113
  result.command = first === 'setup' ? 'init' : first;
94
114
  tokens.shift();
95
115
  }
@@ -534,7 +554,9 @@ function resolveMetaCommand(parsed, targetHelp) {
534
554
  async function main(argv) {
535
555
  const parsed = parseArgs(argv);
536
556
 
537
- if (parsed.command !== 'update') {
557
+ // `version` is a quiet query: no update-check banner (it would corrupt the raw
558
+ // version string scripts read) and no launcher config side effects.
559
+ if (parsed.command !== 'update' && parsed.command !== 'version') {
538
560
  startBackgroundUpdateCheck({ quiet: parsed.options.quiet });
539
561
  }
540
562
 
@@ -568,6 +590,19 @@ async function main(argv) {
568
590
  return helpResult.exitCode;
569
591
  }
570
592
 
593
+ if (parsed.command === 'version') {
594
+ const versionResult = await handleVersion(parsed.options, ctx);
595
+ // Default formats print the bare version so `genexus-mcp --version` is usable
596
+ // from scripts/CI; only --format json opts into the axi-cli/1 envelope.
597
+ if (versionResult.exitCode === EXIT_CODES.OK
598
+ && (parsed.options.format === 'toon' || parsed.options.format === 'text')) {
599
+ process.stdout.write(`${versionResult.envelope.ok.version}\n`);
600
+ } else {
601
+ writeStructured(process.stdout, withCommandMeta(versionResult.envelope, 'version'), parsed.options.format);
602
+ }
603
+ return versionResult.exitCode;
604
+ }
605
+
571
606
  let result;
572
607
 
573
608
  switch (parsed.command) {
@@ -682,6 +717,9 @@ module.exports = {
682
717
  main,
683
718
  parseArgs,
684
719
  EXIT_CODES,
720
+ KNOWN_COMMANDS,
721
+ VERSION_ALIASES,
722
+ isKnownCommandToken,
685
723
  renderOutput,
686
724
  formatToonObject
687
725
  };
package/cli/run.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const { main, EXIT_CODES } = require('./index');
2
+ const { main, EXIT_CODES, isKnownCommandToken } = require('./index');
3
3
  const { writeStructured } = require('./lib/output');
4
4
  const { operationalErrorEnvelope } = require('./commands/axi');
5
5
  const { writeLastStdioError } = require('./lib/stdio-diagnostics');
@@ -8,8 +8,9 @@ const { writeLastStdioError } = require('./lib/stdio-diagnostics');
8
8
  // as the MCP JSON-RPC channel. Writing a JSON envelope to stdout there would
9
9
  // corrupt the protocol stream. Route errors to stderr instead.
10
10
  const argv = process.argv.slice(2);
11
- const KNOWN_COMMANDS = new Set(['status', 'doctor', 'tools', 'config', 'init', 'setup', 'whoami', 'uninstall', 'kb', 'clients', 'help', 'home', 'axi', 'llm', 'layout', 'update']);
12
- const isInteractiveCommand = argv.length > 0 && KNOWN_COMMANDS.has(argv[0]);
11
+ // Issue #207: share the command table with the parser instead of keeping a second
12
+ // hand-synced copy here.
13
+ const isInteractiveCommand = argv.length > 0 && isKnownCommandToken(argv[0]);
13
14
  const errorOut = isInteractiveCommand ? process.stdout : process.stderr;
14
15
 
15
16
  main(argv)
package/cli/run.test.js CHANGED
@@ -2046,6 +2046,84 @@ test('gateway passthrough remains intact when no AXI subcommand is used', () =>
2046
2046
  removeTempPath(tempRoot, { recursive: true, force: true });
2047
2047
  });
2048
2048
 
2049
+ test('parseArgs recognizes every version alias as a command token', () => {
2050
+ const { parseArgs } = require('./index');
2051
+ for (const alias of ['--version', '-v', 'version']) {
2052
+ const parsed = parseArgs([alias]);
2053
+ assert.equal(parsed.command, 'version', `${alias} must route to the version command`);
2054
+ assert.deepEqual(parsed.unknownFlags, [], `${alias} must not be reported as an unknown flag`);
2055
+ }
2056
+ // Version aliases are consumed as command tokens, so the remaining flags are parsed.
2057
+ assert.equal(parseArgs(['version', '--format', 'json']).options.format, 'json');
2058
+ assert.equal(parseArgs(['-v', '--format', 'json']).options.format, 'json');
2059
+ assert.equal(parseArgs(['--version', '--format', 'json']).options.format, 'json');
2060
+ // Arbitrary passthrough arguments stay in the passthrough lane.
2061
+ assert.equal(parseArgs(['hello', 'world']).command, null);
2062
+ });
2063
+
2064
+ test('version aliases print the package version without entering gateway passthrough', () => {
2065
+ const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-version-'));
2066
+ const fakeConfig = path.join(tempRoot, 'config.json');
2067
+ fs.writeFileSync(fakeConfig, JSON.stringify({ ok: true }));
2068
+
2069
+ const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'));
2070
+ // Pointing the gateway exe at the Node binary makes a regression loud: a leaked
2071
+ // passthrough of `--version` would print Node's version instead of the package's.
2072
+ const env = { GX_CONFIG_PATH: fakeConfig, GENEXUS_MCP_GATEWAY_EXE: process.execPath };
2073
+
2074
+ try {
2075
+ for (const alias of [['--version'], ['-v'], ['version']]) {
2076
+ const result = runCli(alias, { env });
2077
+ assert.equal(result.status, 0, `${alias.join(' ')} must exit 0`);
2078
+ assert.equal(result.stdout.trim(), pkg.version, `${alias.join(' ')} must print the package version`);
2079
+ }
2080
+ } finally {
2081
+ removeTempPath(tempRoot, { recursive: true, force: true });
2082
+ }
2083
+ });
2084
+
2085
+ test('version --format json returns an axi-cli/1 envelope for every alias', () => {
2086
+ const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'));
2087
+
2088
+ for (const args of [
2089
+ ['version', '--format', 'json'],
2090
+ ['-v', '--format', 'json'],
2091
+ ['--version', '--format', 'json']
2092
+ ]) {
2093
+ const result = runCli(args);
2094
+ assert.equal(result.status, 0, `${args.join(' ')} must exit 0`);
2095
+ const parsed = JSON.parse(result.stdout);
2096
+ assert.equal(parsed.ok.version, pkg.version);
2097
+ assert.equal(parsed.meta.schemaVersion, 'axi-cli/1');
2098
+ assert.equal(parsed.meta.command, 'version');
2099
+ }
2100
+ });
2101
+
2102
+ test('version rejects unknown flags instead of printing a version', () => {
2103
+ const result = runCli(['version', '--bogus']);
2104
+ assert.equal(result.status, 2);
2105
+ assert.match(result.stdout, /Unknown flag: --bogus/);
2106
+ });
2107
+
2108
+ test('version --help documents the command', () => {
2109
+ const result = runCli(['version', '--help', '--format', 'json']);
2110
+ assert.equal(result.status, 0);
2111
+ const parsed = JSON.parse(result.stdout);
2112
+ assert.equal(parsed.ok.command, 'version');
2113
+ assert.match(parsed.ok.usage, /--version/);
2114
+ });
2115
+
2116
+ test('version fails loudly when the package version cannot be read', async () => {
2117
+ const { handleVersion } = require('./commands/axi');
2118
+ const result = await handleVersion({}, { EXIT_CODES: { OK: 0, ERROR: 1, USAGE: 2 } }, {
2119
+ getPackageVersion: () => null
2120
+ });
2121
+
2122
+ assert.equal(result.exitCode, 1);
2123
+ assert.equal(result.envelope.error.code, 'version_unavailable');
2124
+ assert.match(result.envelope.error.message, /package\.json/);
2125
+ });
2126
+
2049
2127
  test('stdio launcher persists the last child stderr when the gateway exits non-zero', () => {
2050
2128
  const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-stdio-crash-'));
2051
2129
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genexus-mcp",
3
- "version": "3.5.2",
3
+ "version": "3.5.3",
4
4
  "mcpName": "io.github.lennix1337/genexus",
5
5
  "description": "GeneXus 17, GeneXus 18 MCP server — 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.5.2": {
10
+ "GxMcp.Gateway/3.5.3": {
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.5.2": {
69
+ "GxMcp.Gateway/3.5.3": {
70
70
  "type": "project",
71
71
  "serviceable": false,
72
72
  "sha512": ""
Binary file
Binary file
@@ -1,19 +1,19 @@
1
1
  {
2
- "Environment": {
3
- "ResolutionPolicy": "strict"
4
- },
5
2
  "GeneXus": {
6
3
  "WorkerExecutable": "worker\\\\GxMcp.Worker.exe",
7
4
  "InstallationPath": "C:\\Program Files (x86)\\GeneXus\\GeneXus18"
8
5
  },
9
- "ConfigSchemaVersion": 2,
6
+ "Environment": {
7
+ "ResolutionPolicy": "strict"
8
+ },
10
9
  "Server": {
11
10
  "SessionIdleTimeoutMinutes": 10,
12
- "HttpPort": 0,
13
- "TerseResponses": true,
14
- "McpStdio": true,
11
+ "EmitStructuredContent": false,
15
12
  "WorkerIdleTimeoutMinutes": 5,
16
- "EmitStructuredContent": false
13
+ "McpStdio": true,
14
+ "HttpPort": 0,
15
+ "TerseResponses": true
17
16
  },
17
+ "ConfigSchemaVersion": 2,
18
18
  "GatewayMode": "stdio-isolated"
19
19
  }
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "schemaVersion": "gxmcp-release-manifest/1",
3
- "version": "3.5.2",
4
- "sourceCommit": "7a7e6de34c078087186a7e0b1abd1cb87bc0cb07",
3
+ "version": "3.5.3",
4
+ "sourceCommit": "a4936251058358b0c5ee47745834f40c2e049073",
5
5
  "sourceCommitPolicy": "exact-tag",
6
- "generatedAtUtc": "2026-09-15T19:35:27.5122175Z",
6
+ "generatedAtUtc": "2026-09-16T02:19:28.3928043Z",
7
7
  "runtime": {
8
8
  "gateway": "net10.0-windows",
9
9
  "worker": "net48-x86",
@@ -15,33 +15,28 @@
15
15
  "2026-07-28"
16
16
  ],
17
17
  "schema": "tool_definitions.json",
18
- "schemaSha256": "933523c5d3b7719494226db977a20373446dcbc90b15685ff15eb56d1ed4bfe2",
18
+ "schemaSha256": "37db05de8cc994b9839682a94f6dce92a72e3060f8f146b91173a5f0b3e0d01d",
19
19
  "provenance": "gxmcp-sbom.json",
20
20
  "artifacts": [
21
21
  {
22
22
  "path": "gxmcp-sbom.json",
23
23
  "size": 590,
24
- "sha256": "d003f52ed89d53fd8e6a986ccc6726ac1ed4e2a094febc2ab8ba92350ef401b8"
24
+ "sha256": "21bb6a121a14d4837a879e984e31dee26ec607876728ecb290f1784a26374e4d"
25
25
  },
26
26
  {
27
27
  "path": "GxMcp.Gateway.exe",
28
28
  "size": 162304,
29
- "sha256": "6d2480ca6282ac9a8da08d880fff3d693805c224a0064eb3ab11593569d56a8d"
30
- },
31
- {
32
- "path": "nexus-ide.vsix",
33
- "size": 1318671,
34
- "sha256": "9fbfc3d402f0a0eb545ddbbd00850cee7651561dd5e44e64c582cf078a069729"
29
+ "sha256": "ac8598c50a5580f2b86d497600d60d51faa5c38e81b4f01d3e6da480937acf9f"
35
30
  },
36
31
  {
37
32
  "path": "tool_definitions.json",
38
- "size": 113695,
39
- "sha256": "933523c5d3b7719494226db977a20373446dcbc90b15685ff15eb56d1ed4bfe2"
33
+ "size": 116717,
34
+ "sha256": "37db05de8cc994b9839682a94f6dce92a72e3060f8f146b91173a5f0b3e0d01d"
40
35
  },
41
36
  {
42
37
  "path": "worker/GxMcp.Worker.exe",
43
- "size": 3146752,
44
- "sha256": "b85fb0326558d207e6c9595cb7991c2409b73fadd2e2517a98f15dca976289f6"
38
+ "size": 3163648,
39
+ "sha256": "bdb1452a05bfbe36254ae559613bc3a4b9d01ff2c63ee32c480f552077362f01"
45
40
  }
46
41
  ]
47
42
  }
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "schemaVersion": "gxmcp-provenance/1",
3
- "version": "3.5.2",
4
- "sourceCommit": "7a7e6de34c078087186a7e0b1abd1cb87bc0cb07",
3
+ "version": "3.5.3",
4
+ "sourceCommit": "a4936251058358b0c5ee47745834f40c2e049073",
5
5
  "sourceCommitPolicy": "exact-tag",
6
6
  "components": [
7
7
  {
8
8
  "name": "genexus-mcp",
9
9
  "lockfile": "package-lock.json",
10
10
  "size": 39914,
11
- "sha256": "b98fd8f9211c9b6bc8ea7805902d0dae7a26574618c35b365b27f36fe92708bf"
11
+ "sha256": "917bb4c603907353638848605f923989b02f21210fa67463aefa1deeba4a553b"
12
12
  },
13
13
  {
14
14
  "name": "nexus-ide",
15
15
  "lockfile": "src/nexus-ide/package-lock.json",
16
16
  "size": 274983,
17
- "sha256": "c7dbd3f89cf6258d365f6d40ab7935138e89a90e102af7a258a1d4bf51f72513"
17
+ "sha256": "1d1227f6e14d80bff122ff94343eb9923a0470e469e9102d28e43e0c3f103c23"
18
18
  }
19
19
  ]
20
20
  }
@@ -5,10 +5,10 @@
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. 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."},"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}]},"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. 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"},"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"}]},"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":{"description":"Shorthand for {find,replace}. Equivalent to operation=Replace + context=find + content=replace."},"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)."},"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: restore a valid pre-write snapshot when post-save verification or validationMode=specify fails. No rollback occurs when false or omitted."},"requireObjectSave":{"type":"boolean","default":false,"description":"Events patch complete-save requirement. dryRun remains available; real writes are blocked before persistence with ObjectSaveIsolationUnverified until SDK/pattern save-event isolation is established. No override. baseVersion remains required for a real write."},"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 for patch mode. Source/Rules default to normalized (EOL, encoding marker, trailing whitespace and repeated blank lines); exact preserves logical text but treats CRLF/LF as the same SDK Source rendering; semantic also tolerates SDK casing/spacing format changes. Comment-only Replace writes require baseVersion and return CommentOnlyWriteNotPersisted on a divergent forced re-read. The part is always re-read after Save."},"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}]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"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} on mode=patch: 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)."},"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: restore a valid pre-write snapshot when post-save verification or validationMode=specify fails. No rollback occurs when false or omitted."},"requireObjectSave":{"type":"boolean","default":false,"description":"Events patch complete-save requirement. dryRun remains available; real writes are blocked before persistence with ObjectSaveIsolationUnverified until SDK/pattern save-event isolation is established. No override. baseVersion remains required for a real write."},"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 for patch mode. Source/Rules default to normalized (EOL, encoding marker, trailing whitespace and repeated blank lines); exact preserves logical text but treats CRLF/LF as the same SDK Source rendering; semantic also tolerates SDK casing/spacing format changes. Comment-only Replace writes require baseVersion and return CommentOnlyWriteNotPersisted on a divergent forced re-read. The part is always re-read after Save."},"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
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=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","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: continuation cursor returned by a budgeted context page."},"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
- {"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."},"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)."},"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."},"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}},
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."},"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)."},"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/."}},"examples":[{},{"mode":"capabilities"}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},
14
14
  {"name":"genexus_worker_reload","description":"Reload worker. mode=soft drains and respawns; mode=hard copies sourceDir during the drain window and respawns. force=true: gateway kills directly. See tool-help.","inputSchema":{"type":"object","properties":{"mode":{"type":"string","enum":["soft","hard"]},"force":{"type":"boolean","description":"Bypass drain; gateway kills + respawns. Use when worker is wedged."},"sourceDir":{"type":"string","description":"Required for mode=hard."},"drainTimeoutMs":{"type":"integer","description":"Soft only; default 30000."},"alias":{"type":"string","description":"KB alias to reload when more than one worker is open."},"kb":{"type":"string","description":"Alias of alias."}},"examples":[{"mode":"soft"},{"mode":"hard","sourceDir":"C:\\Projetos\\Genexus18MCP\\src\\GxMcp.Worker\\bin\\Debug"}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":true}},
Binary file
Binary file