Browse the documentation

MCP tools

Tenders and search

MCP tools for searching and reading tenders, their summaries and price history, plus favorites, saved searches and export.

These tools find and read the tenders the platform collects from Etimad and NUPCO, together with the manual tenders your own team added, which only your organization sees. A tender's ID, which comes from the listing and search tools here, is what the bid, item, quotation and price tools on the other pages take. To add or edit a manual tender, see Manual tenders, items and participation.

Tip:To look a tender up by its tender number or reference number, pass the number on its own as q to tenders_list. It is found under any spelling (NPT0002/26, NPT0002-26, NPT 0002/26) and even after its deadline has passed. The syntax of q is the same in tenders_list and tenders_search, and Searching tenders explains it.
Note:Two dates, two filters. A tender's deadline (last_offer_date) is when offers close, and its publication date (submission_date) is when it was published. tenders_list and export_tenders_csv filter by the deadline, while tenders_search filters by the publication date.
ToolWhat it does
tenders_listList tenders
tenders_searchSearch tenders
agencies_listList agencies
tenders_getGet a tender
tenders_summaryGet a tender's AI summary
tenders_distributionItem distribution
tenders_historical_pricesPast awards for a tender's items
tenders_sourcing_historyPast supplier prices for a tender's items
tenders_submission_historyYour history with a tender's items
favorites_listList favorites
favorites_addAdd a favorite
favorites_removeRemove a favorite
saved_searches_listList saved searches
saved_searches_createSave a search
saved_searches_deleteDelete a saved search
export_tenders_csvExport tenders as CSV

Finding tenders

Four ways in: a listing with filters, a full-text search, a quick lookup for what you already follow, and the list of agencies for building filters.

tenders_list

Lists tenders from Etimad, NUPCO and your team's manual tenders, newest published first, each with a one-line AI headline when one exists. This is the tool for finding a tender by its tender or reference number: pass the number as q.

Read-only · scope tenders.read · all roles · Pro and Enterprise plans

ParameterTypeRequiredDescription
pageintegerNoPage number, starting at 1.
page_sizeintegerNoResults per page: 20 by default, 100 at most.
sourcestringNoOnly tenders from this source: etimad, nupco, or manual for the tenders your team added.
agencystringNoPart of the government agency's name; capitals do not matter.
qstringNoWhat to look for in the tender's name, agency, tender and reference numbers and item text. A keyword of 8 or more digits (a NUPCO material code) also matches the items' material codes. A comma means OR, + or an uppercase AND means AND, and a space is literal, so gloves nitrile looks for that exact phrase: put + between words you want together. The structured syntax works too: the fields agency:, name:, number:, reference:, source:, type:, status: and code: (an exact material code), plus NOT, - to exclude, quoted phrases, parentheses, and item:(...) to require a whole condition within one item, for example agency:health item:(suture AND absorbable) -pediatric. Invalid syntax answers 400 with a readable message, and an unfinished query runs on the part that is complete.
typestringNoThe tender type: open, direct, limited, contest or badail (NUPCO Badail pay-on-account requests). The stored Arabic value is accepted too.
date_fromstringNoThe lower bound on the offer deadline (last_offer_date), as YYYY-MM-DD.
date_tostringNoThe upper bound on the offer deadline, as YYYY-MM-DD; the whole of that day counts.
created_withinintegerNoOnly tenders that reached the platform within this many past days, from 1 to 3,650.
expiredbooleanNoSend true to include tenders whose deadline has passed. Without it, a listing that uses q, product_id, a date filter or created_within shows open tenders only.
past_onlybooleanNoSend true to see only tenders whose deadline has passed.
product_idintegerNoA catalog product's ID, from `products_list`. Only tenders that ask for this product: those with a live item carrying one of the product's linked NUPCO codes.
{
  "q": "syringe + sterile",
  "source": "nupco",
  "created_within": 7,
  "page_size": 10
}
Example arguments

Returns: A page of tenders with total, total_pages, depth_limited and max_rows. Each tender carries its details, summary_headline_en and summary_headline_ar (empty until an AI summary exists), and item_match set to item when the match came through its items.

  • The bare listing, and one filtered only by source, agency or type, includes tenders whose deadline has passed. A search with q, product_id or a date filter shows open tenders only unless you send expired. Two things are exempt: a tender or reference number sent on its own is always found, and your team's manual tenders always show, even without a deadline.
  • When you send both q and product_id, the tenders matching the product are added to those matching q; q does not narrow the product's results.
  • For a search that matches expired tenders without expired, or that filters by publication date, use `tenders_search`.
  • Paging stops at a depth set by your organization's subscription, and before its first payment pages are smaller and the depth shallower. When a result holds more, depth_limited is true, max_rows gives how many results paging reaches, and total_pages counts only reachable pages. To see others, narrow q or the filters rather than paging further.
  • Tender and price-history searches share a per-minute budget across the whole organization, and a smaller one per connection. When either is reached, the tool answers rate_limited with the seconds to wait. Walking one search page after page quickly slows responses for a while (slowed_down).

Searches tenders and their items by name, agency, tender and reference numbers and item text. Unlike `tenders_list`, it has no open-tenders default, so expired tenders match too, and its date filters bound the publication date rather than the deadline.

Read-only · scope search · all roles · Pro and Enterprise plans

ParameterTypeRequiredDescription
qstringYesWhat to look for: a tender or reference number, plain keywords (a comma means OR, + or an uppercase AND means AND, a space is literal), or the structured syntax with fields, NOT, -, quotes, parentheses and item:(...), for example agency:health item:(suture AND absorbable) -pediatric. A keyword of 8 or more digits (a NUPCO material code) also matches item material codes. See Searching tenders.
pageintegerNoPage number, starting at 1.
page_sizeintegerNoResults per page: 20 by default, 100 at most.
sourcestringNoOnly tenders from this source: etimad, nupco, or manual for the tenders your team added.
agencystringNoPart of the government agency's name.
typestringNoThe tender type: open, direct, limited, contest or badail (NUPCO Badail pay-on-account requests). The stored Arabic value is accepted too.
date_fromstringNoThe lower bound on the publication date (submission_date), as YYYY-MM-DD.
date_tostringNoThe upper bound on the publication date, as YYYY-MM-DD.
{
  "q": "agency:health item:(suture AND absorbable) -pediatric",
  "source": "nupco",
  "date_from": "2026-09-01"
}
Example arguments

Returns: A page of tenders with total, total_pages, depth_limited and max_rows, newest published first. Each carries item_match, true when the match came through its items.

  • Tenders of every deadline appear here, expired and open. To keep only open ones, or to filter by the offer deadline, use tenders_list.
  • The results do not carry the one-line AI headline that tenders_list adds.
  • Paging stops at a depth set by your organization's subscription, and before its first payment pages are smaller and the depth shallower. When a result holds more, depth_limited is true, max_rows gives how many results paging reaches, and total_pages counts only reachable pages. To see others, narrow q or the filters rather than paging further.
  • Tender and price-history searches share a per-minute budget across the whole organization, and a smaller one per connection. When either is reached, the tool answers rate_limited with the seconds to wait. Walking one search page after page quickly slows responses for a while (slowed_down).

agencies_list

Lists every distinct government agency name found on the tenders you can see, in Arabic alphabetical order. Use it to see which agencies exist before filtering by agency.

Read-only · scope search · all roles · Pro and Enterprise plans

No parameters.

Returns: agencies: a list of agency names.

  • The list includes the agencies of your team's manual tenders and nothing from other organizations' manual tenders.

Reading a tender

tenders_get

Returns one tender in full: its details and all of its items, with a link to its page in the app. For a short description of what the tender buys, use `tenders_summary` instead.

Read-only · scope tenders.read · all roles · Pro and Enterprise plans

ParameterTypeRequiredDescription
idintegerYesThe tender's ID, from tenders_list or tenders_search.

Returns: The tender's fields (such as tender_name, agency_name, tender_number, reference_number, last_offer_date and submission_date), its items and its web_url.

  • The tool returns every item however many there are, so the reply can be long for a large tender. Each item has item_number, item_name, description, quantity and unit, and material_code on NUPCO tenders. An item with a value in deleted_at was removed from the tender.
  • A tender that does not exist, or another organization's manual tender, answers 404.

tenders_summary

Returns the AI-written summary of a collected tender: a one-sentence headline, a short summary, a few highlights, and the items grouped into product families with a count each (twenty syringe variants read as one entry, "Syringes", counted 20). The first request for a tender writes and stores its summary, and everyone after it reads the stored one.

Changes data · scope tenders.read · roles: owner, admin, sales, purchasing · Pro and Enterprise plans

ParameterTypeRequiredDescription
idintegerYesThe tender's ID.

Returns: tender_id, status and summary. The summary holds headline_en and headline_ar, summary_en and summary_ar, highlights_en and highlights_ar, item_groups (each with name_en, name_ar and item_count), generated_at and items_meta.

  • status is ready when summary is filled. generating means another request is writing the summary: call again after a few seconds. unavailable means there is no summary and none could be made now, with summary empty; the reply does not say why.
  • When no summary exists yet, the call writes it now, which can take up to a minute. Each key may start 60 new summaries an hour; past that the call answers 429.
  • Only tenders collected from Etimad and NUPCO have summaries. Your team's manual tenders always answer unavailable.
  • The text is written from the tender record and NUPCO's earlier award results for the same item codes, in Arabic and English together, so present it as an AI summary. The viewer, technical and viewer (no pricing) roles cannot call this tool, though they still see the one-line headline in tenders_list.

tenders_distribution

Returns how a tender's items are distributed across locations: for each item, the plant and delivery address it goes to and the quantity for each. Items with no distribution rows are left out.

Read-only · scope tenders.read · all roles · Pro and Enterprise plans

ParameterTypeRequiredDescription
idintegerYesThe tender's ID.

Returns: distributions: a list with one entry per item, holding tender_item_id and its rows, each with plant, delivery_address and quantity.

  • A tender that does not exist, or another organization's manual tender, answers 404.

Price history for a tender's items

Three views of what is already known about a tender's items before you price them: what NUPCO awarded earlier, the supplier prices your organization recorded, and what your organization submitted. All three tools belong to the Pro and Enterprise plans. The app shows the same information, explained in Price History.

tenders_historical_prices

Matches a tender's items to earlier NUPCO award results by material code. For each code it lists who won, from which manufacturer and at what unit price, cheapest first.

Read-only · scope tenders.read · roles: owner, admin, sales, purchasing, viewer · Pro and Enterprise plans

ParameterTypeRequiredDescription
idintegerYesThe tender's ID.

Returns: prices: one entry per material code, with its rows. Each row has unit_price, currency, uom, vendor_name, manufacturer, country, catalog_no, source_tender_number, award_date, awarded_to_us and price_hidden, plus price_hidden_reason on a row hidden until the subscription is paid. Beside it, prices_hidden is unpaid when prices are hidden for that reason, else null.

  • A row whose award announcement published no price has an empty unit_price (null). That means the price was not published, never zero, and these rows come last.
  • awarded_to_us is true when the winning vendor's name matches your organization's name or its legal name in Arabic or English.
  • Until your organization's first subscription payment clears, rows may come back without prices: a row hidden for that reason has unit_price null, price_hidden set to true and price_hidden_reason set to unpaid, and rows are ordered by vendor, not price. The price exists and is hidden; it is not an unpublished one.
  • A row with price_hidden set to true and no price_hidden_reason has a price your organization does not see, ranked with the rows that have no price. The price exists and is hidden; it is not an unpublished one.
  • Each read counts against your organization's per-minute budget for searches of tenders and price history, shared by every key, connector and the web app. When it runs out the tool answers 429 rate_limited with the seconds to wait.
  • Only items with a material code are matched, so a tender whose items have none returns an empty prices list. To search the whole record by code or vendor, use `historical_prices_list`.

tenders_sourcing_history

Shows the supplier prices your organization recorded earlier for the same items on its other tenders and RFQs, matched to this tender's items by catalog product or NUPCO code.

Read-only · scope tenders.read · roles: owner, admin, purchasing, viewer · Pro and Enterprise plans

ParameterTypeRequiredDescription
idintegerYesThe tender's ID.

Returns: items: one entry per item that has history, holding tender_item_id and its quotes. Each quote has matchBasis (product or code), unitPriceUsd, unitPriceSar, currency with quotedUnitPrice, vendorName, leadTimeDays, catalogNo, source and submittedAt, along with the RFQ or tender it came from.

  • At most 50 quotes per item, newest first, and quotes without a price are dropped. matchBasis is product when the quote prices the item's catalog product, and code when it shares the item's NUPCO code.
  • This tender's own quotes are left out: only your other tenders and RFQs count. The history is evidence, not a current cost, so it changes nothing in this tender's costs.
  • An item with neither a NUPCO code nor a selected product has no history. Supplier prices are cost data, so the sales and technical roles do not see them.

tenders_submission_history

Shows your organization's own history with a tender's products, matched by material code: the NUPCO awards that went to you and the prices you quoted before.

Read-only · scope tenders.read · roles: owner, admin, sales, purchasing, viewer · Pro and Enterprise plans

ParameterTypeRequiredDescription
idintegerYesThe tender's ID.

Returns: submissions: one entry per material code that has history, holding awarded (each with unit_price, currency, uom, source_tender_number, award_date and price_hidden, plus price_hidden_reason on an award hidden until the subscription is paid) and quotes (each with unit_price, currency, source, reference, customer_name, status, quote_date and tender_id). Beside it, prices_hidden, as on tenders_historical_prices.

  • awarded holds only the awards whose winning vendor's name matches your organization's name or legal name, newest first. Its unit_price can be empty when the award was published without a price.
  • Award prices here follow the same rules as tenders_historical_prices, so renaming the organization reveals no price it cannot see. Until your organization's first subscription payment clears, prices_hidden may be unpaid, and an award hidden for that reason comes back with unit_price null, price_hidden set to true and price_hidden_reason set to unpaid. An award with price_hidden set to true and no price_hidden_reason has a price your organization does not see. The price exists and is hidden; it is not an unpublished one.
  • quotes are your organization's own prices, so none of them is hidden.
  • quotes come from two places: quotes you imported earlier (source is import) and the item prices you set on your other tenders in ProcDuck (source is system, in SAR, with a tender_id). This tender's own prices are left out.
  • Only items with a material code are matched, so a tender whose items have none returns an empty submissions list.

Favorites

A favorite is a tender your organization follows, with an optional note. Favorites belong to the whole organization, not one member, and they count with bids toward your plan's limit on active tenders: 10 on Starter, 100 on Pro, unlimited on Enterprise.

favorites_list

Lists the tenders your organization has favorited, newest first, each with the tender record and the note saved with it. Every member sees the same list.

Read-only · scope favorites.read · all roles · Pro and Enterprise plans

ParameterTypeRequiredDescription
pageintegerNoPage number, starting at 1.
page_sizeintegerNoResults per page: 20 by default, 100 at most.

Returns: A page of favorites with total and total_pages. Each has tender_id, notes, created_at and the tender itself in tenders.

favorites_add

Adds a tender to your organization's favorites, with an optional note. Adding a tender that is already a favorite replaces its note only, and leaving notes out clears it, so repeating the call never creates a duplicate.

Changes data · scope favorites.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans

ParameterTypeRequiredDescription
tender_idintegerYesThe tender's ID, from tenders_list or tenders_search.
notesstringNoA note saved with the favorite, up to 2,000 characters. Send null or leave it out for no note.
{
  "tender_id": 48213,
  "notes": "Follow up with the procurement desk before the briefing"
}
Example arguments

Returns: The favorite as saved, with tender_id, notes and created_at.

  • Favorites count with bids toward the active-tenders limit, and a tender in both counts once. A new favorite past the limit is refused with 402 and plan_limit_reached, naming the limit and current. Changing the note of an existing favorite is never refused.
  • A tender you cannot see answers 404.

favorites_remove

Removes a tender from your organization's favorites, and the note saved with it goes too. Removing a tender that is not a favorite is not an error.

Deletes or overwrites data · scope favorites.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans

ParameterTypeRequiredDescription
tender_idintegerYesThe ID of the tender to remove.

Returns: A confirmation of the removal.

Saved searches

A saved search stores a query and filters under a name so your team can run them again from the search page. It does not notify you of new matches; for that, create a keyword alert.

saved_searches_list

Lists your organization's saved searches, newest first. Every member sees the same list.

Read-only · scope search · all roles · Pro and Enterprise plans

No parameters.

Returns: saved_searches: a list in which each search has id, name, query, agency, tender_type, source, date_from, date_to and created_at.

saved_searches_create

Saves a search, its query and filters, under a name, and it appears in your organization's list of saved searches.

Changes data · scope searches.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans

ParameterTypeRequiredDescription
namestringYesThe saved search's name, 1 to 200 characters.
querystringNoThe search text, in the syntax that q takes in tenders_list, up to 500 characters. Send null for none.
agencystringNoThe agency filter, up to 300 characters.
tender_typestringNoThe tender type filter: open, direct, limited, contest or badail.
sourcestringNoThe source filter: etimad, nupco or manual.
date_fromstringNoThe earliest offer deadline, as YYYY-MM-DD.
date_tostringNoThe latest offer deadline, as YYYY-MM-DD.
{
  "name": "Ministry of Health sutures",
  "query": "item:(suture AND absorbable)",
  "agency": "Health",
  "source": "nupco"
}
Example arguments

Returns: The saved search, in saved_search.

  • When a member opens the saved search on the search page, date_to becomes the nearest "expires in" choice of 7 days, 30 days or a year, and it is ignored once that date has passed. date_from is stored but the page does not apply it.
  • Everything you send is saved as given, without a check that the query is valid.

saved_searches_delete

Deletes a saved search from your organization's list. This cannot be undone.

Deletes or overwrites data · scope searches.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans

ParameterTypeRequiredDescription
idintegerYesThe saved search's ID, from saved_searches_list.

Returns: A confirmation of the deletion.

  • An ID that does not belong to your organization deletes nothing and is not an error.

Exporting

export_tenders_csv

Exports up to 1,000 tenders as CSV text, or those tenders' items when you send items as true. The column headings are in Arabic and the text is UTF-8 with a BOM, so Excel opens it correctly.

Read-only · scope export · roles: owner, admin · Pro and Enterprise plans

ParameterTypeRequiredDescription
qstringNoPlain keywords to look for in the tender's name, agency, tender and reference numbers and item text: a comma means OR, + or an uppercase AND means AND. This tool does not understand the structured syntax of tenders_search (such as agency:), so narrow with the other parameters instead.
sourcestringNoOnly tenders from this source: etimad, nupco, or manual for the tenders your team added.
agencystringNoPart of the government agency's name.
typestringNoThe tender type: open, direct, limited, contest or badail (NUPCO Badail pay-on-account requests). The stored Arabic value is accepted too.
date_fromstringNoThe lower bound on the offer deadline, as YYYY-MM-DD.
date_tostringNoThe upper bound on the offer deadline, as YYYY-MM-DD; the whole of that day counts.
created_withinintegerNoOnly tenders that reached the platform within this many past days, from 1 to 3,650.
expiredbooleanNoSend true to include tenders whose deadline has passed. Without it, only open tenders are exported.
itemsbooleanNoSend true for one row per tender item instead of one row per tender.
{
  "q": "gloves",
  "source": "nupco",
  "created_within": 30,
  "items": true
}
Example arguments

Returns: CSV text whose first line is the column headings. Each tender is a row with its source, name, agency, type, reference number, publication date, offer deadline, purchase fee, remaining days and link. With items, each item is a row with its tender's name and agency, the item number, name, description, quantity, unit and estimated price.

  • Only the owner and admin roles may export, and the export scope is separate from tenders.read.
  • At most 1,000 tenders are exported and there is no paging: narrow the results with the filters. With items, the items of those tenders are exported, so the file can still be long.
  • The date filters here bound the offer deadline, as in tenders_list and unlike tenders_search, and only open tenders are exported unless you send expired.
  • Every export is recorded in the team activity log under the member who created the key, where the owner sees it in team_activity_list.