MCP tools
Manufacturers
MCP tools for the manufacturer directory, its price intelligence and authorization letters.
A manufacturer is an entry in your organization's directory of the companies that make what you sell. It holds contact details, the country and the validity window of the authorization letter, links to catalog products, and is the base for price intelligence and authorization letters. The directory belongs to the whole organization: what a teammate adds, you see.
| Tool | What it does |
|---|---|
| manufacturers_list | List manufacturers |
| manufacturers_get | Get a manufacturer |
| manufacturers_export_csv | Export the manufacturer directory |
| manufacturers_create | Create a manufacturer |
| manufacturers_update | Update a manufacturer |
| manufacturers_delete | Delete a manufacturer |
| manufacturers_bulk_update | Update many manufacturers |
| manufacturer_intel_get | Get a manufacturer's price intelligence |
| manufacturer_intel_generate | Generate a manufacturer's AI summary |
| manufacturer_letter_pdf | Generate an authorization letter |
Reading the directory
Search the directory, read one manufacturer, or export the whole directory.
manufacturers_list
Lists the manufacturers in your organization's directory alphabetically, each with the number of catalog products linked to it. Search with plain words or with the directory's fielded syntax in q.
Read-only · scope manufacturers.read · all roles · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
page | integer | No | Page number, starting at 1. |
page_size | integer | No | Results per page: 20 by default, 100 at most. |
q | string | No | The search text. Plain words match the name, contact person, email and country. For precision use the fields name:, country: (a country name in English or Arabic, or its ISO code), contact:, email:, phone: and website:, combined with AND, OR, parentheses and a leading - to exclude, for example country:germany -name:acme. Plain words do not search the phone or the website, so use their fields. |
{
"q": "country:germany -name:acme",
"page": 1,
"page_size": 20
}Returns: A page of manufacturers, each with its fields and product_count, the number of its live products, plus total, page, page_size and total_pages.
- A search the parser cannot read answers 400 with the reason.
manufacturers_get
Returns one manufacturer with all its fields and the number of catalog products linked to it.
Read-only · scope manufacturers.read · all roles · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The manufacturer's ID, from manufacturers_list. |
Returns: The manufacturer with its fields, among them contact_person, country_code, authorization_start_date, authorization_end_date and agency_type, plus product_count.
- Answers 404 when the manufacturer is not in your organization's directory.
manufacturers_export_csv
Exports the entire directory as CSV text: every row, not one page, with each manufacturer's product count. Limited to the owner and admin roles.
Read-only · scope export · roles: owner, admin · Pro and Enterprise plans
No parameters.
Returns: CSV text in UTF-8 with a byte order mark, with the columns ID, Name, Contact person, Country, Email, Phone, Website, Address, Notes, Agency type, Authorization start, Authorization end, Products and Created at.
- The country is exported as its two-letter code, a missing value is an empty cell, and
Productscounts live products. Attachment links are not exported because they expire quickly. - The column names are the field names of the spreadsheet import, so the file can go back through sheet_import with the
manufacturerstarget. The import only creates manufacturers whose names are not already in the directory. - An Excel version of the same export is available to REST callers. See the API reference.
Adding, editing and deleting
Four tools edit the directory. All are open to the owner, admin, sales and purchasing roles.
manufacturers_create
Adds a manufacturer to your organization's directory. In the same call it can link existing catalog products to it or create new products under it. The name is unique, so a name already in use answers with a conflict.
Changes data · scope manufacturers.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | The manufacturer's name, 1 to 200 characters. Names are unique within your organization: a name already in the directory answers 409 with manufacturer_exists. |
contact_person | string | No | The contact person's name, up to 200 characters. |
email | string | No | The contact email address. It must be a valid address, up to 320 characters. |
phone | string | No | The contact phone number, up to 50 characters. |
website | string | No | The manufacturer's website, up to 500 characters. |
address | string | No | The postal address, up to 500 characters. |
country_code | string | No | The two-letter country code in capitals (ISO 3166-1), such as SA or DE. Lowercase is refused. |
notes | string | No | Free-form internal notes, up to 2,000 characters. |
authorization_start_date | string | No | The date the manufacturer's authorization letter takes effect, as YYYY-MM-DD. The signed letter itself is uploaded as an attachment of category authorization with manufacturer_attachment_upload_url_create, and goes with every product linked to the manufacturer in a submission pack. |
authorization_end_date | string | No | The last day of that validity, as YYYY-MM-DD. It must not be earlier than the start date when both are sent, or the call answers 400. An empty end date means an open-ended authorization. |
agency_type | string | No | The agency relationship the manufacturer states on buyer portals, such as Distribution as authorized, up to 200 characters. It is printed on the product document's information file. |
product_ids | integer[] | No | The IDs of existing catalog products to link to the manufacturer, up to 500. Every ID must be a live product of your organization, or the call answers 400 with product_not_found and creates nothing. |
new_products | object[] | No | New products to create and link to the manufacturer in the same call, up to 500, with the core fields below only. For the full product shape (MDMA, packing and delivery), create them with products_bulk_create and manufacturer_names. |
new_products[].product_name | string | Yes | The product's name, 1 to 200 characters. |
new_products[].nupco_product_code | string | No | The product's NUPCO code, up to 100 characters. |
new_products[].catalogue_number | string | No | The catalog number, up to 100 characters. |
new_products[].cost_price | number | No | The cost price in the currency of cost_currency, from 0 to 9,999,999.99. |
new_products[].cost_currency | string | No | The currency of the cost price: USD or SAR. Defaults to USD. |
new_products[].sale_price_sar | number | No | The sale price in SAR, from 0 to 9,999,999.99. |
new_products[].units_per_case | integer | No | Units per case, a positive whole number up to 1,000,000. |
new_products[].is_medical | boolean | No | true when the product is a medical product. |
{
"name": "Medline Europe GmbH",
"contact_person": "Anna Keller",
"email": "export@medline-europe.example",
"country_code": "DE",
"authorization_start_date": "2026-01-01",
"authorization_end_date": "2027-12-31",
"agency_type": "Distribution as authorized",
"new_products": [
{
"product_name": "Syringe 5 ml with needle, sterile",
"nupco_product_code": "4111610529900",
"cost_price": 0.34,
"cost_currency": "USD",
"units_per_case": 1000
}
]
}Returns: The new manufacturer with its fields, plus product_count, linked_count (existing products linked), created_count (new products created) and created_products, the index and id of each new product in the order you sent them.
- The call checks the products and your plan's limit before it creates the manufacturer. It answers 400 with
product_not_foundfor an ID that is not live, and 402 when the new products would pass your plan's product limit. - The sales role cannot see cost prices, so
cost_priceandcost_currencyare silently dropped from the new products, andsale_price_saris kept.
manufacturers_update
Changes a manufacturer in the directory. Only the fields you send change, and null clears an optional field. To change the contact fields of many manufacturers at once, use manufacturers_bulk_update.
Changes data · scope manufacturers.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The manufacturer's ID, from manufacturers_list. |
name | string | No | The new name, 1 to 200 characters. Names are unique within your organization: a name already in the directory answers 409 with manufacturer_exists. |
contact_person | string | No | The contact person's name, up to 200 characters. Send null to clear it. |
email | string | No | The contact email address. It must be a valid address, up to 320 characters. Send null to clear it. |
phone | string | No | The contact phone number, up to 50 characters. Send null to clear it. |
website | string | No | The manufacturer's website, up to 500 characters. Send null to clear it. |
address | string | No | The postal address, up to 500 characters. Send null to clear it. |
country_code | string | No | The two-letter country code in capitals (ISO 3166-1), such as SA or DE. Lowercase is refused. Send null to clear it. |
notes | string | No | Free-form internal notes, up to 2,000 characters. Send null to clear it. |
authorization_start_date | string | No | The date the manufacturer's authorization letter takes effect, as YYYY-MM-DD. The signed letter itself is uploaded as an attachment of category authorization with manufacturer_attachment_upload_url_create, and goes with every product linked to the manufacturer in a submission pack. Send null to clear it. |
authorization_end_date | string | No | The last day of that validity, as YYYY-MM-DD. It must not be earlier than the start date when both are sent, or the call answers 400. An empty end date means an open-ended authorization. Send null to clear it. |
agency_type | string | No | The agency relationship the manufacturer states on buyer portals, such as Distribution as authorized, up to 200 characters. It is printed on the product document's information file. Send null to clear it. |
{
"id": 118,
"phone": "+49 40 5550 1234",
"authorization_end_date": "2028-12-31"
}Returns: The manufacturer after the change.
- Answers 400 when the call names no field, and 409 with
manufacturer_existswhen the new name belongs to another manufacturer. - Answers 404 when the manufacturer is not in your organization's directory.
manufacturers_delete
Deletes a manufacturer from the directory permanently. Its links to products are removed and its uploaded files are erased, while the products themselves stay in the catalog. It cannot be undone, and there is no trash for manufacturers.
Deletes or overwrites data · scope manufacturers.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The manufacturer's ID, from manufacturers_list. |
Returns: A confirmation, success: true.
- Answers 404 when the manufacturer is not in your organization's directory.
manufacturers_bulk_update
Updates up to 200 manufacturers in one transaction: all succeed or nothing changes. Each row replaces the eight contact fields completely, so read the current values first and send every field, with null clearing a value.
Changes data · scope manufacturers.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
updates | object[] | Yes | The manufacturer rows to update, from 1 to 200. |
updates[].id | integer | Yes | The manufacturer's ID. |
updates[].name | string | Yes | The manufacturer's name, 1 to 200 characters. |
updates[].contact_person | string | Yes | The contact person, up to 200 characters. Send null to clear it. |
updates[].country_code | string | Yes | The two-letter country code in capitals, such as SA. Send null to clear it. |
updates[].email | string | Yes | The email address, a valid address up to 320 characters. Send null to clear it. |
updates[].phone | string | Yes | The phone number, up to 50 characters. Send null to clear it. |
updates[].website | string | Yes | The website, up to 500 characters. Send null to clear it. |
updates[].address | string | Yes | The address, up to 500 characters. Send null to clear it. |
{
"updates": [
{
"id": 118,
"name": "Medline Europe GmbH",
"contact_person": "Anna Keller",
"country_code": "DE",
"email": "export@medline-europe.example",
"phone": "+49 40 5550 1234",
"website": "https://medline-europe.example",
"address": null
},
{
"id": 121,
"name": "Hartmann Medical AG",
"contact_person": null,
"country_code": "DE",
"email": null,
"phone": null,
"website": null,
"address": null
}
]
}Returns: The number of manufacturers changed, as updated.
- The notes, the authorization dates and the agency type are not part of this tool and are never touched. To change them, use manufacturers_update.
- An ID that is not in your organization rejects the whole batch with 400 and
manufacturer_not_found, and a name that matches another manufacturer rejects it with 409 andmanufacturer_exists. In both cases nothing changes.
Price intelligence
Price analysis for one manufacturer, computed from the quotes recorded in your organization only. Because it is cost data, it needs the Pro or Enterprise plan and the owner, admin, purchasing or viewer role.
manufacturer_intel_get
Shows how a manufacturer's prices have moved, computed from the quote lines it gave your organization on RFQs and recorded supplier prices: each product's price series, the change from the first quote to the last, and products quoted at different prices. It also returns the stored AI summary when one exists, and never writes a new one: that is the job of manufacturer_intel_generate.
Read-only · scope manufacturers.read · roles: owner, admin, purchasing, viewer · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The manufacturer's ID, from manufacturers_list. |
Returns: facts: lineCount, responseCount, productCount, firstQuoteAt, lastQuoteAt and medianPctChange, the products list (each with label, series of dated prices, firstUsd, lastUsd, minUsd, maxUsd, pctChange, trend and spreadPctMaxOverMin), and the shortlists topIncreases and topSpreads. ai: the stored summary (headline_en, headline_ar, body_en, body_ar, model and generated_at) or null. And ai_stale.
- All prices are in USD.
pctChangecompares the last quote with the first and isnullfor a product with fewer than two quotes, which means no trend, not zero.trendisflatwithin 2%, otherwiseupordown.spreadPctMaxOverMinis the gap between the highest and lowest price as a share of the lowest, and isnullunless two different prices exist. - Only quotes attributed to this manufacturer in your directory count, not quotes recorded under a free-text supplier name. A manufacturer with no quotes returns zeroed facts.
ai_stale: truemeans the quote data changed since the summary was written.- Answers 404 when the manufacturer is not in your organization's directory.
manufacturer_intel_generate
Writes, or refreshes, the stored bilingual AI summary of a manufacturer's price intelligence. It narrates the figures that manufacturer_intel_get returns and adds no figure of its own. It runs the model only when the manufacturer's quotes changed since the last summary, and otherwise returns the stored one at no cost.
Changes data · scope manufacturers.write · roles: owner, admin, purchasing · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The manufacturer's ID, from manufacturers_list. |
Returns: ai with the summary (headline_en, headline_ar, body_en, body_ar, model and generated_at) and ai_stale: false. Instead you may get ai: null with no_data: true (no priced quotes to narrate) or disabled: true (the feature is switched off), or a 202 with status: "generating" while another request is writing it.
- On a 202, call manufacturer_intel_get a little later to read the summary.
- After a failed attempt the call answers 503 with a message and does not try again for ten minutes.
- The summary is written from the aggregated price figures alone, not from contact details or notes.
- Answers 404 when the manufacturer is not in your organization's directory.
Authorization letters
A ready-to-print authorization letter, issued by the manufacturer in favor of your organization.
manufacturer_letter_pdf
Generates an authorization letter PDF for a manufacturer. The top and bottom of the page are left blank so you can print it on the manufacturer's own letterhead for them to sign. The letter is in English, dated today, and names your organization's legal name in English as the distributor. Nothing is stored: every call generates it again.
Read-only · scope manufacturers.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The manufacturer's ID, from manufacturers_list. |
letter_type | string | Yes | The letter type: new_relation (an authorization letter: authorizes your organization as a distributor without claiming exclusivity, and certifies the manufacturer will supply every quoted item), change_agency (an attestation of a change of agency: your organization replaces a previous agent, and previous_agency_name is required) or exclusive_distribution (a declaration of exclusive distributorship: the only type that claims exclusivity). |
territory | string | No | The territory the letter covers, up to 200 characters. Defaults to Saudi Arabia. |
recipient | string | No | The party the letter is addressed to, up to 300 characters. Defaults to NUPCO, the National Unified Procurement Company. |
previous_agency_name | string | No | The name of the previous agency your organization replaces, up to 300 characters. Required with change_agency; without it the call answers 400. |
tender_number | string | No | The number of the tender the letter is issued for, up to 100 characters. It is printed in the letter's header, and on new_relation it limits the authorization to the items quoted under that tender. |
notes | string | No | An extra sentence added to the letter's body, up to 1,000 characters. |
{
"id": 118,
"letter_type": "new_relation",
"tender_number": "NPT0042/26"
}Returns: A PDF file: filename, content_type, size_bytes and the content as base64 in base64.
- The manufacturer's address is not printed: a blank line is left for the signatory to fill in.
- The tool changes nothing, yet it needs the
manufacturers.writescope and the editing roles, like the screen that creates the letter. - Answers 404 when the manufacturer is not in your organization's directory.