er-guard
Emits SARIF and includes a GitHub Actions workflow example so ER Guard lint findings can be surfaced as GitHub code-scanning alerts on pull requests.
Supports ISO 20022 pain.008 SEPA direct debit exports through a SEPA SDD knowledge pack, checking mandate fields, sequence type, and requested collection date.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
ER Guard
Static analysis for Dynamics 365 Finance & Operations Electronic Reporting (ER) configurations. Lint, diff and rebase-check ER exports before the bank rejects the payment file or the tax authority rejects the e-invoice.
CLI · MCP server · Microsoft Copilot harness skill · SARIF for GitHub/Azure DevOps code scanning
Why
ER runs every payment file (ISO 20022), e-invoice (PEPPOL, XRechnung, PINT-AE, ZATCA, FatturaPA) and statutory report in D365 F&O. Yet ER changes today are reviewed by clicking through the designer, and the problems show up in production:
a customised
<Ustrd>binding without an empty-value guard →<Ustrd/>in the file → pain.002 RJCTa remittance text that is not truncated to 140 characters → schema rejection
FIRST()on an empty invoice list → the whole payment export fails at runtimea rebase onto Microsoft's new version silently overwrites (or is overwritten by) your customisation
a production BIC or endpoint URL hard-coded in a formula
There are many MCP servers for D365 F&O (OData, metadata, X++). None of them understands ER. ER Guard fills that gap.
Related MCP server: gx3-mcp-server
What it does
Command / MCP tool | Purpose |
| 10 rules with business impact and a ready-to-paste fix |
| Structural + binding diff. Breaking changes first, including removed safety nets (dropped |
| Three-way check: old Microsoft base × new base × your derived version → conflicts before you click Rebase |
| What is in this export, which standard it targets |
| Tag/attribute census to tune recognition for unusual exports |
Knowledge packs (auto-detected):
ISO 20022 pain.001 (credit transfer): Max35Text/Max140Text limits, ISODate/ISODateTime, IBAN/BIC patterns, mandatory GrpHdr/PmtInf/CdtTrfTxInf children
ISO 20022 pain.008 (direct debit, SEPA SDD): mandate fields (MndtId, DtOfSgntr), SeqTp, ReqdColltnDt
UBL 2.1 / EN 16931: PEPPOL BIS 3, XRechnung (UBL), PINT-AE: mandatory invoice structure, BT references
ZATCA Fatoora (KSA): UUID, IssueTime, TaxCurrencyCode = SAR, AdditionalDocumentReference (on top of UBL)
Generic rules (ER001, ER003, ER004, ER006, ER007, ER010) apply to every ER configuration: JSON e-invoices, text formats, Excel/Word reports and model mappings.
Rules
Rule | Catches |
ER001 | Leaf element with no binding and no value → emitted empty |
ER002 | Value can be blank, standard needs ≥1 char, no |
ER003 | Dangling binding (target removed/renamed, typical after rebase) |
ER004 | Expression uses an undeclared data source |
ER005 | Value not truncated to the standard's max length |
ER006 |
|
ER007 | Hard-coded IBAN, BIC, URL, GUID, e-mail, registration number |
ER008 | Mandatory element missing or disabled |
ER009 | Date/time without explicit ISO format |
ER010 | Data source declared but never used |
Example
$ er-guard rebase base-v9.1.xml base-v9.2.xml derived-dh-v9.1.1.xml
## ER Guard rebase check
Base changed 3 things; your derived version changed 8.
1 conflicts, 2 base changes merge cleanly.
🔴 …/RmtInf/Ustrd: Microsoft changed the expression you overrode:
base now LEFT(IF(ISEMPTY(@.PaymentNote), @.InvoiceList, @.PaymentNote), 140),
yours CONCATENATE(@.PaymentNote, " ", FIRST(@.Invoices).Number)$ er-guard lint derived-dh-v9.1.1.xml
❌ ER008 Mandatory element missing …/GrpHdr/InitgPty
ISO 20022 pain.001: <GrpHdr> requires <InitgPty>, which is missing from the format.
Impact: Rejected by the bank (schema validation, pain.002 status RJCT).
⚠️ ER002 No empty-value guard …/RmtInf/Ustrd
If the source is blank the file contains <Ustrd/> (minimum length 1).
Fix: set the element's 'enabled' binding to NOT(ISEMPTY(@.PaymentNote)) …
⚠️ ER006 FIRST() on possibly empty list …/RmtInf/UstrdInstall
# from GitHub (builds on install, Node 20+)
npm i -g github:D365Wale/er-guard
er-guard summary "ISO20022 Credit transfer.version.9.xml" # check it recognised your export
er-guard lint "ISO20022 Credit transfer.version.9.xml"Export a configuration in F&O: Electronic reporting → Configurations → Exchange → Export as XML file.
As an MCP server
Any MCP host (Copilot CLI, VS Code, Claude, …):
{
"mcpServers": {
"er-guard": { "command": "er-guard-mcp" }
}
}All tools are read-only. They analyse files and never connect to an F&O environment.
On the Microsoft Copilot harness
examples/copilot-sdk/review-er.ts builds a rebase-review
agent with @github/copilot-sdk: the harness runs the loop and model routing, ER Guard brings the
MCP tools and the er-guard skill, and a permission handler blocks
everything except ER Guard tools and file reads.
npx tsx examples/copilot-sdk/review-er.ts old-base.xml new-base.xml derived.xmlIn CI (ER configs in git)
.github/workflows/er-guard-example.yml lints every
changed ER export on pull requests and uploads SARIF, so findings appear as code-scanning alerts.
--fail-on error|warning|none controls the exit code.
How recognition works (and its limits)
ER exports have no published schema, so ER Guard does not depend on exact tag names:
Format components: any
ER…Format…element/attribute/item/component with aName(plus the patterns insrc/profile.ts).Expressions: every
ExpressionAsString(including nested<ERModelExpressionItem … SyntaxVersion="1"/>items) is linked to the component whose ID/GUID appears on the nearest enclosing node. Wrappers namedEnabled.mark condition bindings.Model mappings: exports without format components are treated as mappings, so model paths aren't reported as dangling bindings.
Diff identity: components match by GUID first and path second, so a rename is reported as a rename.
If er-guard summary reports 0 elements for one of your exports, run er-guard inspect and pass a
profile override:
{ "formatElementTag": "^ER.*(XMLElement|MyComponent)", "bindingTargetAttrs": ["ComponentId"] }er-guard lint my.xml --profile my-profile.jsonStatus: v0.1, early. The fixtures are synthetic ER-style exports. They follow the
structure seen in real exports (GUID component IDs, nested ERModelExpressionItem) and reproduce
real-world defects, but they are not Microsoft files. If er-guard summary shows 0 elements for
one of your exports, please open an issue with the er-guard inspect output. It contains tag and
attribute names only, no customer data.
Performance: ~6 MB / 30,000 components parse in under 2 s; lint, diff and rebase each take under 1 s.
What ER Guard does not do: run the format, validate against each bank's usage rules (CGI-MP, EPC, local), or check SAF-T/Intrastat/FatturaPA/camt specifics yet. The generic rules still apply to every format.
Roadmap
Knowledge packs: camt.053/054 (import formats), FatturaPA, SAF-T, Slovakia/Germany CIUS specifics
Model-mapping analysis (unused data sources, expensive
ALLITEMS/FILTERpatterns)Optional live mode via d365fo-mcp-server: pull configs straight from an environment
VS Code extension view
Develop
npm i && npm run build && npm test
node scripts/make-fixtures.mjs # regenerate fixturesMIT © Dhruv Khatri
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
This server cannot be deployed
Maintenance
Related MCP Connectors
Public read-only MCP for products, frameworks, guides, methodology, and blog metadata.
Render, verify, describe, and safely edit Mermaid diagrams through MCP.
Read-only MCP access to a documented IT fleet: state, changes, posture. 15 tools.
Read-only MCP access to sessions, funnels, campaigns, errors, live visitors, and anomalies.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables D365 F\&O development including object creation, modification, deletion, and analysis through the MCP standard.42MIT
- FlicenseAqualityBmaintenanceProvides read-only analysis of Mitsubishi GX Works3 PLC projects via MCP, enabling device tracing, cross-referencing, ladder inspection, linting, and report generation without modifying source projects.1575 PyPI10-
- AlicenseBqualityCmaintenanceA read-only MCP server for Microsoft Intune and Entra ID that enables list, get, search, and reporting operations for tenant visibility, audits, troubleshooting, and health reporting without write actions. It includes authentication helpers, report exports, and metadata discovery tools.361MIT
- FlicenseNot gradedqualityBmaintenanceProvides MCP tools to read, validate, propose, and review architecture models and UML diagrams in local workspaces.-