The problem we started with
Every system that needs ERP data gets its own integration. Scoped, built, security-reviewed, tested, deployed — then maintained forever. N systems multiplied by M consumers, and every cell in that grid is a bespoke piece of engineering with its own lifecycle, its own credentials and its own owner.
The question worth asking is not how to build those integrations faster. It is whether the consumer needs one at all.
Adding a consumer should be an access decision, not a development project.
What is running
| Actor | MCP server | Service | Auth | Status |
|---|---|---|---|---|
| ERP Director | Azure DevOps MCP | Azure DevOps | Interactive Entra | Live |
| Consultant | Dynamics 365 ERP MCP | F&O runtime | Delegated + PKCE | Live |
| Business user | Dataverse MCP | Dataverse | Delegated OAuth | Live |
| X++ developer | F&O Development MCP | Local dev VM | Local machine trust | Community |
| Knowledge worker | Work IQ MCP | Microsoft 365 Graph | Delegated OAuth | Preview |
The mental model
Five columns, and a band underneath that carries all of them:
Actor › Agent › MCP › Service › Data
Identity / Credential — cuts across all five. Who the agent acts as decides what it can see, what it can change, and what the audit trail says afterwards.
Most conversations about AI in ERP happen entirely in the Agent column. They discuss models, prompts and orchestration frameworks, and they stall at the security review — because nobody asked the identity question until it was someone else's job to refuse.
Every server in this estate answers it the same way: delegated identity. The agent acts as the signed-in person, inside that person's existing roles, with row-level security and audit trail intact. No service principal in this design can read across the tenant.
The demonstration that makes the argument
Two questions, run in sequence, against two entirely separate Microsoft products:
- Find the customer in Dataverse → returns
US-001, Contoso Retail San Diego - Pull that customer's open orders from Finance and Operations → returns 47 open sales orders against that same account
The account numbers match across both systems. No pipeline was built between them for this. No middleware, no integration project, no scheduled sync written for the purpose. Two MCP servers and one identity.
The second query is worth watching closely, because the agent is not permitted to guess its way there. It searches for the entity, lands on SalesOrderHeadersV4, reads the schema and the status enum, and only then filters on open orders. The grounding described in Part 2 is not a claim about the protocol — it is visible in the tool calls on screen.
This is the whole thesis in about forty seconds of live query. Everything else in this series is supporting detail.
The maturity curve
All four speak the same open protocol. What differs is which clients Microsoft has published guidance for — and that turns out to be the practical constraint, not anything technical.
| Server | Openness today |
|---|---|
| Azure DevOps MCP | Open npm package. Any MCP client. |
| Dataverse MCP | Microsoft publishes a recipe for non-Microsoft clients explicitly. |
| Work IQ MCP (M365) | Microsoft publishes a recipe for coding agents. Preview, and needs a Copilot licence. |
| Dynamics 365 ERP MCP | Microsoft documents one client — VS Code — which requires a GitHub Copilot seat. |
We did not have that seat. The route through was to apply the configuration pattern Microsoft publishes for Work IQ — an own Entra app, public client with PKCE, redirect on localhost:8080 — to the F&O endpoint, with the client ID added to the environment's Allowed MCP clients allow-list by an administrator.
Nothing was bypassed. Access is still gated by Entra, and still gated by a list the environment owner controls.
The gate isn't technical. It's an allow-list — and a properly governed ERP organisation controls that gate itself.
What did not work
A summary that only lists successes is marketing. These cost real time:
- Copilot Studio — no licence access, so it stayed a diagram. It is a consumer of MCP servers, not a server; people routinely put it in the wrong column.
- Dataverse tenant consent — environment admin was not enough. Needed a Global Administrator for thirty seconds, and no amount of configuration got around it.
- Dataverse environment gate — then, with consent granted and sign-in working, every tool call still failed with a bare
-32603: An error occurred. Trace logging showed the real cause:403 Forbiddenon the MCP endpoint. A valid token and a connected server, refused at the environment's own feature gate. Two separate administrative gates, failing in two completely different registers. - Work IQ MCP — available and documented for Claude Code, but gated on a Microsoft 365 Copilot licence. Preview, and Microsoft is explicit that preview is not for production.
- CRM lifecycle scenarios — the Dataverse environment turned out to be a dual-write mirror of the F&O customer master, with zero opportunities and zero leads. A demo built on pipeline stages would have died on stage. Query first, design second.
- X++ bridge on a non-standard path — sixty-one compile errors that read like a broken repository, caused entirely by assembly auto-detection looking in the two places our Unified Developer Experience install was not. One explicit path argument fixed it.
- Zero-value demo data — every open sales order in the sandbox carries an order total of zero, because the headers have no priced lines behind them. The query is correct, the integration is working, and the number on the slide is still nothing. Verify the fields you intend to project, not just the connection.
A pattern runs through four of those six. The configuration was right and the error message described something else — a licence gate reported as a documentation gap, an environment feature reported as an internal error, a path problem reported as a missing namespace. Budget debugging time for layered access models accordingly: the outermost layer is the one that speaks, and it rarely knows what is actually wrong.
What it changes for ERP leadership
The technical result is four servers. The leadership result is a different job description.
Administer
Keep the system running. Upgrades, patches, tickets, user support.
Integrate
Connect the system. Point-to-point builds, middleware, bespoke pipelines.
Orchestrate
Design how agents act. Governed autonomy, delegated identity, reusable capability.
The third does not replace the first two. It is additive, and it is the one most organisations have no operating model for yet. The skill that mattered in 2015 was integration architecture. The skill that matters now is agent governance.
What decides whether this is a demonstration or a capability is not the protocol, the models, or the vendor roadmap. It is the identity model underneath it — and that is an ERP leadership decision.
The series
- Part 1 — Azure DevOps MCP: your delivery board, readable by an agent
- Part 2 — Dynamics 365 ERP MCP: connecting F&O to an agent Microsoft hasn't documented
- Part 3 — Dataverse MCP: one consent, and the data layer opens
- Part 4 — F&O Development MCP: why AI is bad at X++, and what fixes it
- Part 5 — this article
Ask a question or leave feedback
This is a review interaction. The WordPress version will store, thread and moderate comments.