MCP tools
RFQs and supplier quotes
MCP tools for supplier RFQs, recording their quotes in any currency, the price book and exchange rates.
An RFQ (request for quotation) is the buying side of a tender: a list of tender items you ask your suppliers to price, frozen when the request is created. Each supplier reply is recorded as a quote with its priced lines, in the supplier's own currency. These tools create and manage requests, record and correct quotes, and read the prices your organization has collected. The guide to the app side is RFQs.
fx_rates_get, which every role and plan can use.sourcing, which shows in listings like any request but cannot be deleted or given another currency.| Tool | What it does |
|---|---|
| rfqs_list | List RFQs |
| rfqs_get | Get an RFQ |
| rfqs_create | Create an RFQ |
| rfqs_update | Set an RFQ's currency |
| rfqs_delete | Delete an RFQ |
| rfq_excel_export | Download the RFQ workbook |
| fx_rates_get | Get exchange rates for quotes |
| rfq_responses_add | Record a supplier quote |
| rfq_responses_update | Update a supplier quote |
| rfq_responses_delete | Delete a supplier quote |
| tender_rfq_matrix | Get a tender's supplier quotes |
| rfq_responses_list | List supplier quote lines |
| rfq_price_book | Get the vendor price book |
Requests
Create a request from a tender's items, read it back, change its currency, download the supplier workbook or delete it.
rfqs_list
Lists your organization's RFQs across all tenders, newest first, each with its tender and the number of items and supplier quotes. Narrow it to one tender with tender_id, or use kind to leave out the holding requests that single-item sourcing prices live on.
Read-only · scope rfqs.read · roles: owner, admin, purchasing, viewer · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
tender_id | integer | No | Only the requests of this tender. The ID comes from the tender tools. |
kind | string | No | Only requests of this kind: rfq for requests you created for a tender with rfqs_create, or sourcing for the holding request that keeps single-item sourcing prices. |
page | integer | No | Page number, starting at 1. |
page_size | integer | No | Results per page: 20 by default, 100 at most. |
{
"tender_id": 48213,
"kind": "rfq",
"page": 1
}Returns: A page of requests in data, with total, page, page_size and total_pages. Each request has its id, tender_id, title, kind, currency and created_at, its tender's name and agency, item_count and response_count.
- Holding requests (kind
sourcing) appear in the list unless you filter them out withkind. They hold prices typed onto single items and are not requests you send to a supplier.
rfqs_get
Returns one RFQ in full: its frozen item list, every supplier quote recorded on it and every priced line of those quotes. Use it to find the IDs, item numbers and NUPCO codes you need before recording a quote, or to check what suppliers have answered.
Read-only · scope rfqs.read · roles: owner, admin, purchasing, viewer · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The RFQ's ID, from rfqs_list or the rfq_id that rfqs_create returns. |
Returns: rfq (including tender_id, currency and kind), items (the frozen lines: id, item_number, description, quantity and unit, plus the live tender item's item_name and material_code), responses (one per quote: the supplier's details, source, submitted_at, currency, fx_rate with its date and source, and manufacturer_name) and response_items (the priced lines: unit_price in US dollars, quoted_unit_price as the supplier gave it, lead time, catalog number, weights, packing and product_id).
- A line's
descriptionis the copy frozen at creation, whileitem_nameandmaterial_codeare read from the tender item as it is now, so a later edit to the item shows in them. - The server answers 404 when the request is not your organization's.
rfqs_create
Creates an RFQ for a tender from the items you pick. The request freezes those items when it is created, so later edits to the tender never change a file already in a supplier's hands. Each call makes a separate request, so different item sets can go to different suppliers. Nothing is sent: download the workbook with rfq_excel_export and pass it on yourself.
Changes data · scope rfqs.write · roles: owner, admin, purchasing · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
tender_id | integer | Yes | The tender's ID. |
item_ids | integer[] | Yes | IDs of the tender's live items to include, from 1 to 2000. They come from tenders_get, and repeats are merged. |
currency | string | No | ISO 4217 code of the currency suppliers are asked to quote in, such as USD, SAR, EUR, CNY or GBP. Defaults to USD. It presets the workbook's Currency dropdown and becomes the default of rfq_responses_add, and a supplier may still quote in another. fx_rates_get lists every supported code. |
{
"tender_id": 48213,
"item_ids": [
902114,
902115,
902118
],
"currency": "EUR"
}Returns: The new request: rfq_id, item_count and currency.
- The server answers 400
invalid_itemswhen any ID is not a live item of this tender (a deleted item is not live), and 404 when the tender is not visible to your organization. - The request is titled with the tender's name (first 200 characters) and its items follow the tender's item order.
rfqs_update
Changes the currency an RFQ asks suppliers to quote in. It applies to workbooks you export from now on and to the default of rfq_responses_add. Quotes already recorded keep their own currency, and a workbook already sent still names the currency it went out with.
Changes data · scope rfqs.write · roles: owner, admin, purchasing · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The RFQ's ID. |
currency | string | Yes | ISO 4217 code of the new currency, such as USD, SAR, EUR, CNY or GBP. fx_rates_get lists every supported code. |
{
"id": 731,
"currency": "CNY"
}Returns: The request's id and its new currency.
- The tool refuses the holding request (kind
sourcing) with 400sourcing_container, and answers 404 when the request is not your organization's. - To change the currency of a quote already recorded, use `rfq_responses_update`.
rfqs_delete
Deletes an RFQ together with its frozen item list and every supplier quote recorded on it. This cannot be undone.
Deletes or overwrites data · scope rfqs.write · roles: owner, admin, purchasing · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The RFQ's ID. |
Returns: A confirmation, with deleted_responses, the number of quotes that were deleted with the request.
- The holding request (kind
sourcing) cannot be deleted and the server answers 400sourcing_container. Delete its prices one at a time with `rfq_responses_delete`.
rfq_excel_export
Builds the Excel workbook you send to suppliers for an RFQ and returns it as a file. It is rebuilt from the request's frozen item list and carries the request's identity in hidden data, so a copy filled in later can be matched back to its request. Its Currency dropdown is preset to the request's currency. Beside each item's description, a read-only Similar products column lists the manufacturer and catalog number of each product past NUPCO tenders awarded for the item's material code, unique and comma-separated.
Read-only · scope rfqs.read · roles: owner, admin, purchasing, viewer · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The RFQ's ID. |
locale | string | No | The workbook's language: ar (the default) or en. |
Returns: An Excel file: filename (like rfq-731-tender-48213.xlsx), content_type, size_bytes and base64.
- The server answers 400
no_itemswhen the request has no items. Every new download carries the same request identity, so every copy matches its request. - To record what a supplier sends back, read the filled workbook and record its prices with `rfq_responses_add`.
Currencies and exchange rates
A quote keeps its own currency and one exchange rate frozen when it is recorded. A rate reads as the units of the currency that buy one US dollar.
fx_rates_get
Lists the currencies a supplier quote can be recorded in and the rate each would use today, as units of the currency per 1 US dollar. Check it before recording a quote in a foreign currency to see which rate will apply and whether you must supply your own.
Read-only · scope rfqs.read · all roles · Pro and Enterprise plans
No parameters.
Returns: base (always USD), currencies (every supported code) and rates: for each currency that has a default, currency, fx_rate, rate_date (the ECB publication day, empty for fixed and pegged rates), source (identity, peg or ecb) and fixed.
- The US dollar (1) and the Saudi riyal (3.75, the peg the platform converts to riyals at) are fixed: a quote in them cannot use another rate. The UAE dirham, Qatari riyal, Bahraini dinar, Omani rial and Jordanian dinar use their official pegs. Every other currency uses the latest European Central Bank reference rate, updated on working days.
- A supported currency missing from
rateshas no rate on file (the Kuwaiti dinar, Egyptian pound and Pakistani rupee, for example), so passfx_ratewhen recording a quote in it. - A recorded quote freezes its own rate, so these rates matter only for quotes you record from now on. This is the one tool on the page open to every role and plan.
Supplier quotes
A quote is one supplier's reply, covering any of the request's items. Record it, correct it as often as needed, or delete it.
rfq_responses_add
Records one supplier's quote against an RFQ, covering any of its items. Use it when a supplier replies in any format (a PDF, an email, a photo, a reworked spreadsheet): match each row of the reply to an item of the request and record its price as printed. The quote keeps the figures as the supplier gave them, in the supplier's currency, and the server converts them to US dollars for comparison at the rate it reports back.
Changes data · scope rfqs.write · roles: owner, admin, purchasing · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
rfq_id | integer | Yes | The RFQ's ID. |
manufacturer_id | integer | No | The supplier's record in your manufacturer directory, from manufacturers_list. Send null or leave it out for a supplier that is not in the directory. This or supplier_name is required. |
supplier_name | string | No | The supplier or contact name shown on the quote, up to 200 characters. If you leave it out and give manufacturer_id, the manufacturer's directory name is used. |
supplier_company | string | No | The supplier's company, up to 200 characters. |
supplier_email | string | No | The supplier's email address. |
supplier_phone | string | No | The supplier's phone number, up to 50 characters. |
incoterms | string | No | The delivery terms the supplier quoted, such as CIF Riyadh, up to 100 characters. |
currency | string | No | ISO 4217 code of the currency the quote's prices are in, such as EUR. Defaults to the RFQ's own currency. Send each price exactly as printed in the document and name its currency here; do not convert prices yourself. fx_rates_get lists the supported codes. |
fx_rate | number | No | Units of the quote currency per 1 US dollar, for example 0.88 for EUR or 7.1 for CNY. Leave it out to use the default: USD and SAR are fixed (1 and 3.75, and any other value is refused), the Gulf currencies use their pegs, and other currencies the latest ECB rate. A currency with no rate on file, such as KWD, EGP or PKR, needs it. |
notes | string | No | Notes on the whole quote, up to 5,000 characters. |
lines | object[] | Yes | The priced lines, from 1 to 2000. Each line names its item with exactly one of rfq_item_id, item_number or material_code. |
lines[].rfq_item_id | integer | No | The request item's own ID, from rfqs_get. |
lines[].item_number | integer | No | The item number printed on the workbook sent to the supplier, an alternative to rfq_item_id. Refused when two request items carry the same number; use rfq_item_id then. |
lines[].material_code | string | No | The NUPCO material code of the tender item, a third way to name the item. Refused when it matches more than one item of the request. |
lines[].unit_price | number | No | The quoted unit price in the quote's currency, zero or more. Send null or leave it out to record the item's details with no price yet. |
lines[].lead_time_days | integer | No | Lead time in days, from 0 to 3650. |
lines[].catalog_no | string | No | The supplier's catalog number, up to 100 characters. |
lines[].weight_kg | number | No | Unit weight in kilograms. |
lines[].units_per_case | integer | No | Units in one case, a whole number above 0. |
lines[].product_id | integer | No | The product in your catalog this price was quoted for, from products_list. It must be one of your organization's products. |
lines[].notes | string | No | Notes on the line, up to 2,000 characters. |
{
"rfq_id": 731,
"supplier_name": "Li Wei",
"supplier_company": "Shenzhen Medical Co",
"incoterms": "CIF Riyadh",
"currency": "CNY",
"lines": [
{
"item_number": 1,
"unit_price": 2.35,
"lead_time_days": 45,
"catalog_no": "SY-10ML"
},
{
"material_code": "4111610529900",
"unit_price": 14.8,
"units_per_case": 100
}
]
}Returns: The new quote's response_id, the supplier_name recorded, the number of saved lines in lines, and the currency and fx_rate the quote was recorded at.
- A reference that matches no item of the request, or more than one, is refused with a message naming the line and nothing is saved, so a price never lands on the wrong item.
- The server answers 400 when you give neither a supplier name nor a manufacturer, 400
manufacturer_not_foundwhen the manufacturer is not your organization's, and 400product_not_foundwhen aproduct_idis not one of your products. - The quote is recorded as a typed quote (
sourceismanual). Lines with no price stay out of the comparisons and the price book.
rfq_responses_update
Changes a recorded quote without recording it again: the supplier's details, the lines, or the quote's currency and rate. Use it to fill a long supplier document in several passes, correct a mis-read price, or fix a quote recorded in the wrong currency. Only what you send changes.
Changes data · scope rfqs.write · roles: owner, admin, purchasing · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
rfq_id | integer | Yes | The RFQ's ID. |
response_id | integer | Yes | The quote's ID, from rfqs_get. |
manufacturer_id | integer | No | Links the quote to a manufacturer in your directory. Send null to unlink it. |
supplier_name | string | No | The new supplier name, 1 to 200 characters. It cannot be cleared. |
supplier_company | string | No | The supplier's company. Send null to clear it. |
supplier_email | string | No | The supplier's email address. Send null to clear it. |
supplier_phone | string | No | The supplier's phone number. Send null to clear it. |
incoterms | string | No | The delivery terms. Send null to clear them. |
currency | string | No | ISO 4217 code of the quote's currency. Sending a different currency, or fx_rate, re-denominates the whole quote: every line keeps its price as the supplier gave it and its US dollar price is recomputed at the new rate. Use it when the prices were recorded in the wrong currency (euros read as dollars). Send neither and the recorded rate stays frozen. A new currency with no fx_rate takes that currency's default rate. |
fx_rate | number | No | A new rate, in units of the quote's currency per 1 US dollar, which reprices every line the same way. For USD and SAR only the fixed rate (1 and 3.75) is accepted. |
notes | string | No | Notes on the whole quote. Send null to clear them. |
lines | object[] | No | Lines to add or change. A line for an item the quote already prices is updated field by field: what you leave out keeps its value and null clears it. A line for an item the quote does not price yet is added. Each line names its item as in rfq_responses_add. |
lines[].rfq_item_id | integer | No | The request item's ID, from rfqs_get. |
lines[].item_number | integer | No | The item number printed on the supplier's workbook, an alternative to rfq_item_id. |
lines[].material_code | string | No | The NUPCO material code of the tender item, a third way to name the item. |
lines[].unit_price | number | No | The unit price in the quote's currency as it stands after this update. Send null to clear it. |
lines[].lead_time_days | integer | No | Lead time in days. Send null to clear it. |
lines[].catalog_no | string | No | The supplier's catalog number. Send null to clear it. |
lines[].weight_kg | number | No | Unit weight in kilograms. Send null to clear it. |
lines[].units_per_case | integer | No | Units in one case. Send null to clear it. |
lines[].product_id | integer | No | The product in your catalog this price was quoted for. Send null to clear it. |
lines[].notes | string | No | Notes on the line. Send null to clear them. |
remove_rfq_item_ids | integer[] | No | IDs of the request items whose priced lines are removed from this quote, up to 2000. |
{
"rfq_id": 731,
"response_id": 2087,
"currency": "EUR",
"lines": [
{
"item_number": 3,
"unit_price": 4.1,
"lead_time_days": 30
}
],
"remove_rfq_item_ids": [
8812
]
}Returns: response_id and supplier_name, the counts updated_lines, inserted_lines and removed_lines, the quote's currency and fx_rate after the change, and repriced_lines, the number of lines whose US dollar price was recomputed by a currency or rate change.
- Send at least one change: an empty update is refused with a 400.
- A currency or rate change applies first: lines you send in the same call are stored at the final rate, and their
unit_pricevalues are read in the final currency. - The server answers 409 when one request item appears more than once on the quote (remove the repeats with
remove_rfq_item_idsfirst), 404 when the quote is not on this request, and 400missing_supplier_namewhen the change would leave the quote with no supplier name and no manufacturer. - It works on a quote from any source: a returned Excel workbook, a typed quote or a single-item sourcing price.
rfq_responses_delete
Removes one supplier quote from an RFQ together with its lines, such as a mistyped sourcing price or a stale import. This cannot be undone, and the request itself stays.
Deletes or overwrites data · scope rfqs.write · roles: owner, admin, purchasing · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
rfq_id | integer | Yes | The RFQ's ID. |
response_id | integer | Yes | The quote's ID, from rfqs_get. |
Returns: A confirmation: success is true.
- The server answers 404 when the quote is not on this request. This is also how you remove a single-item sourcing price, which is kept on the tender's holding request.
Reading the collected prices
Three read-only views of the same data: one tender, every quote line in the organization, and the same lines grouped by product.
tender_rfq_matrix
Returns all supplier-quote data for one tender in a single call: every RFQ made for it, their items, every supplier quote and every priced line. It is the raw material for comparing suppliers' prices item by item.
Read-only · scope rfqs.read · roles: owner, admin, purchasing, viewer · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
tender_id | integer | Yes | The tender's ID. |
Returns: rfqs (each with item_count), items, responses (each with manufacturer_name) and response_items. All four are empty lists when the tender has no request.
- The tool does not build the comparison for you: join
response_itemstoitemsthroughrfq_item_idand toresponsesthroughresponse_id.unit_priceis in US dollars andquoted_unit_priceis as the supplier gave it. itemscarry the frozen description, quantity, unit and item number, but notitem_nameormaterial_code. Read those from `rfqs_get`.- The result includes the tender's holding request (kind
sourcing) with the prices typed onto single items.
rfq_responses_list
Lists every priced quote line your organization has collected from suppliers, from any request, Excel reply or single-item sourcing price, newest first, with a summary of each vendor. Use it to see what a supplier has quoted over time or to compare vendors across tenders.
Read-only · scope rfqs.read · roles: owner, admin, purchasing, viewer · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
manufacturer_id | integer | No | Only lines from quotes linked to this manufacturer in your directory. The ID comes from manufacturers_list. |
vendor | string | No | Only lines of one vendor, by the vendor key you find in the vendors list of an earlier call: mfr: plus the manufacturer ID for a vendor linked to your directory (mfr:512), or label: plus the supplier's company name (else contact name) in lowercase for a typed one (label:shenzhen medical co). Lines with no supplier identity at all are grouped under unknown. A display name does not match. 1 to 200 characters. |
limit | integer | No | The most lines to return, from 1 to 2000. Defaults to 2000, which is also the ceiling. |
{
"manufacturer_id": 512,
"limit": 200
}Returns: vendors, a summary per vendor (key, name, lineCount, responseCount, productCount, firstQuoteAt and lastQuoteAt), and lines, newest first. Each line has its vendor, its product or item description, catalogNo, materialCode and quantity, the price in US dollars (unitPriceUsd), in riyals (unitPriceSar) and as the supplier quoted it (quotedUnitPrice with currency), then leadTimeDays, source, submittedAt and the request and tender it came from. Also total and truncated.
totalis the count of all matching lines, andtruncatedistruewhen the 2000 cap cut the list. The vendor summaries cover the whole set and do not shrink when you filter.- Lines with no price are left out.
sourceisexcelfor a returned workbook,manualfor a typed quote (including single-item sourcing prices) orwebfor older replies through the web.
rfq_price_book
The same priced lines that `rfq_responses_list` returns, grouped by product: one row per product with every vendor that quoted it, their latest price and the vendor to beat. Use it to see who is cheapest for a product across all your requests.
Read-only · scope rfqs.read · roles: owner, admin, purchasing, viewer · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
manufacturer_id | integer | No | Only products this manufacturer from your directory has quoted. |
vendor | string | No | Only products quoted by one vendor, by its key as in rfq_responses_list: mfr: plus the ID, or label: plus the vendor name in lowercase. |
source | string | No | Only products with at least one quote recorded this way: excel for a returned workbook, manual for a typed quote (including single-item sourcing prices) or web for older replies through the web. |
limit | integer | No | The most products to return, from 1 to 2000. Defaults to 2000, which is also the ceiling. |
{
"source": "excel",
"limit": 100
}Returns: products, newest quote first. Each has name, kind, productId, vendorCount, quoteCount, its latest, lowest and highest price in US dollars and riyals, bestVendorKey, and vendors ordered cheapest latest price first. Also vendors for the whole set, total, truncated and quoteCount.
- Each vendor inside a product carries its newest quote: the price in US dollars, riyals and its own currency, lead time, catalog number, source, and the request or tender it came from, with its quote count and price range.
bestVendorKeyis the vendor whose latest price is the cheapest, the price to beat. - A row is a product from your catalog when the line was tagged with it, you selected it on the quoted item, or the line's NUPCO code belongs to exactly one catalog product. Otherwise the row is the NUPCO code, or else the item description.
kindsays which:product,codeordescription. - Filters select products, not vendors: a product stays when one of its lines matches everything you sent, and it then keeps all its vendors so you can compare them.
totalcounts the matching products, whilevendorsandquoteCountdescribe the whole set whatever you filter.