<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: hexadata</title>
    <description>The latest articles on DEV Community by hexadata (@hexadata).</description>
    <link>https://dev.to/hexadata</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4214091%2F03a4b46a-66a2-4ef7-aeb3-bc5134c807d1.png</url>
      <title>DEV Community: hexadata</title>
      <link>https://dev.to/hexadata</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hexadata"/>
    <language>en</language>
    <item>
      <title>15 deterministic tools your AI agent should call instead of guessing</title>
      <dc:creator>hexadata</dc:creator>
      <pubDate>Thu, 29 Oct 2026 19:09:40 +0000</pubDate>
      <link>https://dev.to/hexadata/15-deterministic-tools-your-ai-agent-should-call-instead-of-guessing-7ke</link>
      <guid>https://dev.to/hexadata/15-deterministic-tools-your-ai-agent-should-call-instead-of-guessing-7ke</guid>
      <description>&lt;p&gt;Ask an LLM whether &lt;code&gt;EKU9003173C9&lt;/code&gt; is a valid Mexican RFC, what the German VAT rate was on a given date, or which HTS code applies to a stainless steel sink, and you get a confident answer. Sometimes it is right. For an invoicing, KYC or customs agent, "sometimes" is not good enough: a check digit is either correct or not, a tariff code is either in the official schedule or not, and a payroll withholding comes from a published table, not from a model's memory.&lt;/p&gt;

&lt;p&gt;This post is about the class of work an agent should &lt;strong&gt;delegate to deterministic tools&lt;/strong&gt; and how we packaged 15 of them as one &lt;a href="https://apify.com/hexadatalabs/business-validation-tools-mcp" rel="noopener noreferrer"&gt;MCP server on Apify&lt;/a&gt;. Everything runs against official or open sources, has no LLM inside, stores nothing, and costs half a cent per call.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmct9rtn84zl5nqb6u8re.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmct9rtn84zl5nqb6u8re.png" alt="The 15 Hexadata Tools grouped by validate, look up and calculate, with the agent → MCP server → official sources flow and prices" width="800" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What belongs in a tool, not in a prompt
&lt;/h2&gt;

&lt;p&gt;Three tests. If the answer (1) has a published algorithm or table, (2) is needed many times per task (one call per invoice, supplier, shipment or employee) and (3) is expensive to get wrong, it belongs in a tool. Business validation passes all three:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Use this when…&lt;/th&gt;
&lt;th&gt;Official source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;validate_tax_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;checking a company or taxpayer ID from MX, ES, AR, CL, CO, BR, GB, US, IT, FR, DE, PE, CA, AU or IN&lt;/td&gt;
&lt;td&gt;check-digit algorithms published by each tax authority&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;validate_vat_eu&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;confirming an EU VAT number is registered (reverse charge)&lt;/td&gt;
&lt;td&gt;VIES, European Commission&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;validate_iban&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;validating an IBAN and splitting bank, branch and account&lt;/td&gt;
&lt;td&gt;ISO 13616 + IBAN registry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lookup_lei&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;finding the legal entity behind an LEI, or the LEI of a name&lt;/td&gt;
&lt;td&gt;GLEIF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lookup_postal_code&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;resolving a postal code to city/region/coordinates in 120+ countries&lt;/td&gt;
&lt;td&gt;GeoNames (CC BY)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;validate_bank_account&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;checking a Mexican CLABE, a US ABA routing number or a SWIFT/BIC&lt;/td&gt;
&lt;td&gt;Banxico SPEI list, ABA rules, ISO 9362&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;normalize_phone&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;storing a phone as E.164 with country and line type&lt;/td&gt;
&lt;td&gt;libphonenumber&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;validate_email_domain&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;checking syntax and whether the domain receives mail (MX, disposable)&lt;/td&gt;
&lt;td&gt;DNS + open blocklist&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;get_fx_rate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;converting with an official rate for a date&lt;/td&gt;
&lt;td&gt;ECB reference rates, Banxico FIX&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;business_days&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;adding business days or listing holidays in 200+ countries&lt;/td&gt;
&lt;td&gt;Nager.Date, Mexican LFT art. 74&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lookup_industry_code&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;classifying an activity with NAICS, NACE, CPV or SCIAN&lt;/td&gt;
&lt;td&gt;Census, Eurostat, EU Publications Office, INEGI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lookup_hs_code&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;finding a customs tariff code and the US duty rate&lt;/td&gt;
&lt;td&gt;USITC HTS, EU Combined Nomenclature&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;get_vat_rates&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;getting standard and reduced VAT/GST rates of 35 countries for a date&lt;/td&gt;
&lt;td&gt;TEDB + national laws&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lookup_sat_catalog&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;picking a Mexican CFDI 4.0 catalog value (product key, unit, CFDI use, regime)&lt;/td&gt;
&lt;td&gt;SAT official workbook&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;calc_payroll_mx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;computing Mexican ISR, subsidy, IMSS, Infonavit and net pay&lt;/td&gt;
&lt;td&gt;DOF, INEGI, Ley del Seguro Social&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Every answer carries the same envelope: &lt;code&gt;ok&lt;/code&gt;, the result, &lt;code&gt;source&lt;/code&gt;, &lt;code&gt;sourceUrl&lt;/code&gt;, &lt;code&gt;sourceDate&lt;/code&gt; or &lt;code&gt;tableVersion&lt;/code&gt;, and &lt;code&gt;scrapedAt&lt;/code&gt;. Items that cannot be answered (&lt;code&gt;INVALID_INPUT&lt;/code&gt;, &lt;code&gt;UNSUPPORTED_COUNTRY&lt;/code&gt;, &lt;code&gt;SOURCE_UNAVAILABLE&lt;/code&gt;) come back with &lt;code&gt;ok: false&lt;/code&gt; and are never charged.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three design rules
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic.&lt;/strong&gt; No model inside. The same input always gives the same output, except market data (FX rates) that carries its date.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stateless.&lt;/strong&gt; A tax ID or a phone number is validated and forgotten. Logs contain counts and error codes only. No lists of people.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explicit coverage.&lt;/strong&gt; Every multi-country tool declares its supported countries in its description and returns &lt;code&gt;UNSUPPORTED_COUNTRY&lt;/code&gt; (free) for the rest, so the agent knows when not to trust it.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Call it from an MCP client
&lt;/h2&gt;

&lt;p&gt;The Actor runs as a Streamable HTTP MCP server. Add it to Claude Desktop, Cursor, VS Code or any MCP client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hexadata-validation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://hexadatalabs--business-validation-tools-mcp.apify.actor/mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"headers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bearer &amp;lt;APIFY_TOKEN&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then ask: &lt;em&gt;"Validate these supplier tax IDs: MX EKU9003173C9, ES B12345674 and BR 11.222.333/0001-81, and tell me which are malformed."&lt;/em&gt; The agent calls &lt;code&gt;validate_tax_id&lt;/code&gt; once with three items and reports the &lt;code&gt;valid&lt;/code&gt; and &lt;code&gt;reason&lt;/code&gt; fields instead of guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Call it from n8n, Make or plain HTTP
&lt;/h2&gt;

&lt;p&gt;Batch mode takes &lt;code&gt;{ tool, items[], params }&lt;/code&gt; and writes one dataset row per item. One HTTP call, synchronous:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://api.apify.com/v2/acts/hexadatalabs~business-validation-tools-mcp/run-sync-get-dataset-items?token=&lt;/span&gt;&lt;span class="nv"&gt;$APIFY_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"tool":"validate_iban","items":[{"iban":"DE89 3704 0044 0532 0130 00"},{"iban":"DE89370400440532013001"}]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second IBAN comes back with &lt;code&gt;valid: false, reason: "INVALID_CHECK_DIGITS"&lt;/code&gt;. In n8n or Make, use the Apify node with "Run an Actor and get dataset items" and the same JSON.&lt;/p&gt;

&lt;h2&gt;
  
  
  Python
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;apify_client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ApifyClient&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ApifyClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;APIFY_TOKEN&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hexadatalabs/business-validation-tools-mcp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;calc_payroll_mx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;items&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;monthlyGross&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;riskClass&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;year&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2026&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;defaultDatasetId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;iterate_items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;isr&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;imssEmployee&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;net&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;employerCost&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tableVersion&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Agents without an account: USDC via x402
&lt;/h2&gt;

&lt;p&gt;The Actor runs with limited permissions, so an agent can buy a prepaid Apify token with USDC through a Coinbase Agentic Wallet (x402) and call it with no Apify account. $1 USDC ≈ 200 single calls or 500 batch items.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it costs
&lt;/h2&gt;

&lt;p&gt;$0.005 per single-item call, $0.002 per item when a call carries 2–500 items. 1,000 IBAN checks ≈ $2; 5,000 supplier tax IDs across 12 countries ≈ $10; 100 Mexican payroll calculations ≈ $0.20. Invalid input is free.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does not do
&lt;/h2&gt;

&lt;p&gt;It checks formats and check digits, not registries (except VIES and GLEIF, which are live). It does not return bank names for ABA or BIC (those directories forbid commercial redistribution). Text search over code systems is a deterministic word match, not semantic search. It is a calculation aid, not tax advice.&lt;/p&gt;

&lt;p&gt;Full documentation, the per-tool input and output fields and the legal notes are on the &lt;a href="https://apify.com/hexadatalabs/business-validation-tools-mcp" rel="noopener noreferrer"&gt;Actor page&lt;/a&gt;. Missing a country or a catalog? Open an issue with the official source and we add it.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>api</category>
      <category>automation</category>
    </item>
    <item>
      <title>Public tenders, company registers and business data via API in 5 minutes</title>
      <dc:creator>hexadata</dc:creator>
      <pubDate>Thu, 29 Oct 2026 01:44:47 +0000</pubDate>
      <link>https://dev.to/hexadata/public-tenders-company-registers-and-business-data-via-api-in-5-minutes-1iai</link>
      <guid>https://dev.to/hexadata/public-tenders-company-registers-and-business-data-via-api-in-5-minutes-1iai</guid>
      <description>&lt;p&gt;Most of the data that sales, procurement and research teams need already exists in official, free sources: the EU's tender journal, the US federal contracting portal, the UK company register, the US healthcare provider registry, Mexico's statistical business directory. The problem is never access. It is that every source has its own API quirks, pagination caps, encodings and field names, and nobody wants to maintain seven different clients.&lt;/p&gt;

&lt;p&gt;This post shows how we packaged seven of those sources as &lt;a href="https://apify.com/hexadatalabs" rel="noopener noreferrer"&gt;Apify Actors&lt;/a&gt; with one consistent JSON shape, and how to call them from curl, Python, or directly from an AI agent through MCP. Everything below runs against the official sources and is billed per result, so a test costs cents.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is in the box
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Actor&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;th&gt;What you get&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;EU Tenders (TED) Scraper&lt;/td&gt;
&lt;td&gt;TED Search API, no key&lt;/td&gt;
&lt;td&gt;Contract notices and awards by keyword, country, CPV code, date; buyer, deadline, estimated value&lt;/td&gt;
&lt;td&gt;$5.00 / 1,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SAM.gov Opportunities Scraper&lt;/td&gt;
&lt;td&gt;SAM.gov public daily extract, no key&lt;/td&gt;
&lt;td&gt;US federal solicitations, sources sought, awards by keyword, NAICS, set-aside, agency, state&lt;/td&gt;
&lt;td&gt;$5.00 / 1,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;US Healthcare Providers (NPI Registry) Scraper&lt;/td&gt;
&lt;td&gt;NPPES API, no key&lt;/td&gt;
&lt;td&gt;Clinics, hospitals, pharmacies, practices by specialty, city, state, ZIP; address, phone, taxonomy&lt;/td&gt;
&lt;td&gt;$1.50 / 1,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UK Companies House Scraper&lt;/td&gt;
&lt;td&gt;Companies House API, your free key&lt;/td&gt;
&lt;td&gt;Companies and new incorporations by name, SIC code, location, date; profile and officers optional&lt;/td&gt;
&lt;td&gt;$2.00 / 1,000 + $1.00 / 1,000 detail requests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mexico Business Directory (DENUE / INEGI)&lt;/td&gt;
&lt;td&gt;INEGI DENUE API&lt;/td&gt;
&lt;td&gt;5M+ Mexican establishments with activity, size, address, GPS&lt;/td&gt;
&lt;td&gt;$2.00 / 1,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OCC Mundial Jobs Scraper&lt;/td&gt;
&lt;td&gt;occ.com.mx&lt;/td&gt;
&lt;td&gt;Mexican job listings with salary, company, work mode&lt;/td&gt;
&lt;td&gt;$1.50 / 1,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sección Amarilla Mexico Business Scraper&lt;/td&gt;
&lt;td&gt;seccionamarilla.com.mx&lt;/td&gt;
&lt;td&gt;Mexican businesses with phone, WhatsApp, website, hours&lt;/td&gt;
&lt;td&gt;$5.00 / 1,000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three design rules apply to all of them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Same field names.&lt;/strong&gt; &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;title&lt;/code&gt; or &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;url&lt;/code&gt;, &lt;code&gt;country&lt;/code&gt;, &lt;code&gt;publishedAt&lt;/code&gt;, &lt;code&gt;scrapedAt&lt;/code&gt;, and typed values (numbers as numbers, dates in ISO 8601, &lt;code&gt;currency&lt;/code&gt; as its own field, &lt;code&gt;null&lt;/code&gt; instead of empty strings). A tender from TED and an opportunity from SAM.gov land in the same table without mapping.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A hard cost cap.&lt;/strong&gt; &lt;code&gt;maxResults&lt;/code&gt; stops the run at exactly that number, and only items saved to the dataset are charged. Duplicates, invalid rows and failed runs cost nothing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Incremental mode.&lt;/strong&gt; &lt;code&gt;onlyNewSinceLastRun: true&lt;/code&gt; makes the Actor remember what it delivered (a named key-value store in your account), so a daily schedule returns only new tenders, new solicitations or new companies. That is where the recurring value is.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Under the hood each Actor does the boring part: TED's expert query language and 15,000-result window (the Actor switches to iteration mode), SAM.gov's 200 MB Windows-1252 CSV that has to be streamed and stopped early, NPPES's silent 1,200-record cap (the Actor splits the area by ZIP prefix), Companies House's 10,000-result window and 600-requests-per-5-minutes limit (the Actor splits by incorporation date and waits out 429s).&lt;/p&gt;

&lt;h2&gt;
  
  
  1. curl: open tenders for software in Germany
&lt;/h2&gt;

&lt;p&gt;The simplest way is the synchronous endpoint, which runs the Actor and returns the dataset in one call. Get a token from Apify Console (Settings → API &amp;amp; Integrations); a free account includes monthly usage credit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://api.apify.com/v2/acts/hexadatalabs~eu-tenders-ted-scraper/run-sync-get-dataset-items?token=&lt;/span&gt;&lt;span class="nv"&gt;$APIFY_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"searchQueries":["software"],"countries":["DE"],"noticeTypes":"competition","dateFrom":"2026-10-20","maxResults":50}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A typical item:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"745163-2026"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Germany – Software package and information systems – PolBln 423_26 EU Beschaffung Storagesystem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"buyerName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Polizei Berlin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"noticeTypeLabel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Contract notice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"publishedAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-27"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"deadline"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-11-26T07:00:00+01:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"estimatedValue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1680672.27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"currency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"EUR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cpvCodes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"48000000"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://ted.europa.eu/en/notice/-/detail/745163-2026"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fifty results cost $0.25.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Python: a daily feed of new UK companies with their directors
&lt;/h2&gt;

&lt;p&gt;Install the client (&lt;code&gt;pip install apify-client&lt;/code&gt;), create a free Companies House API key (two minutes at developer.company-information.service.gov.uk), and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;apify_client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ApifyClient&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ApifyClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;APIFY_TOKEN&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hexadatalabs/uk-companies-house-scraper&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;apiKey&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;COMPANIES_HOUSE_KEY&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sicCodes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;62012&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;62020&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;        &lt;span class="c1"&gt;# software development, IT consultancy
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;location&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Manchester&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;onlyNewSinceLastRun&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;# first run: everything since 7 days ago; then only new ones
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;includeOfficers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;maxResults&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;defaultDatasetId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;iterate_items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;directors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;officers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;director&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;incorporatedAt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postalCode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;directors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Put the same input on an Apify Schedule (every weekday at 08:00) and add a webhook or an integration (Slack, e-mail, Google Sheets, HubSpot) on the run-succeeded event. Each morning you get the companies incorporated the day before, nothing twice. At about 100 companies a day with officers, that is roughly $0.30 per day.&lt;/p&gt;

&lt;p&gt;The same pattern works for SAM.gov (&lt;code&gt;naicsCodes&lt;/code&gt; + &lt;code&gt;states&lt;/code&gt; + &lt;code&gt;onlyNewSinceLastRun&lt;/code&gt;) and for TED (&lt;code&gt;cpvCodes&lt;/code&gt; + &lt;code&gt;countries&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  3. From an AI agent (MCP)
&lt;/h2&gt;

&lt;p&gt;Every Apify Actor is exposed as a tool by the Apify MCP server, so an agent can call these sources directly. Add the server to Claude Desktop, Cursor, VS Code or any MCP client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hexadata"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://mcp.apify.com?tools=hexadatalabs/eu-tenders-ted-scraper,hexadatalabs/sam-gov-opportunities-scraper,hexadatalabs/us-healthcare-providers-npi-scraper"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"headers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bearer &amp;lt;APIFY_TOKEN&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then ask in plain language:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Which small-business set-aside solicitations for IT services in Virginia or Maryland were posted this week, and when do they close? At most 100 results."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agent calls &lt;code&gt;sam-gov-opportunities-scraper&lt;/code&gt; with &lt;code&gt;{"naicsCodes":["5415"],"setAsides":["SBA"],"states":["VA","MD"],"noticeTypes":"solicitation","dateFrom":"...","maxResults":100}&lt;/code&gt; and answers from the &lt;code&gt;deadline&lt;/code&gt;, &lt;code&gt;setAside&lt;/code&gt; and &lt;code&gt;url&lt;/code&gt; fields. Tool selection works because every Actor description and every input field starts with "Use this when…", which is what the model reads when it picks a tool. Saying "at most N results" in the prompt is the same cost cap as &lt;code&gt;maxResults&lt;/code&gt; in code.&lt;/p&gt;

&lt;p&gt;In Claude Code the same server is one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http hexadata &lt;span class="s2"&gt;"https://mcp.apify.com?tools=hexadatalabs/uk-companies-house-scraper"&lt;/span&gt; &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &amp;lt;APIFY_TOKEN&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What about legality and personal data
&lt;/h2&gt;

&lt;p&gt;All seven Actors read official APIs or public pages within their terms, identify themselves, and pace requests. Personal data is opt-in only: Companies House officers (&lt;code&gt;includeOfficers&lt;/code&gt;), SAM.gov contracting-officer contacts (&lt;code&gt;includeContacts&lt;/code&gt;), NPPES individual practitioners (&lt;code&gt;includeIndividuals&lt;/code&gt;), DENUE business contact fields. By default you get organisations, notices and establishments, with the source attribution in every item.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Each Actor's page on Apify has a "Try for free" input with a cheap prefill, the full field list, cost examples and the MCP snippet: &lt;a href="https://apify.com/hexadatalabs" rel="noopener noreferrer"&gt;apify.com/hexadatalabs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The MCP connection guide and &lt;code&gt;server.json&lt;/code&gt; are in the &lt;a href="https://github.com/4robot/hexadata-mcp" rel="noopener noreferrer"&gt;hexadata-mcp repository&lt;/a&gt;, and the server is listed in the official MCP registry as &lt;code&gt;io.github.4robot/hexadata&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Missing a source (another country's tender portal, another register)? Open an issue on any Actor and say what you need; the next one is usually a clone of an existing one.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>api</category>
      <category>data</category>
      <category>ai</category>
      <category>python</category>
    </item>
  </channel>
</rss>
