Skip to main content
Glama

D365 F&O MCP Server

22 AI tools that know every X++ class, table, form, and EDT in your D365FO codebase

npm License: MIT Node.js TypeScript Tests

Core coverage Total coverage

Grounded AI development for Dynamics 365 Finance & Operations — works with GitHub Copilot and Claude Code

Install in VS Code Install in VS Code Insiders Add to Cursor

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 22 specialized MCP tools (axdb_sql and trace_d365fo only once configured). Every signature, every CoC wrapper, every label, every form pattern — verified against your real metadata before the AI writes a single line.

Solution Architecture

Task

Without this server

With this server

Method signatures

Guessed → compile errors

Exact, from your codebase

Existing CoC wrappers

Manual AOT search

extension_info(mode="coc") in < 50 ms

New forms

Hand-written XML, broken patterns

Cloned from reference forms, validated against the pattern catalog

Labels

Hardcoded strings

Right @SYS/@MODULE key found instantly

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: Dynamics 365 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: prepare issues grounding tokens, validate_code(mode="references") proves every identifier, validate_code(mode="syntax") enforces best practices — hallucinated code never reaches disk

🧩 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 IMetadataProvider wherever it can express the object; the few types and ops it cannot go through structured XML writers with ambiguity guards — never blind string replacement. Automatic .rnrproj registration, one-call undo

🏗️ SDLC integration

MSBuild compilation with structured diagnostics, DB sync, xppbp best practices, SysTestRunner — all from chat. Optional restartAos: true refreshes the matching local IIS/IIS Express runtime after a successful build and requested sync. Runtime restart

🗄️ Optional AxDB SQL

Off by default and not even published until configured: axdb_sql runs read-only, parameterized queries against AxDB on the development VM, so the agent can check what the code actually persisted. Windows authentication; one SELECT checked on the parsed T-SQL tree, inside a transaction that is always rolled back; no result cache. Setup

⏱️ Optional performance trace

Off by default and not published until enabled: trace_d365fo captures the AOS's ETW events (X++ method enter/exit, SQL latency) on the development VM while the agent — or you — reproduce a slow scenario, and analyses the capture: where the time goes per method, which statements run thousands of times from one caller. No timer code added to the application; parameter values never returned. Setup and accuracy

📐 X++ knowledge base

Queryable rules: select grammar, CoC authoring, financial dimensions, the posting engine (LedgerVoucher), number sequences, SysExtension, Electronic Reporting, AX2012→D365FO migration — prevents deprecated APIs

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–FP011"]
    D -->|clean| E["d365fo_file<br/>(action=create) write + project"]
    D -->|errors| C

Structural 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 | iex

Already have Node.js 24+? Then the one-liner has nothing to bootstrap and you can skip it:

npm install -g d365fo-mcp
d365fo-mcp setup

Re-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.net

Both 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.

Deploy to Azure

Deployment guide: docs/SETUP_AZURE.md — includes CI/CD pipeline automation


Documentation

License

MIT

Available Tools

20 tools
analyze_codeA
Read-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.

Inputs: mode (required), limit, apiName, context, +6 more.

build_d365fo_projectA
Idempotent

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.

Inputs: wait, force, aosUrl, dbSync, +6 more.

d365fo_fileA
Destructive

D365FO AOT object files and VS projects. Choose an action: • create → write a NEW object file into PackagesLocalDirectory (auto-added to .rnrproj). THE WRITE STEP — incomplete until isError=false; ⚠️/❌ = failure. Extensions: objectName="Base.PrefixExtension". • project → VS project + .sln ops via params.operation: create|delete (confirm first)|add-object|remove-object. • 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 listing 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/outside git → deleted only if created this session. • generate → XML as TEXT only, no write (Azure/Linux fallback). Try create first. The rest need Windows. 📖 Parameters are NOT inlined here: get_knowledge(kind="op-spec", topic=""|"") returns its contract — pass its values nested in params (modify) / properties (create), along with any packageName/packagePath/solutionPath/workspacePath override. Model + prefix auto-applied.

Inputs: action (required), params, filePath, modelName, +12 more.

extension_infoA
Read-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.

Inputs: mode (required), goal, method, target, +6 more.

find_referencesA
Read-only

Find all references (where-used) to a class, method, field, table, enum, EDT, or LABEL. 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).

Inputs: targetName (required), limit, ownerName, targetType.

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.

Inputs: mode (required), name, params, pattern, +2 more.

get_knowledgeA
Read-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.

Inputs: kind, path, topic, action, +6 more.

get_object_infoA
Read-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, menu, service, map, config-key, security-policy, macro. The *-extension types 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.

Inputs: name, objects, options, objectType.

get_workspace_infoA
Read-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.

Inputs: changes, diagnostics, projectName, projectPath.

labelsA
Destructive

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").

Inputs: action (required), model, query, dryRun, +10 more.

object_patternsA
Read-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-FP011. 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=.

Inputs: xml, limit, action, domain, +8 more.

prepareA
Read-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.

Inputs: goal (required), mode (required), objectName (required), operation, +4 more.

run_bp_checkA
Read-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.

Inputs: objects, modelName, packagePath, projectPath.

run_systest_classB

Run a D365FO unit test class (SysTestConsole; UDE: cloud runtime), returning per-method results.

Inputs: className (required), modelName, testMethod, packagePath.

security_infoA
Read-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).

Inputs: mode (required), name, objectName, objectType, +2 more.

update_symbol_indexA
Idempotent

Index D365FO XML changed OUTSIDE this server (VS, hand edit, git pull). Do NOT call after d365fo_file create/modify — they re-index already. No args = bridge/cache refresh only.

Inputs: model, filePath.

validate_codeA
Read-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.

Inputs: code (required), mode (required), context, codeType.

validate_object_namingA
Read-only

Validate a proposed D365FO object name: extension naming/formats, ISV prefix, type suffixes, conflicts in the symbol index.

Inputs: objectType (required), proposedName (required), modelPrefix, baseObjectName, +1 more.

verify_d365fo_projectA
Read-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).

Inputs: objects, modelName, projectPath.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.7/5.0

    Scored across 20 tools

    Disambiguation3/5

    Most tools target distinct lifecycle stages, but generation/pattern/knowledge/validation capabilities overlap heavily across generate_object, d365fo_file, object_patterns, analyze_code, get_knowledge, validate_code, and prepare. The very detailed descriptions provide routing guidance, but an agent still has multiple plausible entry points for common tasks such as generating or validating an object.

    Naming Consistency3/5

    Names are consistently snake_case and readable, but the set mixes verb_noun names (generate_object, get_object_info) with bare nouns/actions (search, labels, prepare, d365fo_file) and noun_info names (security_info, extension_info). The convention is recognizable but not uniform.

    Tool Count3/5

    Twenty tools is plausible for a broad D365FO development lifecycle, but it sits at the heavy end and includes several mode-heavy tools whose responsibilities overlap. Some consolidation, especially around generation, knowledge lookup, and preparation, could reduce surface area without losing capability.

    Completeness4/5

    The surface covers workspace discovery, search, object inspection, generation, file/project operations, labels, extensibility, security, validation, build, BP checks, verification, and unit tests. Minor gaps remain around packaging/deployment or environment lifecycle operations, but core development workflows are well represented.

    Maintenance

    ActivityActive
    ResponsivenessUsually handled

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables 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.
      44 npm
      10
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Exposes 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.
      49
      118 PyPI
      41
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables D365 F\&O development including object creation, modification, deletion, and analysis through the MCP standard.
      42
      MIT
    • F
      license
      Not graded
      quality
      B
      maintenance
      Enables AI assistants to search and analyze Microsoft Dynamics 365 Finance & Operations artifacts, read local source code, and generate context-aware solutions through natural language.
      118 npm
      12
      -