Skip to main content
Glama

create_aot_object

Read-onlyIdempotent
Generate a complete, ready-to-deploy D365 F&O AOT XML scaffold for any object type.
Returns the XML + the correct file path inside the model -- the calling client (VS Extension,
Cursor, Copilot Chat) is responsible for writing the result to disk. This tool is fully
read-only on the server: it never writes to the filesystem, never mutates external state,
and is safe to expose from the cloud MCP.
When the knowledge base is available the scaffold is auto-enriched with real metadata
(existing field EDTs, related-table validation, auto-detected grid fields, etc.).

  Supported aotType values ----------------------------------------------
AxTable       . AxClass     . AxForm       . AxEnum
    AxEdt      . AxView            . AxQuery           . AxDataEntityView
    AxMenuItemDisplay . AxMenuItemAction  . AxMenuItemOutput
    AxSecurityPrivilege . AxSecurityDuty . AxSecurityRole . AxSecurityPolicy
    AxReport          . AxFormExtension  . AxTableExtension  . AxClassExtension
    AxEnumExtension   . AxEdtExtension   . AxQueryExtension  . AxWorkflow

     Common options (all types) --------------------------------------------
label - human-readable label shown in the UI

developerDoc - developer documentation string (tables/classes)

     AxTable --------------------------------------------------------------------------
    tableGroup     - Main | WorksheetHeader | WorksheetLine | Transaction | Parameter | Group
    cacheLookup  - None | Found | FoundAndEmpty | NotInTTS | EntireTable
  fields         - csv  "Name:Type[:EDT[:Label[:mandatory]]]"

Types: String Int Int64 Real Date DateTime Enum Container Guid indexes - csv "IndexName:field1+field2[:unique|:alternatekey]" relations - csv "RelName:RelatedTable:Field:RelatedField" titleField1/2 - field names for the lookup title createdBy / modifiedBy - true | false (default true) generateFind / generateExist / generateValidateWrite / generateInitValue - true | false

AxClass -------------------------------------------------------------------------- extends - base class name implements - csv of interfaces abstract / final - true | false pattern - SysOperation | RunBase | Service | EventHandler | none (default) methods - csv of additional method names to stub

     AxForm ----------------------------------------------------------------------------
    dataSourceTable - primary data-source table name
    pattern  - SimpleList | DetailsTransaction | DetailsMaster | ListPage | Dialog
    gridFields      - csv of field names for the grid (auto-detected from KB if omitted)
    detailFields    - csv of field names for the detail group
  methods      - csv of form method names to stub

     AxEnum ----------------------------------------------------------------------------
    style - Ordinary | ComboBox | Radio | CheckBox

values - csv "Name[:Label[:intValue]]" e.g. "Draft:Draft:0,Posted:Posted:1"

     AxEdt -----------------------------------------------------------------------------
    extends        - base EDT (e.g. Name, Description, Amount)

stringSize - integer enumType - base enum for enum EDTs referenceTable - table that provides the lookup

     AxView ----------------------------------------------------------------------------
    dataSources    - csv  "Table[:Alias]"
    fields    - csv  "DataSource.Field[:Alias]"

     AxQuery -------------------------------------------------------------------------
dataSources    - csv  "Table[:Alias[:JoinMode]]"

     AxDataEntityView -----------------------------------------------------------
    primaryTable    - root table

joinTables - csv of additional tables publicEntityName - OData collection name (pluralised entity name) isPublic - true | false (default true) fields - csv "Table.Field[:PublicName]" (auto-detected from KB if omitted)

     AxMenuItemDisplay / Action / Output ------------------------------------------
    objectName     - target form / class / report name
    runOn       - Server | Client | Called from  (default Server)

helpText - tooltip string

     AxSecurityPrivilege -----------------------------------------------------------
    entryPoints    - csv  "MenuItemName[:ObjectType[:Grant]]"
    ObjectType: MenuItemDisplay | MenuItemAction | MenuItemOutput

Grant: NoAccess | Read | Update | Create | Delete

AxSecurityDuty --------------------------------------------------------------------- privileges - csv of privilege names to include

AxSecurityRole ---------------------------------------------------------------------- duties - csv of duty names privileges - csv of privilege names (direct assignment -- avoid if possible)

     AxReport -------------------------------------------------------------------------

query- AxQuery name driving the dataset dataSourceTable - alternative: direct table name (if no query)

   AxFormExtension -----------------------------------------------------------------
    baseForm   - name of the standard form to extend
    fields  - csv  "ControlName[:EDT]"

AxTableExtension --------------------------------------------------------------------- baseTable - name of the standard table to extend fields - csv "Name:Type[:EDT[:Label[:mandatory]]]" indexes - csv "IndexName:field1+field2[:unique|:alternatekey]"

AxClassExtension (Chain of Command) ------------------------------------------- baseClass - name of the standard class/table/form to wrap baseType - class | table | form (default class) methods - csv of method names to wrap with CoC

     AxEnumExtension ---------------------------------------------------------------
    baseEnum       - name of the standard enum to extend
    values         - csv  "Name[:Label[:intValue]]"  IMPORTANT: start from value 10 or higher
                     to avoid conflicts with standard values (D365 extension contract)

     AxEdtExtension ----------------------------------------------------------------
    baseEdt        - name of the standard EDT to extend
    stringSize     - new StringSize (must be <= base EDT limit; omit to inherit)
    label          - override label for this extension

     AxQueryExtension --------------------------------------------------------------
    baseQuery      - name of the standard query to extend
    dataSources    - csv  "Table[:Alias[:JoinMode]]"  (add extra data sources)
    ranges         - csv  "DataSource.Field:value"  (add filter ranges)

     AxSecurityPolicy  (Row Level Security) ----------------------------------------
    constrainedTable - primary table this policy restricts
    query           - AxQuery name that defines the allowed rows
    operation       - Select | Update | Create | Delete | Insert (default Select)
    enabled         - true | false  (default true)

     AxWorkflow ---------------------------------------------------------------------
    category       - category name (links to a module/table)
    documentTable  - table the workflow operates on
    documentMenuItem - menu item that opens the record

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nameYesObject name -- must start with the ISV prefix, e.g. 'ALMMyTable', 'ABCSalesService'.
aotTypeYesAOT type, e.g. 'AxTable', 'AxClass', 'AxForm', 'AxEnum', 'AxEdt', 'AxSecurityPrivilege', etc.
optionsNoKey-value options dict. Provide only the keys relevant to your aotType. Example for AxTable: { "label": "My Table", "tableGroup": "Main", "fields": "MyId:String:MyIdEdt:My ID:mandatory,Description:String::Description", "indexes": "MyIdIdx:MyId:alternatekey", "relations": "CustTable:CustTable:CustAccount:AccountNum", "titleField1": "MyId", "generateFind": "true", "generateExist": "true", "generateValidateWrite": "true" }

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / options / description
      Previous value: -"Key-value options dict. Provide only the keys relevant to your aotType.\r\nExample for AxTable:\r\n{\r\n  \"label\":      \"My Table\",\r\n  \"tableGroup\":     \"Main\",\r\n  \"fields\":         \"MyId:String:MyIdEdt:My ID:mandatory,Description:String::Description\",\r\n  \"indexes\":      \"MyIdIdx:MyId:alternatekey\",\r\n  \"relations\": \"CustTable:CustTable:CustAccount:AccountNum\",\r\n  \"titleField1\":    \"MyId\",\r\n  \"generateFind\":   \"true\",\r\n  \"generateExist\":  \"true\",\r\n  \"generateValidateWrite\": \"true\"\r\n}"New value: +"Key-value options dict. Provide only the keys relevant to your aotType.\nExample for AxTable:\n{\n  \"label\":      \"My Table\",\n  \"tableGroup\":     \"Main\",\n  \"fields\":         \"MyId:String:MyIdEdt:My ID:mandatory,Description:String::Description\",\n  \"indexes\":      \"MyIdIdx:MyId:alternatekey\",\n  \"relations\": \"CustTable:CustTable:CustAccount:AccountNum\",\n  \"titleField1\":    \"MyId\",\n  \"generateFind\":   \"true\",\n  \"generateExist\":  \"true\",\n  \"generateValidateWrite\": \"true\"\n}"
  2. Changed1 schema field changed
    • changedInput schema / properties / options / description
      Previous value: -"Key-value options dict. Provide only the keys relevant to your aotType.\nExample for AxTable:\n{\n  \"label\":      \"My Table\",\n  \"tableGroup\":     \"Main\",\n  \"fields\":         \"MyId:String:MyIdEdt:My ID:mandatory,Description:String::Description\",\n  \"indexes\":      \"MyIdIdx:MyId:alternatekey\",\n  \"relations\": \"CustTable:CustTable:CustAccount:AccountNum\",\n  \"titleField1\":    \"MyId\",\n  \"generateFind\":   \"true\",\n  \"generateExist\":  \"true\",\n  \"generateValidateWrite\": \"true\"\n}"New value: +"Key-value options dict. Provide only the keys relevant to your aotType.\r\nExample for AxTable:\r\n{\r\n  \"label\":      \"My Table\",\r\n  \"tableGroup\":     \"Main\",\r\n  \"fields\":         \"MyId:String:MyIdEdt:My ID:mandatory,Description:String::Description\",\r\n  \"indexes\":      \"MyIdIdx:MyId:alternatekey\",\r\n  \"relations\": \"CustTable:CustTable:CustAccount:AccountNum\",\r\n  \"titleField1\":    \"MyId\",\r\n  \"generateFind\":   \"true\",\r\n  \"generateExist\":  \"true\",\r\n  \"generateValidateWrite\": \"true\"\r\n}"
  3. Changed1 schema field changed
    • changedInput schema / properties / options / description
      Previous value: -"Key-value options dict. Provide only the keys relevant to your aotType.\r\nExample for AxTable:\r\n{\r\n  \"label\":      \"My Table\",\r\n  \"tableGroup\":     \"Main\",\r\n  \"fields\":         \"MyId:String:MyIdEdt:My ID:mandatory,Description:String::Description\",\r\n  \"indexes\":      \"MyIdIdx:MyId:alternatekey\",\r\n  \"relations\": \"CustTable:CustTable:CustAccount:AccountNum\",\r\n  \"titleField1\":    \"MyId\",\r\n  \"generateFind\":   \"true\",\r\n  \"generateExist\":  \"true\",\r\n  \"generateValidateWrite\": \"true\"\r\n}"New value: +"Key-value options dict. Provide only the keys relevant to your aotType.\nExample for AxTable:\n{\n  \"label\":      \"My Table\",\n  \"tableGroup\":     \"Main\",\n  \"fields\":         \"MyId:String:MyIdEdt:My ID:mandatory,Description:String::Description\",\n  \"indexes\":      \"MyIdIdx:MyId:alternatekey\",\n  \"relations\": \"CustTable:CustTable:CustAccount:AccountNum\",\n  \"titleField1\":    \"MyId\",\n  \"generateFind\":   \"true\",\n  \"generateExist\":  \"true\",\n  \"generateValidateWrite\": \"true\"\n}"
  4. Changed1 schema field changed
    • changedInput schema / properties / options / description
      Previous value: -"Key-value options dict. Provide only the keys relevant to your aotType.\nExample for AxTable:\n{\n  \"label\":      \"My Table\",\n  \"tableGroup\":     \"Main\",\n  \"fields\":         \"MyId:String:MyIdEdt:My ID:mandatory,Description:String::Description\",\n  \"indexes\":      \"MyIdIdx:MyId:alternatekey\",\n  \"relations\": \"CustTable:CustTable:CustAccount:AccountNum\",\n  \"titleField1\":    \"MyId\",\n  \"generateFind\":   \"true\",\n  \"generateExist\":  \"true\",\n  \"generateValidateWrite\": \"true\"\n}"New value: +"Key-value options dict. Provide only the keys relevant to your aotType.\r\nExample for AxTable:\r\n{\r\n  \"label\":      \"My Table\",\r\n  \"tableGroup\":     \"Main\",\r\n  \"fields\":         \"MyId:String:MyIdEdt:My ID:mandatory,Description:String::Description\",\r\n  \"indexes\":      \"MyIdIdx:MyId:alternatekey\",\r\n  \"relations\": \"CustTable:CustTable:CustAccount:AccountNum\",\r\n  \"titleField1\":    \"MyId\",\r\n  \"generateFind\":   \"true\",\r\n  \"generateExist\":  \"true\",\r\n  \"generateValidateWrite\": \"true\"\r\n}"
  5. Changed1 schema field changed
    • changedInput schema / properties / options / description
      Previous value: -"Key-value options dict. Provide only the keys relevant to your aotType.\r\nExample for AxTable:\r\n{\r\n  \"label\":      \"My Table\",\r\n  \"tableGroup\":     \"Main\",\r\n  \"fields\":         \"MyId:String:MyIdEdt:My ID:mandatory,Description:String::Description\",\r\n  \"indexes\":      \"MyIdIdx:MyId:alternatekey\",\r\n  \"relations\": \"CustTable:CustTable:CustAccount:AccountNum\",\r\n  \"titleField1\":    \"MyId\",\r\n  \"generateFind\":   \"true\",\r\n  \"generateExist\":  \"true\",\r\n  \"generateValidateWrite\": \"true\"\r\n}"New value: +"Key-value options dict. Provide only the keys relevant to your aotType.\nExample for AxTable:\n{\n  \"label\":      \"My Table\",\n  \"tableGroup\":     \"Main\",\n  \"fields\":         \"MyId:String:MyIdEdt:My ID:mandatory,Description:String::Description\",\n  \"indexes\":      \"MyIdIdx:MyId:alternatekey\",\n  \"relations\": \"CustTable:CustTable:CustAccount:AccountNum\",\n  \"titleField1\":    \"MyId\",\n  \"generateFind\":   \"true\",\n  \"generateExist\":  \"true\",\n  \"generateValidateWrite\": \"true\"\n}"
  6. Added
  7. Removed
  8. Changed1 schema field changed
    • changedInput schema / properties / options / description
      Previous value: -"Key-value options dict. Provide only the keys relevant to your aotType.\nExample for AxTable:\n{\n  \"label\":      \"My Table\",\n  \"tableGroup\":     \"Main\",\n  \"fields\":         \"MyId:String:MyIdEdt:My ID:mandatory,Description:String::Description\",\n  \"indexes\":      \"MyIdIdx:MyId:alternatekey\",\n  \"relations\": \"CustTable:CustTable:CustAccount:AccountNum\",\n  \"titleField1\":    \"MyId\",\n  \"generateFind\":   \"true\",\n  \"generateExist\":  \"true\",\n  \"generateValidateWrite\": \"true\"\n}"New value: +"Key-value options dict. Provide only the keys relevant to your aotType.\r\nExample for AxTable:\r\n{\r\n  \"label\":      \"My Table\",\r\n  \"tableGroup\":     \"Main\",\r\n  \"fields\":         \"MyId:String:MyIdEdt:My ID:mandatory,Description:String::Description\",\r\n  \"indexes\":      \"MyIdIdx:MyId:alternatekey\",\r\n  \"relations\": \"CustTable:CustTable:CustAccount:AccountNum\",\r\n  \"titleField1\":    \"MyId\",\r\n  \"generateFind\":   \"true\",\r\n  \"generateExist\":  \"true\",\r\n  \"generateValidateWrite\": \"true\"\r\n}"
  9. First observed

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnlyHint, idempotentHint, destructiveHint), it explicitly states 'never writes to the filesystem, never mutates external state, and is safe to expose from the cloud MCP' and clarifies that disk writing is the client's job. This fully discloses the tool's side-effect boundary and is consistent with the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is very long, but the length is justified by about 20 AOT types with distinct option sets. It is front-loaded with purpose and safety, then organized by type with consistent formatting; minor formatting inconsistencies and overall bulk keep it from a perfect score.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema, it states the return value ('XML + the correct file path') and the caller's follow-up action. Combined with exhaustive parameter documentation and side-effect disclosure, nothing critical is missing for an agent to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema only defines a generic options dictionary, but the description documents every aotType-specific option with syntax, defaults, enums, CSV layouts, and examples. This is far beyond what the input schema provides and is essential for correctly invoking the tool.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource: 'Generate a complete, ready-to-deploy D365 F&O AOT XML scaffold for any object type.' It also states the two outputs (XML + file path) and the caller's write responsibility, making the tool's scope unambiguous and distinct from code-generation siblings like generate_xpp_form or generate_query.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context: it is for producing AOT XML scaffolds, is server-side read-only, and the client is responsible for persisting output. It does not explicitly name sibling tools to use instead for other generation tasks, so it stops short of a full when/when-not statement.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.