Connecting F&O to an agent Microsoft hasn’t documented

Connecting F&O to an agent Microsoft hasn’t documented

MCP · Azure DevOpsYour delivery board, readable by an agentMCP · DataverseOne consent, and the data layer opensMCP · ArchitectureWhat we automated, and what it cost

The wall

The Dynamics 365 ERP MCP server is real, official, and built directly into the Finance and Operations environment. It exposes 21 tools across three families: data tools for OData and SQL access, form tools that drive application forms server-side, and API tools that invoke X++ logic exposed through ICustomAPI.

Microsoft's guidance for connecting to it is a page titled, unambiguously, "Connect to the Dynamics 365 ERP MCP server with VS Code." There is no parallel page for anything else.

That is a licensing problem before it is a technical one. VS Code's agent mode runs on GitHub Copilot, which needs a Copilot seat. We did not have one, and buying one to evaluate an ERP integration is a strange purchase order to raise.

The gate was never technical. It was a licence, and a documentation gap.

Two doors into the same room

The server sits behind an allow-list. Every F&O environment has a form — Allowed MCP clients — listing the Entra client IDs permitted to reach the MCP endpoint. Microsoft pre-populates it:

ClientClient ID
Microsoft Copilot Studio7ab7862c-4c57-491e-8a45-d52a7e023983
Visual Studio Codeaebc6443-996d-45c2-90f0-388ff96faa56
Microsoft Cowork6ab48b67-cd74-4ad4-81af-5932984589be

Read that form carefully and the architecture reveals itself. The endpoint speaks standard MCP over HTTP with Entra OAuth. It does not care what client is calling. What it cares about is whether that client's ID appears in a list the environment administrator controls.

Not Microsoft. The administrator.

The pattern was already published

Here is the part that turned this from a workaround into an argument.

Microsoft's documentation for their Work IQ MCP servers — the Microsoft 365 family under Agent 365 — includes a section called "Set up Work IQ MCP servers for coding agents." It covers GitHub Copilot CLI, VS Code, and Claude Code. For Claude Code, Microsoft publishes this configuration:

JSON
{
  "mcpServers": {
    "WorkIQ-MailServer": {
      "type": "http",
      "url": "https://agent365.svc.cloud.microsoft/agents/tenants/{tenantId}/servers/mcp_MailTools",
      "oauth": { "clientId": "{clientId}", "callbackPort": 8080 }
    }
  }
}

Register your own Entra enterprise application, make it a public client, add the redirect URI http://localhost:8080/callback, grant the per-server permission, and point the client at the endpoint.

That is a complete, Microsoft-authored recipe for connecting a non-Microsoft agent to a Microsoft MCP server using delegated Entra identity. It just happens to be written about Outlook rather than about Finance and Operations.

Applying it to Finance and Operations

The same shape, pointed at the ERP endpoint:

JSON
{
  "mcpServers": {
    "d365-erp": {
      "type": "http",
      "url": "https://<env>.operations.dynamics.com/mcp",
      "oauth": {
        "clientId": "<your Entra app>",
        "callbackPort": 8080
      }
    }
  }
}

Four steps, none of which bypass anything:

  1. Register an Entra app in your tenant. Public client, PKCE, redirect http://localhost:8080/callback. No client secret — the whole point of PKCE is that a desktop client does not need one.
  2. Add its client ID to Allowed MCP clients in F&O, set to true. This is an administrator's deliberate act.
  3. Configure the client with the JSON above.
  4. Sign in through the browser, as yourself.

Twenty-one tools, live, against a Tier 2 sandbox. First real query returned five open sales orders with customer, status, currency and requested ship date.

The server refuses to guess

Something we did not expect, and which turned out to be the most quietly impressive part.

The ERP MCP server enforces a sequence. Before any data query, the agent must call data_find_entity_type to identify the entity, then data_get_entity_metadata to read the real schema. Only then may it query. Skip a step and you get an error, not a plausible-looking wrong answer.

Watch an agent answer "list five open sales orders" and you see it search for the entity, discover SalesOrderHeadersV4, read the field names and the status enum, and only then write SQL. It is not permitted to assume a field is called Status because that would be a sensible name.

This is anti-hallucination designed into the protocol surface rather than bolted on with prompt instructions. For anyone who has watched a language model confidently invent a column name, it is a meaningful piece of engineering.

Whose permissions?

The question every architect asks, usually within thirty seconds. The answer is: yours.

The token is delegated. The agent acts as the signed-in user, inside that user's F&O security roles, with row-level security and the audit trail intact. There is no service principal in this design, and nothing in it can read across the tenant.

Finance and Operations makes this distinction structural, which is the best evidence that it is designed behaviour rather than a happy accident. There are two separate forms:

Microsoft Entra ID applications

Maps an application to a service user — because an app-only token contains no human. This is the classic client_credentials integration pattern.

Not used here

Allowed MCP clients

Gates which client applications may reach the MCP endpoint. The user signs in; the token carries their own claims and their own roles.

What we use

Two forms because they are two genuinely different security models. Reusing an app registration does not mean reusing app-only authentication — an app registration is a client identity, and the flow decides what the token means.

Honest caveats

This is not a supported configuration. Microsoft documents VS Code for this server and nothing else. What we did was apply a Microsoft-published pattern to a case Microsoft has not written up. It works, it is governed, and it is a sandbox demonstration — not a production recommendation.

  • The write tools are live and inherit the signed-in user's role. If you are demonstrating to an audience, use read-only prompts or a scoped-down account.
  • Requires F&O 10.0.47 or later, on a Tier 2+ sandbox or Unified Developer Environment. Cloud Hosted Environments are not supported.
  • The older "static" ERP MCP server is being retired on 1 October 2026. Any guidance you find describing thirteen tools is describing that one.
  • Check the demo data, not just the connection. Every open sales order in our sandbox returned OrderTotalAmount = 0 — headers without priced lines behind them. The integration is working perfectly and the number on screen is still zero. Query the fields you intend to project before you build a slide around them.

What it means for ERP leadership

The finding is not "here is a clever trick." It is that openness in this ecosystem is increasingly an organisational decision rather than a vendor one. Microsoft built the gate and handed the key to the environment administrator.

The protocol is open. The gate is an allow-list. And a properly governed ERP organisation controls that gate itself.

Sources

  • Microsoft Learn — Dynamics 365 ERP MCP overview: https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/copilot/copilot-mcp
  • Microsoft Learn — Connect with VS Code: https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/copilot/mcp/mcp-vscode
  • Microsoft Learn — Work IQ MCP overview (preview): https://learn.microsoft.com/en-us/microsoft-agent-365/tooling-servers-overview
Previous article← What we automated, and what it cost
Discussion

Ask a question or leave feedback

This is a review interaction. The WordPress version will store, thread and moderate comments.

Thanks — submitted for moderation in this review.
Search the whole site · Ctrl/⌘ + K