tools/call over
POST /business-central/mcp. The connector reads Microsoft Dynamics 365 Business
Central online and is connected through OAuth with a Microsoft work or school
account (see Forbind Business Central). You need
an active Business Central subscription, and your user must hold a seat on it
(assigned under Team in the portal, see Team).
The connector is in early access. It currently serves five tools: three discovery tools
(
list_environments, list_companies, get_company_information) and a generic,
allow-listed query tool (query_entity) with its companion
(list_entity_metadata). More curated read tools are planned. This page documents
only what is served today.Endpoint:
https://mcp.consile.ai/business-central/mcp. Business Central is its
own named connector with only its own tools. Tool names are namespaced
business-central__<tool> (e.g. business-central__list_companies); the bare
names are used below for readability. A bare name in a request returns
Unknown tool.The connector is multi-instance: one instance covers one Microsoft Entra
tenant, including all of its environments and companies. An additional tenant is
added as a portal by an administrator and served at its own endpoint, e.g.
https://mcp.consile.ai/business-central-2/mcp, with tools named
business-central-2__<tool>.tools/list returns
the five business-central__* tools plus the unprefixed system tool
connect_account. Without a subscription only
connect_account is listed, and the initialize result includes instructions
explaining how to get access. A user without a seat still sees the tools, but every
call is refused. Every tool has a title and the annotations readOnlyHint: true,
destructiveHint: false and openWorldHint: false. A successful result contains
the payload twice: as JSON text in content and as the same object in
structuredContent. The examples below show that payload.
Authorization and read-only enforcement
The connect flow is a standard authorization-code flow with PKCE againsthttps://login.microsoftonline.com/organizations/oauth2/v2.0/authorize. Because it
uses the organizations endpoint, only work or school accounts can connect; a
personal Microsoft account fails at Microsoft. The requested scopes are:
https://api.businesscentral.dynamics.com/Financials.ReadWrite.Alloffline_access(for the refresh token)
- The connector has no write tools.
- Consile sends only read requests to the Business Central API. Reads ask for
Business Central’s read-only data access intent (
Data-Access-Intent: ReadOnly), which routes them to a read replica. If an API page answers400to that, the request is retried once without it. - The granted scope is checked as a closed set when the account is connected. It
must contain a Business Central API scope (
Financials.ReadWrite.Alloruser_impersonation, qualified or bare).openid,profile,emailandoffline_accessare tolerated. Any other scope rejects the connect, and so does a token response without a refresh token.
Shared conventions
Environments and companies
Business Central addresses data by an environment name (a Production or Sandbox environment in the tenant) and a company id (a legal entity inside that environment). Both are per-call arguments. Nothing about the choice is stored on Consile’s side. The intended order islist_environments (only when the default is
wrong), then list_companies, then the company-scoped tools with the GUID in hand.
string
default:"Production"
Business Central environment name, 1 to 80 characters. Optional on every tool that
takes it. Call
list_environments if the tenant uses
another name. An unknown name returns an error that lists the environments that
exist.string (GUID)
required
The company id from
list_companies. Required on
get_company_information and query_entity. It cannot be derived from a company
name. A wrong GUID returns a 404 error, not another company’s data.string
Optional case-insensitive substring filter, applied by Consile after the read
(
list_companies and list_entity_metadata). At least one character.Result context
Every result exceptlist_environments echoes a context object with the
environment (and the companyId, where one applies) it was read from, so a result
cannot be misattributed to another company. @odata.* annotation keys are removed
from every row.
Typical call order
list_companies(andlist_environmentsonly if the environment is notProduction).get_company_information, to confirm which books are being read.list_entity_metadata, to see which entity sets the environment serves.query_entitywithselectandfilter.
list_environments
Lists the Business Central environments in the connected Microsoft Entra tenant. Only Business Central environments are returned. Call it only when the tenant runs several environments or a tool reported an unknown environment name. Arguments: none.array
Each item has
name, type (Production or Sandbox), countryCode and
aadTenantId (the Entra tenant id). A missing countryCode or aadTenantId
is null.list_companies
Lists the companies (legal entities) in an environment, with the GUID every company-scoped tool requires.string
default:"Production"
string
Filters
name and displayName case-insensitively.array
Each item has
id (the companyId), name, displayName and systemVersion.boolean
true when a search matched more than one company. The tool description tells
the model to ask the user which one is meant instead of guessing.get_company_information
Reads a company’s own master data: registered name, address, VAT registration number (the CVR number in Denmark), currency code and the start of the current fiscal year. Use it to confirm which books you are reading before reporting numbers.string
default:"Production"
string (GUID)
required
object | null
The company’s
companyInformation record as Business Central returns it (for
example displayName, addressLine1, city, postalCode, country,
taxRegistrationNumber, currencyCode, currentFiscalYearStartDate), or null
if the company has none.list_entity_metadata
Lists the entity sets an environment exposes, read from its OData service document. Use thename values as the entity argument of query_entity.
It is environment-level, so it takes no companyId: the same sets are served inside
every company of that environment.
string
default:"Production"
string
Filters on
name, case-insensitively.array
Each item has
name, kind, url and queryable. queryable: false means the
set exists in the environment but is outside the allow-list query_entity accepts
(for example companies, or a custom API page), so it cannot be read here.search to narrow it.
query_entity
Reads one entity set of the standard Business Central API v2.0 with OData options, one page at a time, or one record by id. Only the 85 allow-listed entity sets can be read (see the list below).string
default:"Production"
string (GUID)
required
string
required
Entity set name, 1 to 80 characters, letters and digits only (e.g.
customers,
salesInvoices, generalLedgerEntries). Matched case-insensitively against the
allow-list. A name with any other character, or one outside the allow-list, is
refused before any request is made; an unknown name is answered with up to five
closest matches.string (GUID)
Reads one record instead of a page.
filter, orderby and pageSize do not
apply; select and expand do.string
Raw OData
$filter expression, 1 to 1,000 characters. String literals are
single-quoted, with an embedded single quote doubled
(displayName eq 'O''Brien'). Dates are written unquoted as YYYY-MM-DD
(postingDate ge 2026-01-01); a quoted date is rejected by Business Central.string[]
Field names for
$select. Always pass it: Business Central rows are wide, and a
page of full rows is likely to exceed the size cap.string
$expand expression, 1 to 500 characters (e.g. dimensionSetLines). It
multiplies the result size, so use it sparingly.string
$orderby expression, 1 to 200 characters (e.g. postingDate desc).integer
default:"50"
Rows per page,
1 to 500.string
Opaque continuation token from a previous result’s
nextCursor. Omit it for the
first page and never construct or edit one.array
The rows of the page, with only the selected fields.
string | null
Token for the next page, or
null when the collection is exhausted. hasMore is
true when a next page exists. There is no total count.object
Returned instead of
count/items/nextCursor/hasMore when id is given.Paging
Paging is server-driven. Pass thenextCursor back as cursor to read the next
page. The cursor carries the original query, so environment, filter, select,
expand and orderby are ignored on a continuation, and pageSize applies to the
next page. entity and companyId are still required and validated, so pass the
same values again. A cursor is only accepted if it points back to the Business
Central API; anything else returns an Invalid cursor error. If you pass both id
and cursor, the cursor is used.
Size cap
A result larger than 100,000 JSON characters is refused, and the client sees onlyTool invocation failed. Narrow select, add a filter or lower pageSize.
Allow-listed entity sets
All 85 entity sets query_entity accepts
All 85 entity sets query_entity accepts
accounts, accountingPeriods, agedAccountsPayable, agedAccountsReceivable,
applyVendorEntries, approvalEntries, approvalUserSetups, attachments,
balanceSheets, bankAccounts, cashFlowStatements, companyInformation,
contacts, contactsInformation, countriesRegions, currencies,
currencyExchangeRates, customers, customerContacts,
customerFinancialDetails, customerPaymentJournals, customerPayments,
customerReturnReasons, customerSales, defaultDimensions, dimensions,
dimensionSetLines, dimensionValues, disputeStatus, documentAttachments,
employees, fixedAssets, fixedAssetLocations, generalLedgerEntries,
generalLedgerSetup, generalProductPostingGroups, incomeStatements,
inventoryPostingGroups, items, itemCategories, itemLedgerEntries,
itemVariants, jobQueueEntries, jobQueueLogEntries, journals,
journalLines, locations, opportunities, paymentMethods, paymentTerms,
pictures, postedApprovalEntries, projects, purchaseCreditMemos,
purchaseCreditMemoLines, purchaseInvoices, purchaseInvoiceLines,
purchaseOrders, purchaseOrderLines, purchaseReceipts,
purchaseReceiptLines, retainedEarningsStatements, salesCreditMemos,
salesCreditMemoLines, salesInvoices, salesInvoiceLines, salesOrders,
salesOrderLines, salesQuotes, salesQuoteLines, salesShipments,
salesShipmentLines, salespersonsPurchasers, shipmentMethods,
subscriptions, taxAreas, taxGroups, timeRegistrationEntries,
trialBalances, unitsOfMeasure, vendors, vendorPayments,
vendorPaymentJournals, vendorPurchases, workflowApprovers.companies is deliberately not on the list; use list_companies. A listed set can
still be missing in a given environment, depending on localisation and version.
list_entity_metadata shows what the environment actually serves. Custom API pages
and extension APIs cannot be read.
connect_account
connect_account is a system tool that the Business Central endpoint lists next to
the five tools. It takes no arguments and its name has no business-central__
prefix. It returns { "connect_url": "…", "instructions": "…" }. The user opens
connect_url in a browser and is sent to Microsoft to sign in and approve access.
The link expires after 10 minutes. It only works for accounts that subscribe to
Business Central and for users who have accepted Consile’s terms in the portal.
Calling it on an account that is already connected replaces the stored Microsoft
access, which is how you reconnect after the access expired or was removed.
Request
Errors
Tool failures come back as a normaltools/call result with isError: true and one
text block, not as a JSON-RPC error. The checks run in this order: tool name,
subscription, seat, connection, then argument validation and the call to Business
Central. Business Central is one of the connectors that returns explanatory
messages for the common upstream failures:
Limits
- Timeout: each request to Business Central times out after 30 seconds.
- Throttling: a
429from Business Central is retried once, after itsRetry-After(at most 5 seconds, 1 second if none is given). - Business Central’s own budget: Microsoft allows 6,000 requests per 5 minutes
per Business Central user, shared with every other Business Central client of that
user. Narrow the
filterinstead of paging through everything. - Page size: default 50, maximum 500 rows.
- Result size: 100,000 JSON characters for
query_entity, 40,000 forlist_entity_metadata.
429 (JSON-RPC error -32029, Retry-After: 1)
instead of a tool result. See Errors & limits for
the current limits and the protocol-level errors shared by all connectors.