This folder bundles everything the Acumatica side of the GI exposure gate needs (see docs/generic-inquiries.md for the rationale and full setup).
| File | What it is |
|---|---|
MCP4Acumatica-AIDescription.zip |
Customization project: adds the custom fields + SM208000 form changes. |
MCPGIs.xml |
The MCPGIs feed GI (one row per exposed GI). |
MCPGIFields.xml |
The MCPGIFields feed GI (one row per exposed GI's output column). |
MCPAccess.xml |
The MCPAccess canary GI used by the login role gate (see the README's Acumatica-side configuration). |
MCPGIColumnsAll.xml |
Authoring aid: one row per (GI, result column) for every GI in the instance. |
MCPGIJoinsAll.xml |
Authoring aid: one row per join condition — tables, aliases, join types. |
MCPGIWhereAll.xml |
Authoring aid: one row per design-time WHERE condition. |
MCPGIDescriptionEditor.xml |
Editor GI: edit GIDesign.UsrAIDescription in a grid. |
MCPGIColumnDescEditor.xml |
Editor GI: edit GIResult.UsrResAIDescription in a grid. |
| No drafted descriptions ship in this repo. A description states what one tenant's inquiry | |
| actually does — its document-type filters, custom fields and business rules — so it is instance | |
data, not project source, and this repo is public. .gitignore keeps |
|
acumatica/gi-descriptions*.csv out of git; write yours somewhere private. |
To produce your own, use the skill at skills/acumatica-gi-descriptions/: it covers selecting
which GIs are worth describing, pulling the design metadata, and — via
scripts/align_columns.mjs — mapping each design row to the OData property it actually becomes,
which cannot be predicted from the design and is the step everything else depends on.
The customization is built on Acumatica 2025 R2 (
product-version 25.201). TheAIDescriptionfields are a stopgap until native support lands in 26R1+.
| DAC | Field | Type | Form label (SM208000) |
|---|---|---|---|
GIDesign |
UsrExposedToMCP |
bool | Exposed to MCP (checkbox, GI header) |
GIDesign |
UsrAIDescription |
string(2000) | AI Description (GI header) |
GIResult |
UsrResAIDescription |
string(1000) | AI Description (Results grid column) |
Plus the SM208000 screen changes that surface these fields, so an admin can tick the box and
write descriptions without a developer. (project.xml = DAC field defs + screen-edit metadata;
one generated SM208000 screen extension.)
MCPGIs / MCPGIFields are read by the server when it builds the registry. Acumatica derives
each OData property name from the result-column caption, so the captions below are the
property names — they must match what src/lib/gi-registry.ts reads:
MCPGIs — row filter: UsrExposedToMCP = true AND ExposeViaOData = true AND parameter-free
(GIFilter.LineNbr IS NULL):
| OData column (caption) | Source field | Registry use |
|---|---|---|
Name |
GIDesign.name |
GI name / OData entity (giName) |
AIDescription |
GIDesign.UsrAIDescription |
GI-level description |
ScreenID |
GIDesign.primaryScreenID |
entry screen (informational) |
DesignID |
GIDesign.designID |
traceability |
MCPGIFields — same row filter as MCPGIs minus the parameter-free clause:
UsrExposedToMCP = true AND ExposeViaOData = true:
| OData column (caption) | Source field | Registry use |
|---|---|---|
Name |
GIDesign.name |
owning GI (groups columns) |
Caption |
GIResult.caption |
column caption, when set — also the alignment constraint |
AIDescription |
GIResult.UsrResAIDescription |
per-column description |
SortOrder |
GIResult.sortOrder |
grid position — the order the columns align in |
IsActive |
GIResult.isActive |
inactive columns never reach OData; they must be dropped |
LineNbr |
GIResult.lineNbr |
row identity (dedupe); tiebreak within one SortOrder |
Field |
GIResult.field |
weak tiebreak for uncaptioned columns during alignment |
SchemaField |
GIResult.schemaField |
name guess on the degraded no-$metadata path only |
SortOrder and IsActive were added after the original release — re-import
MCPGIFields.xml if your instance predates them. Without both columns most curated column
descriptions cannot be attached: a column's OData property name is not predictable from the design
(a caption is only an override and is NULL for the majority of columns; SchemaField is NULL for
most rows and DAC-qualified — INTran.RefNbr — where present), so the registry joins design rows
to $metadata properties positionally, which requires the true grid order and the exclusion of
inactive rows. See resolveFields in src/lib/gi-registry.ts.
(MCPGIFields also emits DesignID, ObjectName, FieldName — present but not consumed by the
registry. If you change a caption here, change the matching field in gi-registry.ts.)
MCPGIColumnsAll / MCPGIJoinsAll / MCPGIWhereAll exist so descriptions can be written from
the GI design rather than from guesswork. A live sample row shows values but not what one row
represents, which filters are baked in, or why a left-joined column is null — the three things a
useful AIDescription has to state.
They are deliberately separate from the MCPGIs/MCPGIFields feeds:
- The feeds are consumed by the server at runtime and are listed in
EXCLUDED_GI_NAMES(src/lib/gi-registry.ts), soacumatica_run_inquiryrefuses them. These aids are not excluded, so they can be queried while drafting. - The feeds are scoped to exposed GIs; these cover every GI, including ones not yet tagged
ExposedToMCPand not yet exposed via OData — which is the population you pick candidates from.
There are three rather than one because a GI has a single row grain and these are three different
children of GIDesign: result columns, join conditions, and WHERE conditions. Merging them would
cross-product the rows.
All three ship with UsrExposedToMCP="1", which is load-bearing and easy to get wrong. The
MCPGIs/MCPGIFields feeds work while untagged because the server's registry builder reads them
directly; these aids are read through acumatica_run_inquiry, which is gated — untagged, the
gate refuses them with "not exposed to the AI assistant."
Untag them when the authoring session is done. While tagged they sit in the model's own GI menu, which is exactly the context pollution the gate exists to prevent. Clear Exposed to MCP on all three (and run
acumatica_clear_cache) once descriptions are loaded.
Three field names in these files are unverified —
GIWhere.value2,GIWhere.openBrackets, andGIWhere.closeBracketsinMCPGIWhereAll.xml. Every other field was taken from a known-good export. If SM208000 rejects the import, delete those three<GIResult>lines and re-import; the only loss is bracket grouping in multi-condition filters.
Once you have drafted text (see the file table above — none ships here), getting it into
Acumatica is the awkward step, because GIDesign and GIResult are system DACs and are not in
the contract-based REST API — there is no write path from this MCP server, and none from any
REST client. That leaves two routes.
Editor GIs (shipped here). MCPGIDescriptionEditor exposes UsrAIDescription and
MCPGIColumnDescEditor exposes UsrResAIDescription, both with record editing switched on, so the
values can be typed straight into the results grid. Both ship ExposeViaOData="0" and
UsrExposedToMCP="0" — they are human tools and must never enter the model's menu.
Know the limit before you start. Acumatica's mass update applies one value to many selected rows; it is not a paste-a-column-of-distinct-values mechanism. Row-by-row editing is perfectly workable for the 116 GI-level descriptions. It is not a realistic way to enter 1 788 column descriptions — for that, an Import Scenario is the right tool.
Two attributes on
GIMassUpdateField(ObjectName,FieldName) were inferred rather than copied from a known-good export. If the Mass Record Update tab is empty after import, add the field there by hand — it is a two-click fix, and the rest of the GI is unaffected.
Import Scenario (not shipped). A scenario on SM208000 keyed by Inquiry Title (plus result
LineNbr for columns) is the only practical route for the column pass. It is deliberately absent:
SM208000 is the screen that defines every GI in the instance, and a scenario whose match-versus-
create semantics are wrong can alter GI definitions rather than just annotate them. Export any
existing scenario from SM206025 to XML first and use its envelope as the template — the same method
that made the GIs in this folder import correctly the first time.
- Customization Projects (SM204505) → Import → upload
MCP4Acumatica-AIDescription.zip→ open it and Publish. Verify on Generic Inquiry (SM208000): the Exposed to MCP checkbox + AI Description box on the header, and an AI Description column on Results. - Generic Inquiry (SM208000) → import
MCPGIs.xml,MCPGIFields.xml, andMCPAccess.xml(these are SM208000 GI exports). Confirm all three are Exposed via OData. - Access Rights: grant the
MCP Accessrole read access toMCPGIs+MCPGIFields, and assign theMCPAccesscanary GI to theMCP Accessrole (role-gate prerequisite). - Tag the GIs you want the assistant to see: set Exposed to MCP and write an AI Description on each (and per-column AI Descriptions as desired).
Until at least one GI is tagged and the feeds are readable, the gate stays inactive (all OData-exposed GIs remain available, exactly as before).
The custom fields live on system DACs (GIDesign/GIResult). They should carry forward across
Acumatica releases, but re-validate (and re-publish) after a version upgrade — and drop the
customization once a release ships native AI-description metadata. See
docs/upgrading-acumatica.md.
Copyright 2026 Hall Boys, Inc. · Apache-2.0 (same license as the rest of this repository).