Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

ALM X++ MCP Server

REMOTE · API.ALMXPP.COM · 2 COMPONENTS · SCANNED AUG 19

D365 F&O: 90 AI tools over 200K+ objects, 25M+ cross-refs, 24M+ label translations.

67 Trust /100
Trust breakdown (6 categories)

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score →

Endpoint Security66
  • The endpoint's TLS certificate is valid, in date, and uses a strong key. View diagnostics → Pass
  • Authorisation not fully verified: this server exposes a tool marked destructive (dmf_import_file) and its handshake is open, but we could not confirm whether a tool call is gated, so we do not assert it is callable unauthenticated. View diagnostics → Unverified
  • HTTPS is enforced; there's no plaintext access path. View diagnostics → Pass
  • The HSTS (Strict-Transport-Security) header is present. View diagnostics → Pass
  • DNSSEC is configured correctly; the domain's records validate against the full chain to the root. View diagnostics → Pass
Transport & Reachability100
Schema Quality & AI Usability77
  • 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 27883 tokens (~296/item across 94 items; 90 tools + 4 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management3
  • Stability observed for 1 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage100
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 100% of tool parameters carry a description.Pass
  • Structured output schemas are declared (1% of tools); any adoption earns full credit.Pass
Capabilities100
  • Implements a current MCP spec version (2026-07-28).Pass
Install

Add this component to your MCP client. Where a client-specific snippet is available, pick your client below and copy it straight into your config; otherwise use the connection detail shown.

remote · api.almxpp.com

# add to Claude Code
claude mcp add --transport http alimbenhelal-pro-alm-xpp-mcp https://api.almxpp.com/mcp
# ~/.codex/config.toml
[mcp_servers.alimbenhelal-pro-alm-xpp-mcp]
url = "https://api.almxpp.com/mcp"
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "alimbenhelal-pro-alm-xpp-mcp": {
      "type": "remote",
      "url": "https://api.almxpp.com/mcp",
      "enabled": true
    }
  }
}
# add to OpenClaw
openclaw mcp add alimbenhelal-pro-alm-xpp-mcp --url https://api.almxpp.com/mcp --transport streamable-http
# ~/.hermes/config.yaml
mcp_servers:
  alimbenhelal-pro-alm-xpp-mcp:
    url: "https://api.almxpp.com/mcp"
// mcp.json
{
  "mcpServers": {
    "alimbenhelal-pro-alm-xpp-mcp": {
      "type": "http",
      "url": "https://api.almxpp.com/mcp"
    }
  }
}

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 19 Aug 26 0
    • Stability: unverified → 0.03 functional
    • Server version: 1.4.447 → 1.4.450 functional
    • Server version: 1.4.442 → 1.4.447 functional
  • 18 Aug 26 67

    First indexed and scored.

Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 19 Aug 2026 · Probed https://api.almxpp.com/mcp

TLS valid

Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .

Subject Issuer Valid from Valid until Key Signature Serial
CN=api.almxpp.com CN=GeoTrust TLS RSA CA G1,OU=www.digicert.com,O=DigiCert Inc,C=US 13 Aug 2026 11 Feb 2027 RSA 2048 SHA256-RSA 87577e9fc48f42828f95e780d2a2a88
SANs: api.almxpp.com
CN=GeoTrust TLS RSA CA G1,OU=www.digicert.com,O=DigiCert Inc,C=US (CA) CN=DigiCert Global Root G2,OU=www.digicert.com,O=DigiCert Inc,C=US 2 Nov 2017 2 Nov 2027 RSA 2048 SHA256-RSA d07782a133fc6f9a57296e131ffd179
CN=DigiCert Global Root G2,OU=www.digicert.com,O=DigiCert Inc,C=US (CA) CN=DigiCert Global Root G2,OU=www.digicert.com,O=DigiCert Inc,C=US 1 Aug 2013 15 Jan 2038 RSA 2048 SHA256-RSA 33af1e6a711a9a0bb2864b11d09fae5
DNSSEC secure

Validation of api.almxpp.com. Secure

Zone DS Keys Algorithms Outcome
. trust_anchor 20326, 38696 8, 8 Verified
com. present 19718 13 Verified
almxpp.com. present 43502 8 Verified
api.almxpp.com. Verified address RRset verified with the apex keys
Authentication No authorisation required

The endpoint answered without asking for a token. Anyone who knows the URL can reach it.

Result No authorisation required
HTTP status 200
Header Value
strict-transport-security max-age=31536000; includeSubDomains; preload
content-security-policy default-src 'self'; script-src 'self' 'nonce-pKGpnYYD2xmP/uVdedD6+g==' cdn.jsdelivr.net blob:; style-src 'self' 'unsafe-inline' cdn.jsdelivr.net fonts.googleapis.com; font-src 'self' cdn.jsdelivr.net fonts.gstatic.com; img-src 'self' data: https: lh3.googleusercontent.com; connect-src 'self' blob: https://*.azurecontainerapps.io https://www.almxpp.com https://api.almxpp.com cdn.jsdelivr.net https://ipapi.co; worker-src 'self' blob:; object-src 'none'; frame-ancestors 'none'; base-uri 'self'; form-action 'self' https://accounts.google.com https://login.microsoftonline.com;
x-content-type-options nosniff
x-frame-options SAMEORIGIN
referrer-policy strict-origin-when-cross-origin
permissions-policy camera=(), microphone=(), geolocation=(), payment=()
Transports 2 probes
Transport URL Outcome Status Location
streamable-http https://api.almxpp.com/mcp Verified 200
http (plaintext) http://api.almxpp.com/mcp HTTPS enforced 301 https://api.almxpp.com/mcp
MCP tools · 90 exposed · ~25,099 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability.

Tool Tokens
generate_diagram ~286

WHEN: generating a visual diagram of D365 table relationships or security chains. Triggers: 'generate diagram', 'diagramme', 'visualize', 'schéma', 'ER diagram', 'entity-relationship', 'relation diagram', 'security diagram', 'show connections'. Generate visual Mermaid diagrams from D365 F&O knowledge base data. Diagrams render directly in Copilot Chat, Cursor, Claude, and markdown viewers. Types: 'er' (entity-relationship diagram for a table and its relations), 'security' (security chain: Role->Duty->Privilege->EntryPoints -- use when you need a VISUAL Mermaid diagram; for the structured text chain with tables of duties/privileges/entry-points use `trace_security_chain` instead). Note: 'flow' (execution flowchart) is disabled -- static call trees are misleading in D365 due to CoC and event handlers.

NameTypeReqDescription
diagramTypestringyesDiagram type: 'er' (entity-relationship) or 'security' (security chain). 'flow' is disabled.
maxRelatedintegerOptional: maximum related entities to show (default: 12, max: 20)
methodNamestring|nullNot used -- flow diagrams are disabled.
objectNamestringyesObject name to diagram, e.g. 'SalesTable', 'SystemAdministrator'

No output schema declared.

No examples provided.

generate_fdd ~234

WHEN: user asks to write or generate a Functional Design Document, FDD, functional spec, CdC, or cahier des charges. NOT for developer technical docs -- use `get_object_details` for that. FUNCTIONAL DESIGN DOCUMENT GENERATOR -- Produces a structured FDD ready for review and sign-off. Sections generated: Purpose, Business Context, Data Fields (with resolved labels), Business Rules, Related Objects, Security, and Open Questions. Triggers: 'write FDD for', 'generate FDD', 'functional spec for', 'document this process', 'write functional design', 'rédiger le cahier des charges', 'CdC pour', 'fiche de conception'.

NameTypeReqDescription
contextstring|nullOptional: additional business context, requirements, or audience note to include in the header
languagestringOptional: output language ('en', 'fr', 'nl', 'de'). Default: en
objectNamestringyesD365 object or business process name, e.g. 'SalesTable', 'VendInvoiceInfoTable', 'ALMDemandeAchat'

No output schema declared.

No examples provided.

generate_query ~442

WHEN: developer needs correct X++ select or T-SQL for D365 tables with proper joins. Triggers: 'X++ select', 'generate a query', 'SQL for', 'join with', 'how to query', 'générer une requête', 'write a select statement', 'select from', 'X++ query for', 'requête X++', 'écrire une select'. Generate both X++ select statements and equivalent T-SQL queries for D365 F&O tables. Uses real field names, relations, and indexes from the knowledge base to produce correct joins. Supports: field selection, multi-table joins (auto-detects relations), WHERE filters, ORDER BY, TOP/firstonly, cross-company. Also accepts natural language descriptions like 'find all open sales orders for customer 1001 with CustTable join'. [!] For multi-table joins, call find_related_objects (or get_relation_graph if the relation index is loaded) FIRST to get the correct FK relations -- this tool will then produce accurate join conditions. [!] The generated X++ is a template -- adapt it to your custom code context before using in production. Returns side-by-side X++ and SQL with explanations.

NameTypeReqDescription
crossCompanybooleanWhether to add crosscompany clause (default: false)
descriptionstring|nullOptional: natural language description of the query. If provided, fields/joins/filters are auto-detected.
fieldsstring|nullOptional: specific fields to select (comma-separated). All fields if not specified.
filtersstring|nullOptional: WHERE filter expressions (comma-separated), e.g. 'CustAccount == 1001, SalesStatus == SalesStatus::Open'
joinTablesstring|nullOptional: tables to join (comma-separated), e.g. 'CustTable,SalesLine'
orderBystring|nullOptional: field to ORDER BY
tableNamestringyesPrimary table name, e.g. 'SalesTable', 'CustTable'
topinteger|nullOptional: limit rows (1 = firstonly, N = top N)

No output schema declared.

No examples provided.

generate_release_note_document ~352

WHEN: you have already called prepare_release_note_context and analyzed its 'objects' array yourself, producing a findings JSON array per the 'instructions' field it returned. This tool renders that findings array into a downloadable Word (.docx, detailed appendix) and PowerPoint (.pptx, executive summary) release note and returns their download URLs. Does NOT call any LLM itself -- the reasoning must already be done by you.

NameTypeReqDescription
businessContextstring|nullOptional business/functional context (same value passed to prepare_release_note_context), included in the Word document.
customModelLabelstringyesCustom model label(s) -- use the customModelLabel field returned by prepare_release_note_context.
findingsJsonstringyesJSON array of your findings, one per object from prepare_release_note_context's 'objects' array. Schema: [{"aotType":"...","objectName":"...","changeType":"Added|Removed|Modified","riskLevel":"Critic…
touchedAddedintegeryestouchedAdded count returned by prepare_release_note_context.
touchedModifiedintegeryestouchedModified count returned by prepare_release_note_context.
touchedRemovedintegeryestouchedRemoved count returned by prepare_release_note_context.
v1stringyesOlder D365FO version (same value passed to prepare_release_note_context).
v2stringyesNewer D365FO version (same value passed to prepare_release_note_context).

No output schema declared.

No examples provided.

generate_security_report ~123

Generate a security & licensing governance report for the indexed model(s). For each role, lists duties, privileges, entry points and the inferred user-license tier (Activity, Operations, Finance, etc.). Surfaces orphan duties/privileges that grant no real access.

NameTypeReqDescription
filterModelstring|nullOptional: restrict the report to a single model name (e.g. 'ApplicationSuite', 'ContosoCustom'). Empty = all indexed models.
maxRolesDetailintegerMaximum number of roles to expand in detail (default 50, max 200).

No output schema declared.

No examples provided.

generate_unit_test ~358

WHEN: developer needs to write or scaffold unit tests for a custom D365 object. Triggers: 'generate tests', 'unit test', 'SysTest', 'write test for', 'scénarios de test', 'test this class'. Generate X++ SysTest unit test code for a CUSTOM D365 F&O object based on functional test scenarios. [!] Only meaningful on custom/extension code (D365_CUSTOM_MODEL_PATH). SysTest tests in D365 are highly context-specific -- a generic template rarely compiles without adaptation. REQUIRED: provide test scenarios in the 'testScenarios' parameter (supplied by the functional consultant). Each scenario becomes a concrete test method with arrange/act/assert. For tables: generates tests for find(), exist(), validateWrite(), initValue(). For classes: generates stubs for each public method listed in scenarios. Uses REAL field names and method signatures from the knowledge base.

NameTypeReqDescription
methodNamestring|nullOptional: specific method to test. If not provided, generates tests for all testable methods.
objectNamestringyesObject name to generate tests for, e.g. 'ALMERSftpConnectionTable', 'ALMMyClass'
sampleValuesstring|nullOptional: JSON object mapping field name to sample value used in each ARRANGE block, e.g. '{"AccountNum":"C0001","Amount":1500.50}'. Replaces the 'TODO: set up test data' placeholders with concrete a…
testScenariosstring|nullTest scenarios provided by the functional consultant, e.g. 'Create a connection with valid SFTP host; Validate that empty host fails; Delete cleans up related records'. Separate scenarios with semico…

No output schema declared.

No examples provided.

generate_xpp_form ~314

Generate a complete, compilable AxForm AOT XML with the CORRECT control serialization (<AxFormControl xmlns="" i:type="...">) for the requested pattern. Patterns: SimpleList, DetailsMaster, DetailsTransaction, ListPage, Dialog, DropDialog, Workspace, Extension. After generation, call validate_form_pattern on the result before write_aot_object.

NameTypeReqDescription
fieldTypesstring|nullOptional: comma-separated control type per field (aligned 1:1 with fields). Values: String, Int, Real, Date, DateTime, Enum, CheckBox, Reference. If omitted, all fields default to AxFormStringControl…
fieldsstring|nullComma-separated field names to include in the grid/header, e.g. 'AccountNum,Name,Status'
formNamestringyesPascalCase form name, e.g. 'ALMCustomerForm'
formPatternstringyesForm pattern: 'SimpleList', 'DetailsMaster', 'DetailsTransaction', 'ListPage', 'Dialog', 'DropDialog', 'Workspace', 'Extension'
modelNamestring|nullModel name for label prefix, e.g. 'ALMMyModel'
primaryTablestring|nullPrimary/header table name, e.g. 'ALMCustomerTable'
secondaryTablestring|nullSecondary/joined table name (DetailsTransaction: lines table; ListPage: InnerJoin lookup table), e.g. 'SalesTable'

No output schema declared.

No examples provided.

generate_xpp_template ~212

WHEN: writing an extension or customization -- generates ready-to-use X++ code. Triggers: 'génère un CoC', 'crée une extension', 'generate extension', 'write a CoC class', 'event handler pour', 'template pour'. Uses REAL metadata from the KB (actual field names, method signatures). 'coc' = Chain of Command class, 'table_extension' = extend table with fields/methods, 'event_handler' = pre/post event handler, 'job' = runnable class, 'find_method' = find/exist pattern. ALWAYS call get_object_details first to verify the object exists.

NameTypeReqDescription
methodNamestring|nullOptional: specific method name for CoC or event handler templates
objectNamestringyesThe base object, e.g. 'SalesTable', 'VendInvoiceJour'
templateTypestringyesTemplate type: 'coc', 'table_extension', 'event_handler', 'job', 'find_method'

No output schema declared.

No examples provided.

get_data_entity_info ~118

WHEN: developer building an OData / DMF integration needs a quick rundown of a specific data entity: its public OData name, datasources, key fields, and IsPublic status. Triggers: 'data entity info', 'OData entity details', 'is X a public entity', 'entity datasources'. Cloud-safe: pure metadata read from the KB.

NameTypeReqDescription
entityNamestringyesData entity name (AxDataEntityView), e.g. 'CustCustomerV3Entity', 'SalesOrderHeaderV2Entity'.

No output schema declared.

No examples provided.

get_menu_item_info ~187

WHEN: developer needs to resolve a menu item -- find its target object (form / action / output), linked security privilege, label, and parameters. Triggers: 'menu item info', 'what does menu item X open', 'menu item target', 'security privilege for menu item'. Cloud-safe: parses the AxMenuItem XML already loaded in the KB. Returns the resolved object name, menu item type (Display/Action/Output), linked privilege, and the form/class/report it points to.

NameTypeReqDescription
menuItemNamestringyesMenu item name (without prefix), e.g. 'CustTable', 'SalesTableListPage', 'ALMMyMenuItem'.
menuItemTypestring|nullOptional: menu item type to disambiguate when multiple exist with the same name. 'Display', 'Action', or 'Output'. Default: try all.

No output schema declared.

No examples provided.

get_object_context ~228

WHEN: you need a COMPLETE picture of a D365 object in ONE call. Returns in a single response: full structure (fields, method signatures, relation summary) AND all CoC extensions / event handlers -- equivalent to calling get_object_details THEN find_extensions. Use this INSTEAD of those two separate calls to reduce round-trips. Optionally includes best-practice violations (set includeValidation=true). Pass `methodName` to also include the full body of a specific method. Pass `aotType` to disambiguate when several AOT objects share the same name.

NameTypeReqDescription
aotTypestring|nullOptional: AOT type to disambiguate, e.g. 'AxTable', 'AxClass', 'AxForm'.
includeValidationbooleanInclude best-practice violations (default false -- adds latency for large objects).
methodNamestring|nullOptional: specific method name to include full body for.
objectNamestringyesExact object name, e.g. 'SalesTable', 'CustTable', 'VendInvoiceJour'

No output schema declared.

No examples provided.

get_object_details ~542

WHEN: you know the EXACT object name. Triggers: user gives an exact name like 'SalesTable', 'CustTable', 'VendInvoiceJour', any PascalCase D365 object name. Get complete details: all fields, methods, relations, indexes, source code, and metadata. COST NOTE: this returns the FULL object and can be very large (100KB+ for big tables/forms like SalesLine). If you ONLY need relations / FK / DeleteActions / data sources / who-references, call get_relation_graph instead -- it is O(1) and roughly 6x lighter (no source code). Reserve get_object_details for when you genuinely need field details, method bodies, or source code. Also merges live disk source when a custom model path is configured (disk takes priority). Pass `methodName` to get the FULL body of a specific method -- without it, only signatures are returned. Calling twice -- first without methodName to get the full structure and method table, then again with a specific methodName for its full body -- is the CORRECT and INTENDED two-step pattern. Do NOT call a third time for the same object. DISAMBIGUATION: when a name exists as several AOT types (e.g. a Table AND a Form both named 'SalesLine'), this returns the PRIMARY type (Table/Class/Entity before the much heavier Form) and notes the others -- pass `aotType` (e.g. 'AxTable', 'AxForm', or shorthand 'table'/'form'/'class') to pick a specific one. This prevents dumping the heaviest object and truncating the rest. NOT for searching -- use search_d365_code when the name is uncertain. NOT for listing a model's objects -- use list_objects for that.

NameTypeReqDescription
aotTypestring|nullOptional: AOT type to disambiguate when several objects share the name, e.g. 'AxTable', 'AxForm', 'AxClass' (shorthand 'table'/'form'/'class'/'enum'/'edt'/'view'/'entity' also accepted). When omitted…
methodNamestring|nullOptional: specific method name to return full body for, e.g. 'send', 'run', 'validate'. When provided, returns the complete method source instead of the signature table.
objectNamestringyesThe exact object name, e.g. 'SalesTable', 'VendInvoiceApprovalConfig', 'ALMAlternativeItemsTable'

No output schema declared.

No examples provided.

get_output_page ~180

Retrieve the NEXT page of a previously PAGINATED tool output. When a tool result is too large for a single response, it is split losslessly into ordered pages — the footer of each page gives you a `token` and the next `page` number. Call this tool with that token to read the continuation; nothing is dropped, so you can walk every page in order and reconstruct the full result. Pages are cached only briefly (the last few large results). If the token is unknown or expired, re-run the original tool to regenerate it.

NameTypeReqDescription
pageintegerThe page number to retrieve (the previous page footer tells you the next one). Defaults to 2.
tokenstringyesThe pagination token from a paginated tool's footer, e.g. 'op_a1b2c3d4e5'.

No output schema declared.

No examples provided.

get_relation_graph ~293

WHEN: you need the COMPLETE bidirectional relation graph for an object in ONE call. Triggers: 'relations of', 'FK of', 'what tables link to', 'quelles tables liées à', 'avant de générer du code', 'before generating code', 'foreign keys', 'delete actions', 'who references', 'qui référence', 'graph de relations'. Returns ALL outgoing edges (FK relations, DeleteActions, DataSources, Extensions, Security...) AND all incoming back-references (forms, entities, CoC classes, privileges... that reference it). Backed by the pre-computed relation index -- O(1) lookup, no vector scan. Much faster and more complete than find_related_objects for known object names. ALWAYS call this before generating code that touches multiple objects or requires join logic. Use find_related_objects when the relation index is not yet built (fallback to vector scan).

NameTypeReqDescription
aotTypeFilterstring|nullOptional: filter edges by relation kind to reduce noise. Comma-separated. Examples: 'TableFK', 'DeleteAction', 'Extension', 'DataSource', 'Security'. Leave empty for all kinds.
maxEdgesintegerMaximum edges to show per direction (default: 200, max: 500)
objectNamestringyesThe exact object name, e.g. 'SalesTable', 'CustTable', 'SalesFormLetter'

No output schema declared.

No examples provided.

get_security_coverage_for_object ~226

WHEN: developer/security architect needs to know WHICH ROLES can access a specific form, table, menu item or service operation. Triggers: 'who can access', 'which roles see', 'security coverage for', 'quels roles ont accès à', 'find roles with access'. Walks the security graph backwards (EntryPoint -> Privilege -> Duty -> Role) and returns all roles that grant any level of access (Read / Update / Create / Delete / Correct) on the given object. Read-only: scans the in-memory KB, never writes.

NameTypeReqDescription
maxRolesintegerMaximum roles to expand (default 30, max 100).
minGrantstringOptional: minimum grant level to include in results. Values: 'Read', 'Update', 'Create', 'Delete', 'Correct', 'Any'. Default: 'Any'.
objectNamestringyesObject name to audit (form, table, menu item, service operation). Example: 'CustTable', 'SalesTableListPage', 'CustCustomerServiceMenu'.

No output schema declared.

No examples provided.

healthcheck ~66

WHEN: checking server status, loaded D365 version, or custom model path. Triggers: 'status', 'statut', 'is the server ready', 'how many chunks', 'index loaded'. Returns JSON with: status, indexed chunk count, loaded version, custom model path.

Input schema present but exposes no named parameters.

Structured output declared, but exposes no named fields.

No examples provided.

list_custom_model_objects ~176

WHEN: developer wants to see what custom/extension objects exist in their model. Triggers: 'list my custom objects', 'what have we customized', 'show ISV objects', 'list custom model', 'what objects are in our model'. List all D365 F&O objects in the custom/extension model directory on disk. Reads the file system directly -- always reflects the latest uncommitted state. Pass `customModelPath` to specify a model directory; or set it once via the `D365-Custom-Model-Path` header in your .mcp.json (applies to all tool calls automatically).

NameTypeReqDescription
customModelPathstring|nullOptional: path to the custom model directory (e.g. 'C:\\AOTExport\\MyModel'). Overrides the header and server-configured path.

No output schema declared.

No examples provided.

list_objects ~247

WHEN: you need ALL objects of a given type or in a given model. Triggers: 'list all tables in ALM', 'show all classes', 'quels objets dans le modèle', 'give me all forms'. Full index scan -- returns EVERY matching object, not just top search results. Use to discover what tables, classes, forms, enums, etc. exist in a specific model. When no filters are given and a custom model is configured, defaults to listing that model. NOT for a single object -- use get_object_details. NOT for natural language search -- use search_d365_code.

NameTypeReqDescription
aotTypestring|nullFilter by AOT type: AxClass, AxTable, AxForm, AxView, AxEnum, AxEdt, AxDataEntityView, AxSecurityPrivilege, AxSecurityDuty, AxSecurityRole, AxQuery, AxReport, Documentation. Leave empty for all types.
modelNamestring|nullFilter: matches BOTH package/module name (partial) AND object name (substring). Examples: 'ALM' (package), 'Cust' (any object containing 'Cust'), 'SalesTable'. Leave empty for all.

No output schema declared.

No examples provided.

list_release_note_inputs ~251

WHEN: ALWAYS call this FIRST, before prepare_release_note_context -- it discovers the exact D365FO version strings and custom model ids actually indexed on THIS server, which you cannot guess. Triggers: 'release note', 'compare D365 versions', 'upgrade impact for a client', 'what changed for this client', 'regression risk', 'note de version'. Returns every indexed version (exact 'version' string to use as v1/v2, e.g. 10.0.2527.109) and every ready-to-use custom model (exact 'id' to use as customModelIds, plus its name and optional clientGroup tag -- models sharing the same clientGroup belong to the same client and should usually ALL be passed together, e.g. the client's own extensions AND a separate ISV vendor model). IMPORTANT: this server holds the ACTUAL indexed code diff and the client's ACTUAL custom code -- generic Microsoft Learn / Azure Updates / documentation-search tools do NOT have this data and must NOT be used for D365 F&O release-note or upgrade-impact questions about a specific client; those tools only know public, generic release notes, not this client's real regression/opportunity picture.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

map_business_process ~283

WHEN: mapping the technical D365 objects behind a business process, or understanding which tables/forms implement a flow. Triggers: 'processus métier', 'Order-to-Cash', 'Procure-to-Pay', 'Record-to-Report', 'business process flow', 'qui est impliqué dans', 'map the process', 'flux du processus', 'quels objets dans le flux'. Map a D365 F&O business process to its complete object chain. For known processes (Order-to-Cash, Procure-to-Pay, Record-to-Report, Plan-to-Produce, Inventory-Management, Hire-to-Retire, Project-Accounting, Asset-Lifecycle): shows every step with forms, tables, classes, entities, reports, and security roles involved. For any other object name: traces all dependencies (tables, classes, forms, entities) from that entry point. Produces a Mermaid process flow diagram. Use 'list' to see all known process mappings. NOT for a single object's FK relations only -- use `find_related_objects` for that (faster and more precise).

NameTypeReqDescription
processNamestringyesBusiness process name (e.g. 'Order-to-Cash', 'Procure-to-Pay', 'sales', 'purchasing') or an object name to trace from. Use 'list' to see all known processes.

No output schema declared.

No examples provided.

odata_export_entity ~288

Export any D365 F&O data entity via OData (transactional, no DMF project required). Universal: works for ANY public entity. Supports $select, $filter, $orderby and follows server paging automatically. Returns CSV (default) or JSON. Use for live/ad-hoc exports and small-to-medium volumes. For very large bulk exports prefer dmf_export_package. Resolve the entity set name from the KB first (find_entity_for_table / get_data_entity_info) -- do not invent entity names.

NameTypeReqDescription
crossCompanybooleanSet true to query across all legal entities (adds cross-company=true).
entitySetstringyesOData public entity set name, e.g. 'CustomersV3', 'ReleasedProductsV2'.
filterstring|nullOptional OData $filter expression.
formatstringOutput format: 'csv' (default) or 'json'.
maxRowsintegerMax rows to return (0/empty = no cap, follows all pages). Default 1000.
orderBystring|nullOptional $orderby expression.
outputPathstring|nullOptional file path to also write the full result to (e.g. C:\temp\export.csv).
selectstring|nullOptional $select (comma-separated fields). Empty = all fields.

No output schema declared.

No examples provided.

odata_upsert_rows ~231

Idempotent import of rows into any entity via OData: PATCH when the record exists (matched by keyFields), otherwise POST. Safe to re-run -- duplicates are updated, not re-created. Best for small-to-medium transactional loads (e.g. <= a few thousand rows). For bulk loads use dmf_import_file. Provide rows as a JSON array of objects; resolve key fields from the KB (get_data_entity_info) -- do not guess them.

NameTypeReqDescription
crossCompanybooleanSet true to allow cross-company writes.
entitySetstringyesOData public entity set name, e.g. 'CustomersV3'.
keyFieldsstringyesComma-separated business key fields used to detect existing records, e.g. 'CustomerAccount' or 'dataAreaId,ItemNumber'.
legalEntitystring|nullOptional legal entity (dataAreaId) injected into each row when absent.
rowsJsonstringyesJSON array of row objects, e.g. [{"CustomerAccount":"C0001","Name":"Acme"}].

No output schema declared.

No examples provided.

plan_and_execute ~396

CHAIN-OF-TOOLS PLANNER -- Execute a multi-step JSON plan in ONE call by chaining tools. Pass an EXPLICIT JSON array of steps (NL parsing disabled to prevent ambiguity). Maximum 5 steps per plan. The chain stops on any critical failure (ado_analyze_workitem, get_object_details). ## Required Format (JSON array) `[{"tool":"get_object_details","args":{"objectName":"SalesTable"}},{"tool":"validate_best_practices","args":{"objectName":"SalesTable"}}]` ## When to use - You already know the exact sequence of 2-5 tool calls needed - The output of step N is independent of step N+1 (or matches the carried context: analysis_output) - You want SSE progress events between steps ## When NOT to use - Single tool call (use the tool directly) - Plan depends on the user's intermediate decision (call tools one at a time) - More than 5 steps (split into separate calls) ## Cost: $0 -- pure in-process execution.

NameTypeReqDescription
assignTostring|nullOptional: assignee email for task creation step, e.g. 'dev@company.com'.
descriptionstring|nullOptional: additional description text to pass to task creation step.
goalstringyesNatural language goal OR a JSON array of explicit steps. Examples: 'analyse WI #6587 and create a task', 'check best practices for ALMMyClass'.
objectNamestring|nullOptional: object name to use when goal references a D365 object (overrides name parsed from goal).
projectstring|nullOptional: Azure DevOps project name. Falls back to DEVOPS_PROJECT env var.
workItemIdinteger|nullOptional: work item ID to use when goal references 'WI #N' (overrides ID parsed from goal text).

No output schema declared.

No examples provided.

prepare_release_note_context ~475

WHEN: building an AI-assisted D365 F&O upgrade release note (regressions + opportunities) for a specific client, and you (the calling assistant) want to do the reasoning yourself instead of the server calling its own LLM. Call resolve_client_profile FIRST -- if it finds a profile, OMIT v1/v2/customModelIds here and they will be auto-filled from it. If no profile exists, call list_release_note_inputs to get real values and pass them explicitly -- never guess them. Triggers: 'release note', 'upgrade impact for this client', 'what breaks for a client between these versions', 'regression risk', 'note de version'. Diffs two indexed D365FO versions (v1=older, v2=newer) and cross-references EVERY changed standard object against ALL the given custom models (a client can have several -- their own extensions AND a separate ISV vendor model, in which case pass both ids comma-separated) -- returning ONLY the subset of changes actually touched by the client's code (capped at 60, Removed > Modified > Added priority), each with old/new content and which custom object references it. Returns a JSON payload with an 'instructions' field telling you the EXACT schema to produce -- analyze the 'objects' array yourself, then call generate_release_note_document with your findings JSON to get the downloadable Word/PowerPoint.

NameTypeReqDescription
businessContextstring|nullOptional free-text business/functional context about the client (modules used, key customizations, priorities) to sharpen the opportunity/regression assessment.
customModelIdsstring|nullComma-separated custom model id(s) from the Admin > Custom Models tab. Omit to auto-fill from the caller's resolved client profile. Pass several when a client combines their own extensions with a sep…
v1string|nullOlder/baseline D365FO version to compare FROM, e.g. "10.0.2527.109". Omit to auto-fill from the caller's resolved client profile (see resolve_client_profile).
v2string|nullNewer D365FO version to compare TO, e.g. "10.0.2645.32". Omit to auto-fill from the caller's resolved client profile.

No output schema declared.

No examples provided.

recommend_extension_strategy ~195

WHEN: developer about to customise a standard D365 object asks 'should I use AxTableExtension, Chain of Command, EventHandler, or Delegate?'. Triggers: 'how to extend', 'best way to customise', 'extension strategy for', 'CoC ou event handler', 'comment etendre X'. Returns a ranked recommendation based on the target AOT type and the intent, with citations to the Microsoft Learn extensibility guide. Cloud-safe: pure KB lookup, no writes.

NameTypeReqDescription
intentstringyesPlain-language goal of the customisation. Examples: 'add a status field', 'change validateWrite logic', 'react to record insert', 'replace the posting logic', 'override the find method', 'extend the…
objectNamestringyesTarget standard D365 object name, e.g. 'SalesTable', 'CustTable', 'SalesLineType', 'PurchFormLetter_Confirmation'.

No output schema declared.

No examples provided.

resolve_client_profile ~149

WHEN: at the START of any release-note / upgrade-impact conversation -- call this BEFORE list_release_note_inputs to check whether a Client Profile already exists for the CURRENT caller's Azure DevOps org/project (auto-detected from DEVOPS_ORG_URL/DEVOPS_PROJECT MCP headers -- you don't pass anything). If found, it gives you the client's currentVersionTag, targetVersionTag, customModelIds (their own extensions AND any attached ISV/vendor models) and the latest diff snapshot in one call -- use those directly as v1/v2/customModelIds for prepare_release_note_context, no further discovery needed. If not found, fall back to list_release_note_inputs and/or save_client_profile.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

resolve_workspace_roots ~74

WHEN: you need to know which folder(s) are configured as the workspace/project root for the current caller. Reads D365-Custom-Model-Path and D365-Standard-Model-Path from the request headers or environment variables. Use before any tool that accepts a customModelPath/standardModelPath parameter.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

resync_devops_index ~230

WHEN: the user wants to force a full re-download and re-index of their Azure DevOps custom model. Triggers: 'resync', 'reindex', 'force sync', 'rebuild index', 'my model is stale', 'update index', 'mon index est vieux', 'rafraîchir l\'index', 'relancer l\'indexation'. Useful when the server's built-in PAT does not have access to the target DevOps organisation (e.g. a different Azure DevOps org or tenant). Pass a `pat` parameter to override the server PAT for this resync. The eviction + download runs in the background; returns status immediately. After calling, wait ~60 s then call `healthcheck` or any search tool to confirm the index is ready.

NameTypeReqDescription
patstring|nullOptional: Personal Access Token with Code (Read) permission for the target Azure DevOps org. Provide this when the server's built-in PAT lacks access (e.g. a different tenant, cross-org). Leave blank…

No output schema declared.

No examples provided.

save_client_profile ~211

WHEN: no profile was found by resolve_client_profile and the user wants one created (or updated) for their client, so future release-note requests never need v1/v2/customModelIds again. Creates or updates a Client Profile keyed by the CURRENT caller's ADO org/project (auto-detected from MCP headers -- not a parameter). Only the fields you pass are changed; omit a field to leave it untouched on an existing profile.

NameTypeReqDescription
currentVersionTagstring|nullThe client's current live D365FO version tag, e.g. "10.0.2527.109".
customModelIdsstring|nullComma-separated custom model id(s) from the Custom Models tab -- the client's own extensions AND any separate ISV vendor models.
namestringyesFriendly client name, e.g. "Acme Corp".
targetVersionTagstring|nullThe version being evaluated for upgrade, e.g. "10.0.2645.32".

No output schema declared.

No examples provided.

search_context_docs ~173

WHEN: the user asks about business/functional context that lives OUTSIDE the D365 code KB -- specs, functional design docs, mapping sheets, contracts, meeting notes, screenshots' captions -- anything an admin uploaded via the admin portal's 'Context Documents' library (PDF, Word .docx, Excel .xlsx/.xlsm, CSV, plain text/Markdown/JSON). Does NOT search X++ code or AOT objects -- use search_d365_code / get_object_details for that. Triggers: 'what does the spec say about...', 'check the mapping document for...', 'cherche dans les documents de contexte', 'according to the functional design'.

NameTypeReqDescription
maxResultsintegerMax distinct documents to return (1-20). Default 8.
querystringyesNatural-language search query.

No output schema declared.

No examples provided.

search_d365_code ~440

WHEN: object name is unknown, partial, or you need to find by concept/keyword. Search the D365 F&O knowledge base for X++ code, tables, classes, forms, views, enums, EDTs, security objects using natural language or partial names. Returns ALL chunks (metadata, Declaration, methods) for the top-scoring objects so the LLM has complete context on the first call. Lower-scoring results return a short preview. No follow-up get_object_details call is needed for top results. NOT for listing all objects in a model -- use list_objects for that. NOT when the exact name is known -- use get_object_details for that. NEVER call search_d365_code twice in the same conversation turn. If one search did not find the object, answer from what you have -- do not repeat the search. When you need context on MORE THAN ONE concept simultaneously, use batch_search instead -- it runs all queries in parallel and is faster. NEVER call for ADO items (FDD, RDD, IDD, Bug, Task, PR, WorkItem, sprint, #1234) -- use ado_* tools instead.

NameTypeReqDescription
domainstring|nullOptional: filter results to a specific AOT type. Examples: 'AxTable', 'AxClass', 'AxForm', 'AxEnum'. Leave empty for all types.
querystringyesNatural language search query. Examples: 'vendor invoice approval', 'tables in ALM', 'SalesTable fields', 'security privileges for purchasing'
scopestring|nullOptional routing override: 'auto' (default — session/custom first, standard fallback), 'custom' (session only — fails over to standard if nothing found), 'standard' (skip session entirely), 'both' (f…
topKintegerMaximum number of results to return (default: 10, max: 50)
topObjectsintegerNumber of top-scoring objects whose ALL chunks are returned (default: 5, max: 20). Increase to broaden coverage, decrease for tighter focus.

No output schema declared.

No examples provided.

search_labels ~286

Search D365 F&O labels across all indexed languages. Given text (e.g. 'Sales order'), finds the matching label ID (@SYS12345). Given a label ID (e.g. '@SYS12345' or '@SYS:12345'), finds the text in all languages. Accepts both D365 short form (@SYS124480) and colon form (@SYS:124480) -- both are normalized automatically. Searches across 392K+ label entries. WORKFLOW: call search_labels first to resolve the label text, then call find_references with the same label ID to find ALL X++ objects (forms, tables, classes, reports) that use it in their code or metadata. Languages: en-US and fr are loaded at startup. Other languages (de, nl, ar, es, zh...) are loaded on-demand -- first call ~15s, then instant.

NameTypeReqDescription
languagestring|nullOptional: filter by language code (e.g. 'en-US', 'fr', 'de', 'nl'). Leave empty for all languages.
maxResultsintegerMaximum results (default: 20, max: 50)
querystringyesText to search for (e.g. 'Sales order', 'Invoice amount') or a label ID (e.g. '@SYS12345', '@AccountsReceivable:CustInvoice')

No output schema declared.

No examples provided.

suggest_edt ~247

WHEN: adding a new field to a table -- find the best existing D365 EDT to extend instead of using raw primitives (str, int64, real, date). Triggers: 'what EDT for', 'which EDT should I extend', 'quel EDT pour', 'quel type étendu', 'EDT for a field'. D365 best practice mandates EDT reuse over raw primitive types. Call BEFORE declaring any field with a primitive type. Returns ranked candidate EDTs with their base type, label, and model.

NameTypeReqDescription
baseTypestring|nullOptional: D365 primitive base type to filter by, e.g. 'str', 'int64', 'real', 'date', 'enum'. Leave empty to search all types.
fieldNamestringyesField name or concept, e.g. 'AccountNum', 'vendorId', 'itemCode', 'approvalStatus'
purposestringyesPurpose of the field in plain language, e.g. 'customer account number', 'approval status enum', 'invoice amount in transaction currency'
topKintegerNumber of EDT candidates to return (default: 8, max: 20)

No output schema declared.

No examples provided.

suggest_refactoring ~203

WHEN: developer wants to improve code quality before a PR merge or code review. Triggers: 'refactor', 'clean up', 'simplify', 'too long method', 'nested ifs', 'code smells', 'améliorer le code'. Suggest concrete refactoring actions for YOUR custom D365 F&O X++ code. [!] Only runs on custom/extension code (D365_CUSTOM_MODEL_PATH). Refactoring standard Microsoft code is not actionable. Analyzes: long methods (extract method), deep nesting (guard clauses), row-by-row operations (set-based), large switch statements (strategy pattern), hardcoded strings (constants), unprotected CLR calls (error handling), wide transactions (narrow scope). Returns before/after code examples.

NameTypeReqDescription
methodNamestring|nullOptional: specific method to analyze.
objectNamestringyesObject name to analyze, e.g. 'ALMMyClass', 'ALMMyTable'

No output schema declared.

No examples provided.

summarize_for_stakeholder ~151

WHEN: you have a large technical tool output (get_object_details, validate_best_practices, ado_analyze_workitem, detect_performance_issues...) and need it reframed for a non-technical audience. Calls the local Ollama instance (OLLAMA_HOST env var, default localhost:11434) to produce the summary. Model is configurable via ALMXPP_SUMMARIZE_MODEL (default: llama3.2).

NameTypeReqDescription
audiencestringTarget audience: 'executive', 'business-analyst', or 'developer'. Default 'business-analyst'.
textstringyesThe technical text to summarize/explain -- typically the raw output of another tool call.

No output schema declared.

No examples provided.

trace_field_lineage ~195

WHEN: you need to understand the full data lifecycle of a D365 F&O table field: who writes it, who reads it, which forms display it, which reports use it, and which tables have FK relationships to its parent table. Triggers: 'where is field X set', 'qui écrit ce champ', 'data lineage', 'GDPR field audit', 'origin of field', 'what touches this field'. Requires XRef index for writer/reader analysis. Relation graph for forms and FKs. Examples: trace_field_lineage('CustTable','CreditMax') or trace_field_lineage('LedgerJournalTrans','AmountCurDebit').

NameTypeReqDescription
fieldNamestringyesField or property name, e.g. 'CreditMax'.
maxPerCategoryintegerMax results per category (default 15).
tableNamestringyesTable or class name, e.g. 'CustTable'.

No output schema declared.

No examples provided.

trace_role_license_tree ~383

WHEN: security design, licence audit, or 'what licence does this role require?'. Triggers: 'arborescence du rôle', 'licence nécessaire pour', 'what licence for role', 'role tree', 'droits du rôle', 'entry points of role', 'privilege tree for'. Builds the COMPLETE tree for ONE role: Role -> Duties -> Privileges -> Entry Points. For each entry point, classifies the required D365 licence per the March 2026 Licensing Guide: Team Members (~$8/user/mo, read-only + named tasks), Operations-Activity (~$50, warehouse mobile & production floor), Finance (~$180), Supply Chain Mgmt (~$180), Human Resources (~$22), Project Operations (~$120), Commerce (~$180). Grant-level aware: NoAccess/Read/View -> Team Members; Activity writes -> Operations-Activity; transactional writes -> full product licence based on functional area. Confidence: High (known module prefix) . Medium (keyword) . Low (fallback). Ends with a Optimization section: Team Members / Activity eligibility, role-split opportunities, per-user/month cost estimates (March 2026 MSRP). Always validate against the [Microsoft D365 Licensing Guide](https://go.microsoft.com/fwlink/?LinkId=866544). For a full multi-role scan, call `trace_role_license_tree` multiple times -- once per role. NOT for the pure technical duty/privilege/entry-point chain without licence inference -- use `trace_security_chain` for that.

NameTypeReqDescription
maxEntryPointsintegerMaximum entry points to show per privilege (default: 20, max: 100)
roleNamestringyesThe exact security role name, e.g. 'SystemAdministrator', 'AccountsPayablePaymentsClerk', 'ALMMyCustomRole'

No output schema declared.

No examples provided.

trace_security_chain ~289

WHEN: security audit -- need the TECHNICAL chain from Role/Duty/Privilege to Entry Points and Table/Form permissions. Also handles BUSINESS-LANGUAGE role explanation when businessLanguage=true. Triggers (technical): 'sécurité de', 'who can access', 'security for', 'role duty privilege', 'droits sur', 'technical security chain', 'trace le rôle', 'what privileges does', 'what duties are assigned', 'which role allows', 'accès au formulaire', 'what roles have access', 'quel rôle donne accès'. Triggers (business language): 'what can a user with role X do', 'explain this role', 'what does this role give access to', 'quel accès donne ce rôle', 'droits du rôle', 'what licence does this role need', 'droits requis pour'. Traverses: Role -> Duties -> Privileges -> Entry Points -> Table/Form Permissions. Set businessLanguage=true for plain-language capability list (no Duty/Privilege IDs). NOT for licence cost inference per entry point -- use trace_role_license_tree for that.

NameTypeReqDescription
businessLanguagebooleanWhen true, explains the role in plain business language (capabilities list) instead of the technical Role->Duty->Privilege chain. Default: false.
securityObjectNamestringyesSecurity object name, e.g. 'SystemAdministrator', 'VendInvoiceApprovalConfig'

No output schema declared.

No examples provided.

validate_best_practices ~219

Run D365 best-practice audit on any AOT object (custom or standard). Returns violation table: severity (Critical/Warning), rule ID, code snippet, fix instruction. Critical violations block deployment. Checks: ISV prefix, security chain, ttsbegin/ttscommit, firstOnly on single-record selects, hardcoded strings (BP1001), CoC next() vs super(), EDT on fields (BP4570), form DataSource/TitleDataSource/InsertIfEmpty. For deep N+1 / row-by-row performance profiling use detect_performance_issues instead. [!] Auto-fixing Critical violations requires D365_CUSTOM_MODEL_PATH (custom code only).

NameTypeReqDescription
methodNamestring|nullOptional: specific method to validate. Validates all methods if not provided.
minSeveritystringMinimum severity: 'Info', 'Warning', 'Critical' (default: 'Warning')
objectNamestringyesObject name to validate, e.g. 'SalesTable', 'CustInvoiceJour'

No output schema declared.

No examples provided.

validate_object_naming ~192

WHEN: developer needs to check that a proposed object name follows D365 + ISV naming conventions, is unique against the indexed KB, and does not collide with a reserved or standard prefix. Triggers: 'is this a valid name', 'check naming', 'name conflict', 'valider le nommage'. Cloud-safe: KB read only, no writes.

NameTypeReqDescription
aotTypestringyesAOT type the name will live in: AxClass, AxTable, AxForm, AxEdt, AxEnum, AxTableExtension, AxFormExtension, AxClassExtension, etc.
isvPrefixstringyesISV prefix you must use, e.g. 'ALM'. Required for all custom objects.
proposedNamestringyesProposed name, e.g. 'ALMSalesLine.Extension', 'ALMCustomerTable', 'SalesLineALM_Extension'.

No output schema declared.

No examples provided.