Skip to content

Connect Microsoft Dynamics 365 Business Central to Claude: Sales & Pay

Learn how to connect Microsoft Dynamics 365 Business Central to Claude using Truto's managed MCP server. Automate sales orders, payments, and AP processing.

Nachi Raman Nachi Raman · · 9 min read
Connect Microsoft Dynamics 365 Business Central to Claude: Sales & Pay

If your team needs to connect Microsoft Dynamics 365 Business Central to Claude to automate sales order entry, AP invoice processing, or customer payment reconciliation, you need a Model Context Protocol (MCP) server. This server acts as the translation layer between Claude's tool calls and Business Central's OData V4 REST API. You can either build and maintain this infrastructure yourself, or use a managed integration platform like Truto to dynamically generate a secure, authenticated MCP server URL. If your team uses ChatGPT, check out our guide on connecting Microsoft Dynamics 365 Business Central to ChatGPT or explore our broader architectural overview on connecting Microsoft Dynamics 365 Business Central to AI Agents.

Giving a Large Language Model (LLM) read and write access to a monolithic ERP like Dynamics 365 Business Central is a complex engineering challenge. You must handle strict OData schema requirements, multi-company routing logic, and mandatory concurrency controls. Every time Microsoft updates an endpoint, you have to update your server code, redeploy, and test the integration.

This guide breaks down exactly how to use Truto to generate a secure, managed MCP server for Microsoft Dynamics 365 Business Central, connect it natively to Claude, and execute complex sales and pay workflows using natural language.

The Engineering Reality of the Business Central API

A custom MCP server is a self-hosted integration layer. While the open MCP standard provides a predictable way for models to discover tools over JSON-RPC 2.0, implementing it against Business Central's API is notoriously difficult. Business Central is built on OData V4, which carries highly specific architectural patterns that LLMs struggle to navigate natively.

If you decide to build a custom MCP server for Business Central, here are the specific challenges you will face:

Mandatory Concurrency Control (ETags) Business Central enforces strict concurrency checks. You cannot simply PATCH or DELETE a vendor or a sales order using its ID. The API requires an @odata.etag value passed in the If-Match header to ensure the record hasn't been modified since it was last read. An LLM cannot guess this value. A managed MCP server handles this by explicitly injecting the etag requirement into the tool's JSON Schema, forcing the LLM to first fetch the record, extract the ETag, and pass it into the update tool call.

Strict Multi-Company Routing Business Central isolates all data by company. There is no global /customers endpoint. Instead, the route is /companies({company_id})/customers. This means an LLM must always know the target environment's company ID before executing any financial operation. Exposing raw routes to Claude often results in hallucinated endpoints. Truto normalizes this by injecting company_id as a required parameter into every tool schema, forcing Claude to chain its logic: first list companies, extract the ID, then query the resource.

Deep Inserts and Nested Dimensions Creating a Sales Invoice or Purchase Order often requires a "deep insert" - sending the header (the invoice) and the lines (the items) in a single nested JSON payload. Business Central's schema for these deep inserts is massive. If you pass the raw OpenAPI spec to Claude, you will quickly blow past context limits. Truto distills the documentation into optimized query_schema and body_schema definitions, explicitly guiding the LLM on required fields while stripping out extraneous OData metadata.

Rate Limits and 429 Handling Business Central throttles API traffic heavily during peak ERP usage windows. Factual note on rate limits: Truto does not retry, throttle, or apply backoff on rate limit errors. When Business Central returns an HTTP 429, Truto passes that error directly to the caller. Truto normalizes the upstream rate limit information into standardized headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset) per the IETF specification. Your client architecture (or the AI agent framework you are using) is entirely responsible for implementing retry and backoff logic.

How to Create the Business Central MCP Server

Truto dynamically generates MCP tools from the integration's resource definitions. To get started, you need to generate the secure MCP Server URL. You can do this via the Truto UI or programmatically via the API.

Method 1: Via the Truto UI

For teams setting up internal tools or testing workflows, the dashboard is the fastest path:

  1. Log into Truto and navigate to your Integrated Accounts.
  2. Select your connected Microsoft Dynamics 365 Business Central account.
  3. Click the MCP Servers tab.
  4. Click Create MCP Server.
  5. Select your desired configuration (name, allowed methods, tags, and expiration).
  6. Copy the generated MCP server URL (e.g., https://api.truto.one/mcp/a1b2c3...).

Method 2: Via the Truto API

If you are dynamically provisioning AI agents for your own customers, you can generate MCP servers programmatically. Make an authenticated POST request to the Truto API.

Endpoint: POST /integrated-account/:id/mcp

{
  "name": "Dynamics 365 Sales Agent",
  "config": {
    "methods": ["read", "write"]
  }
}

The API validates that tools are available, stores a cryptographic token linked strictly to that specific integrated account, and returns the endpoint:

{
  "id": "mcp_8f7d6a5b",
  "name": "Dynamics 365 Sales Agent",
  "config": { "methods": ["read", "write"] },
  "expires_at": null,
  "url": "https://api.truto.one/mcp/a1b2c3d4e5f67890"
}

This URL is fully self-contained. It encodes the tenant mapping and handles authentication automatically.

Connecting the MCP Server to Claude

Once you have your Truto MCP URL, you can connect it to Claude in less than a minute.

Method A: Via the Claude UI (Claude for Work / ChatGPT)

If you are using Claude's web interface (or ChatGPT's equivalent custom connector feature):

  1. In Claude, navigate to Settings -> Integrations -> Add MCP Server.
  2. (If using ChatGPT, navigate to Settings -> Connectors -> Add custom connector).
  3. Provide a name (e.g., "Business Central ERP").
  4. Paste the Truto MCP URL.
  5. Click Add or Save.

Claude will immediately ping the /initialize endpoint, complete the JSON-RPC handshake, and populate its context window with the available Business Central tools.

Method B: Via Manual Config File (Claude Desktop)

If you are running Claude Desktop locally or configuring an agentic framework like Cursor, you must edit the claude_desktop_config.json file.

Since Truto exposes a Server-Sent Events (SSE) endpoint over HTTPS, you use the official @modelcontextprotocol/server-sse transport proxy to connect.

{
  "mcpServers": {
    "business_central": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-sse",
        "https://api.truto.one/mcp/a1b2c3d4e5f67890"
      ]
    }
  }
}

Restart Claude Desktop. A new "hammer" icon will appear, indicating that the Business Central tools are active and ready to be called.

Security and Access Control

Giving an LLM unconstrained access to your corporate ERP is dangerous. Truto MCP servers include native governance controls applied at token generation time to limit the blast radius:

  • Method Filtering: Pass config: { methods: ["read"] } to ensure the agent can only execute get and list operations. The server will silently drop write tools from the tools/list response, preventing accidental invoice deletion.
  • Tag Filtering: Limit the server's scope by functional area. By passing config: { tags: ["sales"] }, the LLM will only see tools related to sales orders and customers, completely hiding payroll or general ledger endpoints.
  • Require API Token Auth: By default, the MCP URL acts as a bearer token. By setting require_api_token_auth: true, the caller must also pass a valid Truto API token in the Authorization header. This prevents leaked URLs from being abused.
  • Automatic Expiration: Set an expires_at timestamp for temporary access. Truto relies on Cloudflare KV expirations and Durable Object alarms to guarantee the token is purged from the database the moment it expires.

Hero Tools for Sales & Pay

Truto exposes the entirety of the Business Central API as tools. Here are the highest-leverage tools for automating order-to-cash and procure-to-pay pipelines.

List All Companies

The prerequisite for almost all Business Central operations. Because OData routes require a company_id, Claude must use this tool to fetch the correct GUID before querying customers or generating invoices.

Usage notes: The LLM will automatically extract the id from the response and pass it to subsequent tool calls.

"I need to run some financial reports. First, list all the companies configured in our Business Central environment so we know which ID to use for the US entity."

List All Customers

Retrieves a paginated list of customers for a specific company, including their balances, currency codes, and tax liabilities.

Usage notes: Truto handles pagination natively. The tool schema explicitly instructs the LLM to pass back the next_cursor exactly as received to fetch subsequent pages.

"Pull the list of all customers for company ID 'abcd-1234'. Show me the top 5 customers with an active balance and ensure they aren't marked as blocked."

Create a Sales Order

Generates a new sales order document. This tool supports nested deep inserts, allowing Claude to create the header and the salesOrderLines in a single request.

Usage notes: The schema requires environment, company_id, and a valid customerId.

"Create a new sales order in company 'abcd-1234' for customer ID 'cust-999'. Add one line item for item ID 'item-555' with a quantity of 10 and a unit price of $50."

Create a Customer Payment

Records a payment against a customer's account, optionally applying it to a specific invoice.

Usage notes: You must pass the company_id and the customerId. To apply the payment, the LLM should also pass the appliesToInvoiceId.

"Record a customer payment of $500 for customer 'cust-999' in company 'abcd-1234'. The posting date should be today, and it should apply to invoice ID 'inv-777'."

List All Vendors

Retrieves the vendor directory, including payment terms, balances, and tax registration numbers. Crucial for AP automation workflows.

Usage notes: Like customers, this is scoped by company_id.

"List all our active vendors in company 'abcd-1234'. Filter out anyone who has the 'blocked' flag set to true, and give me their default payment terms."

Create a Purchase Invoice

Creates a new AP invoice from a vendor. This is typically used by agents parsing PDF invoices via OCR and pushing the structured data into the ERP.

Usage notes: Claude must provide the vendorId and vendorInvoiceNumber to prevent duplicates.

"Create a new purchase invoice for vendor 'ven-111' in company 'abcd-1234'. The invoice date is yesterday, the vendor invoice number is 'INV-2023-88', and the total amount including tax should be $1,200."

To view the complete inventory of available Business Central tools, including General Ledger, Inventory, and HR endpoints, visit the Microsoft Dynamics 365 Business Central integration page.

Workflows in Action

Exposing an API to an LLM changes the integration paradigm. Instead of hardcoding linear logic, you give the agent a goal, and it orchestrates the tool calls dynamically. Here is how Claude uses the Business Central MCP server in the real world.

Scenario 1: Automated Order-to-Cash Generation

Persona: Sales Operations Coordinator

"A customer named 'Contoso Ltd' just approved our quote via email. Please find their account in Business Central and generate a new sales order for 50 units of item 'Desk Chair'. Return the final sales order number to me."

Execution Steps:

  1. list_all_microsoft_dynamics_365_business_central_companies: Claude fetches the active companies to find the correct company_id.
  2. list_all_microsoft_dynamics_365_business_central_customers: Claude searches the customer directory for "Contoso Ltd" and extracts their id.
  3. list_all_microsoft_dynamics_365_business_central_items: Claude searches the inventory to find the internal id for "Desk Chair".
  4. create_a_microsoft_dynamics_365_business_central_sales_order: Claude constructs the deep insert payload, combining the customer ID and the item ID, and executes the creation.

Result: The user receives a confirmation message: "Sales Order #SO-00452 has been successfully created for Contoso Ltd for 50 Desk Chairs."

Scenario 2: Agentic AP Invoice Processing

Persona: Accounts Payable Manager

"I just uploaded a PDF invoice from 'Tech Supply Co' for $4,500. Check if they exist as a vendor in our main company. If they do, draft a new purchase invoice for this amount so I can approve it."

sequenceDiagram
    participant User as AP Manager
    participant Claude as Claude (AI Agent)
    participant Truto as Truto MCP Server
    participant BC as Dynamics 365 BC

    User->>Claude: "Process invoice from Tech Supply Co for $4,500"
    Claude->>Truto: call list_companies()
    Truto->>BC: GET /companies
    BC-->>Truto: Return company list
    Truto-->>Claude: [ {id: "company-123", name: "Main"} ]
    
    Claude->>Truto: call list_vendors(company_id="company-123")
    Truto->>BC: GET /companies(company-123)/vendors
    BC-->>Truto: Return vendor list
    Truto-->>Claude: [ {id: "vendor-456", displayName: "Tech Supply Co"} ]
    
    Claude->>Truto: call create_purchase_invoice(vendorId="vendor-456", amount=4500)
    Truto->>BC: POST /companies(company-123)/purchaseInvoices
    BC-->>Truto: Return 201 Created (Invoice #PI-999)
    Truto-->>Claude: Invoice created successfully
    Claude-->>User: "Draft invoice PI-999 created for Tech Supply Co."

Execution Steps:

  1. list_all_microsoft_dynamics_365_business_central_companies: Claude determines the primary company ID.
  2. list_all_microsoft_dynamics_365_business_central_vendors: Claude validates the vendor name exists and grabs vendor-456.
  3. create_purchase_invoice: Claude drafts the AP record with the extracted financial amounts.

Result: The manual data entry is eliminated. The AP manager simply logs into Business Central to hit "Post".

Moving from Prototypes to Production

Connecting Microsoft Dynamics 365 Business Central to Claude via MCP unlocks massive workflow automation potential, but building that infrastructure in-house requires deep OData expertise and constant maintenance.

Truto's managed MCP servers eliminate the boilerplate. By dynamically deriving tool schemas directly from API documentation and normalizing authentication, Truto allows your engineering team to focus on prompt engineering and agent logic - not maintaining ETag parsing and paginated OData queries.

FAQ

Does Truto handle rate limits for Microsoft Dynamics 365 Business Central automatically?
No. Truto does not retry, throttle, or apply backoff logic. It passes upstream HTTP 429 errors directly to the caller, normalizing the rate limit information into standard IETF headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset) so your AI agent framework can handle the backoff.
How do I ensure Claude doesn't delete financial records?
You can restrict the MCP server configuration at creation time using the methods filter (e.g., config: { methods: ["read"] }). This completely hides write and delete tools from the LLM.
Do I need to manage ETags for Business Central updates?
Yes, Business Central requires an @odata.etag for all updates and deletes. Truto handles this by injecting the etag requirement into the JSON Schema of the generated MCP tools, forcing Claude to fetch the record first and pass the ETag back.
Can I connect the Business Central MCP server to ChatGPT?
Yes. While this guide focuses on Claude, any MCP-compliant client can use the server. In ChatGPT, simply navigate to Settings -> Apps -> Advanced settings and add the Truto MCP URL as a custom connector.

More from our Blog