genexus-mcp 2.57.0 → 3.0.1
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 +31 -17
- package/cli/lib/config.js +8 -12
- package/cli/run.test.js +76 -36
- package/docs/llm_cli_mcp_playbook.md +7 -0
- package/package.json +2 -2
- package/publish/GxMcp.Gateway.deps.json +9 -9
- package/publish/GxMcp.Gateway.dll +0 -0
- package/publish/GxMcp.Gateway.exe +0 -0
- package/publish/GxMcp.Gateway.runtimeconfig.json +3 -3
- package/publish/Newtonsoft.Json.dll +0 -0
- package/publish/System.CodeDom.dll +0 -0
- package/publish/System.Management.dll +0 -0
- package/publish/System.Security.Permissions.dll +0 -0
- package/publish/System.Windows.Extensions.dll +0 -0
- package/publish/config.json +6 -6
- package/publish/gxmcp-manifest.json +47 -0
- package/publish/gxmcp-sbom.json +20 -0
- package/publish/nexus-ide.vsix +0 -0
- package/publish/tool_definitions.json +7 -7
- package/publish/worker/GxMcp.Worker.exe +0 -0
- package/scripts/verify-install.js +15 -1
package/README.md
CHANGED
|
@@ -183,6 +183,7 @@ Once installed, here's what unlocks. Try these as your first prompts:
|
|
|
183
183
|
- *"Add a menu option 'Customers' to MainMenu that opens CustomerWW."*
|
|
184
184
|
|
|
185
185
|
**WorkWithPlus pattern editing** (full structural + theming control)
|
|
186
|
+
- *"Add a typed tab with variables, an action, and nested responsive tables to a WorkWithPlus WebPanel."*
|
|
186
187
|
- *"In WorkWithPlusOrder, add a 'Duplicate' button to the transaction view alongside Save/Cancel/Delete."*
|
|
187
188
|
- *"Group the Customer transaction attributes into a 'Contact Info' section with theme class GroupTelaResp."*
|
|
188
189
|
- *"On the WorkWithPlusInvoice list, add a new ordering by InvoiceDate descending."*
|
|
@@ -217,25 +218,17 @@ Auto-detected and auto-configured by the installer:
|
|
|
217
218
|
| OpenCode (CLI) | ✅ | Reads both direct and nested MCP layouts; restart required |
|
|
218
219
|
| Codex CLI | ✅ | Writes `~/.codex/config.toml` |
|
|
219
220
|
| VS Code / VS Code Insiders | ✅ | Native MCP (`User/mcp.json`); restart required |
|
|
220
|
-
| OpenCode Desktop |
|
|
221
|
+
| OpenCode Desktop | ✅ | Shares `opencode.jsonc` with OpenCode CLI; restart required |
|
|
221
222
|
| Any MCP client | Manual | Use the JSON snippet printed by `init` |
|
|
222
223
|
|
|
223
224
|
Run **`npx genexus-mcp clients`** at any time to see which agents are installed, which have `genexus` registered, and whether any point at a stale gateway exe. To (re)register specific ones: `npx genexus-mcp clients add --clients antigravity,vscode`.
|
|
224
225
|
|
|
225
|
-
### OpenCode Desktop
|
|
226
|
+
### OpenCode Desktop
|
|
226
227
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
- Name: `genexus18mcp`
|
|
232
|
-
- Command: `npx.cmd` on Windows, `npx` elsewhere
|
|
233
|
-
- Arguments: `-y genexus-mcp@latest`
|
|
234
|
-
- Environment: `GX_CONFIG_PATH=<the config.json path printed by init>`
|
|
235
|
-
|
|
236
|
-
Save the server, fully restart OpenCode Desktop, and call `genexus_whoami` to
|
|
237
|
-
verify the GeneXus server and selected KB. The CLI intentionally leaves the
|
|
238
|
-
Desktop-managed configuration file untouched.
|
|
228
|
+
OpenCode Desktop shares its MCP configuration file (`opencode.jsonc` or `opencode.json`)
|
|
229
|
+
with OpenCode CLI. Running `genexus-mcp init --write-clients` or `genexus-mcp clients add --clients opencode-desktop`
|
|
230
|
+
automatically registers `genexus18mcp` in the shared config. After registration,
|
|
231
|
+
fully restart OpenCode Desktop so it reloads its MCP configuration.
|
|
239
232
|
|
|
240
233
|
---
|
|
241
234
|
|
|
@@ -313,7 +306,7 @@ produced by `DataSelectorStructurePart.ToString()` on U16.
|
|
|
313
306
|
**Refactor, patterns & compare**
|
|
314
307
|
- `genexus_refactor` — rename, extract procedure, WWP condition set
|
|
315
308
|
- `genexus_apply_pattern` — apply a GeneXus pattern (WorkWith, WorkWithPlus, …); `mode=actions` manages typed WorkWithPlus grid actions and Action Groups
|
|
316
|
-
- `genexus_wwp` — WorkWithPlus Action
|
|
309
|
+
- `genexus_wwp` — typed WorkWithPlus editing: Action Groups, atomic native `add_grid_attribute`, plus `add_tab`, `move_tab`, and `remove_tab` for WebPanel tabs and typed children
|
|
317
310
|
- `genexus_compare` — IDE "Compare Objects" parity (`IComparerService`)
|
|
318
311
|
- `genexus_merge` — 2- or 3-way object merge (`IMergeService`)
|
|
319
312
|
|
|
@@ -324,7 +317,7 @@ produced by `DataSelectorStructurePart.ToString()` on U16.
|
|
|
324
317
|
- `genexus_security` — audit KB security: `audit_gam` (env/GAM props), `scan_secrets` (regex over Source), `scan_native` (the SDK's own Security Scanner, `ISecurityScannerService`)
|
|
325
318
|
|
|
326
319
|
**Lifecycle, build, test & DB**
|
|
327
|
-
- `genexus_lifecycle` — build (incl. `compile_check`), validate, index, reorg, poll status
|
|
320
|
+
- `genexus_lifecycle` — directed `build` (incl. `compile_check`), incremental global `build_all`, forced global `rebuild`, validate, index, reorg, and poll status
|
|
328
321
|
- `genexus_test` — run native GXtest tests
|
|
329
322
|
- `genexus_db` — DB umbrella: schema-drift, `sql_ddl`/`sql_navigation`, static index advisor, `sample_data`, typed Transaction record query/insert/update with dry-run, optimistic versioning, reread and verified rollback, Domain/SDT type introspection, translation import, `reorg_impact`, and non-mutating `reorg_preview` with exact DDL only from a current Impact Analysis artifact
|
|
330
323
|
- `genexus_deploy` — deploy application (`IDeploymentService`): `list_targets` (read) / `deploy` (destructive, `confirm=true`)
|
|
@@ -378,6 +371,8 @@ WorkWithPlus patterns are XML documents that drive Transaction-and-Selection scr
|
|
|
378
371
|
| Reorganize Transaction view (form layout, action row) | edit under `/instance/transaction/...` | ✅ verified live |
|
|
379
372
|
| Reorganize Selection view (list/grid, filters, orders) | edit under `/instance/level/selection/...` | ✅ verified live |
|
|
380
373
|
| Auto-rebuild `childrenOrderedList` from XML order | done implicitly on every write; report under `childrenOrderedListReconciliation` | ✅ verified live |
|
|
374
|
+
| Add / move / remove WebPanel tabs and typed controls | `genexus_wwp` `add_tab` / `move_tab` / `remove_tab` | ✅ native Pattern SDK commands; snapshot + re-read + WebForm projection verification |
|
|
375
|
+
| Add or reconcile one grid Attribute caption | `genexus_wwp` `add_grid_attribute` | ✅ isolated dry-run, full PatternInstance/WebForm snapshots, exact rollback and no implicit lifecycle |
|
|
381
376
|
|
|
382
377
|
**Recommended workflow for a screen redesign:**
|
|
383
378
|
|
|
@@ -389,6 +384,25 @@ WorkWithPlus patterns are XML documents that drive Transaction-and-Selection scr
|
|
|
389
384
|
|
|
390
385
|
**Custom buttons use `<userAction>`, not `<standardAction>`.** `Trn_Enter` / `Trn_Cancel` / `Trn_Delete` are the only registered standard actions on a WorkWithPlus transaction; any custom button (Duplicate, Audit, Export, etc.) must be a `<userAction caption="…" name="…" buttonClass="btn ButtonGreen" confirm="False" />`. The MCP's reconciler treats `<userAction>` as a peer of `<standardAction>` (same typeCode 17/18 by context), so they coexist in the same `TableActions` row and the IDE renders them side-by-side.
|
|
391
386
|
|
|
387
|
+
For WebPanel tabs, prefer the native typed operation instead of whole-XML replacement:
|
|
388
|
+
|
|
389
|
+
```json
|
|
390
|
+
{
|
|
391
|
+
"action": "add_tab",
|
|
392
|
+
"name": "SamplePanel",
|
|
393
|
+
"controlName": "IntegrationV3",
|
|
394
|
+
"title": "Integration API V3",
|
|
395
|
+
"position": 5,
|
|
396
|
+
"children": [
|
|
397
|
+
{ "type": "variable", "name": "Operation", "basicType": "VarChar", "length": 40 },
|
|
398
|
+
{ "type": "userAction", "name": "SendIntegration", "caption": "Send" }
|
|
399
|
+
],
|
|
400
|
+
"dryRun": true
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
The dry-run returns a typed diff and `versionToken`. Pass it as `baseVersion` on the persisted call. The write uses Pattern SDK element commands, requires exact PatternInstance/WebForm snapshots, preserves Apply-on-save, re-reads the PatternInstance, projects and re-reads the parent WebForm, and rolls both parts back on any failed confirmation. It never invokes lifecycle operations.
|
|
405
|
+
|
|
392
406
|
**Things to know (orientation, not gotchas):**
|
|
393
407
|
|
|
394
408
|
- **WorkWithPlus normalizes some attributes after every save.** Certain fields are bound to the underlying transaction (e.g., `title` on top-level groups derives from the transaction's friendly name). When `"Apply this pattern on save"` is enabled on the WorkWithPlus object, the engine recomputes those fields — same behavior whether you edit in the IDE or via MCP. To make a hard override stick, toggle that flag via MCP:
|
|
@@ -498,7 +512,7 @@ When the pool is full and no Worker is idle, the server returns `KB_POOL_FULL`
|
|
|
498
512
|
|
|
499
513
|
```mermaid
|
|
500
514
|
graph LR
|
|
501
|
-
A[AI Client / Nexus-IDE] -->|MCP stdio or HTTP /mcp| B[Gateway .NET
|
|
515
|
+
A[AI Client / Nexus-IDE] -->|MCP stdio or HTTP /mcp| B[Gateway .NET 10]
|
|
502
516
|
B -->|JSON-RPC over process boundary| C[Worker .NET Framework 4.8]
|
|
503
517
|
C -->|Native SDK| D[GeneXus KB]
|
|
504
518
|
```
|
package/cli/lib/config.js
CHANGED
|
@@ -650,13 +650,9 @@ function getClientConfigTargets() {
|
|
|
650
650
|
{
|
|
651
651
|
id: 'opencode-desktop',
|
|
652
652
|
name: 'OpenCode Desktop',
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
format: 'manual',
|
|
657
|
-
writeSupported: false,
|
|
658
|
-
manualNote: 'OpenCode Desktop manual setup: Settings > MCP > Add server > Local; name genexus18mcp; command npx.cmd on Windows (npx elsewhere); args -y genexus-mcp@latest; environment GX_CONFIG_PATH=<config.json path printed by init>; save, fully restart the app, then call genexus_whoami. The CLI does not write the app-managed Desktop mcp.json.',
|
|
659
|
-
path: path.join(appData, 'ai.opencode.desktop', 'mcp.json'),
|
|
653
|
+
format: 'opencode',
|
|
654
|
+
path: resolveOpenCodeConfigPath(xdgConfig),
|
|
655
|
+
detectByMarkerOnly: true,
|
|
660
656
|
installMarkers: [
|
|
661
657
|
path.join(localAppData, 'Programs', '@opencode-aidesktop'),
|
|
662
658
|
path.join(appData, 'ai.opencode.desktop'),
|
|
@@ -693,8 +689,9 @@ function detectClientInstalled(client) {
|
|
|
693
689
|
break;
|
|
694
690
|
}
|
|
695
691
|
}
|
|
692
|
+
const installed = client.detectByMarkerOnly ? (markerHit !== null) : (hasConfig || markerHit !== null);
|
|
696
693
|
return {
|
|
697
|
-
installed
|
|
694
|
+
installed,
|
|
698
695
|
hasConfig,
|
|
699
696
|
markerHit,
|
|
700
697
|
markersChecked: markers
|
|
@@ -808,9 +805,8 @@ function patchClientConfig(targetConfigPath, opts = {}) {
|
|
|
808
805
|
platform: process.platform
|
|
809
806
|
});
|
|
810
807
|
|
|
811
|
-
// A direct gateway path only matters to clients that can be written.
|
|
812
|
-
// detect-only client
|
|
813
|
-
// setup guidance when its app-managed config is not detectable.
|
|
808
|
+
// A direct gateway path only matters to clients that can be written. Any
|
|
809
|
+
// detect-only client must still receive manual setup guidance when not writable.
|
|
814
810
|
const writableCandidates = candidates.filter((client) =>
|
|
815
811
|
client.writeSupported !== false
|
|
816
812
|
&& (!onlyExisting || detectClientInstalled(client).installed)
|
|
@@ -831,7 +827,7 @@ function patchClientConfig(targetConfigPath, opts = {}) {
|
|
|
831
827
|
const skipped = [];
|
|
832
828
|
|
|
833
829
|
for (const client of candidates) {
|
|
834
|
-
// Detect-only agents
|
|
830
|
+
// Detect-only agents can't be auto-written; surface
|
|
835
831
|
// the manual step instead of pretending we registered them.
|
|
836
832
|
if (client.writeSupported === false) {
|
|
837
833
|
const detection = detectClientInstalled(client);
|
package/cli/run.test.js
CHANGED
|
@@ -791,7 +791,7 @@ test('clients list returns structured status with summary', () => {
|
|
|
791
791
|
assert.equal(typeof row.registered, 'boolean');
|
|
792
792
|
});
|
|
793
793
|
|
|
794
|
-
test('clients list reports OpenCode Desktop
|
|
794
|
+
test('clients list reports OpenCode Desktop with shared opencode config', () => {
|
|
795
795
|
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-opencode-desktop-status-'));
|
|
796
796
|
try {
|
|
797
797
|
const env = sandboxHomeEnv(tempRoot);
|
|
@@ -803,70 +803,85 @@ test('clients list reports OpenCode Desktop as manual with exact setup fields',
|
|
|
803
803
|
assert.ok(row, 'OpenCode Desktop should be listed');
|
|
804
804
|
assert.equal(row.installed, true);
|
|
805
805
|
assert.equal(row.registered, false);
|
|
806
|
-
assert.equal(row.writeSupported,
|
|
807
|
-
assert.equal(row.registrationMode, '
|
|
808
|
-
assert.equal(row.manualSetup
|
|
809
|
-
assert.
|
|
810
|
-
assert.equal(row.
|
|
811
|
-
|
|
812
|
-
|
|
806
|
+
assert.equal(row.writeSupported, true);
|
|
807
|
+
assert.equal(row.registrationMode, 'automatic');
|
|
808
|
+
assert.equal(row.manualSetup, null);
|
|
809
|
+
assert.equal(row.note, null);
|
|
810
|
+
assert.equal(row.configPath, path.join(env.XDG_CONFIG_HOME, 'opencode', 'opencode.json'));
|
|
811
|
+
|
|
812
|
+
// When the shared opencode.jsonc has the server registered, Desktop is recognized as registered
|
|
813
|
+
const opencodeCfg = path.join(env.XDG_CONFIG_HOME, 'opencode', 'opencode.jsonc');
|
|
814
|
+
fs.mkdirSync(path.dirname(opencodeCfg), { recursive: true });
|
|
815
|
+
fs.writeFileSync(opencodeCfg, JSON.stringify({
|
|
816
|
+
mcp: {
|
|
817
|
+
genexus18mcp: {
|
|
818
|
+
type: 'local',
|
|
819
|
+
command: ['npx.cmd', '-y', 'genexus-mcp@latest'],
|
|
820
|
+
environment: { GX_CONFIG_PATH: 'C:\\test\\config.json' }
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
}, null, 2));
|
|
824
|
+
|
|
825
|
+
const resultRegistered = runCli(['clients', '--format', 'json'], { env });
|
|
826
|
+
assert.equal(resultRegistered.status, 0);
|
|
827
|
+
const rowRegistered = JSON.parse(resultRegistered.stdout).ok.clients.find((client) => client.id === 'opencode-desktop');
|
|
828
|
+
assert.equal(rowRegistered.installed, true);
|
|
829
|
+
assert.equal(rowRegistered.registered, true);
|
|
830
|
+
assert.equal(rowRegistered.command, 'npx.cmd');
|
|
831
|
+
assert.equal(rowRegistered.configPath, opencodeCfg);
|
|
832
|
+
assert.equal(rowRegistered.registrationMode, 'automatic');
|
|
813
833
|
} finally {
|
|
814
834
|
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
815
835
|
}
|
|
816
836
|
});
|
|
817
837
|
|
|
818
|
-
test('clients add
|
|
838
|
+
test('clients add patches OpenCode Desktop into shared opencode config', () => {
|
|
819
839
|
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-opencode-desktop-add-'));
|
|
820
840
|
try {
|
|
821
841
|
const env = sandboxHomeEnv(tempRoot);
|
|
822
842
|
const cfgPath = path.join(tempRoot, 'config.json');
|
|
823
843
|
const desktopDir = path.join(env.APPDATA, 'ai.opencode.desktop');
|
|
824
|
-
const desktopConfig = path.join(desktopDir, 'mcp.json');
|
|
825
|
-
const original = { unrelated: { keep: true } };
|
|
826
844
|
fs.writeFileSync(cfgPath, JSON.stringify({ Environment: { KBPath: tempRoot } }));
|
|
827
845
|
fs.mkdirSync(desktopDir, { recursive: true });
|
|
828
|
-
fs.writeFileSync(desktopConfig, JSON.stringify(original, null, 2));
|
|
829
846
|
|
|
830
847
|
const result = runCli(['clients', 'add', '--clients', 'opencode-desktop', '--format', 'json'], {
|
|
831
848
|
env: { ...env, GX_CONFIG_PATH: cfgPath }
|
|
832
849
|
});
|
|
833
850
|
assert.equal(result.status, 0);
|
|
834
851
|
const parsed = JSON.parse(result.stdout);
|
|
835
|
-
assert.
|
|
836
|
-
const
|
|
837
|
-
assert.ok(
|
|
838
|
-
|
|
839
|
-
assert.
|
|
840
|
-
assert.equal(
|
|
841
|
-
|
|
842
|
-
|
|
852
|
+
assert.ok(parsed.ok.patchedClients.includes('OpenCode Desktop'));
|
|
853
|
+
const opencodeCfg = path.join(env.XDG_CONFIG_HOME, 'opencode', 'opencode.json');
|
|
854
|
+
assert.ok(fs.existsSync(opencodeCfg), 'shared opencode config should be created');
|
|
855
|
+
const written = JSON.parse(fs.readFileSync(opencodeCfg, 'utf8'));
|
|
856
|
+
assert.ok(written.mcp.genexus18mcp, 'shared config should contain genexus18mcp entry');
|
|
857
|
+
assert.equal(written.mcp.genexus18mcp.environment.GX_CONFIG_PATH, cfgPath);
|
|
858
|
+
|
|
859
|
+
const listRes = runCli(['clients', '--format', 'json'], { env });
|
|
860
|
+
const row = JSON.parse(listRes.stdout).ok.clients.find((client) => client.id === 'opencode-desktop');
|
|
861
|
+
assert.ok(row && row.registered, 'OpenCode Desktop should now report registered');
|
|
843
862
|
} finally {
|
|
844
863
|
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
845
864
|
}
|
|
846
865
|
});
|
|
847
866
|
|
|
848
|
-
test('
|
|
867
|
+
test('OpenCode Desktop is not falsely reported as installed when only CLI config exists', () => {
|
|
849
868
|
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-opencode-desktop-undetected-'));
|
|
850
869
|
try {
|
|
851
870
|
const env = sandboxHomeEnv(tempRoot);
|
|
852
|
-
const
|
|
853
|
-
fs.
|
|
871
|
+
const opencodeCfg = path.join(env.XDG_CONFIG_HOME, 'opencode', 'opencode.jsonc');
|
|
872
|
+
fs.mkdirSync(path.dirname(opencodeCfg), { recursive: true });
|
|
873
|
+
fs.writeFileSync(opencodeCfg, JSON.stringify({ mcp: {} }));
|
|
854
874
|
|
|
855
|
-
const result = runCli(['clients', '
|
|
856
|
-
env: {
|
|
857
|
-
...env,
|
|
858
|
-
GX_CONFIG_PATH: cfgPath,
|
|
859
|
-
GENEXUS_MCP_GATEWAY_EXE: path.join(tempRoot, 'missing', 'GxMcp.Gateway.exe')
|
|
860
|
-
}
|
|
861
|
-
});
|
|
875
|
+
const result = runCli(['clients', '--format', 'json'], { env });
|
|
862
876
|
assert.equal(result.status, 0);
|
|
863
877
|
const parsed = JSON.parse(result.stdout);
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
assert.
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
assert.
|
|
878
|
+
const desktopRow = parsed.ok.clients.find((client) => client.id === 'opencode-desktop');
|
|
879
|
+
assert.ok(desktopRow, 'OpenCode Desktop should be present in targets');
|
|
880
|
+
assert.equal(desktopRow.installed, false, 'Desktop must not be detected installed without its install markers');
|
|
881
|
+
|
|
882
|
+
const cliRow = parsed.ok.clients.find((client) => client.id === 'opencode');
|
|
883
|
+
assert.ok(cliRow, 'OpenCode CLI should be present in targets');
|
|
884
|
+
assert.equal(cliRow.installed, true, 'OpenCode CLI is detected installed via config file');
|
|
870
885
|
} finally {
|
|
871
886
|
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
872
887
|
}
|
|
@@ -1133,6 +1148,31 @@ test('init auto-registers detected OpenCode in either config layout', () => {
|
|
|
1133
1148
|
}
|
|
1134
1149
|
});
|
|
1135
1150
|
|
|
1151
|
+
test('init auto-registers detected OpenCode Desktop when its marker is present', () => {
|
|
1152
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-opencode-desktop-init-'));
|
|
1153
|
+
try {
|
|
1154
|
+
const env = sandboxHomeEnv(tempRoot);
|
|
1155
|
+
const kbDir = path.join(tempRoot, 'kb');
|
|
1156
|
+
fs.mkdirSync(kbDir, { recursive: true });
|
|
1157
|
+
fs.mkdirSync(path.join(env.APPDATA, 'ai.opencode.desktop'), { recursive: true });
|
|
1158
|
+
|
|
1159
|
+
const result = runCli(
|
|
1160
|
+
['init', '--kb', kbDir, '--gx', testGxPath, '--no-smoke', '--format', 'json'],
|
|
1161
|
+
{ cwd: kbDir, env: { ...env, ...testGatewayEnv } }
|
|
1162
|
+
);
|
|
1163
|
+
assert.equal(result.status, 0, `init should succeed: ${result.stderr}`);
|
|
1164
|
+
|
|
1165
|
+
const parsed = JSON.parse(result.stdout);
|
|
1166
|
+
assert.ok(parsed.meta.patchedClients.includes('OpenCode Desktop'));
|
|
1167
|
+
const openCodeCfg = path.join(env.XDG_CONFIG_HOME, 'opencode', 'opencode.json');
|
|
1168
|
+
assert.ok(fs.existsSync(openCodeCfg));
|
|
1169
|
+
const written = JSON.parse(fs.readFileSync(openCodeCfg, 'utf8'));
|
|
1170
|
+
assert.ok(written.mcp.genexus18mcp);
|
|
1171
|
+
} finally {
|
|
1172
|
+
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
1173
|
+
}
|
|
1174
|
+
});
|
|
1175
|
+
|
|
1136
1176
|
test('clients add replaces a legacy genexus18 entry instead of duplicating it', () => {
|
|
1137
1177
|
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'genexus-mcp-legacy-'));
|
|
1138
1178
|
const env = sandboxHomeEnv(tempRoot);
|
|
@@ -124,6 +124,13 @@ Follow-up flow:
|
|
|
124
124
|
|
|
125
125
|
Do not treat timeout as hard failure when `operationId` is present.
|
|
126
126
|
|
|
127
|
+
For a complete incremental build of the selected Knowledge Base, use
|
|
128
|
+
`genexus_lifecycle(action='build_all')` without `target`. It runs the native
|
|
129
|
+
`BuildAll` task when available, reports completion evidence, and returns
|
|
130
|
+
`ReorgRequired` instead of applying a schema reorganization implicitly. Use
|
|
131
|
+
`action='build'` for a directed target and `action='rebuild'` for the forced
|
|
132
|
+
Rebuild All contract.
|
|
133
|
+
|
|
127
134
|
## Pagination and Token Budgeting
|
|
128
135
|
|
|
129
136
|
Read/list defaults are intentionally broad for humans, but not for LLMs.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genexus-mcp",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"mcpName": "io.github.lennix1337/genexus",
|
|
5
5
|
"description": "GeneXus 18 MCP server — read, edit, and analyze GeneXus knowledge base objects (transactions, web panels, procedures, SDTs) directly from Claude, Cursor, and other AI agents over the Model Context Protocol.",
|
|
6
6
|
"keywords": [
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"win32"
|
|
51
51
|
],
|
|
52
52
|
"engines": {
|
|
53
|
-
"node": ">=
|
|
53
|
+
"node": ">=22.0.0"
|
|
54
54
|
},
|
|
55
55
|
"author": "lennix1337",
|
|
56
56
|
"license": "MIT",
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"runtimeTarget": {
|
|
3
|
-
"name": ".NETCoreApp,Version=
|
|
3
|
+
"name": ".NETCoreApp,Version=v10.0/win-x64",
|
|
4
4
|
"signature": ""
|
|
5
5
|
},
|
|
6
6
|
"compilationOptions": {},
|
|
7
7
|
"targets": {
|
|
8
|
-
".NETCoreApp,Version=
|
|
9
|
-
".NETCoreApp,Version=
|
|
10
|
-
"GxMcp.Gateway/
|
|
8
|
+
".NETCoreApp,Version=v10.0": {},
|
|
9
|
+
".NETCoreApp,Version=v10.0/win-x64": {
|
|
10
|
+
"GxMcp.Gateway/3.0.1": {
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"Newtonsoft.Json": "13.0.3",
|
|
13
13
|
"System.Management": "10.0.5",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"System.CodeDom/10.0.5": {
|
|
29
29
|
"runtime": {
|
|
30
|
-
"lib/
|
|
30
|
+
"lib/net10.0/System.CodeDom.dll": {
|
|
31
31
|
"assemblyVersion": "10.0.0.0",
|
|
32
32
|
"fileVersion": "10.0.526.15411"
|
|
33
33
|
}
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"System.CodeDom": "10.0.5"
|
|
39
39
|
},
|
|
40
40
|
"runtime": {
|
|
41
|
-
"runtimes/win/lib/
|
|
41
|
+
"runtimes/win/lib/net10.0/System.Management.dll": {
|
|
42
42
|
"assemblyVersion": "10.0.0.5",
|
|
43
43
|
"fileVersion": "10.0.526.15411"
|
|
44
44
|
}
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"System.Windows.Extensions": "10.0.3"
|
|
50
50
|
},
|
|
51
51
|
"runtime": {
|
|
52
|
-
"lib/
|
|
52
|
+
"lib/net10.0/System.Security.Permissions.dll": {
|
|
53
53
|
"assemblyVersion": "10.0.0.0",
|
|
54
54
|
"fileVersion": "10.0.326.7603"
|
|
55
55
|
}
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
},
|
|
58
58
|
"System.Windows.Extensions/10.0.3": {
|
|
59
59
|
"runtime": {
|
|
60
|
-
"runtimes/win/lib/
|
|
60
|
+
"runtimes/win/lib/net10.0/System.Windows.Extensions.dll": {
|
|
61
61
|
"assemblyVersion": "10.0.0.0",
|
|
62
62
|
"fileVersion": "10.0.326.7603"
|
|
63
63
|
}
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
}
|
|
67
67
|
},
|
|
68
68
|
"libraries": {
|
|
69
|
-
"GxMcp.Gateway/
|
|
69
|
+
"GxMcp.Gateway/3.0.1": {
|
|
70
70
|
"type": "project",
|
|
71
71
|
"serviceable": false,
|
|
72
72
|
"sha512": ""
|
|
Binary file
|
|
Binary file
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"runtimeOptions": {
|
|
3
|
-
"tfm": "
|
|
3
|
+
"tfm": "net10.0",
|
|
4
4
|
"frameworks": [
|
|
5
5
|
{
|
|
6
6
|
"name": "Microsoft.NETCore.App",
|
|
7
|
-
"version": "
|
|
7
|
+
"version": "10.0.0"
|
|
8
8
|
},
|
|
9
9
|
{
|
|
10
10
|
"name": "Microsoft.AspNetCore.App",
|
|
11
|
-
"version": "
|
|
11
|
+
"version": "10.0.0"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
14
14
|
"configProperties": {
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/publish/config.json
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
"Environment": {
|
|
3
3
|
"KBPath": "C:\\\\KBs\\\\YourKB"
|
|
4
4
|
},
|
|
5
|
+
"GeneXus": {
|
|
6
|
+
"WorkerExecutable": "worker\\\\GxMcp.Worker.exe",
|
|
7
|
+
"InstallationPath": "C:\\\\Program Files (x86)\\\\GeneXus\\\\GeneXus18"
|
|
8
|
+
},
|
|
5
9
|
"Logging": {
|
|
6
|
-
"
|
|
7
|
-
"
|
|
10
|
+
"Level": "Debug",
|
|
11
|
+
"Path": "logs"
|
|
8
12
|
},
|
|
9
13
|
"Server": {
|
|
10
14
|
"HttpPort": 5000,
|
|
11
15
|
"McpStdio": true
|
|
12
|
-
},
|
|
13
|
-
"GeneXus": {
|
|
14
|
-
"InstallationPath": "C:\\\\Program Files (x86)\\\\GeneXus\\\\GeneXus18",
|
|
15
|
-
"WorkerExecutable": "worker\\\\GxMcp.Worker.exe"
|
|
16
16
|
}
|
|
17
17
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "gxmcp-release-manifest/1",
|
|
3
|
+
"version": "3.0.1",
|
|
4
|
+
"sourceCommit": "16737be62b087071a46744b64fb406ae1c092d1c",
|
|
5
|
+
"sourceCommitPolicy": "exact-tag",
|
|
6
|
+
"generatedAtUtc": "2026-09-07T15:00:21.7001814Z",
|
|
7
|
+
"runtime": {
|
|
8
|
+
"gateway": "net10.0-windows",
|
|
9
|
+
"worker": "net48-x86",
|
|
10
|
+
"node": ">=22.0.0",
|
|
11
|
+
"recommendedNode": "24 LTS"
|
|
12
|
+
},
|
|
13
|
+
"protocolVersions": [
|
|
14
|
+
"2025-11-25",
|
|
15
|
+
"2026-07-28"
|
|
16
|
+
],
|
|
17
|
+
"schema": "tool_definitions.json",
|
|
18
|
+
"schemaSha256": "98f4680e9da9505db5be670e3562002a114bbcfd2bf56703ce1d7424abb431aa",
|
|
19
|
+
"provenance": "gxmcp-sbom.json",
|
|
20
|
+
"artifacts": [
|
|
21
|
+
{
|
|
22
|
+
"path": "gxmcp-sbom.json",
|
|
23
|
+
"size": 590,
|
|
24
|
+
"sha256": "de0f58d64013a142aced1f70041f14d615bef52e80fec702308fedbe20645c7c"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"path": "GxMcp.Gateway.exe",
|
|
28
|
+
"size": 162304,
|
|
29
|
+
"sha256": "10612de14e9bf693ffbebb2d4dacfd9f4964978be3a839ecc1d2a27655b79b78"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"path": "nexus-ide.vsix",
|
|
33
|
+
"size": 1318668,
|
|
34
|
+
"sha256": "d119604573da301222e78694a73cc18dd82ac86cba6b5eac5c891f3a45a1294e"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"path": "tool_definitions.json",
|
|
38
|
+
"size": 104391,
|
|
39
|
+
"sha256": "98f4680e9da9505db5be670e3562002a114bbcfd2bf56703ce1d7424abb431aa"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"path": "worker/GxMcp.Worker.exe",
|
|
43
|
+
"size": 2848768,
|
|
44
|
+
"sha256": "0ec449681a26738a247a52e8f50e13bd203311a3acf34ca7868b22d150f31554"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "gxmcp-provenance/1",
|
|
3
|
+
"version": "3.0.1",
|
|
4
|
+
"sourceCommit": "16737be62b087071a46744b64fb406ae1c092d1c",
|
|
5
|
+
"sourceCommitPolicy": "exact-tag",
|
|
6
|
+
"components": [
|
|
7
|
+
{
|
|
8
|
+
"name": "genexus-mcp",
|
|
9
|
+
"lockfile": "package-lock.json",
|
|
10
|
+
"size": 39914,
|
|
11
|
+
"sha256": "417f4f5e2cf75646bf5a3cb2eed8d454553b6ddcec617bc81daf63f8f40a060a"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "nexus-ide",
|
|
15
|
+
"lockfile": "src/nexus-ide/package-lock.json",
|
|
16
|
+
"size": 274983,
|
|
17
|
+
"sha256": "11d8e03bfc38157c3621315a56ed9f5dbe7c1410c3e9765da13326005eeb4fdb"
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
Binary file
|
|
@@ -5,12 +5,12 @@
|
|
|
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}},"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","items":{"type":"object","properties":{"name":{"type":"string"},"content":{"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."},"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."}},"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":{"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."},"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"}}}},"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}},
|
|
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."}},"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 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 preserves the legacy compatibility envelope and returns NotImplemented until a typed code explanation is available. Requires Ready index for impact/callers.","inputSchema":{"type":"object","properties":{"name":{"type":"string"},"mode":{"type":"string","enum":["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"]},"format":{"type":"string","enum":["json","ascii"],"description":"mode=dependency_heatmap: ascii adds rendered bar chart."},"kb":{"type":"string","description":"KB alias."},"waitForIndex":{"type":"boolean","description":"mode=impact: block up to 30s for Ready index (default true).","default":true}},"required":["mode"],"examples":[{"name":"Customer","mode":"impact"},{"name":"Customer","mode":"summary"}]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},
|
|
11
|
-
{"name":"genexus_lifecycle","description":"Build, validate, index, or poll the KB. action=
|
|
10
|
+
{"name":"genexus_analyze","description":"Use this for cross-object semantic analysis. mode=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 preserves the legacy compatibility envelope and returns NotImplemented until a typed code explanation is available. Requires Ready index for impact/callers.","inputSchema":{"type":"object","properties":{"name":{"type":"string"},"mode":{"type":"string","enum":["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 to carry through the compatibility envelope."},"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}},"required":["mode"],"examples":[{"name":"Customer","mode":"impact"},{"name":"Customer","mode":"summary"}]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"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 name(s), taskId, job_id, or op:<id>. Build accepts CSV ('Foo,Bar'); build_all is KB-global and 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}},
|
|
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
|
-
{"name":"genexus_sdk_probe","description":"
|
|
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":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},
|
|
14
14
|
{"name":"genexus_worker_reload","description":"Reload worker. modes: soft (drain+respawn), hard (copy sourceDir+respawn). 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."}},"examples":[{"mode":"soft"},{"mode":"hard","sourceDir":"C:\\Projetos\\Genexus18MCP\\src\\GxMcp.Worker\\bin\\Debug"}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":true}},
|
|
15
15
|
{"name":"genexus_connection_recover","description":"Self-healing recovery for a broken MCP connection (connection closed, unresponsive worker). Probes every open worker, kills and respawns only the unhealthy ones (force=true targets all), confirms SDK-ready, and clears the semantic cache. Use when calls hang or return WorkerBusy.","inputSchema":{"type":"object","properties":{"force":{"type":"boolean","default":false,"description":"Recover ALL workers, even responsive ones."}},"examples":[{},{"force":true}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}},
|
|
16
16
|
{"name":"genexus_delete_object","description":"Delete an object from the KB through its native SDK identity. Irreversible — confirm=true required. Inspects native incoming references first; dryRun=true previews without deleting it.","inputSchema":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"confirm":{"type":"boolean"},"dryRun":{"type":"boolean","default":false,"description":"When true, returns the resolved object and native references without deleting it."},"expectedVersion":{"type":"string","description":"Optional optimistic-concurrency token returned by a prior dry run."},"kb":{"type":"string","description":"KB alias."}},"required":["name","confirm"],"examples":[{"name":"ObsoletePanel","type":"WebPanel","confirm":true},{"name":"TemporaryDomain","type":"Domain","confirm":true,"dryRun":true}]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":true,"openWorldHint":false}},
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
{"name":"genexus_doc","description":"Use to generate structured docs (wiki, dependency graph, health reports). Don't use for programmatic analysis (see genexus_analyze) or source (see genexus_read).","inputSchema":{"type":"object","properties":{"action":{"type":"string","enum":["wiki","visualize","health"],"description":"wiki: generate markdown docs; visualize: generate dependency graph; health: produce health report."},"target":{"type":"string","description":"Object or domain name (required for wiki/visualize)."}},"required":["action"],"examples":[{"action":"wiki","target":"Customer"},{"action":"health"}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},
|
|
26
26
|
{"name":"genexus_search_source","description":"Regex/semantic search across Procedure/DataProvider/WebPanel/Transaction source. Restrict a scan by object name, persisted GUID, EntityKey, or module/folder-qualified path. Requires the KB index to be Ready — check genexus_lifecycle action=status if results look empty.","inputSchema":{"type":"object","properties":{"callee":{"type":"string","description":"Method/function name (qualified or unqualified)."},"argMatches":{"type":"object","description":"Positional arg index to expected literal text."},"pattern":{"type":"string"},"typeFilter":{"type":"string"},"objectName":{"type":"string","description":"Restrict the scan to these exact object name(s), comma-separated. Makes a search inside one known object O(object) not O(KB), and bypasses the type whitelist."},"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."},"startIndex":{"type":"integer","description":"Legacy object-boundary resume. For a page that ended inside an object, prefer the opaque cursor returned in nextCursor."},"cursor":{"type":"string","description":"Opaque continuation token from nextCursor; preferred when a result page ended inside an object. Do not edit."},"timeoutMs":{"type":"integer","description":"Wall-clock budget (default 30000). Raise it to scan more objects per call."},"scope":{"type":"array","items":{"type":"string","enum":["source","rules","conditions","events","webForm","layout"]},"description":"Parts to scan with line-numbered context. Default [source]. webForm/layout scans the WebPanel/Transaction visual XML (control names, captions, classes, bindings)."},"fields":{"type":"array","items":{"type":"string","enum":["source","caption","description","parmNames","webForm"]},"description":"Whole-field metadata match (returns matchedValue, no line context). Default [source]. Prefer scope=[webForm] for line-context WebForm hits; use fields=[webForm] only for a coarse contains-match."},"maxResults":{"type":"integer"},"caseSensitive":{"type":"boolean"},"includeComments":{"type":"boolean"},"inline_read_top":{"type":"integer","description":"0-3. Inline reads of top N distinct objects in response."},"kb":{"type":"string","description":"KB alias."}},"examples":[{"pattern":"ControlType=\"Radio\""},{"pattern":"for each","typeFilter":"Procedure","maxResults":20}]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},
|
|
27
27
|
{"name":"genexus_kb","description":"Manage open KBs, startup config, and GeneXus environments. list/open/close/set_default operate on WorkerPool; set_default selects the implicit target for calls that omit kb (an explicit kb always wins for parallel or cross-KB work); set_startup/get_startup mirror IDE 'Set As Startup Object'; list_environments lists all configured environments; get_environment reads the active environment; set_environment selects an environment.","inputSchema":{"type":"object","properties":{"action":{"type":"string","enum":["list","open","close","set_default","set_startup","get_startup","list_environments","get_environment","set_environment"],"description":"KB pool or startup-selection operation to perform."},"alias":{"type":"string","description":"KB alias. open: auto from path basename if omitted."},"path":{"type":"string","description":"Absolute KB path (required for open if alias not in config)."},"name":{"type":"string","description":"Object name (required for set_startup)."},"environment":{"type":"string","description":"Environment name/folder (required for set_environment), e.g. development."}},"required":["action"],"examples":[{"action":"open","path":"C:\\KBs\\MyKb"},{"action":"list"},{"action":"list_environments"},{"action":"get_environment"},{"action":"set_environment","environment":"development"}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},
|
|
28
|
-
{"name":"genexus_navigation","description":"View navigation report (IDE Right-click → View Navigation). latest=true reads the most recent report from .gx/navigation-cache; latest=false runs fresh and refreshes that per-KB cache.","inputSchema":{"type":"object","required":["action","name"],"properties":{"action":{"type":"string","enum":["view"],"description":"Navigation report operation to execute."},"name":{"type":"string"},"latest":{"type":"boolean","default":false,"description":"Read the most recent cached navigation when true; when false, run fresh and refresh the per-KB navigation cache."},"kb":{"type":"string","description":"KB alias."}},"examples":[{"action":"view","name":"Customer"},{"action":"view","name":"Customer","latest":true}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},
|
|
29
|
-
{"name":"genexus_api","description":"Inspect HTTP procedures and native API routes. action=list|describe|routes_inspect|routes_clone|routes_update|snapshot|diff_baseline. API route writes use typed ServiceGroupSource, optimistic versioning, full snapshot, rollback and post-save reread; no lifecycle operation is implicit.","inputSchema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["list","describe","routes_inspect","routes_clone","routes_update","snapshot","diff_baseline"],"description":"API introspection, route-editing, or baseline operation to perform."},"api":{"type":"string","description":"API name (routes_inspect|routes_clone|routes_update)."},"sourcePrefix":{"type":"string","description":"Source method/path prefix, e.g. inbound."},"targetPrefix":{"type":"string","description":"Target method/path prefix, e.g. reverse."},"routes":{"type":"array","items":{"type":"object","required":["sourceMethod","method","route"],"additionalProperties":false,"properties":{"sourceMethod":{"type":"string"},"method":{"type":"string"},"route":{"type":"string","pattern":"^/"},"verb":{"type":"string"}}}},"expectedVersion":{"type":"string","description":"versionToken returned by the preceding dry run or inspection."},"dryRun":{"type":"boolean","default":true,"description":"routes_clone/routes_update: preview first; false writes only with expectedVersion."},"rollbackOnFailure":{"type":"boolean","default":true,"description":"Restore the complete API snapshot when post-save verification diverges."},"operation":{"type":"string","description":"Operation value carried by the reused request contract, e.g. REVERSE."},"target":{"type":"string","description":"Procedure or API name (action=describe)."},"name":{"type":"string","description":"Baseline name (action=snapshot)."},"baseline":{"type":"string","description":"Baseline name under .gx/api-baselines/ or absolute path (action=diff_baseline)."},"pathPrefix":{"type":"string","description":"Folder prefix filter (action=list)."},"kb":{"type":"string","description":"KB alias."}},"examples":[{"action":"list"},{"action":"routes_inspect","api":"OrdersApi"},{"action":"routes_clone","api":"OrdersApi","sourcePrefix":"inbound","targetPrefix":"reverse","operation":"REVERSE","dryRun":true,"rollbackOnFailure":true}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},
|
|
28
|
+
{"name":"genexus_navigation","description":"View navigation report (IDE Right-click → View Navigation). latest=true reads the most recent report from .gx/navigation-cache; latest=false runs fresh and refreshes that per-KB cache.","inputSchema":{"type":"object","required":["action","name"],"properties":{"action":{"type":"string","enum":["view"],"description":"Navigation report operation to execute."},"name":{"type":"string"},"latest":{"type":"boolean","default":false,"description":"Read the most recent cached navigation when true; when false, run fresh and refresh the per-KB navigation cache."},"kb":{"type":"string","description":"KB alias."}},"examples":[{"action":"view","name":"Customer"},{"action":"view","name":"Customer","latest":true}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},
|
|
29
|
+
{"name":"genexus_api","description":"Inspect HTTP procedures and native API routes. action=list|describe|routes_inspect|routes_clone|routes_update|snapshot|diff_baseline. API route writes use typed ServiceGroupSource, optimistic versioning, full snapshot, rollback and post-save reread; no lifecycle operation is implicit.","inputSchema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["list","describe","routes_inspect","routes_clone","routes_update","snapshot","diff_baseline"],"description":"API introspection, route-editing, or baseline operation to perform."},"api":{"type":"string","description":"API name (routes_inspect|routes_clone|routes_update)."},"sourcePrefix":{"type":"string","description":"Source method/path prefix, e.g. inbound."},"targetPrefix":{"type":"string","description":"Target method/path prefix, e.g. reverse."},"routes":{"type":"array","items":{"type":"object","required":["sourceMethod","method","route"],"additionalProperties":false,"properties":{"sourceMethod":{"type":"string"},"method":{"type":"string"},"route":{"type":"string","pattern":"^/"},"verb":{"type":"string"}}}},"expectedVersion":{"type":"string","description":"versionToken returned by the preceding dry run or inspection."},"versionToken":{"type":"string","description":"Backward-compatible alias for expectedVersion; pass the token returned by the preceding dry run or inspection."},"dryRun":{"type":"boolean","default":true,"description":"routes_clone/routes_update: preview first; false writes only with expectedVersion or versionToken."},"rollbackOnFailure":{"type":"boolean","default":true,"description":"Restore the complete API snapshot when post-save verification diverges."},"operation":{"type":"string","description":"Operation value carried by the reused request contract, e.g. REVERSE."},"target":{"type":"string","description":"Procedure or API name (action=describe)."},"name":{"type":"string","description":"Baseline name (action=snapshot)."},"baseline":{"type":"string","description":"Baseline name under .gx/api-baselines/ or absolute path (action=diff_baseline)."},"pathPrefix":{"type":"string","description":"Folder prefix filter (action=list)."},"kb":{"type":"string","description":"KB alias."}},"examples":[{"action":"list"},{"action":"routes_inspect","api":"OrdersApi"},{"action":"routes_clone","api":"OrdersApi","sourcePrefix":"inbound","targetPrefix":"reverse","operation":"REVERSE","dryRun":true,"rollbackOnFailure":true}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},
|
|
30
30
|
{"name":"genexus_apply_pattern","description":"Apply a pattern (e.g. WorkWithPlus) to a parent (IDE Right-click → Apply Pattern). Transaction=family-gen; WebPanel/WebComponent/SDPanel=direct-attach (pass settings.template). mode=diagnose (or dryRun=true) returns findings without mutating. Working on Smart Devices? → resources/read uri=genexus://kb/skills/sd-panel-mobile for Main object semantics. mode=actions manages typed grid actions and Action Groups, persists and re-reads PatternInstance, supports dryRun diff, and never adds security permissions automatically.","inputSchema":{"type":"object","required":["name","pattern"],"properties":{"name":{"type":"string","description":"Target KBObject name."},"pattern":{"type":"string","description":"Pattern key ('WorkWithPlus') or GUID."},"mode":{"type":"string","enum":["apply","diagnose","actions"],"description":"apply (default) mutates; diagnose returns reasons without applying. actions exposes typed WWP action-group editing."},"action":{"type":"string","enum":["list_actions","add_grid_action","update_action","move_action","remove_action"],"description":"mode=actions operation."},"group":{"type":"string","description":"Action group name (e.g. TableActions)."},"actionName":{"type":"string","description":"Name of the action to add, update, or remove."},"newGroup":{"type":"string","description":"move_action: destination action group."},"position":{"type":"integer","minimum":0,"description":"zero-based index among actions in group."},"procedure":{"type":"string","description":"Target Procedure to execute on action click."},"selection":{"type":"string","enum":["current","multiple"],"description":"Execution scope: current (single record) or multiple."},"enabledWhen":{"type":"string","description":"Condition expression for action enablement."},"visibleWhen":{"type":"string","description":"Condition expression for action visibility."},"icon":{"type":"string","description":"Action icon name or class."},"description":{"type":"string","description":"Action tooltip / description text."},"confirmation":{"type":"string","description":"Confirmation message prompt."},"confirmTitle":{"type":"string","description":"Confirmation dialog title."},"settings":{"type":"object","description":"Pattern-instance settings tree."},"reapply":{"type":"boolean","default":false,"description":"Re-run on existing instance."},"validate":{"type":"boolean","default":false,"description":"After apply, build the generated host. Adds validation block (60-180s). Catches binding errors."},"dryRun":{"type":"boolean","default":false,"description":"Alias for mode=diagnose. When true, returns pattern findings without mutating. With mode=actions it previews the typed action diff."},"kb":{"type":"string","description":"KB alias."}},"examples":[{"name":"Customer","pattern":"WorkWithPlus"},{"name":"Customer","pattern":"WorkWithPlus","mode":"diagnose"},{"name":"Customer","pattern":"WorkWithPlus","mode":"actions","action":"add_grid_action","group":"Actions","actionName":"Approve","procedure":"ApproveCustomer","dryRun":true}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},
|
|
31
31
|
{"name":"genexus_edit_and_build","description":"Edit + rebuild callers in one call. Returns edit diff + impact + a build block that may include taskId/pollTarget for lifecycle follow-up. validate=true/validationMode=specify validates the saved object; rollbackOnFailure restores its pre-write snapshot on specification failure.","inputSchema":{"type":"object","properties":{"name":{"type":"string","description":"Target object name."},"part":{"type":"string","description":"Part (Source, Rules, ...)."},"content":{"type":"string","description":"New content. For mode=patch may be {find,replace} object."},"patch":{"description":"Same shape as genexus_edit.patch. Auto-sets mode=patch."},"mode":{"type":"string","enum":["full","patch"],"default":"patch"},"type":{"type":"string","description":"Disambiguates ambiguous names."},"dryRun":{"type":"boolean","default":false},"validate":{"type":"boolean","default":false},"validationMode":{"type":"string","enum":["specify"],"default":"specify"},"rollbackOnFailure":{"type":"boolean","default":true},"buildIncludeCallees":{"type":"string","enum":["none","direct","transitive"],"default":"direct"},"buildPlanCap":{"type":"integer","default":200},"waitForIndex":{"type":"boolean","default":true},"waitTimeoutMs":{"type":"integer","default":30000},"visualVerify":{"type":"boolean","default":false,"description":"Post-edit headless screenshot + pixel-diff vs baseline. See tool-help."}},"required":["name","part"],"examples":[{"name":"Customer","part":"Source","patch":{"find":"oldValue","replace":"newValue"},"validate":true},{"name":"Customer","part":"Rules","mode":"patch","patch":{"find":"error(","replace":"msg("},"dryRun":true}]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},
|
|
32
32
|
{"name":"genexus_security","description":"Audit KB security. action=audit_gam scans GAM/env props; action=scan_secrets greps Source for credential-shaped literals; action=scan_native drives the native GeneXus Security Scanner (ISecurityScannerService). Returns findings with severity.","inputSchema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["audit_gam","scan_secrets","scan_native"],"description":"audit_gam: scans GAM and environment properties; scan_secrets: greps Source for credentials; scan_native: drives native GeneXus Security Scanner."},"kb":{"type":"string","description":"KB alias."}},"examples":[{"action":"audit_gam"},{"action":"scan_secrets"}]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},
|
|
@@ -48,5 +48,5 @@
|
|
|
48
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 requires confirm=true).","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; false applies (needs confirm)."},"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
|
-
{"name":"genexus_wwp","description":"WorkWithPlus
|
|
51
|
+
{"name":"genexus_wwp","description":"Typed WorkWithPlus action, tab, and grid edits with dryRun, optimistic concurrency, exact snapshots, post-save reread, projection verification, and rollback. No lifecycle operation is implicit.","inputSchema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["list","add_action","update_action","move_action","remove_action","add_tab","move_tab","remove_tab","add_grid_attribute"],"description":"WorkWithPlus action-group, tab, or grid-attribute 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."},"actionName":{"type":"string","description":"Action name."},"attribute":{"type":"string","description":"add_grid_attribute: GeneXus Attribute name."},"caption":{"type":"string","description":"Action or grid-column caption."},"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."},"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.","items":{"$ref":"#/$defs/wwpControl"}},"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."}},"$defs":{"wwpControl":{"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":{"$ref":"#/$defs/wwpControl"}}},"additionalProperties":false}},"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}]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false}}
|
|
52
52
|
]
|
|
Binary file
|
|
@@ -11,11 +11,25 @@ const path = require('path');
|
|
|
11
11
|
|
|
12
12
|
const pkgRoot = path.join(__dirname, '..');
|
|
13
13
|
|
|
14
|
+
const packageVersion = (() => {
|
|
15
|
+
try {
|
|
16
|
+
return require(path.join(pkgRoot, 'package.json')).version || '0.0.0';
|
|
17
|
+
} catch {
|
|
18
|
+
return '0.0.0';
|
|
19
|
+
}
|
|
20
|
+
})();
|
|
21
|
+
const packageMajor = Number.parseInt(packageVersion.split('.')[0], 10) || 0;
|
|
22
|
+
|
|
14
23
|
const required = [
|
|
15
24
|
'publish/GxMcp.Gateway.exe',
|
|
16
25
|
'publish/worker/GxMcp.Worker.exe',
|
|
26
|
+
'publish/tool_definitions.json',
|
|
17
27
|
];
|
|
18
28
|
|
|
29
|
+
if (packageMajor >= 3) {
|
|
30
|
+
required.push('publish/gxmcp-manifest.json');
|
|
31
|
+
}
|
|
32
|
+
|
|
19
33
|
const missing = required.filter((rel) => {
|
|
20
34
|
try {
|
|
21
35
|
return !fs.statSync(path.join(pkgRoot, rel)).isFile();
|
|
@@ -25,7 +39,7 @@ const missing = required.filter((rel) => {
|
|
|
25
39
|
});
|
|
26
40
|
|
|
27
41
|
if (missing.length === 0) {
|
|
28
|
-
console.log(
|
|
42
|
+
console.log(`genexus-mcp: Gateway, Worker, schema${packageMajor >= 3 ? ', and v3 manifest' : ''} verified.`);
|
|
29
43
|
process.exit(0);
|
|
30
44
|
}
|
|
31
45
|
|