
List customers in a Business Central company. Use listcompanies to find companyid. Supports OData $filter, $select and $orderby; pass nextoffset from pageinfo to page through.
Get one customer by its GUID, including its '@odata.etag' for safe updates. Use listcustomers to find customerid.
Create a customer. Only the name is required. Note the API cannot set Customer Posting Group, so a customer created here cannot be invoiced until someone sets that in Business Central. Use discoverentitymetadata with entity_set 'customers' for valid field names.
Update fields on an existing customer. Only the supplied fields change. Pass the etag from get_customer to fail safely if someone else edited the record first.
Delete a customer. Business Central refuses this if the customer has ledger entries or open documents, which is expected rather than an error to retry.
List the companies in the connected Business Central environment. Run this first: every other tool needs a company_id, and an environment can hold several companies.
List the API entity sets this Business Central environment exposes, such as customers or salesInvoices. Use it to find valid entityset names before calling discoverentity_metadata or the generic record tools.
Inspect one entity set's fields and expandable relations by sampling a real record. Use before building a $filter, $select or $expand, and use listentities to find valid entityset names.
List the chart of accounts for a company. Only accounts whose accounttype is 'Posting' can take journal entries. Use this to find accountid for createjournalline or an 'Account' document line.
Get one general ledger account by GUID, including its category, type and net change. Use listaccounts to find accountid.
List general journal batches in a company. A batch holds unposted journal lines until postjournal commits them. Use this to find journalid for listjournallines and createjournalline.
List the unposted lines in one journal batch. A journal GUID is required because Business Central cannot list journal lines across a whole company. Use listjournals to find journalid.
Add an unposted line to a journal batch. A positive amount debits the account and a negative amount credits it. The line stays unposted until postjournal runs. Use listjournals for journalid and listaccounts for account_id.
Update an unposted journal line. Only the supplied fields change, and only while the line is unposted. Pass the etag from listjournallines to fail safely on concurrent edits.
Delete an unposted journal line. A posted entry cannot be deleted; it has to be reversed with a balancing entry instead. Use listjournallines to find journallineid.
Post every line in a journal batch to the general ledger at once. The batch must balance, so debits and credits have to net to zero per document or each line needs a balancing account. Cannot be undone. Use listjournals to find journalid.
List customer or vendor payment journal batches, selected with the party parameter. Use this to find journalid for listpayments. These are separate from the general journals returned by list_journals.
List customer or vendor payment lines from one payment journal batch, selected with the party parameter. A journal GUID is required for both parties. Use listpaymentjournals with the same party to find it.
List records from any Business Central entity set, for entities with no dedicated tool such as salesQuotes or dimensions. Use listentities to find entityset names and discoverentitymetadata to see fields. Prefer a dedicated tool where one exists.
Get one record by GUID from any Business Central entity set, including its '@odata.etag' for safe updates. Use listrecords on the same entity set to find recordid.
Create a record in any Business Central entity set. Use discoverentitymetadata on the entity set first to see which fields it takes, since required fields vary by entity. Prefer a dedicated create tool where one exists.
Update a record in any Business Central entity set. Only the supplied fields change. Pass the etag from get_record to fail safely if someone else edited it first. Prefer a dedicated update tool where one exists.
Delete a record from any Business Central entity set. Business Central refuses this for records with ledger entries or open documents, which is expected rather than an error to retry. Prefer a dedicated delete tool where one exists.
List items in a Business Central company. Use listcompanies to find companyid. Supports OData $filter, $select and $orderby; pass nextoffset from pageinfo to page through.
Get one item by its GUID, including its '@odata.etag' for safe updates. Use listitems to find itemid.
Create an item in a Business Central company. Only the name is required; pass any other writable field via 'fields'. Use discoverentitymetadata with entity_set 'items' to see valid field names.
Update fields on an existing item. Only the supplied fields change. Pass the etag from get_item to fail safely if someone else edited the record first.
Delete an item. Business Central refuses this if the item has ledger entries or appears on open documents, which is expected rather than an error to retry.
List purchase orders in a Business Central company. Use listcompanies to find companyid and list_vendors to filter by vendor. Supports OData $filter, $select and $orderby.
Get one purchase order header by GUID, including its '@odata.etag' for safe updates. Use listpurchaseorderlines to read its lines. Use listpurchaseorders to find purchaseorder_id.
Create a purchase order header. Lines are added separately with createpurchaseorderline, because Business Central does not accept lines inline. Use listvendors to find vendor_id.
Update header fields on a purchase order. Only the supplied fields change. Pass the etag from getpurchaseorder to fail safely if someone else edited the order first.
Delete a purchase order and its lines. Only unreceived orders can be deleted; once received and invoiced the document is in the ledger and must be handled with a credit memo instead.
List the lines on one purchase order. A purchase order GUID is required because Business Central cannot list order lines across a whole company. Use listpurchaseorders to find purchaseorderid.
Add a line to a purchase order. Pass itemid when linetype is 'Item' and accountid when it is 'Account'. Note an order line prices with 'directUnitCost', not 'unitCost'. Use listitems and list_accounts to find those IDs.
Receive and invoice a purchase order, creating posted receipt and invoice documents. Cannot be undone. Business Central first requires Vendor Invoice No. on the order, which the v2.0 API cannot set, so this fails unless someone set it in Business Central first.
List purchase invoices in a Business Central company. Supports OData $filter, $select and $orderby; filter on status to separate drafts from posted invoices. Use list_vendors to filter by vendor.
Get one purchase invoice header by GUID, including its '@odata.etag' for safe updates. Use listpurchaseinvoicelines to read its lines. Use listpurchaseinvoices to find purchaseinvoice_id.
Create a draft purchase invoice header. Lines are added separately with createpurchaseinvoiceline. Set 'vendorInvoiceNumber' in fields to record the vendor's own invoice number. Use listvendors to find vendor_id.
Update header fields on a draft purchase invoice. Only the supplied fields change. A posted invoice can no longer be edited. Pass the etag from getpurchaseinvoice to fail safely on concurrent edits.
Delete a draft purchase invoice and its lines. A posted invoice cannot be deleted because it is in the general ledger; it has to be reversed with a credit memo instead.
List the lines on one purchase invoice. An invoice GUID is required because Business Central cannot list invoice lines across a whole company. Use listpurchaseinvoices to find purchaseinvoiceid.
Add a line to a draft purchase invoice. Pass itemid when linetype is 'Item' and accountid when it is 'Account'. Note an invoice line prices with 'unitCost', not 'directUnitCost'. Use listitems and list_accounts to find those IDs.
Post a draft purchase invoice to the general ledger. Posting renumbers the document and it can no longer be edited or deleted; reversing it needs a credit memo. Use listpurchaseinvoices to find purchaseinvoiceid.
List sales invoices in a Business Central company. Supports OData $filter, $select and $orderby; filter on status to separate drafts from posted invoices. Pass 'salesInvoiceLines' in expand to include lines inline.
Get one sales invoice header by GUID, including its '@odata.etag' for safe updates. Use listsalesinvoicelines to read its lines. Use listsalesinvoices to find salesinvoice_id.
Create a draft sales invoice header. Lines are added separately with createsalesinvoiceline, because Business Central does not accept lines inline. Use listcustomers to find customer_id.
Update header fields on a draft sales invoice. Only the supplied fields change. A posted invoice can no longer be edited. Pass the etag from getsalesinvoice to fail safely on concurrent edits.
Delete a draft sales invoice and its lines. A posted invoice cannot be deleted because it is in the general ledger; use cancelsalesinvoice instead.
List the lines on one sales invoice. An invoice GUID is required because Business Central cannot list invoice lines across a whole company. Use listsalesinvoices to find salesinvoiceid.
Add a line to a draft sales invoice. Pass itemid when linetype is 'Item' and accountid when it is 'Account'. Use listitems to find itemid and listsalesinvoices to find salesinvoice_id.
Post a draft sales invoice to the general ledger. Posting renumbers the document, e.g. S-INV102311 becomes PS-INV103297, though its GUID is unchanged. Cannot be undone: reverse it with cancelsalesinvoice. Use listsalesinvoices to find salesinvoiceid.
Post a draft sales invoice and email it to the customer in one step. Use postsalesinvoice when the invoice should not be sent. This cannot be undone. Use listsalesinvoices to find salesinvoiceid.
Cancel a posted sales invoice by issuing a corrective credit memo. This is how a posted invoice is reversed, since it cannot be deleted. Use listsalesinvoices to find salesinvoiceid.
List sales orders in a Business Central company. Use listcompanies to find companyid. Supports OData $filter, $select and $orderby; pass 'salesOrderLines' in expand to include lines inline.
Get one sales order header by GUID, including its '@odata.etag' for safe updates. Use listsalesorderlines to read its lines. Use listsalesorders to find salesorder_id.
Create a sales order header. Lines are added separately with createsalesorderline, because Business Central does not accept lines inline. Use listcustomers to find customer_id.
Update header fields on a sales order. Only the supplied fields change. Pass the etag from getsalesorder to fail safely if someone else edited the order first.
Delete a sales order and its lines. Only unposted orders can be deleted; once shipped and invoiced the document is in the ledger and must be handled with a credit memo instead.
List the lines on one sales order. A sales order GUID is required because Business Central cannot list order lines across a whole company. Use listsalesorders to find salesorderid.
Add a line to a sales order. Pass itemid when linetype is 'Item' and accountid when it is 'Account'. Use listitems to find itemid and listsalesorders to find salesorder_id.
Ship and invoice a sales order, creating posted shipment and invoice documents in the ledger. This cannot be undone: reversing it needs a credit memo. Sales orders have no plain 'post' action.
Validate Business Central credentials by listing the companies in the configured environment. Returns success and the companies found.
List vendors in a Business Central company. Use listcompanies to find companyid. Supports OData $filter, $select and $orderby; pass nextoffset from pageinfo to page through.
Get one vendor by its GUID, including its '@odata.etag' for safe updates. Use listvendors to find vendorid.
Create a vendor in a Business Central company. Only the name is required; pass any other writable field via 'fields'. Use discoverentitymetadata with entity_set 'vendors' to see valid field names.
Update fields on an existing vendor. Only the supplied fields change. Pass the etag from get_vendor to fail safely if someone else edited the record first.
Delete a vendor. Business Central refuses this if the vendor has ledger entries or open documents, which is expected rather than an error to retry.

In an mcp.json file, add the configuration below, and restart Cursor.
Learn more in the official documentation ↗
1{
2 "mcpServers": {
3 "agent-handler": {
4 "url": "https://ah-api-develop.merge.dev/api/v1/tool-packs/{TOOL_PACK_ID}/registered-users/{REGISTERED_USER_ID}/mcp",
5 "headers": {
6 "Authorization": "Bearer yMt*****"
7 }
8 }
9 }
10}
11Open your Claude Desktop configuration file and add the server configuration below. You'll also need to restart the application for the changes to take effect.
Make sure Claude is using the Node v20+.
Learn more in the official documentation ↗
1{
2 "mcpServers": {
3 "agent-handler": {
4 "command": "npx",
5 "args": [
6 "-y",
7 "mcp-remote@latest",
8 "https://ah-api-develop.merge.dev/api/v1/tool-packs/{TOOL_PACK_ID}/registered-users/{REGISTERED_USER_ID}/mcp",
9 "--header",
10 "Authorization: Bearer ${AUTH_TOKEN}"
11 ],
12 "env": {
13 "AUTH_TOKEN": "yMt*****"
14 }
15 }
16 }
17}Open your Windsurf MCP configuration file and add the server configuration below.
Click on the refresh button in the top right of the Manage MCP server page or in the top right of the chat box in the box icon.
Learn more in the official documentation ↗
1{
2 "mcpServers": {
3 "agent-handler": {
4 "command": "npx",
5 "args": [
6 "-y",
7 "mcp-remote@latest",
8 "https://ah-api.merge.dev/api/v1/tool-packs/<tool-pack-id>/registered-users/<registered-user-id>/mcp",
9 "--header",
10 "Authorization: Bearer ${AUTH_TOKEN}"
11 ],
12 "env": {
13 "AUTH_TOKEN": "<ah-production-access-key>"
14 }
15 }
16 }
17 }In Command Palette (Cmd+Shift+P on macOS, Ctrl+Shift+P on Windows), run "MCP: Open User Configuration".
You can then add the configuration below and press "start" right under servers. Enter the auth token when prompted.
Learn more in the official documentation ↗
1{
2 "inputs": [
3 {
4 "type": "promptString",
5 "id": "agent-handler-auth",
6 "description": "Agent Handler AUTH_TOKEN", // "yMt*****" when prompt
7 "password": true
8 }
9 ],
10 "servers": {
11 "agent-handler": {
12 "type": "stdio",
13 "command": "npx",
14 "args": [
15 "-y",
16 "mcp-remote@latest",
17 "https://ah-api-develop.merge.dev/api/v1/tool-packs/{TOOL_PACK_ID}/registered-users/{REGISTERED_USER_ID}/mcp",
18 "--header",
19 "Authorization: Bearer ${input:agent-handler-auth}"
20 ]
21 }
22 }
23}Whether you're an engineer experimenting with agents or a product manager looking to add tools, you can get started for free now