D365 F&O MCP Server
This server provides 23 AI tools for grounded, hallucination-free D365 F&O development, indexing 580,000+ symbols across your codebase.
Search & Discovery: Fast full-text search for objects (classes, tables, forms, etc.), batch lookups, and extension filtering.
Metadata & Code Inspection: Retrieve detailed AOT object info, method signatures, and source code; supports batch and method-level reading.
Code Generation: Scaffold X++ for tables, forms, reports, CoC extensions, event handlers, security artifacts, and more, with pattern awareness and existing form cloning.
Code Analysis: Learn from existing patterns, implementations, completeness gaps, and API usage before generating new code.
File Management: Create new AOT objects (auto-registered in .rnrproj) or safely modify existing ones via IMetadataProvider; generate XML as text.
Reference Finding: Where-used analysis for classes, methods, fields, tables, enums, and labels.
Label Management: Search, create, update, rename, and bulk-manipulate labels across languages, with dry-run support.
Form Patterns: Analyze, recommend, validate, and repair form patterns (SimpleList, DetailsMaster, etc.) with structural checks.
EDT Suggestions: Fuzzy-matched EDT recommendations for new fields.
Security Analysis: Inspect privilege/duty/role hierarchies and reverse access chains (object → menu items → privileges → duties → roles).
Extensibility Analysis: Examine CoC extensions, event subscriptions, table merges, extension points, and get strategy recommendations.
Naming Validation: Check proposed names against conventions, ISV prefixes, and conflicts.
Workspace & Project Tools: Retrieve workspace configuration, verify objects on disk and in .rnrproj, and update the symbol index instantly after changes.
SDLC Integration: Compile (xppc.exe), run database sync (full/partial), execute Best Practices checks, and run SysTest unit tests.
Change Review & Undo: Review uncommitted changes for BP violations/patterns; safely rollback to last commit with index re-sync.
Knowledge & Validation: Query X++ best practices, diagnose errors with fixes; statically validate generated X++/XML syntax and semantic references before writing.
Grounded Context: One-call aggregator for provenance tokens and full context (signatures, CoC wrappers, naming, EDT suggestions, collision checks) to enable safe, validated code creation.
Provides 54 specialized tools for GitHub Copilot to interact with a D365FO codebase, enabling instant lookup of class signatures, table relations, EDT definitions, CoC extensions, menu items, security coverage, labels, and more, directly within Copilot's agent mode in Visual Studio.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@D365 F&O MCP ServerFind CoC extensions for CustTable.insert()"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
D365 F&O MCP Server
20 AI tools that know every X++ class, table, form, and EDT in your D365FO codebase
Grounded AI development for Dynamics 365 Finance & Operations — works with GitHub Copilot and Claude Code
These connect an editor to a server that is already deployed — see Quick Start if you still need to set one up.
Why
AI assistants excel at C#, Python, and JavaScript. X++ is different: your D365FO codebase is private, deeply customized, and invisible to every model — so AI confidently generates code that doesn't compile.
This server pre-indexes your entire D365FO installation (580 000+ symbols across standard, ISV, and custom models) and exposes it as 20 specialized MCP tools. Every signature, every CoC wrapper, every label, every form pattern — verified against your real metadata before the AI writes a single line.
Task | Without this server | With this server |
Method signatures | Guessed → compile errors | Exact, from your codebase |
Existing CoC wrappers | Manual AOT search |
|
New forms | Hand-written XML, broken patterns | Cloned from reference forms, validated against the pattern catalog |
Labels | Hardcoded strings | Right |
Security chains | Hours of manual tracing | Role → Duty → Privilege → Entry Point in one call |
Generated code | Hallucinated fields and types | Every reference proven against the index, gated before write |
Related MCP server: D365 Finance & Operations MCP Server
Capabilities
Feature | Description |
🔍 Full-codebase intelligence | 580K+ symbols indexed: classes, tables, forms, EDTs, enums, labels (20M+ rows), security artifacts — FTS5 search in < 10 ms |
🛡️ Grounded generation | Fail-closed gates: |
🧩 Form pattern engine | Complete catalog of Microsoft form patterns and sub-patterns: recommends the right pattern, clones reference forms with datasource re-binding, deterministically expands patterns that have no reference form, auto-repairs a form's missing required controls, validates structure and blocks invalid writes |
✍️ Safe metadata writes | C# bridge uses Microsoft's own |
🏗️ SDLC integration | MSBuild compilation with structured diagnostics, DB sync, xppbp best practices, SysTestRunner — all from chat |
📐 X++ knowledge base | Queryable rules: select grammar, CoC authoring, financial dimensions, the posting engine ( |
Pattern-grounded form development
Forms are the hardest artifact to generate correctly — each pattern dictates required containers, ordering, and allowed sub-patterns. The form pattern engine makes it a guided pipeline:
flowchart LR
A["object_patterns<br/>(domain=form, action=analyze)"] --> B["object_patterns<br/>(domain=form, action=spec)"]
B --> C["generate_object<br/>objectType=form, cloneFrom"]
C --> D["object_patterns<br/>(domain=form, action=validate) FP001–FP010"]
D -->|clean| E["d365fo_file<br/>(action=create) write + project"]
D -->|errors| CStructural violations (wrong order, missing container, disallowed control) block the write — recommendations only warn. Mined pattern statistics from your own environment ground every suggestion in reality.
Quick Start
From D365FO platform update 10.0.49 (PU74), Visual Studio 2026 is the supported IDE for X++ development — Microsoft no longer supports VS 2022. Earlier platform versions still use VS 2022 ≥ 17.14. Details
Installing on your own D365FO VM — the usual case. One line in PowerShell installs Node.js if it is missing, installs the server from npm, and runs the setup wizard, which asks where the index should live and builds the C# bridge for you:
irm https://raw.githubusercontent.com/dynamics365ninja/d365fo-mcp-server/main/install.ps1 | iexAlready have Node.js 24+? Then the one-liner has nothing to bootstrap and you can skip it:
npm install -g d365fo-mcp
d365fo-mcp setupRe-running either is safe. An installation made before the npm package existed is a git checkout, and both are left exactly where they are and updated in place.
Your team already runs a shared server? Then you install nothing — point your editor at it:
npx d365fo-mcp connect https://your-server.azurewebsites.netBoth paths in full — prerequisites, editor configuration for every scenario, the required instruction file, and how to verify grounding actually works: docs/QUICK_START.md
Azure Deployment
One shared instance for the whole team — the metadata index lives in Blob Storage and downloads automatically on startup.
Deployment guide: docs/SETUP_AZURE.md — includes CI/CD pipeline automation
Documentation
Getting started | Reference | Operations |
Quick Start — connect or install | ||
Usage examples — real tool chains | ||
Coverage — what the badge counts | ||
Backlog — deferred work | Eval loop — the self-improvement harness |
License
MIT
Available Tools
20 toolsanalyze_codeARead-only
Learn from the existing codebase. Choose a mode:
• patterns → common classes/methods/dependencies for a scenario (call BEFORE generate_object(mode="pattern")).
• implementations → real implementation examples of a similar method (actual code).
• completeness → missing standard methods on a class (find/exist/validate gaps).
• api-usage → how an API/class is initialized and called in practice.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | Yes | Which analysis to run. | |
| limit | No | [patterns] Maximum number of pattern examples to return | |
| apiName | No | [api-usage] REQUIRED. Name of the API/class to get usage patterns for. | |
| context | No | [api-usage] Optional context to filter patterns (e.g., "initialization", "validation"). | |
| scenario | No | [patterns] REQUIRED. Scenario/functionality to analyze (e.g., "financial dimensions", "inventory transactions"). | |
| className | No | [implementations|completeness] REQUIRED. Class to analyze / containing the method. | |
| methodName | No | [implementations] REQUIRED. Name of the method to implement. | |
| parameters | No | [implementations] Method parameters. | |
| returnType | No | [implementations] Method return type. | void |
| classPattern | No | [patterns] Optional class name pattern to filter results (e.g., "Helper", "Service"). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true, so the tool is known to be harmless. The description adds value by explaining what each mode returns (e.g., 'real implementation examples', 'missing standard methods'), offering behavioral context beyond the schema. It doesn't discuss performance or limitations, but the read-only nature is covered by annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a brief opening and a bulleted list of modes. It is concise enough for a multi-mode tool and front-loads the core action. Every sentence adds information, though the list is somewhat lengthy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Without an output schema, the description compensates by explaining the return type of each mode (patterns, code examples, gaps, usage). Given the tool's complexity (10 params, 4 modes) and the read-only annotation, the description is sufficiently complete for an agent to select and invoke the tool correctly. Minor gaps remain around edge-case behavior, but not critical.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description repeats mode-to-parameter associations (e.g., '[patterns]', '[api-usage]') but does not add substantive meaning beyond what the schema already provides. Each parameter's purpose is already documented in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Learn from the existing codebase' and then enumerates four distinct modes with concrete outcomes (patterns, implementations, completeness, api-usage). It distinguishes itself by naming these modes, though the verb 'learn' is somewhat abstract and it doesn't explicitly contrast with sibling tools like get_method or object_patterns.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides an explicit usage directive: 'call BEFORE generate_object(mode="pattern")' for the patterns mode. Other modes are described with their purposes, implying appropriate use cases, but no exclusions or comparisons to alternative tools are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
build_d365fo_projectAIdempotent
Build a D365FO model with xppc.exe (compiles the ENTIRE model, not one project). Blocks until done — call ONCE per build, do NOT poll (wait:false = legacy polling mode). fullBuild:true fixes "not been successfully compiled since it was last changed" stale-symbol errors.
| Name | Required | Description | Default |
|---|---|---|---|
| wait | No | When true (default) the tool blocks until the build finishes and returns the final result in a single call. The agent should make exactly one call per requested build. Set false for legacy fire-and-forget polling behaviour. | |
| force | No | Kill any running build processes for this model and restart. | |
| dbSync | No | On a SUCCESSFUL build, also run the database sync (SyncEngine.exe) — REQUIRED after any table/view/data-entity change. true = partial sync of the syncable objects in the project, full-model when it has none; an ARRAY syncs exactly those tables/views (much faster). | |
| bpCheck | No | On a SUCCESSFUL build, also run the best-practice checker and append its findings. Prefer this to a follow-up run_bp_check call: one build call instead of two round trips. | |
| fullBuild | No | Full recompile of the TARGET model only (deps stay incremental). Use when xppc reports stale symbol errors. | |
| modelName | No | D365FO model name to build (e.g. MyCustomModel). Auto-detected from workspace if omitted. | |
| waitTimeoutMs | No | Maximum time (ms) to block when wait:true before returning a "still running" snapshot. Defaults to 30 minutes. The build itself continues in the background. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description clearly discloses that the tool blocks until done and warns against polling, which adds real behavioral context. It also explains the effect of fullBuild on stale-symbol errors. Annotations already cover read-only/destructive hints, so the description builds on them without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences, each earning its place. The key behavioral constraint (blocks, call once, don't poll) is front-loaded, and the fullBuild fix is stated as a specific conditional. No filler or redundant restating of the tool name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-parameter tool with no output schema, the description plus rich input schema covers the important behavioral caveats: blocking, single-call usage, whole-model compilation, and stale-symbol remediation. It is slightly incomplete in not mentioning the dbSync requirement after schema changes, though the schema handles that thoroughly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds some interpretive value by explaining the full-model scope and a concrete use case for fullBuild, but most parameter meaning is already well documented in the schema. It does not materially clarify the other six parameters beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action (Build), a specific resource (D365FO model via xppc.exe), and explicitly distinguishes scope: compiles the ENTIRE model, not one project. This clearly separates it from project-level or verification tools like verify_d365fo_project.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives strong operational guidance: call exactly once per build, do not poll, and use fullBuild:true for stale-symbol errors. It does not explicitly name sibling alternatives or state when to use an alternative tool, but the blocking semantics and fullBuild trigger provide clear usage context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
d365fo_fileADestructive
Create, modify, delete, undo, or generate a D365FO AOT object. Choose an action:
• create → write a NEW object file into PackagesLocalDirectory (UTF-8 BOM, auto-added to .rnrproj). THE WRITE STEP — incomplete until isError=false; ⚠️/❌ = failure. Extensions: objectName="Base.PrefixExtension".
• modify → edit an EXISTING object. APPLIES IMMEDIATELY, no dry-run — confirm with the user first; revert with action="undo". Needs operation.
• delete → remove an object's XML from disk AND un-register it from every .rnrproj of the model that lists it. IRREVERSIBLE — confirm with the user first.
• undo → roll back filePath: git-tracked → git checkout HEAD, which discards ALL uncommitted changes to that file, not just the last edit; untracked → deleted.
• generate → XML as TEXT only, no write (Azure/Linux fallback). Try create first. create/modify/delete/undo need Windows.
📖 Parameters are NOT inlined here: get_knowledge(kind="op-spec", topic=""|"") returns the contract for the one you picked — pass its values nested in params (modify) / properties (create), along with any packageName/packagePath/solutionPath/workspacePath override.
Model + prefix auto-applied.
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | ||
| params | No | [modify] Operation-specific parameters as ONE nested object, per the op-spec lookup above. A missing/wrong one returns that COMPLETE spec — follow it, do not guess. | |
| filePath | No | [modify|delete] Absolute XML path — bypasses symbol-DB lookup. Use for objects just created. [undo] REQUIRED: the file to roll back. | |
| modelName | No | Target model — auto-detected. NEVER take it from search results (those are source models). | |
| operation | No | [modify] REQUIRED unless using operations[]. add-method also UPDATES in place; replace-code is the surgical oldCode→newCode path. | |
| overwrite | No | Allow overwriting — never rewrite via PowerShell. | |
| objectName | No | Base name WITHOUT model prefix — the tool prepends it. Extension classes: "{Base}_Extension". NEVER hand-build the prefix. | |
| objectType | No | Each security/menu-item type is its own AOT folder — NEVER use security-privilege for duty or role. [modify]/[generate] cover the core families + their *-extension variants; [delete] takes the same enum as [create]. | |
| operations | No | [modify|create] PREFERRED for 2+ edits to the SAME object — ONE call, not one per edit. On create they run against the just-created object, under the name it actually got. Entries are {operation, …op-spec params}; objectType/objectName/modelName stay top-level. Applied in order, stopped at the first failure, per-operation results back. | |
| properties | No | [create] Per-objectType creation properties (label, fields[], extends, enumValues[], primaryTable, …) — not in this schema; fetch yours with the op-spec lookup above. | |
| sourceCode | No | X++ source. FOR CLASSES auto-split: <Declaration> = class line + member vars; <Methods> = each method after the closing }. | |
| xmlContent | No | Complete XML written verbatim (+overwrite=true rewrites an object). | |
| projectPath | No | Path to .rnrproj. Set if known, else auto-detected. | |
| addToProject | No | Add to the ACTIVE .rnrproj — keep the default. | |
| createBackup | No | [modify] Back up before modifying. | |
| groundingToken | No | From prepare(change/create). Required for *-extension when GROUNDING_ENFORCE=true; object-bound. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool destructive and non-read-only, but the description adds rich behavioral detail: UTF-8 BOM writes, auto-registration in .rnrproj, IRREVERSIBLE delete semantics, git checkout HEAD behavior for undo, immediate apply with no dry-run for modify, and Windows-only execution. This goes far beyond the annotations and materially changes how an agent should act.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but densely packed and well-structured with per-action bullets, warnings, and navigation hints. Critical safety information is front-loaded and visually emphasized, and no sentence is filler given the tool's genuine complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-action tool with 16 parameters and no output schema, the description covers most operational context: environment constraints, op-spec lookup, project-file behavior, failure signals via isError, and per-operation results. The only minor gap is that it does not describe the success return shape in more detail beyond these signals.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is high at 94%, but the description adds essential semantic context: which params nest under params vs properties, how op-spec lookups supply operation-specific contracts, when filePath bypasses symbol-DB lookup, and critical anti-guidance like 'NEVER hand-build the prefix' and 'NEVER take modelName from search results.' This meaningfully exceeds the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise verb and resource: 'Create, modify, delete, undo, or generate a D365FO AOT object.' Each action is explicitly defined and distinguished from the others, making the tool's boundaries clear even without reading the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives actionable when-to-use guidance for each action: modify applies immediately so confirm first, delete is irreversible, undo discards ALL uncommitted changes, generate is the non-Windows fallback with 'Try create first.' It also tells the agent to fetch op-spec contracts via get_knowledge before invoking, which prevents guessing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
extension_infoARead-only
D365FO extensibility analyzer. Choose a mode:
• coc → Chain of Command extensions + event subscriptions for a class/table. Use before writing a CoC extension to check for conflicts.
• events → event handler subscriptions (SubscribesTo, delegate +=) for a class/table. Use before adding handlers to check for duplicates.
• table-merge → all extensions of a table across models + effective merged schema (base + extension fields/indexes/methods).
• points → available extension points (CoC-eligible/replaceable methods, delegates, blocked methods) and which are already extended.
• strategy → recommends the best extensibility mechanism for a goal (CoC, event handler, business event, data entity, …) with reasoning, risks, alternatives, next steps.
| Name | Required | Description | Default |
|---|---|---|---|
| goal | No | [strategy] REQUIRED. What you want to achieve — e.g. "validate that SalesLine quantity is positive". | |
| mode | Yes | coc/events/table-merge/points need `target`; strategy needs `goal`. | |
| method | No | [coc] filter to a specific method name; [events] filter to a specific event name (e.g. onInserted). | |
| target | No | The base object: [coc] class/table being extended; [events] class/table whose handlers to find; [table-merge] base table; [points] class/table/form; [strategy] optional target object. | |
| scenario | No | [strategy] Scenario category (auto-detected from goal if omitted). field-defaulting = set defaults on NEW records (initValue); field-change-reaction = react when a user/code CHANGES a field (modifiedField). | |
| objectType | No | [events] set "table" when target is a table (else class is assumed); [points] object type (default: auto-detect). | auto |
| handlerType | No | [events] Filter by handler type (default: all). | all |
| includeEventHandlers | No | [coc] Also find static event subscriptions (SubscribesTo) (default: true). | |
| includeEffectiveSchema | No | [table-merge] Merge base + extension counts (default: true). | |
| showExistingExtensions | No | [points] Also list who already wraps/subscribes each point — opt-in, roughly doubles the response. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and openWorldHint=false, so the tool is known to be read-only. The description adds behavioral context by detailing what each mode returns or analyzes (e.g., effective merged schema, available extension points, who already wraps). It also notes that showExistingExtensions 'roughly doubles the response', a practical performance trait. It does not contradict annotations and adds value beyond them, though it doesn't cover potential errors or latency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a compact bulleted list, front-loaded with a clear one-line purpose. Each mode is described in one or two sentences with no redundancy. The structure is scannable and every sentence earns its place, from the overall analysis purpose to mode-specific guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 10 parameters and 5 modes, the description covers all modes and their intended use cases, including which parameters are relevant per mode. It explains outputs (e.g., merged schema, extension points, recommendations) sufficiently without an output schema. No missing critical information prevents an agent from calling the tool correctly, making it complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% with detailed per-parameter descriptions (e.g., mode: 'coc/events/table-merge/points need target; strategy needs goal'). The description adds mode-level context but does not introduce new parameter meanings beyond the schema. Since the schema already documents parameters thoroughly, the baseline of 3 is appropriate; the description names which modes use which parameters, slightly aiding selection but not adding substantial semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states 'D365FO extensibility analyzer' and enumerates five distinct modes (coc, events, table-merge, points, strategy) with specific resources and goals. Each mode is tied to a concrete action (e.g., 'Chain of Command extensions + event subscriptions for a class/table'), making it unambiguous what the tool does and how it differs from generic search or analysis tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Every mode includes explicit usage context: 'Use before writing a CoC extension to check for conflicts', 'Use before adding handlers to check for duplicates'. The strategy mode states it 'recommends the best extensibility mechanism for a goal', and the description explains which parameters each mode requires. This provides clear when-to-use guidance for each variation, effectively distinguishing from siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_referencesARead-only
Find all references (where-used) to a class, method, field, table, enum, or LABEL. Essential for impact analysis before refactoring. For a method, SCOPE it to its declaring type — pass "Owner.method" (e.g. "SalesTable.initFromSalesQuotationTable"), set ownerName alongside a bare method name, or pass an AOT path ("/Tables/SalesTable/Methods/initFromSalesQuotationTable"). A bare method name (no owner) matches that name on every type and over-reports. For a label, pass the label id as targetName (e.g. "@WAX2194" or "@MyLabelFile:MyLabel"); results span every referencing object type (tables, forms, EDTs, enums, reports, menu items, …), not just code, and require the xref database (DYNAMICSXREFDB, full server mode).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of references to return | |
| ownerName | No | Declaring table/class/form that owns the method, when targetName is the bare method name. Scopes the where-used to that single type. | |
| targetName | Yes | Target name. Methods: see the scoping rule in the description above. Labels: the id exactly as written — "@WAX2194" or "@LabelFile:LabelId". | |
| targetType | No | Type of the target to search for. Use "label" for label where-used (or just pass an "@…" / "/Labels/@…" targetName). | all |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so a read operation is understood. The description adds meaningful behavioral detail beyond that: the method-name-matches-every-type over-reporting behavior, that label results span every object type (not just code), and the DYNAMICSXREFDB/full-server-mode requirement. This enriches the safety/behavioral profile without contradicting annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every sentence earns its place — method scoping, label semantics, and prerequisites are all operationally critical for correct invocation. It is front-loaded with the core purpose and scoping rule before edge cases. Slightly dense but no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Comprehensive for a read tool whose annotations already cover safety: all target types, method-scoping edge cases, label behavior, and the xref prerequisite are covered. The only gap is that with no output schema, the return format/pagination behavior (relevant given the limit param) is not described. Otherwise nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite 100% schema coverage, the description substantially enriches parameter meaning. It explains the targetName scoping rule for methods (Owner.method vs bare name vs AOT path), the exact label id format ('@WAX2194' or '@MyLabelFile:MyLabel'), and how ownerName scopes a bare method name. It also clarifies targetType's 'label' value and the '@…' shortcut. This goes well beyond the schema's one-line parameter descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Find all references (where-used) to a class, method, field, table, enum, or LABEL.' This clearly distinguishes it from siblings like search (general search), get_object_info, and validate_code. The 'Essential for impact analysis before refactoring' line reinforces the distinct role. No tautology.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides strong usage context — 'Essential for impact analysis before refactoring' — plus concrete invocation patterns (Owner.method, ownerName, AOT path) and an explicit over-reporting warning for bare method names. Covers label usage and its xref database prerequisite. It doesn't name which sibling to use instead in specific cases, but the guidance is otherwise explicit and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
generate_objectA
Generate X++/AOT code. Choose a mode:
• pattern → a named X++ skeleton from the pattern enum (text only, no write). Call analyze_code(mode="patterns") first, then generate_object(mode="pattern"), then d365fo_file(action="create").
• scaffold → pattern-aware whole-object generation (table/form/report) with intelligent field/index/relation or form-pattern suggestions; set objectType.
• find-methods → find()/findRecId()/exists() for a table (text), keyed on its primary/unique index.
• relation-xpp → a table's relation(s) → X++ select + QueryBuildRange (text).
• fields → field names → AxTableField XML with auto-resolved EDTs + optional field group.
• table-relation → EDT-referencing fields → AxTableRelation XML (inverse of relation-xpp).
📖 Mode parameters are NOT inlined here: get_knowledge(kind="op-spec", topic="") — "scaffold:table"/"scaffold:form"/"scaffold:report" for the scaffolds — returns the contract; pass its values nested in params.
For a single existing object definition's XML use d365fo_file(action="generate") instead.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | Yes | ||
| name | No | REQUIRED. [pattern] element name (extensions: base element; form-datasource/control-extension: the FORM name). [scaffold] object name WITHOUT model prefix. [other modes] the existing table. | |
| params | No | Mode-specific parameters as ONE nested object (label, fields[], fieldsHint, cloneFrom, tableMapping, formPattern, contractParams[], keyFields[], style, fieldGroup, …). A missing required one is answered with that mode's COMPLETE spec. | |
| pattern | No | [pattern] REQUIRED. ssrs-report-full = Contract+DP+Controller; service-class-ais = CRUD service + contract; systest = failing SysTestCase (TDD red); report-* extend a STANDARD report (recipes: object_patterns(domain="report")). | |
| modelName | No | Model name (auto-detected). NEVER use placeholders like "MyModel". | |
| objectType | No | [scaffold] REQUIRED. Kind of object to generate. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description clearly discloses that pattern mode is 'text only, no write', and it labels outputs for most modes (text, XML, X++ snippets). It also reveals that missing required parameters cause the tool to return that mode's complete spec. However, scaffold mode's write-vs-return behavior is not explicitly stated, leaving some ambiguity about side effects beyond what the annotations convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well-organized with a front-loaded purpose statement and a clear bullet list of modes. Every sentence carries routing, parameter, or behavioral information; no filler or redundant restatement of the schema is present. The length is proportional to the tool's six-mode complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no output schema and six distinct modes, the description is remarkably complete: it explains each mode's intent, output form, required setup, and related tools. It intentionally outsources full mode contracts to get_knowledge, which is a reasonable and explicit completeness mechanism. The only slight gap is scaffold's output behavior, but the overall guidance is sufficient for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Even though the schema covers 83% of parameters, the description adds substantial meaning: it explains what `name` means for each mode, clarifies that `params` is one nested object, decodes pattern enum abbreviations, and notes that modelName is auto-detected. This goes well beyond the raw schema and helps an agent construct valid calls.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource, 'Generate X++/AOT code', and immediately enumerates six distinct modes with their concrete outputs. It also explicitly contrasts this tool with d365fo_file(action="generate") for existing objects, making it easy for an agent to distinguish it from a sibling tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit workflow for pattern mode: call analyze_code(mode="patterns") first, then generate_object(mode="pattern"), then d365fo_file(action="create"). It also directs agents to get_knowledge for mode contracts and identifies d365fo_file(action="generate") as the alternative for existing object XML, providing clear when-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_knowledgeARead-only
X++ knowledge lookup. Choose a kind:
• knowledge → queryable X++ rulebook: verified patterns, BP rules, AX2012→D365FO migration. Use BEFORE generating code. Topics incl.: select-statement, coc-authoring, bp-rules, sysoperation, event-handlers, workflow, number-sequences, security, sysda, form patterns.
• error → diagnose a D365FO/X++ compiler or runtime error: structured root cause + step-by-step fix + corrected X++ example (TTS mismatch, UpdateConflict, CSUV1, SYS10028 missing next, overlayering, BP errors, …). Call this instead of guessing — X++ error semantics differ from C#/.NET.
• op-spec → the parameter contract for ONE d365fo_file operation/objectType or ONE generate_object mode (topic = "add-index", "table", "scaffold:form", …). Those two tools deliberately do not ship their parameters inline; call this after picking the operation, before the call. Omit topic for the index of available topics.
• bp-moniker → validate an exact BP-check moniker, search by scenario when you have no moniker yet, or render a _BPSuppressions.xml block. Backed by names/text extracted from a real D365FO install — never invents a moniker.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | ||
| path | No | [bp-moniker suppress] REQUIRED. dynamics:// path, verbatim from the finding. | |
| topic | No | [knowledge] REQUIRED. Topic to query — e.g. "ttsbegin", "RunBase vs SysOperation". [op-spec] The operation / objectType / mode to look up. | |
| action | No | [bp-moniker] REQUIRED. validate = confirm an exact moniker is real; search = free-text scenario query; suppress = render a <Diagnostic> block. | |
| format | No | [knowledge] concise = quick reference (default), detailed = full explanation with code examples | concise |
| topics | No | [knowledge|op-spec] Look up SEVERAL topics in one call instead of one call each. Replaces topic. | |
| moniker | No | [bp-moniker validate/suppress] REQUIRED. Exact moniker, e.g. "BPErrorPrivilegeNotCoveredByDuty". | |
| errorCode | No | [error] Optional error code (e.g. SYS10028, CSUV1, BPUpgradeCodeToday) | |
| errorText | No | [error] REQUIRED. Full error message text as displayed in the X++ compiler or event log | |
| justification | No | [bp-moniker suppress] REQUIRED. Why the warning is ignored; 95% of real entries carry one. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations cover read-only safety, and the description adds behavioral guarantees beyond that: knowledge is a 'queryable rulebook', error mode promises 'structured root cause + step-by-step fix + corrected X++ example', and bp-moniker is 'backed by names/text extracted from a real D365FO install — never invents a moniker'. No contradiction with readOnlyHint or openWorldHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is bulleted and front-loaded with the core instruction ('Choose a kind'), then each mode gets a compact, purposeful sentence with no filler. The length is justified by the four distinct behaviors and the need to route callers correctly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 10-parameter tool with no output schema, the description covers the input space thoroughly: all four kind values, their intended use, the output shape for error mode, the index behavior for op-spec, and the rendered Diagnostic block for bp-moniker. The remaining details are already captured by the high-coverage input schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already high (90%) and each parameter has a mode-tagged description, so the baseline is 3. The description earns an extra point by explaining why op-spec exists, by defining what each kind means for parameter selection, and by adding the 'omit topic for index' rule that clarifies an otherwise underspecified optional parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('knowledge lookup') plus four clearly delineated resource kinds, each with its own purpose: rulebook, error diagnostics, op-spec contract, and bp-moniker validation. It explicitly references the sibling tools d365fo_file and generate_object, making it easy for an agent to distinguish this from nearby operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Each bullet gives an explicit when-to-use rule: knowledge before generating code, error instead of guessing, op-spec after picking the operation and before the call, bp-moniker for validate/search/suppress. It even explains that d365fo_file and generate_object deliberately omit inline parameters, making this lookup a required prerequisite rather than an optional convenience.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_object_infoARead-only
Read D365FO object metadata. For 2+ objects pass objects:[{objectType,objectName},…] (max 10) — ONE call, run in parallel, per-object sections back; never loop single calls. One object: {objectType, name}. Pick the kind via objectType: class, table, form, query, view, enum, edt, report, data-entity, menu-item, service, map, config-key, security-policy, macro. Extension types (table-extension, form-extension, enum-extension, edt-extension, data-entity-extension) list all extensions of a base object — pass the base object name or a full extension name (the dot suffix is stripped automatically). Type-specific flags go in options. For CLASSES, {"members":"names"} (optional {"prefix":...}) returns a fast IntelliSense-style member-name list instead of full metadata.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Exact object name (use search first if unsure). REQUIRED unless using objects[]. | |
| objects | No | PREFERRED for 2+ objects: read them all in one round trip. Each entry takes the same objectType/options as the single form, with the name in objectName. | |
| options | No | Type-specific reader flags: includeRdl (report), searchControl/maxControls (form), compact/methodOffset (class+table), fieldsOffset/fieldFilter/relations (table), filter (macro), mode (edt), includeFields, includeOperations, modelName. On class/table/view/data-entity, {"method":"validateWrite","include":"signature"} returns ONE method (include: signature | source | both) — required before writing a CoC extension. {"include":"xml"} returns raw AOT XML + its path (page: startLine/endLine) — never shell out to find or read a file. Applies to every objects[] entry. | |
| objectType | No | Kind of object to read. REQUIRED unless using objects[]. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark readOnlyHint=true, and openWorldHint=false, so the read-only safety profile is established. The description adds substantial behavioral context beyond that: batching with max 10, parallel execution, per-object sections, automatic dot-suffix stripping for extensions, the members shortcut for classes, and the method-signature option needed before writing CoC extensions. This richly discloses how the tool behaves.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but dense and appropriately front-loaded with the core purpose. Every sentence carries operational value, and guidance like 'never loop single calls' is a necessary addition. It could be slightly improved with clearer visual separation of the many rules, but no sentence is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no output schema and high complexity, the description covers the main calling patterns, type taxonomy, extension behavior, and key options. It gives only a high-level picture of return values ('per-object sections back', 'fast IntelliSense-style member-name list'), which is probably sufficient for invocation but leaves some response-shape detail unspecified. Still, the description is complete enough for an agent to select and call the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description adds significant semantic value beyond the schema: it clarifies that objects[] is the preferred batch form, explains how extension types treat base vs. extension names, lists what each options flag is used for, and gives concrete examples like {"members":"names"} and {"method":"validateWrite","include":"signature"}. This goes well beyond the schema's own descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Read D365FO object metadata.' It also enumerates the supported object types and distinguishes the read-oriented purpose from sibling tools by implication. However, it does not explicitly name or contrast any sibling (e.g., search, find_references), so differentiation is clear but not stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives strong operational guidance: use objects[] for 2+ objects, never loop single calls, pass base or full extension names, and use type-specific options. It also includes an explicit 'never shell out' directive. It does not, however, tell the agent when to prefer this tool over specific siblings such as search or find_references, so exclusion guidance is incomplete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_workspace_infoARead-only
ALWAYS call FIRST at session start. Returns model name, package path, framework directory, project path, environment type, and EXTENSION_PREFIX. Flags placeholder model names and missing prefix. Pass projectName/projectPath when you have the project's name or path. Authoritative source for target model — not search results.
| Name | Required | Description | Default |
|---|---|---|---|
| changes | No | Return the uncommitted X++ changes (`git diff HEAD`) plus per-file rollback hints INSTEAD of the configuration. Review-only — not a way to verify a write. | |
| diagnostics | No | Include verbose sections (config sources, suffix, project paths, index scan, stdio handshake). Use when debugging config or connectivity. | |
| projectName | No | The PROJECT file name, e.g. "Contoso - FeatureManagement" — pass it whenever you have one: the USER named it, or an earlier call listed it. NOT a model name, and not a guess from a ticket: one model has many projects, so naming it selects none. Steers WRITES only; reads span every model already. | |
| projectPath | No | Absolute path to a .rnrproj file. Use when projectName is ambiguous, none was auto-selected, or D365FO_SOLUTIONS_PATH is unset. Example: "K:\\repos\\Contoso\\MyProject\\MyProject.rnrproj" |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond readOnlyHint=true, the description reveals useful traits: it flags placeholder model names and missing EXTENSION_PREFIX, is the authoritative source for the target model, and treats the changes parameter as review-only ('not a way to verify a write'). This gives agents expectations about validation and reliability.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the most important instruction ('ALWAYS call FIRST at session start'), then lists return values, flags, and source authority in four tight sentences. No filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-output-schema tool, it names the key returned fields, flags edge conditions (placeholder model, missing prefix), and tells the agent where the information sits in the session workflow. Combined with the rich parameter schema, nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema already fully documents all four parameters. The description adds only a small usage note about passing projectName/projectPath, but does not materially extend the parameter semantics beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource ('get workspace info') and states precisely what it returns: model name, package path, framework directory, project path, environment type, and EXTENSION_PREFIX. It also distinguishes itself from siblings by declaring it the 'Authoritative source for target model — not search results,' and by being the mandated first call.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit invocation rule ('ALWAYS call FIRST at session start'), tells when to pass projectName/projectPath ('when you have the project's name or path'), and warns against using search results for the target model. The schema's diagnostics and changes parameters further state when to use them (debugging vs review-only), so an agent knows when to call this vs alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
labelsADestructive
Unified label operations — read and write. Writing an object? d365fo_file create/modify already turn a raw-text label/fieldLabel into a real @Ref by themselves; no call here is needed. Choose an action:
• search → full-text query across indexed label files. Never needed before a create.
• info → all translations for a labelId; without labelId lists label files (with labelFileId: physical .label.txt path per language).
• create → add a label to an AxLabelFile across every language .label.txt (write). ALWAYS pass createIfMissing=true: it creates when absent and reuses when present, so this ONE call replaces search-then-create. Bulk: labels:[{labelId, translations}, …] with shared labelFileId/model at top level does a whole object in one call. Label IDs describe MEANING — never a model prefix; target the model's ORIGINAL label file, never an …_Extension… one.
• update → overwrite the text of an EXISTING label; same args as create with corrected translations[] (write).
• rename → rename a label ID across .label.txt + X++ + XML + index. Use dryRun=true first (write).
Write plumbing (paths, languages, sortLabels, allowExtensionLabelFile…) is auto-resolved; override it via get_knowledge(kind="op-spec", topic="labels").
| Name | Required | Description | Default |
|---|---|---|---|
| model | No | [search|info|create|update|rename] Model that owns the label file (e.g. ContosoExt). | |
| query | No | [search] REQUIRED. Search text — matches label ID, text and developer comment. ARRAY = try several phrasings in ONE call. | |
| action | Yes | ||
| dryRun | No | [rename] Preview changes without writing anything. | |
| labels | No | [create] Bulk mode — shared fields stay at the top level (top-level labelId/translations are then ignored); a failed entry does not abort the batch. | |
| params | No | Optional write plumbing — the auto-resolved overrides named at the end of the description above. | |
| labelId | No | [info] Label ID, any spelling: SYS67433, @SYS67433, @ContosoExt:MyLabel (paste search output). labelFileId/model optional. Omit to list label files. | |
| verbose | No | [search] Default one line per label; true = full multi-line block. | |
| language | No | [search] Language/locale (default: en-US). Examples: cs, de, sk. | |
| maxResults | No | [search] Max labels listed (default 10); a truncated set reports how many more matched. | |
| newLabelId | No | [rename] REQUIRED. New label ID. | |
| oldLabelId | No | [rename] REQUIRED. Current label ID (e.g. MyOldField). | |
| labelFileId | No | [search|info|create|update|rename] AxLabelFile ID (e.g. ContosoExt, SYS). For a NEW label file this ID is the MODEL name, never the bare EXTENSION_PREFIX. | |
| translations | No | [create] REQUIRED for single-label create (omit when using labels[]). Translations for each language. Provide at least en-US. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as destructive and not read-only, and the description adds concrete behavioral details: update overwrites existing labels, rename affects .label.txt + X++ + XML + index, bulk failures do not abort the batch, and write plumbing is auto-resolved unless overridden. This is far beyond what annotations alone provide, and there is no contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and then organized by action in a scannable bullet list. It is long, but the tool has 14 parameters and five distinct action modes; the density is justified. One small deduction because some parameter-level details like 'Default one line per label' could have been left to the schema descriptions.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers all five actions, their key parameters, write plumbing, bulk mode, and even output hints for search truncation. However, there is no return-value explanation for create/update/rename and no output schema, so an agent does not know exactly what those write calls respond with. Given the tool's complexity, that is a minor but real gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 93%, but the description adds substantial extra meaning: array queries mean multiple phrasings, labelId accepts @SYS or @Model:Label spellings, labelFileId semantics differ for new vs existing files, label IDs should describe meaning rather than model prefixes, and bulk mode expects shared fields at the top level. It even explains the required createIfMissing=true behavior despite that parameter not being a direct named schema property.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly presents 'Unified label operations — read and write' and enumerates five distinct actions with specific verbs: search, info, create, update, rename. It also distinguishes itself from sibling d365fo_file by explaining when no label call is needed, so an agent can tell what this tool is for.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: search is 'never needed before a create,' createIfMissing=true replaces search-then-create, write operations are labeled as write, and rename advices dryRun first. It also names alternatives like d365fo_file create/modify and tells the agent when to use get_knowledge for overrides.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
object_patternsARead-only
Pattern toolkit. Choose a domain:
• table → field/index/relation patterns for D365FO tables. Filter by tableGroup or similarTo a given table.
• form → form-pattern toolkit; pick an action:
analyze → pattern advisor + usage analysis. For a NEW form pass
recommend(preferred): the Microsoft decision tree picks the pattern and names reference forms to clone. Or filter by formPattern / dataSource / similarTo.spec → structure spec of a pattern/sub-pattern: hierarchy, ordering, allowed children, reference forms, lifecycle.
validate → AxForm XML validator (hierarchy/order, sub-patterns, PatternVersion) → FP001-FP010. Call before d365fo_file action=create. • report → SSRS implementation recipes: object roster, scaffold call, checks. Optional pattern=. • mobile-app → warehouse-app screen recipes, led by the choice between the two frameworks that build them (ProcessGuide vs WHSWorkExecuteDisplay): create a flow, add or replace one screen, step icon/title, GS1 scan input. Optional pattern=.
| Name | Required | Description | Default |
|---|---|---|---|
| xml | No | [validate] Complete AxForm XML to validate. Provide this OR formName/filePath. | |
| limit | No | [analyze] Max pattern examples. | |
| action | No | [form] Which form-pattern operation to run. repair = auto-fill missing required controls. | |
| domain | No | Optional — inferred from the other params (action/pattern/xml/formName → form; tableGroup → table). A concept like "number-sequence" is not a domain: that is get_knowledge. | |
| pattern | No | [spec|report|mobile-app] Pattern name (id, xmlName or alias) — e.g. "SimpleList", "FieldsFieldGroups", "PrintMgmtFormLetter", "processguide-flow". | |
| filePath | No | [form/validate] Path to an AxForm XML file not yet indexed. | |
| formName | No | [validate] Name of an indexed form — XML is loaded from the metadata store. | |
| recommend | No | [analyze] Pattern advisor: describe requirements, get a recommended pattern + reference forms to clone. | |
| similarTo | No | [table] table / [form-analyze] form name to find similar patterns. | |
| dataSource | No | [form/analyze] Table name - find forms using this table | |
| tableGroup | No | [table] Table group type to analyze (choose one). | |
| formPattern | No | [analyze] D365FO form pattern to analyze |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint annotation already covers the non-destructive nature. The description adds useful behavioral context: validation returns FP001-FP010 checks, analyze uses the Microsoft decision tree and names reference forms, and validate is meant to precede d365fo_file creation. It would be stronger if it explained the repair action's in-memory behavior explicitly, but there is no contradiction 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well-structured with domain bullets and action sub-bullets. It front-loads the domain decision and avoids repeating parameter-level detail already in the schema. For a 12-parameter, multi-domain tool, this is appropriately sized and scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Considering the complexity and the read-only annotation, the description is nearly complete: it covers all major domains, the main actions, output-like evidence (reference forms, FP codes), and a cross-tool dependency. The one clear gap is the undocumented 'repair' action, which prevents a perfect score.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds value by showing how parameters combine by domain and action, e.g. recommend for new forms, tableGroup/similarTo for table patterns, and pattern=<id> for report/mobile-app. It does not discuss repair or limit, but the schema documents those clearly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description is a detailed pattern toolkit manual: each domain (table, form, report, mobile-app) is tied to concrete operations such as analyze, spec, validate, and recipe generation. It clearly scopes the tool to D365FO pattern concerns and even names the related d365fo_file create action for the validation flow.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives strong usage guidance inside the tool: 'For a NEW form pass recommend (preferred)', 'Call before d365fo_file action=create', and it explains when to filter by formPattern/dataSource/similarTo. However, the schema's action enum also lists 'repair' yet the description completely omits that action, so guidance for one alternative is missing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
prepareARead-only
ONE-call context aggregator + groundingToken (30-min TTL, required for extension/new-object writes when GROUNDING_ENFORCE=true). Choose a mode:
• change → extending/modifying an EXISTING object: exact signature, existing CoC wrappers, eligibility, recommended strategy, naming, patterns. Replaces the analyze→search→info→generate loop.
• create → a NEW object: collision check, naming with auto-prefix, similar objects, EDT suggestions, reusable labels, mined property defaults.
• test → writing a SysTest for an existing class: methods worth covering, tests that already exist, whether the model references TestEssentials, and the red-first cycle.
| Name | Required | Description | Default |
|---|---|---|---|
| goal | Yes | One-sentence description of the intent. Example (change): "Add CoC on CustTable.validateWrite". Example (create): "Parameter table for the Contoso import feature." | |
| mode | Yes | ||
| operation | No | [change] The modify operation(s) you intend to run — comma-separated for several ("add-field,add-index"). Their full parameter contracts come back in THIS response. Defaults to add-method when methodName is given. | |
| fieldsHint | No | [create] For tables/views: planned field names — each gets EDT suggestions from the index. | |
| methodName | No | [change] Target method name when the change involves a specific method (CoC or event handlers). Example: "validateWrite". | |
| objectName | Yes | [change] Name of the object to extend/modify (e.g. "CustTable"). [create] Proposed BASE name WITHOUT model prefix. | |
| objectType | No | [change] type — auto-detected when omitted. [create] REQUIRED; an extension is Base.Suffix. | |
| proposedName | No | [change] Proposed name for the new extension class/object. When provided, naming validation runs. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true, so safety is covered. The description adds useful behavioral details beyond the annotations: groundingToken has a 30-minute TTL and is required for extension/new-object writes when GROUNDING_ENFORCE=true. It does not describe the full response shape, but the token and its lifecycle are disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well-structured: the core value proposition and token requirement are front-loaded, then each mode gets a concise bullet with concrete outputs. Every sentence contributes useful information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema, the description enumerates exactly what each mode returns: signatures, wrappers, collision checks, naming advice, EDT suggestions, tests, and the red-first cycle. It also explains parameter behavior such as operation defaults and objectType auto-detection, making it sufficient for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 88%, and the input schema already documents each parameter with mode-specific meanings and examples. The description adds high-level mode context but does not materially improve parameter-level understanding beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies 'prepare' as a one-call context aggregator that returns a groundingToken, and it defines distinct change/create/test modes with concrete outputs. It also differentiates itself from the sibling loop by explicitly stating it replaces analyze→search→info→generate.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit mode-specific guidance: change for modifying existing objects, create for new objects, and test for writing SysTests. It also names the multi-tool alternative it replaces, making selection straightforward.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_bp_checkARead-only
Run Microsoft Best Practices checker (xppbp.exe) on a D365FO project. Returns BP warnings and errors with rule codes (e.g. BPErrorLabelIsText, BPXmlDocNoDocumentationComments). Runs AFTER a build, not after a write — and build_d365fo_project(bpCheck:true) already folds this check into the build, so a separate call is rarely needed.
| Name | Required | Description | Default |
|---|---|---|---|
| objects | No | Check several objects in ONE call — preferred over targetFilter. Shared preamble is printed once and findings are grouped per object. | |
| modelName | No | Model name to check. Auto-detected if omitted. | |
| packagePath | No | PackagesLocalDirectory root path. Auto-detected if omitted. | |
| projectPath | No | Absolute path to the .rnrproj file to analyze. Auto-detected if omitted. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the read-only nature is covered. The description adds useful behavioral context: the ordering constraint relative to builds, the kind of findings returned, and the relationship to the integrated build check. It does not cover failure modes or permissions, but the read-only annotation lowers the burden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences deliver purpose, output examples, a usage precondition, and the key alternative in a compact way. There is no filler, and the most important scoping guidance appears early.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description correctly covers what the tool returns: BP warnings and errors with rule codes. It also communicates when to call it and why separate calls are often unnecessary. It could mention result grouping or what happens when all parameters are omitted, but the schema already covers parameter auto-detection and batching.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters (objects, modelName, packagePath, projectPath) are already documented with meaningful descriptions, including auto-detection and preferred batching of objects. The description does not need to repeat these details, and it adds only output-related context. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the specific action: running Microsoft Best Practices checker (xppbp.exe) on a D365FO project, and what the output is: BP warnings and errors with rule codes. It also distinguishes itself from the sibling build_d365fo_project by noting that build already integrates this check.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when the tool should be used — AFTER a build, not after a write — and notes that build_d365fo_project(bpCheck:true) already folds this check in, so a separate call is rarely needed. This gives an agent clear routing guidance toward the preferred alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_systest_classA
Execute a D365FO unit test class via SysTestConsole.exe (/unattended), returning per-method results.
| Name | Required | Description | Default |
|---|---|---|---|
| className | Yes | The name of the SysTest class to run (e.g. "MyModuleTest") | |
| modelName | No | The model containing the test class. Auto-detected if omitted. | |
| testMethod | No | Optional: run only this specific test method within the class (e.g. "testValidation"). | |
| packagePath | No | PackagesLocalDirectory root path. Auto-detected if omitted. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds meaningful behavioral detail beyond the annotations by specifying that execution happens via SysTestConsole.exe in unattended mode and that results are returned per method. This tells the agent what kind of operation this is and what to expect without contradicting 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, well-structured sentence. It front-loads the action and target, then adds the execution mechanism and result format with no unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description does need to convey what the caller receives, and it does so by stating 'returning per-method results'. It also covers the core execution context. However, it does not describe the output shape beyond per-method results, which is a minor gap for a test runner with no output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters are already documented in the input schema. The description does not add additional parameter-level meaning, but it also does not need to; the baseline of 3 is appropriate when the schema fully carries parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb ('Execute'), a specific resource ('D365FO unit test class'), and a concrete mechanism ('SysTestConsole.exe (/unattended)'). It also states the observable outcome ('returning per-method results'), making the tool's purpose unambiguous and distinct from sibling build/validation tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes the usage context clear: it is the tool for executing a D365FO unit test class and getting per-method results. While it does not explicitly name alternatives or exclusions, none of the sibling tools perform unit-test execution, so the context is sufficient without needing an explicit when-not-to-use clause.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchARead-only
Search pre-indexed D365FO objects by name or keyword. Three modes in ONE tool:
• single (default) → pass query; returns name, type, model.
• batch → pass queries[] (max 10) to run searches in parallel (3× faster, with dedup + cross-reference).
• extensions → set scope:"extensions" to restrict to custom/ISV models only (filters out Microsoft standard code). Model names in those results are SOURCE models — never use them as create/modify targets.
Use get_object_info(objectType, name) when you already know the exact name and need full details.
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | [single] Filter by object type ("all" = no filter). | all |
| limit | No | [single|extensions] Maximum results to return | |
| query | No | [single|extensions] Search query (class name, method name, table name, etc.). REQUIRED unless using batch `queries[]`. | |
| scope | No | [single] Whole index, or only custom/ISV models. Ignored when `queries[]` is provided. | all |
| prefix | No | [extensions] Extension prefix filter (e.g., ISV_, Custom_). | |
| queries | No | [batch] Array of search queries to execute in parallel (max 10). When provided, runs in batch mode and `scope`/`query` are ignored. | |
| verbose | No | [single] Include related-searches/patterns/tips sections. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond readOnlyHint, the description explains batch parallelization/dedup/cross-reference behavior and warns that extension results report SOURCE models that must never be used as create/modify targets. It also documents ignored parameters in batch mode. This is meaningful behavioral disclosure beyond 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, scannable, and front-loads the core statement followed by three mode bullets and one routing sentence. Every sentence adds decision-relevant information; no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only search tool with no output schema, it covers return content (name, type, model), mode-specific parameter behavior, the extension-model warning, and the relevant sibling. Nothing essential for selecting or invoking the tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds mode-level semantics that connect parameters (query vs queries[], scope ignored in batch, extensions + prefix), plus the source-model caveat, which goes beyond the schema descriptions and helps agents construct valid calls.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource—'Search pre-indexed D365FO objects by name or keyword'—and goes on to name the sibling alternative get_object_info when exact names are known. This makes the tool's job unambiguous and distinguishes it from nearby lookup tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly defines three modes and when each applies (single, batch, extensions), states the max batch size, and closes with a concrete routing rule: use get_object_info when exact name and full details are needed. This is actionable selection guidance rather than implicit context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
security_infoARead-only
D365FO security lookup. Choose a mode:
• artifact → details + full hierarchy of a named privilege/duty/role (Role → Duties → Privileges → Entry Points).
• coverage → reverse chain for an object: which privileges/duties/roles grant access (object → menu items → privileges → duties → roles).
| Name | Required | Description | Default |
|---|---|---|---|
| mode | Yes | ||
| name | No | [artifact] REQUIRED. Name of the security privilege, duty, or role | |
| objectName | No | [coverage] REQUIRED. Name of the form, table, class, or menu item | |
| objectType | No | [coverage] Type of the object (default: auto-detect) | auto |
| artifactType | No | [artifact] REQUIRED. Type of security artifact to look up | |
| includeChain | No | [artifact] Walk the full hierarchy (default: true) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint annotation already communicates non-destructive behavior, so the description's additional detail is valuable: it discloses the traversal paths (Role → Duties → Privileges → Entry Points and object → menu items → privileges → duties → roles). This exceeds what the annotations alone provide and helps the called tool behave predictably, though it doesn't cover potential errors or edge cases.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well structured, using bullet-like mode definitions with clear arrows to show hierarchy. Every sentence and clause contributes practical information, and the most important routing instruction ('Choose a mode') is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Although there is no output schema, the description gives a fairly concrete picture of what the caller can expect: full artifact hierarchies for artifact mode and reverse access chains for coverage mode. Combined with the input schema, this is sufficient for most call intentions, though a few details such as exact response shape or limit behavior are absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is high (83%), and the schema already explains each parameter, including mode-specific requiredness, defaults, and enums. The description reinforces the conceptual meaning of the modes and their output chains, but doesn't add significant parameter-level detail beyond what the schema already provides. Thus it earns the baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as a D365FO security lookup and breaks down two distinct modes: artifact lookup and coverage analysis. Each mode specifies exactly what is returned, including the full hierarchy and reverse chain, making the tool's purpose unambiguous and differentiating it from generic lookup tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context about when to use each mode: 'artifact' for hierarchy details on a security artifact, and 'coverage' for reverse access chains on an object. It does not explicitly name alternative tools or exclusions, so it stops short of a perfect 5, but the mode guidance is strong enough to guide correct invocation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_symbol_indexAIdempotent
Index D365FO XML file(s) changed OUTSIDE this server (hand edit, Visual Studio, git checkout). Do NOT call after d365fo_file create/modify — those refresh the index themselves, so it is a wasted round trip. Omit filePath for a bridge/cache refresh only.
| Name | Required | Description | Default |
|---|---|---|---|
| filePath | No | Absolute path to the changed XML file, or an ARRAY — batch them, each call costs a bridge refresh. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide idempotentHint=true and destructiveHint=false, and the description adds meaningful behavioral context beyond those: each call triggers a bridge refresh cost, calling it after create/modify is a wasted round trip, and omitting filePath changes the operation to a bridge/cache refresh only. This gives the agent a clear mental model of what the tool actually does and its side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, each with a distinct purpose: stating the tool's role, giving an explicit exclusion, and explaining an optional invocation mode. No unnecessary words or redundancy. Information is front-loaded and easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a low-complexity tool with one optional parameter, no output schema, and rich annotations, the description covers purpose, usage boundaries, and both invocation modes. There is no missing information that an agent would need to correctly select and invoke this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents filePath with type, array support, and batching guidance, so the baseline is 3. The description adds critical semantics beyond the schema: omitting filePath performs a bridge/cache refresh only, and the filePath should identify files changed outside this server, which shapes what value the agent should pass. This is valuable supplementary meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb ('Index'), a specific resource ('D365FO XML file(s)'), and a precise scope ('changed OUTSIDE this server'). It also differentiates the tool from sibling d365fo_file create/modify by explaining that those operations already refresh the index. An agent can clearly tell what this tool is for and what it is not for.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool ('changed OUTSIDE this server') and when not to call it ('Do NOT call after d365fo_file create/modify'), naming the alternative tool. It also documents the special mode where filePath is omitted for a bridge/cache refresh only. This is direct, actionable usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
validate_codeARead-only
Static validator for generated X++/XML (paste the text). Choose a mode:
• syntax → offline best-practice/BP validator (no xppbp.exe). Structured violations {rule, severity, line, excerpt, fix}. Covers select, CoC, BP and table-XML rules mined from standard models.
• references → semantic reference resolver (index-only): verifies every type, field, method (incl. arity), enum, label and intrinsic (tableStr/fieldStr/…) EXISTS in the indexed codebase. codeType="xml-table" checks XML refs instead: EDT/enum/relation/extends/label.
Call mode="both" AFTER generating, BEFORE writes; fix errors in the same turn. Write tools run references internally when GROUNDING_ENFORCE=true.
| Name | Required | Description | Default |
|---|---|---|---|
| code | Yes | X++ source code or XML metadata to validate. Paste the full generated text. | |
| mode | Yes | both = run the two checks in ONE call (preferred). | |
| context | No | Optional: owning class/table name, used in diagnostic messages. | |
| codeType | No | [syntax] "xpp" X++ (default), "xml-table" AxTable, "xml-form" AxForm(+Extension), "xml-report" AxReport, "xml-any" other. | xpp |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description adds rich behavioral context: offline operation, no xppbp.exe, index-only reference resolution, structured violation output, and coverage of specific rule families. This makes the tool's side-effect-free and execution model clear.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a concise opening line and bullet-separated modes. It front-loads the core purpose, then gives mode-specific detail and final actionable timing guidance. Every sentence contributes useful information without unnecessary repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no output schema, the description explains the syntax-mode return shape and the overall verification behavior. It is slightly less explicit about the exact return format for references mode, but the usage context, parameter intent, and integration behavior are otherwise well covered.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already covers all parameters at 100%, so the baseline is 3. The description adds meaningful semantics beyond the schema, especially for mode ('both' preferred), codeType ('xml-table' checks XML refs), and the behavior of references mode. It doesn't enrich the context parameter, but the overall value exceeds baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: a static validator for generated X++/XML. The mode breakdown (syntax vs references) and the 'no xppbp.exe' note clearly distinguish it from related siblings like run_bp_check and find_references.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit timing guidance: call mode='both' AFTER generating and BEFORE writes, and fix errors in the same turn. It also notes that write tools run references internally when GROUNDING_ENFORCE=true. It does not explicitly contrast with sibling alternatives, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
validate_object_namingARead-only
Validate a proposed D365FO object name against naming conventions: extension naming, ISV prefix, type-specific suffixes, and conflict detection against the symbol index.
| Name | Required | Description | Default |
|---|---|---|---|
| objectType | Yes | Type of the D365FO object | |
| modelPrefix | No | Expected ISV/model prefix (2-4 uppercase letters, e.g. "WHS"). Auto-detected if omitted. | |
| proposedName | Yes | The proposed object name to validate | |
| baseObjectName | No | Required for extension types: name of the object being extended |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint annotation already signals safety, and the description adds useful behavioral detail by mentioning conflict detection against the symbol index and the categories of naming rules checked. No contradictions exist between description and annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, tightly worded sentence that front-loads the action and resource, then lists the validation checks. Every phrase adds useful information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the moderate complexity, complete parameter schema, and readOnlyHint annotation, the description is largely sufficient for selecting and invoking the tool. It could explicitly mention the return format or that results indicate pass/fail with reasons, but that is a minor gap because the tool's purpose is clear.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters are already documented. The description reinforces concepts like ISV prefix and extension naming, but does not add significant new parameter-level meaning beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Validate'), a clear resource ('a proposed D365FO object name'), and enumerates the exact validation dimensions (extension naming, ISV prefix, type-specific suffixes, symbol-index conflict detection). This clearly distinguishes it from sibling tools like validate_code or generate_object without ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context: this tool is for checking a proposed object name against naming conventions before use. It does not explicitly name alternatives or state when not to use it, but the purpose is specific enough for an agent to infer when it applies.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
verify_d365fo_projectARead-only
Verify that D365FO objects exist on disk at the correct AOT path and are referenced in the .rnrproj project file. Use instead of PowerShell. Runs AFTER a build, not after a write: d365fo_file already verifies its own write inline (on disk + .rnrproj reference) and says so in its response. Omit objects to verify the ENTIRE project: every object referenced in the .rnrproj is checked on disk (requires projectPath, or an auto-detected/configured project).
| Name | Required | Description | Default |
|---|---|---|---|
| objects | No | List of objects to verify. OPTIONAL — omit to verify every object referenced in the project (.rnrproj). | |
| modelName | No | Model name. Auto-detected if omitted. | |
| projectPath | No | Absolute path to the .rnrproj file. Required for project-reference check. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnlyHint=true, and the description adds useful behavioral context: the tool runs after build, is read-only verification, and supports scoped vs whole-project verification. It does not describe result/output or failure behavior, but this is a minor gap given the read-only nature.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every sentence earns its place: core purpose, alternative tool, timing, and the important omit-objects behavior. It is front-loaded with the primary verification action and keeps all guidance relevant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only verification tool with three optional parameters and no output schema, the description supplies sufficient context for correct selection and invocation. It covers scope, timing, prerequisites, and the key alternative, so an agent can act without further clarification.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema by clarifying that omitting `objects` verifies every object in the project and that projectPath is needed for project-reference checking or can be auto-detected/configured. This goes beyond the raw schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: verify D365FO objects exist on disk at the correct AOT path and are referenced in the .rnrproj project file. It clearly distinguishes this from related tools like d365fo_file by noting it runs after a build rather than after a write.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: after a build, not after a write, and names d365fo_file as the alternative that already verifies its own write inline. It also explains the omit-objects behavior for verifying the entire project and notes the projectPath requirement, leaving little to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
18 tool updates
v1.16.2- Changed
build_d365fo_project3 fields changed- changed
Input schema / properties / bpCheck / descriptionPrevious value: -"On a SUCCESSFUL build, also run the best-practice checker and append its findings — saves the usual follow-up run_bp_check call."New value: +"On a SUCCESSFUL build, also run the best-practice checker and append its findings. Prefer this to a follow-up run_bp_check call: one build call instead of two round trips." - added
Input schema / properties / dbSyncAdded value: +{ + "description": "On a SUCCESSFUL build, also run the database sync (SyncEngine.exe) — REQUIRED after any table/view/data-entity change. true = partial sync of the syncable objects in the project, full-model when it has none; an ARRAY syncs exactly those tables/views (much faster).", + "items": { + "type": "string" + }, + "type": [ + "boolean", + "array" + ] +} - removed
Input schema / properties / projectPathRemoved value: -{ - "description": "(Legacy) Absolute path to a .rnrproj file — used only to extract the model name when modelName is not provided.", - "type": "string" -}
- Changed
d365fo_file6 fields changed- removed
Input schema / properties / action / descriptionRemoved value: -"One of the four modes described above." - changed
Input schema / properties / action / enumPrevious value: -[ - "create", - "modify", - "delete", - "generate" -]New value: +[ + "create", + "modify", + "delete", + "undo", + "generate" +] - changed
Input schema / properties / filePath / descriptionPrevious value: -"[modify|delete] Absolute XML path — bypasses symbol-DB lookup. Use for objects just created."New value: +"[modify|delete] Absolute XML path — bypasses symbol-DB lookup. Use for objects just created. [undo] REQUIRED: the file to roll back." - changed
Input schema / properties / params / descriptionPrevious value: -"[modify] Operation-specific parameters as ONE nested object, per get_knowledge(kind=\"op-spec\", topic=\"<operation>\"). A missing/wrong one returns that COMPLETE spec — follow it, do not guess."New value: +"[modify] Operation-specific parameters as ONE nested object, per the op-spec lookup above. A missing/wrong one returns that COMPLETE spec — follow it, do not guess." - changed
Input schema / properties / projectPath / descriptionPrevious value: -"Path to .rnrproj (auto-detected)."New value: +"Path to .rnrproj. Set if known, else auto-detected." - changed
Input schema / properties / properties / descriptionPrevious value: -"[create] Per-objectType creation properties (label, fields[], extends, enumValues[], primaryTable, …) — NOT in this schema. Fetch yours: get_knowledge(kind=\"op-spec\", topic=\"<objectType>\")."New value: +"[create] Per-objectType creation properties (label, fields[], extends, enumValues[], primaryTable, …) — not in this schema; fetch yours with the op-spec lookup above."
- Changed
generate_object4 fields changed- removed
Input schema / properties / mode / descriptionRemoved value: -"pattern = X++ skeleton; scaffold = whole table/form/report (set objectType); find-methods/relation-xpp/fields/table-relation = X++/XML helpers for an existing table." - changed
Input schema / properties / params / descriptionPrevious value: -"Mode-specific parameters as ONE nested object (label, fields[], fieldsHint, cloneFrom, tableMapping, formPattern, contractParams[], keyFields[], style, fieldGroup, …). Get the contract from get_knowledge(kind=\"op-spec\", topic=\"<mode>\"); a missing required one returns that COMPLETE spec."New value: +"Mode-specific parameters as ONE nested object (label, fields[], fieldsHint, cloneFrom, tableMapping, formPattern, contractParams[], keyFields[], style, fieldGroup, …). A missing required one is answered with that mode's COMPLETE spec." - changed
Input schema / properties / pattern / descriptionPrevious value: -"[pattern] REQUIRED. CoC skeletons: class/table-extension, form-handler, form-datasource-extension, form-control-extension, map-extension. ssrs-report-full = Contract+DP+Controller; service-class-ais = CRUD service + contract."New value: +"[pattern] REQUIRED. ssrs-report-full = Contract+DP+Controller; service-class-ais = CRUD service + contract; systest = failing SysTestCase (TDD red); report-* extend a STANDARD report (recipes: object_patterns(domain=\"report\"))." - changed
Input schema / properties / pattern / enumPrevious value: -[ - "class", - "runnable", - "form-handler", - "data-entity", - "batch-job", - "table-extension", - "sysoperation", - "event-handler", - "security-privilege", - "menu-item", - "class-extension", - "ssrs-report-full", - "lookup-form", - "dialog-box", - "dimension-controller", - "number-seq-handler", - "display-menu-controller", - "data-entity-staging", - "service-class-ais", - "form-datasource-extension", - "form-control-extension", - "map-extension" -]New value: +[ + "class", + "runnable", + "form-handler", + "data-entity", + "batch-job", + "table-extension", + "sysoperation", + "event-handler", + "security-privilege", + "menu-item", + "class-extension", + "ssrs-report-full", + "lookup-form", + "dialog-box", + "dimension-controller", + "number-seq-handler", + "display-menu-controller", + "data-entity-staging", + "service-class-ais", + "form-datasource-extension", + "form-control-extension", + "map-extension", + "systest", + "report-dataset-extension", + "report-custom-design", + "report-menu-redirect" +]
- Changed
get_knowledge2 fields changed- removed
Input schema / properties / kind / descriptionRemoved value: -"knowledge = look up an X++ topic/rule; error = diagnose an error message; op-spec = parameter contract for a d365fo_file operation/objectType or generate_object mode; bp-moniker = validate/search a BP-check moniker or render a suppression." - changed
Input schema / properties / topic / descriptionPrevious value: -"[knowledge] REQUIRED. Topic to query — e.g. \"batch job\", \"ttsbegin\", \"RunBase vs SysOperation\", \"set-based operations\", \"CoC\", \"data entities\", \"number sequences\", \"security\", \"temp tables\", \"today() deprecated\", \"query patterns\", \"form patterns\". [op-spec] The operation / objectType / mode to look up."New value: +"[knowledge] REQUIRED. Topic to query — e.g. \"ttsbegin\", \"RunBase vs SysOperation\". [op-spec] The operation / objectType / mode to look up."
- Changed
get_object_info3 fields changed- changed
Input schema / properties / objects / items / properties / objectType / descriptionPrevious value: -"Kind of object to read"New value: +"Kind of object to read — same values as the top-level `objectType`." - removed
Input schema / properties / objects / items / properties / objectType / enumRemoved value: -[ - "class", - "table", - "form", - "query", - "view", - "enum", - "edt", - "report", - "data-entity", - "menu-item", - "service", - "map", - "config-key", - "security-policy", - "macro", - "table-extension", - "class-extension", - "form-extension", - "enum-extension", - "edt-extension", - "data-entity-extension" -] - changed
Input schema / properties / options / descriptionPrevious value: -"Type-specific reader flags: includeRdl (report), searchControl/maxControls (form), compact/methodOffset (class), fieldsOffset/fieldFilter (table), filter (macro), mode (edt), includeFields, includeOperations, modelName. On class/table/view/data-entity, {\"method\":\"validateWrite\",\"include\":\"signature\"} returns ONE method (include: signature | source | both) — required before writing a CoC extension. {\"include\":\"xml\"} returns raw AOT XML + its path (page: startLine/endLine) — never shell out to find or read a file. Applies to every objects[] entry."New value: +"Type-specific reader flags: includeRdl (report), searchControl/maxControls (form), compact/methodOffset (class+table), fieldsOffset/fieldFilter/relations (table), filter (macro), mode (edt), includeFields, includeOperations, modelName. On class/table/view/data-entity, {\"method\":\"validateWrite\",\"include\":\"signature\"} returns ONE method (include: signature | source | both) — required before writing a CoC extension. {\"include\":\"xml\"} returns raw AOT XML + its path (page: startLine/endLine) — never shell out to find or read a file. Applies to every objects[] entry."
- Changed
get_workspace_info3 fields changed- added
Input schema / properties / changesAdded value: +{ + "default": false, + "description": "Return the uncommitted X++ changes (`git diff HEAD`) plus per-file rollback hints INSTEAD of the configuration. Review-only — not a way to verify a write.", + "type": "boolean" +} - changed
Input schema / properties / projectName / descriptionPrevious value: -"Only when the USER says \"switch to <project>\". The PROJECT file name, e.g. \"Contoso - FeatureManagement\". NOT a model name: one model is built by many projects, so naming it selects none and the call is refused. Reads span every model already."New value: +"The PROJECT file name, e.g. \"Contoso - FeatureManagement\" — pass it whenever you have one: the USER named it, or an earlier call listed it. NOT a model name, and not a guess from a ticket: one model has many projects, so naming it selects none. Steers WRITES only; reads span every model already." - changed
Input schema / properties / projectPath / descriptionPrevious value: -"Absolute path to a .rnrproj file. Fallback when projectName is ambiguous or D365FO_SOLUTIONS_PATH is not configured. Example: \"K:\\\\repos\\\\Contoso\\\\MyProject\\\\MyProject.rnrproj\""New value: +"Absolute path to a .rnrproj file. Use when projectName is ambiguous, none was auto-selected, or D365FO_SOLUTIONS_PATH is unset. Example: \"K:\\\\repos\\\\Contoso\\\\MyProject\\\\MyProject.rnrproj\""
- Changed
labels8 fields changed- removed
Input schema / properties / action / descriptionRemoved value: -"Label operation to perform." - changed
Input schema / properties / labels / descriptionPrevious value: -"[create] OPTIONAL bulk mode — create several labels in one call; shared fields (labelFileId, model, languages, paths…) stay at the top level and top-level labelId/translations are ignored. A failed entry does not abort the batch."New value: +"[create] Bulk mode — shared fields stay at the top level (top-level labelId/translations are then ignored); a failed entry does not abort the batch." - removed
Input schema / properties / labels / items / properties / labelId / descriptionRemoved value: -"Label ID for this entry — alphanumeric, no model prefix." - removed
Input schema / properties / labels / items / properties / translations / descriptionRemoved value: -"Same entries as the top-level translations[]." - changed
Input schema / properties / newLabelId / descriptionPrevious value: -"[rename] REQUIRED. New label ID — must be alphanumeric, no spaces."New value: +"[rename] REQUIRED. New label ID." - changed
Input schema / properties / params / descriptionPrevious value: -"Optional write plumbing (packagePath, projectPath, languages, sortLabels, allowExtensionLabelFile, …) — all auto-resolved when omitted. Contract: get_knowledge(kind=\"op-spec\", topic=\"labels\")."New value: +"Optional write plumbing — the auto-resolved overrides named at the end of the description above." - removed
Input schema / properties / translations / items / properties / comment / descriptionRemoved value: -"Developer comment (optional)" - removed
Input schema / properties / translations / items / properties / text / descriptionRemoved value: -"Label text"
- Changed
object_patterns6 fields changed- changed
Input schema / properties / domain / descriptionPrevious value: -"table = table field/index/relation patterns; form = form-pattern toolkit (set action). Optional — inferred from the other params (action/pattern/xml/formName → form; tableGroup → table). ⚠️ This is NOT a free-form \"pattern type\": a concept like \"number-sequence\"/\"SysOperation\" belongs to get_knowledge, not here."New value: +"Optional — inferred from the other params (action/pattern/xml/formName → form; tableGroup → table). A concept like \"number-sequence\" is not a domain: that is get_knowledge." - changed
Input schema / properties / domain / enumPrevious value: -[ - "table", - "form" -]New value: +[ + "table", + "form", + "report", + "mobile-app" +] - changed
Input schema / properties / filePath / descriptionPrevious value: -"[form/validate] Explicit path to an AxForm XML file (e.g. a freshly created form not yet indexed)."New value: +"[form/validate] Path to an AxForm XML file not yet indexed." - changed
Input schema / properties / limit / descriptionPrevious value: -"[analyze] Maximum number of pattern examples (default: 10)"New value: +"[analyze] Max pattern examples." - changed
Input schema / properties / pattern / descriptionPrevious value: -"[spec] REQUIRED. Pattern name (id, xmlName, or alias) — e.g. \"SimpleList\", \"DetailsMaster\", or a sub-pattern like \"FieldsFieldGroups\"."New value: +"[spec|report|mobile-app] Pattern name (id, xmlName or alias) — e.g. \"SimpleList\", \"FieldsFieldGroups\", \"PrintMgmtFormLetter\", \"processguide-flow\"." - changed
Input schema / properties / similarTo / descriptionPrevious value: -"[table] table name to find similar table patterns; [form/analyze] form name to find similar form patterns."New value: +"[table] table / [form-analyze] form name to find similar patterns."
- Changed
prepare6 fields changed- removed
Input schema / properties / mode / descriptionRemoved value: -"change = extend/modify an existing object; create = a brand-new object." - changed
Input schema / properties / mode / enumPrevious value: -[ - "change", - "create" -]New value: +[ + "change", + "create", + "test" +] - changed
Input schema / properties / objectName / descriptionPrevious value: -"[change] Name of the object to extend/modify (e.g. \"CustTable\"). [create] Proposed BASE name WITHOUT model prefix (same value you would pass to d365fo_file create)."New value: +"[change] Name of the object to extend/modify (e.g. \"CustTable\"). [create] Proposed BASE name WITHOUT model prefix." - changed
Input schema / properties / objectType / descriptionPrevious value: -"[change] D365FO object type — auto-detected when omitted. [create] REQUIRED — type of the new object."New value: +"[change] type — auto-detected when omitted. [create] REQUIRED; an extension is Base.Suffix." - changed
Input schema / properties / objectType / enumPrevious value: -[ - "class", - "table", - "form", - "enum", - "edt", - "query", - "view", - "data-entity", - "report", - "map", - "menu-item-display", - "menu-item-action", - "menu-item-output", - "menu", - "security-privilege", - "security-duty", - "security-role", - "business-event", - "tile", - "kpi", - "service", - "service-group", - "macro", - "configuration-key", - "security-policy", - "aggregate-measurement", - "license-code" -]New value: +[ + "class", + "table", + "form", + "enum", + "edt", + "query", + "view", + "data-entity", + "report", + "map", + "menu-item-display", + "menu-item-action", + "menu-item-output", + "menu", + "security-privilege", + "security-duty", + "security-role", + "business-event", + "tile", + "kpi", + "service", + "service-group", + "macro", + "configuration-key", + "security-policy", + "aggregate-measurement", + "license-code", + "table-extension", + "class-extension", + "form-extension", + "enum-extension", + "edt-extension" +] - changed
Input schema / properties / operation / descriptionPrevious value: -"[change] The modify operation you intend to run; its full parameter contract comes back in THIS response, so no separate op-spec call. Defaults to add-method when methodName is given."New value: +"[change] The modify operation(s) you intend to run — comma-separated for several (\"add-field,add-index\"). Their full parameter contracts come back in THIS response. Defaults to add-method when methodName is given."
- Removed
review_workspace_changes - Changed
run_bp_check2 fields changed- removed
Input schema / properties / targetElementTypeRemoved value: -{ - "description": "Element type for targetFilter. Looked up in the symbol index if omitted; ambiguous or unknown names error rather than being assumed to be a class.", - "type": "string" -} - removed
Input schema / properties / targetFilterRemoved value: -{ - "description": "Single-object form: object name to check. Use objects[] for more than one.", - "type": "string" -}
- Changed
search1 field changed- changed
Input schema / properties / queries / items / properties / query / descriptionPrevious value: -"Search query (class name, method name, etc.)"New value: +"Search query."
- Changed
security_info1 field changed- removed
Input schema / properties / mode / descriptionRemoved value: -"artifact = look up a named privilege/duty/role; coverage = who can access an object."
- Removed
trigger_db_sync - Removed
undo_last_modification - Changed
validate_code3 fields changed- changed
Input schema / properties / codeType / descriptionPrevious value: -"[syntax] \"xpp\" for X++ source (default), \"xml-table\" for AxTable XML, \"xml-any\" for other XML."New value: +"[syntax] \"xpp\" X++ (default), \"xml-table\" AxTable, \"xml-form\" AxForm(+Extension), \"xml-report\" AxReport, \"xml-any\" other." - changed
Input schema / properties / codeType / enumPrevious value: -[ - "xpp", - "xml-table", - "xml-any" -]New value: +[ + "xpp", + "xml-table", + "xml-form", + "xml-any", + "xml-report" +] - changed
Input schema / properties / mode / descriptionPrevious value: -"both = run the two checks in ONE call (preferred); syntax = BP/best-practice rules only; references = symbol resolution only."New value: +"both = run the two checks in ONE call (preferred)."
- Changed
validate_object_naming1 field changed- changed
Input schema / properties / objectType / enumPrevious value: -[ - "class", - "table", - "form", - "enum", - "edt", - "query", - "view", - "table-extension", - "class-extension", - "form-extension", - "enum-extension", - "edt-extension", - "menu-item", - "security-privilege", - "security-duty", - "security-role", - "data-entity" -]New value: +[ + "class", + "table", + "form", + "enum", + "edt", + "query", + "view", + "report", + "table-extension", + "class-extension", + "form-extension", + "enum-extension", + "edt-extension", + "menu-item", + "security-privilege", + "security-duty", + "security-role", + "data-entity" +]
- Changed
verify_d365fo_project2 fields changed- removed
Input schema / properties / packageNameRemoved value: -{ - "description": "Package name. Auto-resolved from model name if omitted.", - "type": "string" -} - removed
Input schema / properties / packagePathRemoved value: -{ - "description": "Base package path (default: auto-detected PackagesLocalDirectory)", - "type": "string" -}
14 tool updates
v1.14.0- Changed
build_d365fo_project2 fields changed- added
Input schema / properties / bpCheckAdded value: +{ + "description": "On a SUCCESSFUL build, also run the best-practice checker and append its findings — saves the usual follow-up run_bp_check call.", + "type": "boolean" +} - removed
Input schema / properties / buildReferencedModelsRemoved value: -{ - "description": "DISABLED — always ignored. Rebuilding dependency models on every build slows the run down and referenced models are expected to already be compiled.", - "type": "boolean" -}
- Changed
d365fo_file3 fields changed- changed
Input schema / properties / operation / descriptionPrevious value: -"[modify] REQUIRED unless using operations[]. add-method also UPDATES in place; replace-code is the surgical oldCode→newCode path. Parameters: get_knowledge(kind=\"op-spec\", topic=\"<operation>\")."New value: +"[modify] REQUIRED unless using operations[]. add-method also UPDATES in place; replace-code is the surgical oldCode→newCode path." - changed
Input schema / properties / operation / enumPrevious value: -[ - "add-method", - "remove-method", - "replace-code", - "add-field", - "modify-field", - "rename-field", - "replace-all-fields", - "remove-field", - "add-display-method", - "add-table-method", - "add-index", - "remove-index", - "add-full-text-index", - "remove-full-text-index", - "add-table-mapping", - "remove-table-mapping", - "add-relation", - "remove-relation", - "add-delete-action", - "remove-delete-action", - "add-field-group", - "remove-field-group", - "add-field-to-field-group", - "add-field-modification", - "add-data-source", - "add-control", - "remove-control", - "remove-entry-point", - "remove-diagnostic-suppression", - "add-diagnostic-suppression", - "add-enum-value", - "modify-enum-value", - "remove-enum-value", - "add-menu-item-to-menu", - "modify-property", - "add-query-range", - "remove-query-range" -]New value: +[ + "add-method", + "remove-method", + "replace-code", + "add-field", + "modify-field", + "rename-field", + "replace-all-fields", + "remove-field", + "add-display-method", + "add-table-method", + "add-index", + "remove-index", + "add-full-text-index", + "remove-full-text-index", + "add-table-mapping", + "remove-table-mapping", + "add-relation", + "remove-relation", + "add-delete-action", + "remove-delete-action", + "add-field-group", + "remove-field-group", + "add-field-to-field-group", + "add-field-modification", + "add-data-source", + "add-control", + "remove-control", + "add-entry-point", + "remove-entry-point", + "remove-diagnostic-suppression", + "add-diagnostic-suppression", + "add-enum-value", + "modify-enum-value", + "remove-enum-value", + "add-menu-item-to-menu", + "modify-property", + "add-query-range", + "remove-query-range" +] - changed
Input schema / properties / operations / descriptionPrevious value: -"[modify] PREFERRED for 2+ edits to the SAME object — ONE call, not one per edit. Entries are {operation, …op-spec params}; objectType/objectName/modelName stay top-level. Applied in order, stopped at the first failure, per-operation results back. 3 fields + their field groups + an index: 7 calls flat, 1 here."New value: +"[modify|create] PREFERRED for 2+ edits to the SAME object — ONE call, not one per edit. On create they run against the just-created object, under the name it actually got. Entries are {operation, …op-spec params}; objectType/objectName/modelName stay top-level. Applied in order, stopped at the first failure, per-operation results back."
- Changed
extension_info2 fields changed- changed
Input schema / properties / showExistingExtensions / defaultPrevious value: -trueNew value: +false - changed
Input schema / properties / showExistingExtensions / descriptionPrevious value: -"[points] Show which extension points are already extended (default: true)."New value: +"[points] Also list who already wraps/subscribes each point — opt-in, roughly doubles the response."
- Changed
find_references1 field changed- changed
Input schema / properties / targetName / descriptionPrevious value: -"Target name. Method where-used: qualify as \"Owner.method\" or pass an AOT path \"/Tables/<Table>/Methods/<method>\" for a result scoped to one declaring type (matches Visual Studio xref). A bare method name is name-only and over-reports. Label where-used: pass the label id exactly as written — old format \"@WAX2194\" or new format \"@LabelFile:LabelId\" (e.g. \"@ApplicationPlatform:AbortButtonText\")."New value: +"Target name. Methods: see the scoping rule in the description above. Labels: the id exactly as written — \"@WAX2194\" or \"@LabelFile:LabelId\"."
- Changed
get_knowledge1 field changed- added
Input schema / properties / topicsAdded value: +{ + "description": "[knowledge|op-spec] Look up SEVERAL topics in one call instead of one call each. Replaces topic.", + "items": { + "type": "string" + }, + "maxItems": 10, + "type": "array" +}
- Changed
get_object_info2 fields changed- changed
Input schema / properties / objectType / descriptionPrevious value: -"Kind of object to read (incl. *-extension types — pass base object name or full extension name). REQUIRED unless using objects[]."New value: +"Kind of object to read. REQUIRED unless using objects[]." - changed
Input schema / properties / objects / items / properties / objectName / descriptionPrevious value: -"Exact object name (use search first if unsure)"New value: +"Exact object name."
- Changed
labels9 fields changed- changed
Input schema / properties / action / descriptionPrevious value: -"Label operation to perform. \"list\"/\"list-files\" are aliases of \"info\" (lists label files)."New value: +"Label operation to perform." - changed
Input schema / properties / action / enumPrevious value: -[ - "search", - "info", - "create", - "update", - "rename", - "list", - "list-files" -]New value: +[ + "search", + "info", + "create", + "update", + "rename" +] - changed
Input schema / properties / dryRun / descriptionPrevious value: -"[rename] Preview changes without writing anything (default: false). Use this first!"New value: +"[rename] Preview changes without writing anything." - changed
Input schema / properties / labelFileId / descriptionPrevious value: -"[search|info|create|update|rename] AxLabelFile ID (e.g. ContosoExt, SYS). For action=info with no labelId, returns the physical .label.txt path per language. For create/update/rename use the model's ORIGINAL label file, not an extension (…_Extension…). For a NEW label file this ID is the MODEL name, never the bare EXTENSION_PREFIX."New value: +"[search|info|create|update|rename] AxLabelFile ID (e.g. ContosoExt, SYS). For a NEW label file this ID is the MODEL name, never the bare EXTENSION_PREFIX." - added
Input schema / properties / labels / items / properties / translations / descriptionAdded value: +"Same entries as the top-level translations[]." - removed
Input schema / properties / labels / items / properties / translations / items / propertiesRemoved value: -{ - "comment": { - "description": "Developer comment (optional)", - "type": "string" - }, - "language": { - "description": "Locale code, e.g. en-US, cs, de, sk", - "type": "string" - }, - "text": { - "description": "Label text", - "type": "string" - } -} - removed
Input schema / properties / labels / items / properties / translations / items / requiredRemoved value: -[ - "language", - "text" -] - removed
Input schema / properties / limitRemoved value: -{ - "description": "[search] Alias of maxResults.", - "type": "number" -} - changed
Input schema / properties / maxResults / descriptionPrevious value: -"[search] Max labels listed (default 10, alias `limit`); a truncated set reports how many more matched."New value: +"[search] Max labels listed (default 10); a truncated set reports how many more matched."
- Changed
object_patterns3 fields changed- changed
Input schema / properties / recommend / properties / entityKind / descriptionPrevious value: -"Kind of entity: master (customers), transaction (orders+lines), setup (group tables), parameters, inquiry (read-only), lookup, workspace, dialogTask"New value: +"Kind of entity being modelled." - changed
Input schema / properties / recommend / properties / fieldCount / descriptionPrevious value: -"Approximate fields users see/edit per record (<10 → SimpleList, ≥10 → SimpleListDetails)"New value: +"Approximate fields users see/edit per record." - changed
Input schema / properties / recommend / properties / tableName / descriptionPrevious value: -"Main table — pulls field count and existing-form evidence from the index"New value: +"Main table — pulls field count and existing-form evidence from the index."
- Changed
run_bp_check3 fields changed- changed
Input schema / properties / modelName / descriptionPrevious value: -"Model name to check. Auto-detected from .mcp.json if omitted."New value: +"Model name to check. Auto-detected if omitted." - changed
Input schema / properties / packagePath / descriptionPrevious value: -"PackagesLocalDirectory root path. Auto-detected from .mcp.json if omitted."New value: +"PackagesLocalDirectory root path. Auto-detected if omitted." - changed
Input schema / properties / projectPath / descriptionPrevious value: -"Absolute path to the .rnrproj file to analyze. Auto-detected from .mcp.json if omitted."New value: +"Absolute path to the .rnrproj file to analyze. Auto-detected if omitted."
- Changed
run_systest_class2 fields changed- changed
Input schema / properties / modelName / descriptionPrevious value: -"The model containing the test class. Auto-detected from .mcp.json if omitted."New value: +"The model containing the test class. Auto-detected if omitted." - changed
Input schema / properties / packagePath / descriptionPrevious value: -"PackagesLocalDirectory root path. Auto-detected from .mcp.json if omitted."New value: +"PackagesLocalDirectory root path. Auto-detected if omitted."
- Changed
search10 fields changed- removed
Input schema / properties / crossReferenceRemoved value: -{ - "default": true, - "description": "[batch] Append a cross-reference summary at the end listing symbols that appeared in multiple queries. Useful for identifying the most relevant / commonly matched objects across all searches.", - "type": "boolean" -} - removed
Input schema / properties / deduplicateRemoved value: -{ - "default": true, - "description": "[batch] When true, symbols appearing in multiple query results are collapsed. Later occurrences are replaced with a reference to the query where they first appeared.", - "type": "boolean" -} - removed
Input schema / properties / globalTypeFilterRemoved value: -{ - "description": "[batch] Default type filter for queries without an explicit per-query type. E.g. [\"class\"] restricts all untyped queries to classes. Multiple values fan out each untyped query into one search per type. Values: same as the top-level `type`, except \"all\" (which means \"no filter\" — omit this instead).", - "items": { - "type": "string" - }, - "maxItems": 5, - "type": "array" -} - removed
Input schema / properties / includeWorkspaceRemoved value: -{ - "default": false, - "description": "[single] Whether to include workspace files in search results (workspace-aware search)", - "type": "boolean" -} - removed
Input schema / properties / queries / items / properties / includeWorkspaceRemoved value: -{ - "default": false, - "description": "Whether to include workspace files in results", - "type": "boolean" -} - changed
Input schema / properties / queries / items / properties / type / descriptionPrevious value: -"Filter by object type — same values as the top-level `type`. Omit to inherit globalTypeFilter or default to \"all\""New value: +"Filter by object type — same values as the top-level `type`." - removed
Input schema / properties / queries / items / properties / workspacePathRemoved value: -{ - "description": "Optional workspace path to search local files", - "type": "string" -} - changed
Input schema / properties / scope / descriptionPrevious value: -"[single] Search the whole index (\"all\", default) or only custom/ISV models (\"extensions\"). Ignored when `queries[]` is provided."New value: +"[single] Whole index, or only custom/ISV models. Ignored when `queries[]` is provided." - changed
Input schema / properties / verbose / descriptionPrevious value: -"[single] Include related-searches/patterns/tips sections (off by default to keep responses compact)."New value: +"[single] Include related-searches/patterns/tips sections." - removed
Input schema / properties / workspacePathRemoved value: -{ - "description": "[single] Optional workspace path to search local project files in addition to external metadata", - "type": "string" -}
- Changed
trigger_db_sync5 fields changed- changed
Input schema / properties / connectionString / descriptionPrevious value: -"SQL Server connection string. Default: \"Data Source=localhost;Initial Catalog=AxDB;Integrated Security=True\"."New value: +"SQL Server connection string. Defaults to localhost/AxDB." - changed
Input schema / properties / modelName / descriptionPrevious value: -"Model to sync. Auto-detected from .mcp.json if omitted."New value: +"Model to sync. Auto-detected if omitted." - changed
Input schema / properties / packagePath / descriptionPrevious value: -"PackagesLocalDirectory root. Auto-detected from .mcp.json if omitted."New value: +"PackagesLocalDirectory root. Auto-detected if omitted." - changed
Input schema / properties / syncViews / descriptionPrevious value: -"FULL sync only: use syncmode FullAllAndViews. Not needed for partial sync — name the view in tables[] instead. Default: false."New value: +"FULL sync only: use syncmode FullAllAndViews. For partial sync, name the view in tables[] instead." - removed
Input schema / properties / tableNameRemoved value: -{ - "description": "Single-table shorthand — equivalent to tables=[\"tableName\"]. Kept for backwards compatibility.", - "type": "string" -}
- Changed
validate_code2 fields changed- changed
Input schema / properties / mode / descriptionPrevious value: -"syntax = BP/best-practice rules; references = symbol resolution against the index. Defaults to syntax."New value: +"both = run the two checks in ONE call (preferred); syntax = BP/best-practice rules only; references = symbol resolution only." - changed
Input schema / properties / mode / enumPrevious value: -[ - "syntax", - "references" -]New value: +[ + "both", + "syntax", + "references" +]
- Changed
verify_d365fo_project1 field changed- changed
Input schema / properties / modelName / descriptionPrevious value: -"Model name. Auto-detected from mcp.json if omitted."New value: +"Model name. Auto-detected if omitted."
1 tool update
v1.13.0- Changed
d365fo_file1 field changed- changed
Input schema / properties / operation / enumPrevious value: -[ - "add-method", - "remove-method", - "replace-code", - "add-field", - "modify-field", - "rename-field", - "replace-all-fields", - "remove-field", - "add-display-method", - "add-table-method", - "add-index", - "remove-index", - "add-full-text-index", - "remove-full-text-index", - "add-table-mapping", - "remove-table-mapping", - "add-relation", - "remove-relation", - "add-delete-action", - "remove-delete-action", - "add-field-group", - "remove-field-group", - "add-field-to-field-group", - "add-field-modification", - "add-data-source", - "add-control", - "remove-control", - "remove-entry-point", - "remove-diagnostic-suppression", - "add-diagnostic-suppression", - "add-enum-value", - "modify-enum-value", - "remove-enum-value", - "add-menu-item-to-menu", - "modify-property" -]New value: +[ + "add-method", + "remove-method", + "replace-code", + "add-field", + "modify-field", + "rename-field", + "replace-all-fields", + "remove-field", + "add-display-method", + "add-table-method", + "add-index", + "remove-index", + "add-full-text-index", + "remove-full-text-index", + "add-table-mapping", + "remove-table-mapping", + "add-relation", + "remove-relation", + "add-delete-action", + "remove-delete-action", + "add-field-group", + "remove-field-group", + "add-field-to-field-group", + "add-field-modification", + "add-data-source", + "add-control", + "remove-control", + "remove-entry-point", + "remove-diagnostic-suppression", + "add-diagnostic-suppression", + "add-enum-value", + "modify-enum-value", + "remove-enum-value", + "add-menu-item-to-menu", + "modify-property", + "add-query-range", + "remove-query-range" +]
3 tool updates
v1.12.0- Changed
d365fo_file6 fields changed- changed
Input schema / properties / action / descriptionPrevious value: -"One of the three modes described above."New value: +"One of the four modes described above." - changed
Input schema / properties / action / enumPrevious value: -[ - "create", - "modify", - "generate" -]New value: +[ + "create", + "modify", + "delete", + "generate" +] - changed
Input schema / properties / filePath / descriptionPrevious value: -"[modify] Absolute XML path — bypasses symbol-DB lookup. Use for objects just created."New value: +"[modify|delete] Absolute XML path — bypasses symbol-DB lookup. Use for objects just created." - changed
Input schema / properties / objectType / descriptionPrevious value: -"Each security/menu-item type is its own AOT folder — NEVER use security-privilege for duty or role. [modify]/[generate] cover the core families + their *-extension variants."New value: +"Each security/menu-item type is its own AOT folder — NEVER use security-privilege for duty or role. [modify]/[generate] cover the core families + their *-extension variants; [delete] takes the same enum as [create]." - changed
Input schema / properties / objectType / enumPrevious value: -[ - "class", - "table", - "enum", - "form", - "query", - "view", - "data-entity", - "report", - "edt", - "table-extension", - "class-extension", - "form-extension", - "enum-extension", - "edt-extension", - "data-entity-extension", - "menu-item-display-extension", - "menu-item-action-extension", - "menu-item-output-extension", - "menu-extension", - "menu-item-display", - "menu-item-action", - "menu-item-output", - "menu", - "security-privilege", - "security-duty", - "security-role", - "security-duty-extension", - "security-role-extension", - "business-event", - "tile", - "kpi", - "map", - "service", - "service-group", - "macro", - "configuration-key", - "security-policy", - "aggregate-measurement", - "license-code" -]New value: +[ + "class", + "table", + "enum", + "form", + "query", + "view", + "data-entity", + "report", + "edt", + "table-extension", + "class-extension", + "form-extension", + "enum-extension", + "edt-extension", + "data-entity-extension", + "menu-item-display-extension", + "menu-item-action-extension", + "menu-item-output-extension", + "menu-extension", + "menu-item-display", + "menu-item-action", + "menu-item-output", + "menu", + "security-privilege", + "security-duty", + "security-role", + "security-duty-extension", + "security-role-extension", + "ignore-diagnostic-list", + "business-event", + "tile", + "kpi", + "map", + "service", + "service-group", + "macro", + "configuration-key", + "security-policy", + "aggregate-measurement", + "license-code" +] - changed
Input schema / properties / operation / enumPrevious value: -[ - "add-method", - "remove-method", - "replace-code", - "add-field", - "modify-field", - "rename-field", - "replace-all-fields", - "remove-field", - "add-display-method", - "add-table-method", - "add-index", - "remove-index", - "add-full-text-index", - "remove-full-text-index", - "add-table-mapping", - "remove-table-mapping", - "add-relation", - "remove-relation", - "add-delete-action", - "remove-delete-action", - "add-field-group", - "remove-field-group", - "add-field-to-field-group", - "add-field-modification", - "add-data-source", - "add-control", - "add-enum-value", - "modify-enum-value", - "remove-enum-value", - "add-menu-item-to-menu", - "modify-property" -]New value: +[ + "add-method", + "remove-method", + "replace-code", + "add-field", + "modify-field", + "rename-field", + "replace-all-fields", + "remove-field", + "add-display-method", + "add-table-method", + "add-index", + "remove-index", + "add-full-text-index", + "remove-full-text-index", + "add-table-mapping", + "remove-table-mapping", + "add-relation", + "remove-relation", + "add-delete-action", + "remove-delete-action", + "add-field-group", + "remove-field-group", + "add-field-to-field-group", + "add-field-modification", + "add-data-source", + "add-control", + "remove-control", + "remove-entry-point", + "remove-diagnostic-suppression", + "add-diagnostic-suppression", + "add-enum-value", + "modify-enum-value", + "remove-enum-value", + "add-menu-item-to-menu", + "modify-property" +]
- Changed
get_knowledge6 fields changed- added
Input schema / properties / actionAdded value: +{ + "description": "[bp-moniker] REQUIRED. validate = confirm an exact moniker is real; search = free-text scenario query; suppress = render a <Diagnostic> block.", + "enum": [ + "validate", + "search", + "suppress" + ], + "type": "string" +} - added
Input schema / properties / justificationAdded value: +{ + "description": "[bp-moniker suppress] REQUIRED. Why the warning is ignored; 95% of real entries carry one.", + "type": "string" +} - changed
Input schema / properties / kind / descriptionPrevious value: -"knowledge = look up an X++ topic/rule; error = diagnose an error message; op-spec = parameter contract for a d365fo_file operation/objectType or generate_object mode."New value: +"knowledge = look up an X++ topic/rule; error = diagnose an error message; op-spec = parameter contract for a d365fo_file operation/objectType or generate_object mode; bp-moniker = validate/search a BP-check moniker or render a suppression." - changed
Input schema / properties / kind / enumPrevious value: -[ - "knowledge", - "error", - "op-spec" -]New value: +[ + "knowledge", + "error", + "op-spec", + "bp-moniker" +] - added
Input schema / properties / monikerAdded value: +{ + "description": "[bp-moniker validate/suppress] REQUIRED. Exact moniker, e.g. \"BPErrorPrivilegeNotCoveredByDuty\".", + "type": "string" +} - added
Input schema / properties / pathAdded value: +{ + "description": "[bp-moniker suppress] REQUIRED. dynamics:// path, verbatim from the finding.", + "type": "string" +}
- Changed
labels1 field changed- changed
Input schema / properties / labelId / descriptionPrevious value: -"[info] Exact label ID. Omit for action=info to list available label files for the model."New value: +"[info] Label ID, any spelling: SYS67433, @SYS67433, @ContosoExt:MyLabel (paste search output). labelFileId/model optional. Omit to list label files."
4 tool updates
v1.10.0- Changed
d365fo_file1 field changed- changed
Input schema / properties / addToProject / descriptionPrevious value: -"Add to the .rnrproj — keep the default."New value: +"Add to the ACTIVE .rnrproj — keep the default."
- Changed
get_object_info1 field changed- changed
Input schema / properties / options / descriptionPrevious value: -"Type-specific flags forwarded to the reader: includeRdl, includeFields, searchControl, compact, includeOperations, filter, mode, modelName. For a CLASS, {\"method\":\"validateWrite\",\"include\":\"signature\"} returns ONE method (include: signature | source | both) — required before writing a CoC extension. Big objects are paged — table fieldsOffset/fieldFilter, form maxControls. Applies to every objects[] entry."New value: +"Type-specific reader flags: includeRdl (report), searchControl/maxControls (form), compact/methodOffset (class), fieldsOffset/fieldFilter (table), filter (macro), mode (edt), includeFields, includeOperations, modelName. On class/table/view/data-entity, {\"method\":\"validateWrite\",\"include\":\"signature\"} returns ONE method (include: signature | source | both) — required before writing a CoC extension. {\"include\":\"xml\"} returns raw AOT XML + its path (page: startLine/endLine) — never shell out to find or read a file. Applies to every objects[] entry."
- Changed
get_workspace_info1 field changed- changed
Input schema / properties / projectName / descriptionPrevious value: -"Only when the USER says \"switch to <project>\". Just the model name, e.g. \"ContosoEDS\"; path resolved from D365FO_SOLUTIONS_PATH. NOT a way to reach another model — reads span every model already, writes stay in the workspace model."New value: +"Only when the USER says \"switch to <project>\". The PROJECT file name, e.g. \"Contoso - FeatureManagement\". NOT a model name: one model is built by many projects, so naming it selects none and the call is refused. Reads span every model already."
- Changed
labels3 fields changed- changed
Input schema / properties / query / descriptionPrevious value: -"[search] REQUIRED. Search text — matches label ID, text and developer comment."New value: +"[search] REQUIRED. Search text — matches label ID, text and developer comment. ARRAY = try several phrasings in ONE call." - added
Input schema / properties / query / itemsAdded value: +{ + "type": "string" +} - changed
Input schema / properties / query / typePrevious value: -"string"New value: +[ + "string", + "array" +]
14 tool updates
v1.9.0- Removed
batch_get_info - Changed
build_d365fo_project1 field changed- changed
Input schema / properties / buildReferencedModels / descriptionPrevious value: -"Also build all custom/ISV models this model depends on before building the target. Skips Microsoft standard models."New value: +"DISABLED — always ignored. Rebuilding dependency models on every build slows the run down and referenced models are expected to already be compiled."
- Changed
d365fo_file20 fields changed- changed
Input schema / properties / addToProject / descriptionPrevious value: -"Add the file to the .rnrproj project. Keep the default (true) unless explicitly asked otherwise."New value: +"Add to the .rnrproj — keep the default." - changed
Input schema / properties / createBackup / descriptionPrevious value: -"[modify] Create backup before modification (default false)"New value: +"[modify] Back up before modifying." - changed
Input schema / properties / filePath / descriptionPrevious value: -"[modify] Absolute path to the XML file — bypasses symbol-DB lookup. Use when the object was just created."New value: +"[modify] Absolute XML path — bypasses symbol-DB lookup. Use for objects just created." - changed
Input schema / properties / groundingToken / descriptionPrevious value: -"Provenance token from prepare(change/create). Required for *-extension objectTypes when GROUNDING_ENFORCE=true; object-bound — only valid for the object it was issued for."New value: +"From prepare(change/create). Required for *-extension when GROUNDING_ENFORCE=true; object-bound." - changed
Input schema / properties / modelName / descriptionPrevious value: -"Target model name — auto-detected from .mcp.json if omitted. NEVER guess or take model names from search results (source models)."New value: +"Target model — auto-detected. NEVER take it from search results (those are source models)." - changed
Input schema / properties / objectName / descriptionPrevious value: -"Base name WITHOUT model prefix — the tool prepends EXTENSION_PREFIX (or modelName) and detects an existing prefix. Extension classes: pass \"{Base}_Extension\" with NO prefix infix. NEVER hand-build the prefix."New value: +"Base name WITHOUT model prefix — the tool prepends it. Extension classes: \"{Base}_Extension\". NEVER hand-build the prefix." - changed
Input schema / properties / objectType / descriptionPrevious value: -"Each security/menu-item type maps to its own AOT folder — NEVER use security-privilege for duty or role. class-extension = [ExtensionOf] final class skeleton; business-event = BusinessEventsBase + Contract pair. [modify] supports class/table/form/enum/query/view/edt/data-entity/report + *-extension variants. [generate] supports class/table/enum/form/query/view/data-entity/report + table/form/enum/edt/data-entity-extension."New value: +"Each security/menu-item type is its own AOT folder — NEVER use security-privilege for duty or role. [modify]/[generate] cover the core families + their *-extension variants." - changed
Input schema / properties / operation / descriptionPrevious value: -"[modify] REQUIRED. Modification to perform. Non-obvious ones:\nadd-method: adds OR updates in place if the name exists (position kept).\nreplace-code: surgical oldCode→newCode; preferred for rewriting a known method. Control overrides: methodName=\"Control.method\".\nrename-field: also fixes index DataField refs and TitleField1/2.\nreplace-all-fields: atomic rewrite of ALL fields.\nadd-display-method: display method with [SysClientCacheDataMethodAttribute].\nadd-table-method: canonical find/exist/findByRecId/validate*/initValue boilerplate.\nadd-field-modification: override base-table field label/mandatory in a table-extension.\nadd-delete-action: DeleteActions entry — deleteActionName + optional deleteActionTable/deleteActionType.\nadd-full-text-index/add-table-mapping: the <FullTextIndexes>/<Mappings> collections.\nmodify-property: any object-level property (TableGroup, TitleField1, Extends…) — see propertyPath; on an *-extension it becomes a PropertyModification."New value: +"[modify] REQUIRED unless using operations[]. add-method also UPDATES in place; replace-code is the surgical oldCode→newCode path. Parameters: get_knowledge(kind=\"op-spec\", topic=\"<operation>\")." - added
Input schema / properties / operationsAdded value: +{ + "description": "[modify] PREFERRED for 2+ edits to the SAME object — ONE call, not one per edit. Entries are {operation, …op-spec params}; objectType/objectName/modelName stay top-level. Applied in order, stopped at the first failure, per-operation results back. 3 fields + their field groups + an index: 7 calls flat, 1 here.", + "items": { + "additionalProperties": true, + "type": "object" + }, + "maxItems": 20, + "type": "array" +} - changed
Input schema / properties / overwrite / descriptionPrevious value: -"Allow overwriting an existing file (use with xmlContent to rewrite an object — never via PowerShell/create_file)."New value: +"Allow overwriting — never rewrite via PowerShell." - removed
Input schema / properties / packageNameRemoved value: -{ - "description": "Package name — auto-resolved from model name; pass only if they differ.", - "type": "string" -} - removed
Input schema / properties / packagePathRemoved value: -{ - "description": "Base package path (default: auto-detected PackagesLocalDirectory). [modify] also locates objects outside the default dir; for models outside bridge startup roots set D365FO_CUSTOM_PACKAGES_PATH or pass filePath.", - "type": "string" -} - changed
Input schema / properties / params / descriptionPrevious value: -"[modify] Operation-specific parameters as ONE object — NEST them here. Common shapes: add-method {methodName, sourceCode} · replace-code {oldCode, newCode, methodName?} · add-field {fieldName, fieldType(EDT), fieldBaseType?}; data-entity-ext {fieldName, dataField, dataSource} · rename-field {fieldName, fieldNewName} · add-index {indexName, indexFields[{fieldName}]} · add-relation {relationName, relatedTable, relationConstraints?} · add-field-group {fieldGroupName, fieldGroupFields?} · add-data-source {dataSourceName, dataSourceTable} · add-control {controlName, parentControl, controlDataSource?, controlDataField?} · enum ops {enumValueName, enumValueNewName?(modify-enum-value rename), enumValueLabel?, enumValueInt?} · add-menu-item-to-menu {menuItemToAdd} · modify-property {propertyPath, propertyValue} · add-table-method {tableMethodType, tableKeyField?} · add-display-method {methodName, displayMethodReturnEdt}. A missing/wrong parameter returns the COMPLETE spec for that operation — follow it instead of guessing."New value: +"[modify] Operation-specific parameters as ONE nested object, per get_knowledge(kind=\"op-spec\", topic=\"<operation>\"). A missing/wrong one returns that COMPLETE spec — follow it, do not guess." - changed
Input schema / properties / projectPath / descriptionPrevious value: -"Path to .rnrproj file (needed for addToProject). Auto-detected from .mcp.json or workspace if omitted."New value: +"Path to .rnrproj (auto-detected)." - added
Input schema / properties / properties / additionalPropertiesAdded value: +true - changed
Input schema / properties / properties / descriptionPrevious value: -"Additional properties by objectType:\n• class: extends, implements, isFinal, isAbstract\n• table: label, tableGroup, tableType, titleField1/2, cacheLookup?, primaryIndex?, allowRowVersionChangeTracking? (dual-write), created/modifiedBy/DateTime?, fields[{name,type?|edt?|fieldType?,enumType?,label?,mandatory?}] — enum fields need enumType (+ optionally fieldType:\"AxTableFieldEnum\")\n• enum: label, useEnumValue, configurationKey, isExtensible, enumValues[{name,value?,label?,helpText?}]\n• enum-extension: enumValues[{name,label?,value?,countryRegionCodes?}]\n• table-extension: fields[{name,edt?,enumType?,label?,mandatory?,fieldType?}] — enum fields need fieldType:\"AxTableFieldEnum\" + enumType\n• edt: label, extends, edtType, stringSize\n• edt-extension: label?, helpText?, stringSize?, extends?, formHelp?, propertyModifications?[{name,value}] = the change\n• form: caption, formTemplate, dataSource\n• security-privilege: label, targetObject, objectType (MenuItemDisplay|Action|Output), accessLevel (view|maintain), dataEntity (grants perms)\n• security-duty: label, privileges[]\n• security-role: label, duties[], privileges[]\n• menu-item-*: label, object, objectType\n• data-entity: primaryTable, fields[{name,dataField?}], primaryKey?, primaryKeyFields?[], isPublic?, entityCategory?, dynamicFields?, allowRowVersionChangeTracking? (dual-write: set on the source TABLES too), dataManagementEnabled? (needs staging table)\n• map: label?, developerDocumentation?, fields[{name,type?,edt?,enumType?,stringSize?}], mappingTable?, mappings?[{mapField,mapFieldTo}] (one connection/field by default)\n• query: title?, dataSource (root table; table also works), dataSourceName?, fields?[{name,field?}]\n• view: query (existing AxQuery), fields[{name,dataField?}] — dataSource defaults to query\n• service: serviceClass (defaults to the service name), externalName?, namespace?, description?, operations[\"opName\"] or [{name?,method?,enableIdempotence?,subscriberAccessLevelRead?}]\n• service-group: autoDeploy? (Yes publishes at /api/services), description?, services[\"MyService\"] or [{name?,service?}]\n ⚠ service/service-group CROSS-REFS (serviceClass, services[].service) are written VERBATIM — only objectName is prefixed. Pass the FINAL name (e.g. \"ContosoDemoNoteService\", not \"DemoNoteService\") or the group resolves to nothing; verbatim also lets it reference an unprefixed MS service."New value: +"[create] Per-objectType creation properties (label, fields[], extends, enumValues[], primaryTable, …) — NOT in this schema. Fetch yours: get_knowledge(kind=\"op-spec\", topic=\"<objectType>\")." - removed
Input schema / properties / solutionPathRemoved value: -{ - "description": "VS solution directory — used to find .rnrproj when projectPath unset.", - "type": "string" -} - changed
Input schema / properties / sourceCode / descriptionPrevious value: -"X++ source for the object. FOR CLASSES the content is auto-split: <Declaration> = the class line + ALL member variables inside the outer { }; <Methods> = each method AFTER the closing }."New value: +"X++ source. FOR CLASSES auto-split: <Declaration> = class line + member vars; <Methods> = each method after the closing }." - removed
Input schema / properties / workspacePathRemoved value: -{ - "description": "[modify] Workspace path for finding file", - "type": "string" -} - changed
Input schema / properties / xmlContent / descriptionPrevious value: -"Complete XML to write verbatim (with overwrite=true rewrites an existing object; Azure/Linux: pass XML from action=generate)."New value: +"Complete XML written verbatim (+overwrite=true rewrites an object)."
- Changed
generate_object36 fields changed- removed
Input schema / properties / additionalDatasetsRemoved value: -{ - "description": "[scaffold:report] Multi-dataset report: each entry adds a TempDB TmpTable + a get<Table>() DP method. name = suffix (\"Header\" → <Report>HeaderTmp).", - "items": { - "properties": { - "fields": { - "items": { - "properties": { - "name": { - "type": "string" - } - }, - "required": [ - "name" - ], - "type": "object" - }, - "type": "array" - }, - "fieldsHint": { - "type": "string" - }, - "name": { - "type": "string" - } - }, - "required": [ - "name" - ], - "type": "object" - }, - "type": "array" -} - removed
Input schema / properties / baseNameRemoved value: -{ - "description": "[pattern] event-handler: base class/table. form-datasource-extension: data source name (defaults to form name). form-control-extension: exact control name (find via get_object_info(objectType=\"form\")).", - "type": "string" -} - removed
Input schema / properties / captionRemoved value: -{ - "description": "[scaffold:form|report] Optional caption/title (form: window title; report: human-readable report title).", - "type": "string" -} - removed
Input schema / properties / cloneFromRemoved value: -{ - "description": "[scaffold:form] PREFERRED: clone a reference form's XML re-bound via tableMapping (methods stripped; fields missing on target tables dropped and reported).", - "type": "string" -} - removed
Input schema / properties / contractParamsRemoved value: -{ - "description": "[scaffold:report] Dialog parameters for the Contract class.", - "items": { - "properties": { - "label": { - "type": "string" - }, - "mandatory": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "type": { - "description": "X++ type — EDT or primitive (e.g. \"TransDate\", \"CustAccount\")", - "type": "string" - } - }, - "required": [ - "name" - ], - "type": "object" - }, - "type": "array" -} - removed
Input schema / properties / copyFromRemoved value: -{ - "description": "[scaffold] Copy structure from an existing object (forms: prefer cloneFrom).", - "type": "string" -} - removed
Input schema / properties / dataSourceRemoved value: -{ - "description": "[scaffold:form] Optional: Table name for primary datasource.", - "type": "string" -} - removed
Input schema / properties / designStyleRemoved value: -{ - "description": "[scaffold:report] RDL design pattern: \"SimpleList\" (default) or \"GroupedWithTotals\".", - "type": "string" -} - removed
Input schema / properties / fieldGroupRemoved value: -{ - "description": "[fields] Field-group name — emits an AxTableFieldGroup listing the new fields.", - "type": "string" -} - removed
Input schema / properties / fieldsRemoved value: -{ - "description": "[scaffold:table|report | fields] Structured field specs; takes priority over fieldsHint. PREFER for enum-backed fields or an explicit EDT — a bare name cannot express either. name + optional edt/enumType/type/label/mandatory (EDT auto-resolved when omitted).", - "items": { - "properties": { - "dataType": { - "description": "[scaffold:report] .NET type, e.g. \"System.Double\"", - "type": "string" - }, - "edt": { - "description": "Explicit EDT — for mode=\"fields\", omit to auto-resolve from the field name.", - "type": "string" - }, - "enumType": { - "description": "[fields] Enum name for an enum-backed field (AxTableFieldEnum).", - "type": "string" - }, - "label": { - "type": "string" - }, - "mandatory": { - "description": "[fields] Mark the field Mandatory=Yes.", - "type": "boolean" - }, - "name": { - "type": "string" - }, - "type": { - "description": "[fields] Explicit base type (String/Integer/Int64/Real/Date/UtcDateTime/Guid).", - "type": "string" - } - }, - "required": [ - "name" - ], - "type": "object" - }, - "type": "array" -} - removed
Input schema / properties / fieldsHintRemoved value: -{ - "description": "[scaffold:table|report] Comma-separated field names; EDTs auto-suggested from the index. ⚠️ EDTs/enums created this session are not yet indexed — call update_symbol_index first, else those fields default to String255.", - "type": "string" -} - removed
Input schema / properties / formPatternRemoved value: -{ - "description": "[scaffold:form] Optional: Form pattern (SimpleList, SimpleListDetails, DetailsMaster, DetailsTransaction, Dialog, DropDialog, TableOfContents, Lookup, ListPage, Workspace).", - "type": "string" -} - removed
Input schema / properties / generateCommonFieldsRemoved value: -{ - "description": "[scaffold:table] Auto-generate common fields based on table group patterns.", - "type": "boolean" -} - removed
Input schema / properties / generateControllerRemoved value: -{ - "description": "[scaffold:report] Generate Controller class (default: true).", - "type": "boolean" -} - removed
Input schema / properties / generateControlsRemoved value: -{ - "description": "[scaffold:form] Auto-generate grid controls for datasource.", - "type": "boolean" -} - removed
Input schema / properties / includeExistsRemoved value: -{ - "description": "[find-methods] Emit exists() (default true).", - "type": "boolean" -} - removed
Input schema / properties / includeFindRecIdRemoved value: -{ - "description": "[find-methods] Emit findRecId() (default true).", - "type": "boolean" -} - removed
Input schema / properties / includeMethodStubsRemoved value: -{ - "description": "[scaffold:form] Inject pattern-appropriate lifecycle method stubs with TODO markers.", - "type": "boolean" -} - removed
Input schema / properties / keyFieldsRemoved value: -{ - "description": "[find-methods] Explicit key field names (order matters); overrides index detection.", - "items": { - "type": "string" - }, - "type": "array" -} - removed
Input schema / properties / labelRemoved value: -{ - "description": "[scaffold:table|form] Optional label for the generated object.", - "type": "string" -} - removed
Input schema / properties / menuItemTypeRemoved value: -{ - "description": "[pattern] For menu-item pattern: type of menu item (display=form, action=class, output=report)", - "enum": [ - "display", - "action", - "output" - ], - "type": "string" -} - changed
Input schema / properties / modelName / descriptionPrevious value: -"Model name from .mcp.json (auto-detected if omitted). NEVER use placeholders like \"MyModel\"."New value: +"Model name (auto-detected). NEVER use placeholders like \"MyModel\"." - changed
Input schema / properties / name / descriptionPrevious value: -"REQUIRED. [pattern] element name (extensions: base element; form-datasource/control-extension: the FORM name). [scaffold] object name WITHOUT model prefix."New value: +"REQUIRED. [pattern] element name (extensions: base element; form-datasource/control-extension: the FORM name). [scaffold] object name WITHOUT model prefix. [other modes] the existing table." - removed
Input schema / properties / packagePathRemoved value: -{ - "description": "[scaffold:report] Base packages directory path.", - "type": "string" -} - added
Input schema / properties / paramsAdded value: +{ + "additionalProperties": true, + "description": "Mode-specific parameters as ONE nested object (label, fields[], fieldsHint, cloneFrom, tableMapping, formPattern, contractParams[], keyFields[], style, fieldGroup, …). Get the contract from get_knowledge(kind=\"op-spec\", topic=\"<mode>\"); a missing required one returns that COMPLETE spec.", + "type": "object" +} - changed
Input schema / properties / pattern / descriptionPrevious value: -"[pattern] REQUIRED. CoC skeletons: class/table-extension, form-handler, form-datasource-extension (name=FormName, baseName=DataSourceName), form-control-extension (name=FormName, baseName=ControlName), map-extension. ssrs-report-full = Contract+DP+Controller; service-class-ais = CRUD service + contract."New value: +"[pattern] REQUIRED. CoC skeletons: class/table-extension, form-handler, form-datasource-extension, form-control-extension, map-extension. ssrs-report-full = Contract+DP+Controller; service-class-ais = CRUD service + contract." - removed
Input schema / properties / previewRemoved value: -{ - "description": "[scaffold:table] Return the XML without writing to disk.", - "type": "boolean" -} - removed
Input schema / properties / projectPathRemoved value: -{ - "description": "[scaffold] Path to .rnrproj file for model extraction.", - "type": "string" -} - removed
Input schema / properties / relationNameRemoved value: -{ - "description": "[relation-xpp] One relation to convert. Omit = all relations.", - "type": "string" -} - removed
Input schema / properties / serviceMethodRemoved value: -{ - "description": "[pattern] sysoperation: Service method the Controller calls (default \"process\").", - "type": "string" -} - removed
Input schema / properties / solutionPathRemoved value: -{ - "description": "[scaffold] Path to solution directory (alternative to projectPath).", - "type": "string" -} - removed
Input schema / properties / styleRemoved value: -{ - "description": "[relation-xpp] select | query | both (default).", - "enum": [ - "select", - "query", - "both" - ], - "type": "string" -} - removed
Input schema / properties / tableGroupRemoved value: -{ - "description": "[scaffold:table] Business role (TableGroup enum): Main, Transaction, Parameter, Group, WorksheetHeader/WorksheetLine, Reference, Miscellaneous, Framework. ⛔ NEVER pass \"TempDB\"/\"InMemory\" here — that is tableType.", - "type": "string" -} - removed
Input schema / properties / tableMappingRemoved value: -{ - "additionalProperties": { - "type": "string" - }, - "description": "[scaffold:form] With cloneFrom: sourceTable → targetTable map, e.g. {\"CustGroup\": \"MyRentalGroup\"}.", - "type": "object" -} - removed
Input schema / properties / tableTypeRemoved value: -{ - "description": "[scaffold:table] Storage type: Regular (default, omit), TempDB, InMemory. ⛔ NEVER pass as tableGroup.", - "type": "string" -} - removed
Input schema / properties / targetObjectRemoved value: -{ - "description": "[pattern] For menu-item and security-privilege patterns: target form/class/report name", - "type": "string" -}
- Changed
get_knowledge3 fields changed- changed
Input schema / properties / kind / descriptionPrevious value: -"knowledge = look up an X++ topic/rule; error = diagnose an error message."New value: +"knowledge = look up an X++ topic/rule; error = diagnose an error message; op-spec = parameter contract for a d365fo_file operation/objectType or generate_object mode." - changed
Input schema / properties / kind / enumPrevious value: -[ - "knowledge", - "error" -]New value: +[ + "knowledge", + "error", + "op-spec" +] - changed
Input schema / properties / topic / descriptionPrevious value: -"[knowledge] REQUIRED. Topic to query — e.g. \"batch job\", \"ttsbegin\", \"RunBase vs SysOperation\", \"set-based operations\", \"CoC\", \"data entities\", \"number sequences\", \"security\", \"temp tables\", \"today() deprecated\", \"query patterns\", \"form patterns\""New value: +"[knowledge] REQUIRED. Topic to query — e.g. \"batch job\", \"ttsbegin\", \"RunBase vs SysOperation\", \"set-based operations\", \"CoC\", \"data entities\", \"number sequences\", \"security\", \"temp tables\", \"today() deprecated\", \"query patterns\", \"form patterns\". [op-spec] The operation / objectType / mode to look up."
- Removed
get_method - Changed
get_object_info5 fields changed- changed
Input schema / properties / name / descriptionPrevious value: -"Exact object name (use search first if unsure)"New value: +"Exact object name (use search first if unsure). REQUIRED unless using objects[]." - changed
Input schema / properties / objectType / descriptionPrevious value: -"Kind of object to read (incl. *-extension types — pass base object name or full extension name)"New value: +"Kind of object to read (incl. *-extension types — pass base object name or full extension name). REQUIRED unless using objects[]." - added
Input schema / properties / objectsAdded value: +{ + "description": "PREFERRED for 2+ objects: read them all in one round trip. Each entry takes the same objectType/options as the single form, with the name in objectName.", + "items": { + "properties": { + "objectName": { + "description": "Exact object name (use search first if unsure)", + "type": "string" + }, + "objectType": { + "description": "Kind of object to read", + "enum": [ + "class", + "table", + "form", + "query", + "view", + "enum", + "edt", + "report", + "data-entity", + "menu-item", + "service", + "map", + "config-key", + "security-policy", + "macro", + "table-extension", + "class-extension", + "form-extension", + "enum-extension", + "edt-extension", + "data-entity-extension" + ], + "type": "string" + }, + "options": { + "description": "Optional type-specific flags for this object; overrides the top-level options.", + "type": "object" + } + }, + "required": [ + "objectType", + "objectName" + ], + "type": "object" + }, + "maxItems": 10, + "minItems": 1, + "type": "array" +} - changed
Input schema / properties / options / descriptionPrevious value: -"Optional type-specific flags forwarded to the reader (e.g. includeRdl, includeFields, searchControl, compact, includeOperations, filter, mode, modelName)."New value: +"Type-specific flags forwarded to the reader: includeRdl, includeFields, searchControl, compact, includeOperations, filter, mode, modelName. For a CLASS, {\"method\":\"validateWrite\",\"include\":\"signature\"} returns ONE method (include: signature | source | both) — required before writing a CoC extension. Big objects are paged — table fieldsOffset/fieldFilter, form maxControls. Applies to every objects[] entry." - removed
Input schema / requiredRemoved value: -[ - "objectType", - "name" -]
- Changed
get_workspace_info1 field changed- changed
Input schema / properties / diagnostics / descriptionPrevious value: -"Include verbose diagnostic sections (suffix breakdown, stdio session/handshake dump). Use when debugging client-server connectivity."New value: +"Include verbose sections (config sources, suffix, project paths, index scan, stdio handshake). Use when debugging config or connectivity."
- Changed
labels17 fields changed- removed
Input schema / properties / addToProjectRemoved value: -{ - "description": "[create] Add label file XML descriptors to the VS project (default: true).", - "type": "boolean" -} - removed
Input schema / properties / allowExtensionLabelFileRemoved value: -{ - "description": "[create|rename] Allow writing to a label file EXTENSION (\"_Extension\" marker). Default false — new labels belong in the model's ORIGINAL label file.", - "type": "boolean" -} - removed
Input schema / properties / createLabelFileIfMissingRemoved value: -{ - "description": "[create] Create the AxLabelFile structure if missing (default: true). A wrong-path guard still fails loudly when the model directory is not found, so no phantom file is produced. Set false to fail fast instead.", - "type": "boolean" -} - removed
Input schema / properties / defaultCommentRemoved value: -{ - "description": "[create] Developer comment for languages without explicit comment.", - "type": "string" -} - removed
Input schema / properties / descriptionRemoved value: -{ - "description": "[create] Label description (comment line in .label.txt). Defaults to VS project name from .rnrproj when omitted, then falls back to labelFileId. Per-translation comment and defaultComment take priority.", - "type": "string" -} - removed
Input schema / properties / languagesRemoved value: -{ - "description": "[create] Restrict which language .label.txt files are written (e.g. [\"en-US\"]). Omitted = every language folder present in the model.", - "items": { - "type": "string" - }, - "type": "array" -} - changed
Input schema / properties / limit / descriptionPrevious value: -"[search] Maximum number of results (default 30)."New value: +"[search] Alias of maxResults." - added
Input schema / properties / maxResultsAdded value: +{ + "description": "[search] Max labels listed (default 10, alias `limit`); a truncated set reports how many more matched.", + "type": "number" +} - removed
Input schema / properties / packageNameRemoved value: -{ - "description": "[create|rename] Package name for the model. Auto-resolved if omitted.", - "type": "string" -} - removed
Input schema / properties / packagePathRemoved value: -{ - "description": "[create|rename] Root packages path. Auto-detected from environment config if omitted.", - "type": "string" -} - added
Input schema / properties / paramsAdded value: +{ + "additionalProperties": true, + "description": "Optional write plumbing (packagePath, projectPath, languages, sortLabels, allowExtensionLabelFile, …) — all auto-resolved when omitted. Contract: get_knowledge(kind=\"op-spec\", topic=\"labels\").", + "type": "object" +} - removed
Input schema / properties / projectPathRemoved value: -{ - "description": "[create] Path to the .rnrproj project file. Auto-detected from .mcp.json if omitted.", - "type": "string" -} - removed
Input schema / properties / searchPathsRemoved value: -{ - "description": "[rename] Additional absolute directory paths to scan for X++ / XML references.", - "items": { - "type": "string" - }, - "type": "array" -} - removed
Input schema / properties / solutionPathRemoved value: -{ - "description": "[create] Path to the .sln solution directory. Fallback to find .rnrproj if projectPath is not set.", - "type": "string" -} - removed
Input schema / properties / sortLabelsRemoved value: -{ - "description": "[create] Sort labels alphabetically in .label.txt (default true, from LABEL_SORT_ORDER env; false = append at end).", - "type": "boolean" -} - removed
Input schema / properties / updateIndexRemoved value: -{ - "description": "[create|rename] Update the MCP label index after writing (default: true).", - "type": "boolean" -} - added
Input schema / properties / verboseAdded value: +{ + "description": "[search] Default one line per label; true = full multi-line block.", + "type": "boolean" +}
- Changed
prepare1 field changed- added
Input schema / properties / operationAdded value: +{ + "description": "[change] The modify operation you intend to run; its full parameter contract comes back in THIS response, so no separate op-spec call. Defaults to add-method when methodName is given.", + "type": "string" +}
- Changed
run_bp_check3 fields changed- added
Input schema / properties / objectsAdded value: +{ + "description": "Check several objects in ONE call — preferred over targetFilter. Shared preamble is printed once and findings are grouped per object.", + "items": { + "properties": { + "objectName": { + "description": "Object name.", + "type": "string" + }, + "objectType": { + "description": "class, table, form, enum, view, query, edt, ... Looked up in the symbol index if omitted.", + "type": "string" + } + }, + "required": [ + "objectName" + ], + "type": "object" + }, + "type": "array" +} - changed
Input schema / properties / targetElementType / descriptionPrevious value: -"Element type for the filter when using xppbp 10.0.24+ (equals-style CLI). Common values: class, table, form, enum, view, query. Defaults to \"class\" when targetFilter is set but this is omitted."New value: +"Element type for targetFilter. Looked up in the symbol index if omitted; ambiguous or unknown names error rather than being assumed to be a class." - changed
Input schema / properties / targetFilter / descriptionPrevious value: -"Optional: filter results to a specific object name (class, table, form, enum, ...)."New value: +"Single-object form: object name to check. Use objects[] for more than one."
- Changed
search4 fields changed- changed
Input schema / properties / globalTypeFilter / descriptionPrevious value: -"[batch] Default type filter for queries without an explicit per-query type. E.g. [\"class\"] restricts all untyped queries to classes. Multiple values fan out each untyped query into one search per type."New value: +"[batch] Default type filter for queries without an explicit per-query type. E.g. [\"class\"] restricts all untyped queries to classes. Multiple values fan out each untyped query into one search per type. Values: same as the top-level `type`, except \"all\" (which means \"no filter\" — omit this instead)." - removed
Input schema / properties / globalTypeFilter / items / enumRemoved value: -[ - "class", - "table", - "form", - "field", - "method", - "enum", - "edt", - "query", - "view", - "report", - "security-privilege", - "security-duty", - "security-role", - "menu-item-display", - "menu-item-action", - "menu-item-output", - "table-extension", - "class-extension", - "form-extension", - "enum-extension", - "edt-extension", - "data-entity-extension" -] - changed
Input schema / properties / queries / items / properties / type / descriptionPrevious value: -"Filter by object type. Omit to inherit globalTypeFilter or default to \"all\""New value: +"Filter by object type — same values as the top-level `type`. Omit to inherit globalTypeFilter or default to \"all\"" - removed
Input schema / properties / queries / items / properties / type / enumRemoved value: -[ - "class", - "table", - "field", - "method", - "enum", - "edt", - "form", - "query", - "view", - "report", - "security-privilege", - "security-duty", - "security-role", - "menu-item-display", - "menu-item-action", - "menu-item-output", - "table-extension", - "class-extension", - "form-extension", - "enum-extension", - "edt-extension", - "data-entity-extension", - "all" -]
- Removed
suggest_edt - Changed
update_symbol_index1 field changed- changed
Input schema / properties / filePath / descriptionPrevious value: -"Absolute path to the modified or created XML file (e.g. K:\\\\AosService\\\\PackagesLocalDirectory\\\\MyModel\\\\MyModel\\\\AxClass\\\\MyClass.xml), or an ARRAY — batch them, each call costs a bridge refresh."New value: +"Absolute path to the changed XML file, or an ARRAY — batch them, each call costs a bridge refresh."
2 tool updates
v1.8.5- Changed
get_workspace_info1 field changed- changed
Input schema / properties / projectName / descriptionPrevious value: -"Preferred way to switch projects. Just the model name, e.g. \"ContosoEDS\" or \"ContosoBank\". The server resolves the full path from D365FO_SOLUTIONS_PATH automatically. Use this when the user says \"switch to <project>\" or opens a different solution."New value: +"Only when the USER says \"switch to <project>\". Just the model name, e.g. \"ContosoEDS\"; path resolved from D365FO_SOLUTIONS_PATH. NOT a way to reach another model — reads span every model already, writes stay in the workspace model."
- Changed
update_symbol_index3 fields changed- changed
Input schema / properties / filePath / descriptionPrevious value: -"Absolute path to the modified or created XML file (e.g. K:\\\\AosService\\\\PackagesLocalDirectory\\\\MyModel\\\\MyModel\\\\AxClass\\\\MyClass.xml). Omit to run a lightweight bridge/workspace refresh instead of indexing a specific file."New value: +"Absolute path to the modified or created XML file (e.g. K:\\\\AosService\\\\PackagesLocalDirectory\\\\MyModel\\\\MyModel\\\\AxClass\\\\MyClass.xml), or an ARRAY — batch them, each call costs a bridge refresh." - added
Input schema / properties / filePath / itemsAdded value: +{ + "type": "string" +} - changed
Input schema / properties / filePath / typePrevious value: -"string"New value: +[ + "string", + "array" +]
26 tool updates
v1.8.0- First observed
analyze_code - First observed
batch_get_info - First observed
build_d365fo_project - First observed
d365fo_file - First observed
extension_info - First observed
find_references - First observed
generate_object - First observed
get_knowledge - First observed
get_method - First observed
get_object_info - First observed
get_workspace_info - First observed
labels - First observed
object_patterns - First observed
prepare - First observed
review_workspace_changes - First observed
run_bp_check - First observed
run_systest_class - First observed
search - First observed
security_info - First observed
suggest_edt - First observed
trigger_db_sync - First observed
undo_last_modification - First observed
update_symbol_index - First observed
validate_code - First observed
validate_object_naming - First observed
verify_d365fo_project
TDQS
Most tools map cleanly to distinct operations (search vs exact-info vs references vs knowledge), and the descriptions explicitly manage the few shared boundaries—e.g. analyze_code vs object_patterns vs prepare, or d365fo_file generate vs generate_object. A couple of analysis/context tools could be confused when choosing how to start, but the mode/scenario guidance makes selection reliable.
Thirteen of the twenty tools use clear verb_object names (validate_code, build_d365fo_project, get_object_info), but the set also mixes in bare nouns (labels, object_patterns, security_info, extension_info) and bare verbs (search, prepare), plus the odd d365fo_file. The convention is mostly readable but not consistently applied.
20 tools for a D365FO development MCP is on the heavy side, but the domain is broad and several tools are multi-mode bundles (d365fo_file, get_knowledge, object_patterns, prepare), so the count is defensible. It exceeds the typical 3–15 range, but none of the tools feel truly redundant; it is slightly over-scoped rather than bloated.
The surface covers the full object lifecycle—search/info/references, generate/validate, create/modify/delete/undo, build, BP check, and unit tests—plus security, extensibility, labels, naming, and knowledge lookup. There are no glaring dead ends for an agent building and maintaining D365FO code.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
D365 F&O: 90 AI tools over 200K+ objects, 25M+ cross-refs, 24M+ label translations.
Governance copilot for AI-assisted coding. 72 packs, 532 rules, proof bundles.
Read-only AI coding tools for change verification, release readiness, capacity, and guidance.
Code intelligence platform for AI agents. 20 tools for architecture, security & impact analysis.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceAn MCP server for Microsoft Dynamics 365 Finance & Operations that enables the creation, modification, and analysis of D365 objects like classes, tables, and forms. It integrates with Visual Studio 2022 to provide tools for X++ code extraction, codebase search, and safe object deletion with dependency validation.-
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to explore metadata, query data, and perform write operations across multiple Microsoft Dynamics 365 Finance & Operations environments. It features specialized tools for OData execution and data analysis with built-in read-only safety for production environments.4710MIT
- AlicenseAqualityAmaintenanceExposes the full capabilities of Microsoft Dynamics 365 Finance & Operations to AI assistants through 49 comprehensive tools and standardized protocol interactions. It enables sophisticated workflows including OData operations, metadata discovery, and secure database analysis.4938MIT
- AlicenseNot gradedqualityCmaintenanceEnables D365 F\&O development including object creation, modification, deletion, and analysis through the MCP standard.40MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/dynamics365ninja/d365fo-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server