# Stipple — Document Verification & Extraction

> Document forensics: tamper/AI checks, fields, tables, identity, screening, tenders, citations.

- name: sh.stipple/openwarrant
- version: 0.3.1
- connection class: R0 (autonomous)
- trust: 89/100 flags: duplicate-repo
- quality: 77/100 (good)
- owner: not claimed
- descriptor: https://api.protogrid.dev/v1/servers/sh.stipple%2Fopenwarrant
- tools: https://api.protogrid.dev/v1/servers/sh.stipple%2Fopenwarrant/tools

**An agent can connect right now, no human step.** Remote endpoint, no authentication, reachable on the last probe.

## Connection (mcpServers)

```json
{
  "mcpServers": {
    "openwarrant": {
      "type": "http",
      "url": "https://www.stipple.sh/mcp"
    }
  }
}
```


## Trust

- hygiene: 80
- liveness: 100
- freshness: 85
- provenance: 85
- drivers: +repository +dns-namespace +website +reachable +uptime-100% ~updated-52d-ago -duplicate-repo(4 names)
- Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed.

## Quality 77/100 (good)

### protocol: 75 (weight 25)

- warn `protocol.modern`: newest supported version is 2025-11-25; 2026-07-28 not supported, older versions are deprecated until 2027-07-28
- n/a `protocol.stateless`: only applies to 2026-07-28 servers
- pass `protocol.transport`: streamable HTTP
- n/a `protocol.list_ttl`: only applies to 2026-07-28 servers

### authorization: n/a (weight 15)

- n/a `auth.prm`, `auth.as_metadata`, `auth.cimd`: no remote uses OAuth
- n/a `auth.secret_in_url`: no templated URL

### tool hygiene: 79 (weight 30)

- pass `tools.descriptions`: every tool has a description
- warn `tools.description_length`: 12 tools have descriptions over 1,024 characters, which crowds the context
- pass `tools.schemas`: every tool has an object input schema
- pass `tools.annotations`: 16 of 16 tools declare readOnlyHint or destructiveHint
- fail `tools.directory_hints`: no tool declares all four of readOnlyHint, destructiveHint, idempotentHint and openWorldHint; missing: verify_document (destructiveHint, idempotentHint, openWorldHint); check_document (destructiveHint, idempotentHint, openWorldHint); get_warrant (destructiveHint, idempotentHint, openWorldHint); …
- pass `tools.token_cost`: about 7,884 tokens to load every tool
- pass `tools.api_dump`: tools are not a one-to-one API dump

### stability: 75 (weight 15)

- warn `stability.changes`: 10 tool changes in 30 days
- pass `stability.rug_pull`: no tool changed its meaning under the same name

### dependencies: n/a (weight 15)

- n/a `deps.known_vulns`, `deps.mcp_sdk_version`, `deps.resolvable`: no npm or PyPI package

- tools: 16, about 7,884 tokens to load them all
- tool set hash: 0550ce05942bae693afe054e491ff52c
- tools last changed: 2026-10-08T11:38:30.164Z
- badge: [![protogrid quality](https://protogrid.dev/badge/sh.stipple/openwarrant.svg)](https://protogrid.dev/servers/sh.stipple/openwarrant)
- Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed.

### Tool changes

- 2026-10-08 `find_signals` changed (description)
  - before: Signals: what may be tendered before it is. FREE. USE THIS WHEN someone asks what is coming: "which contracts in Queensland end in the next six months", "what is planned for ICT next quarter", "what is expiring for this buyer". `kind` is one of contract_expiry (a contract ending, with its incumbent), planned_procurement (a buyer's stated plan with its quarter and spend band as published) or recurring_tender (derived from our own history, labelled `derived`). `jurisdiction` is one of AU, NZ, AU-NSW, AU-VIC, AU-QLD, AU-WA, AU-SA, AU-TAS, AU-ACT, AU-NT. `window_before` is an ISO date: signals whose window starts on or before it. `q` searches the subject, buyer and incumbent. Returns `{total, results[], computed_at, sources}`. Each signal carries `confidence` (`published` or `derived` - a vocabulary, not a score), its window (never invented: an expiry's window IS the contract's end date; a planned row with no parseable quarter has none), `evidence_ref` and `evidence_url`. ANONYMOUS CALLERS SEE EVERYTHING BUT THE INCUMBENT'S NAME; `withheld_reason` says so - relay it as it is.
  - after: Signals: what may be tendered before it is. FREE. USE THIS WHEN someone asks what is coming: "which contracts in Queensland end in the next six months", "what is planned for ICT next quarter", "what is expiring for this buyer". `kind` is one of contract_expiry (a contract ending, with its incumbent), planned_procurement (a buyer's stated plan with its quarter and spend band as published) or recurring_tender (derived from our own history, labelled `derived`). `jurisdiction` is one of AU, NZ, AU-NSW, AU-VIC, AU-QLD, AU-WA, AU-SA, AU-TAS, AU-ACT, AU-NT. `window_before` is an ISO date: signals whose window starts on or before it. `q` searches the subject, buyer and incumbent. Returns `{total, results[], computed_at, sources}`. Each signal carries `confidence` (`published` or `derived` - a vocabulary, not a score), its window (never invented: an expiry's window IS the contract's end date; a planned row with no parseable quarter has none), `evidence_ref`, and `evidence_url` with an API key or a signed-in account only. ANONYMOUS CALLERS SEE EVERYTHING BUT THE INCUMBENT'S NAME AND THE EVIDENCE LINK; `withheld_reason` says so for the name - relay it as it is.
- 2026-10-08 `buyer_awards` changed (description)
  - before: What a buyer has awarded, what is ending, and what they plan. FREE. USE THIS WHEN someone asks about a specific buyer before a bid: "who holds Transport for NSW's work", "what is ending soon at Queensland Health", "what does this agency usually pay". Give `buyer` (the organisation name as published) or `buyer_key` (from a tender's buyer, or a previous answer). Returns `{buyer, expiring[], planned[], recent_awards[], top_suppliers[], open_tenders[], computed_at, sources}`: the nightly rollup (awards in the window, value quartiles as published, median response window), contracts ending within 12 months with the incumbent, planned procurements with their quarter and spend band, the suppliers who win from them (name and share), and open tenders under the same name. ANONYMOUS CALLERS SEE COUNTS, VALUES, DATES AND BUYERS; supplier and incumbent names are withheld and `withheld_reason` says so. Relay that sentence as it is. Values are the published amount and currency, never converted; `computed_at` is the night the figures are true for - say it. Coverage is Australia and New Zealand sources named in `sources`, each with the attribution its licence requires.
  - after: What a buyer has awarded, what is ending, and what they plan. FREE. USE THIS WHEN someone asks about a specific buyer before a bid: "who holds Transport for NSW's work", "what is ending soon at Queensland Health", "what does this agency usually pay". Give `buyer` (the organisation name as published) or `buyer_key` (from a tender's buyer, or a previous answer). Returns `{buyer, expiring[], planned[], recent_awards[], top_suppliers[], open_tenders[], computed_at, sources}`: the nightly rollup (awards in the window, value quartiles as published, median response window), contracts ending within 12 months with the incumbent, planned procurements with their quarter and spend band, the suppliers who win from them (name and share), and open tenders under the same name. ANONYMOUS CALLERS SEE COUNTS, VALUES, DATES AND BUYERS; supplier and incumbent names are withheld and `withheld_reason` says so. Relay that sentence as it is. Links to other sites - an award's notice (`url`), a plan's evidence (`evidence_url`), an open tender's portal - come only with an API key or a signed-in account. Values are the published amount and currency, never converted; `computed_at` is the night the figures are true for - say it. Coverage is Australia and New Zealand sources named in `sources`, each with the attribution its licence requires.
- 2026-10-08 `tender_sources` changed (description)
  - before: Every source we search, what it is allowed to do, and what the last run returned. FREE. USE THIS WHEN someone asks where the data comes from, whether a particular portal is covered, or why a search came back empty. It is the honesty surface: it names sources behind login walls, sources whose robots.txt refuses us, and sources that returned nothing on the last run and why. Returns `{sources[], coverage}` — per source: id, tag, name, URL, refresh mode, jurisdiction, tier, how it is accessed, what its robots.txt says, how many tenders we hold from it, and its status on the most recent run. Snapshot sources include their observed date and are not presented as nightly feeds.
  - after: Every source we search, what it is allowed to do, and what the last run returned. FREE. USE THIS WHEN someone asks where the data comes from, whether a particular portal is covered, or why a search came back empty. It is the honesty surface: it names sources behind login walls, sources whose robots.txt refuses us, and sources that returned nothing on the last run and why. Returns `{sources[], coverage}` — per source: id, tag, name, refresh mode, jurisdiction, tier, how it is accessed, what its robots.txt says, how many tenders we hold from it, and its status on the most recent run; its URL (`source_url`) with an API key or a signed-in account only. Snapshot sources include their observed date and are not presented as nightly feeds.
- 2026-10-08 `match_tenders` changed (description)
  - before: Rank open tenders against what a company actually does. Free, inside the weekly cap. USE THIS WHEN someone asks which opportunities suit a specific business: "what could we bid for", "is there anything for a civil contractor in Victoria", "find work for acme.com.au". Give `company_url` — a plain domain is fine, we resolve it — and we read their site, build a capability profile, and score the shortlist against it. `example` runs a built-in profile (civil, it, facilities) with no site read, for demonstrating the shape of the answer. Returns `{profile, matched, shown, withheld, withheld_reason, matches[], degraded, score_means, coverage}`. Each match has `score`, `band`, `why[]` — the company's own stated capabilities this tender needs — and `gaps[]`, things the tender asks for that their website does not mention. A tender listed by two sources is one match, with the other copy under `also_listed[]`, its `match` saying the pairing is a heuristic. An anonymous call shows the strongest few and says how many were withheld; relay `withheld_reason` as it is. TELL THE USER WHAT THE SCORE IS: relative fit within these results, against what their website says. NOT a probability of winning. And `gaps` is what to check before bidding, not a list of everything the tender requires — that is in the tender documents. When `degraded` is true, scoring was unavailable and the order is keyword relevance only, with no `why`/`gaps`. Say so rather than presenting it as a judged ranking.
  - after: Rank open tenders against what a company actually does. Free, inside the weekly cap. USE THIS WHEN someone asks which opportunities suit a specific business: "what could we bid for", "is there anything for a civil contractor in Victoria", "find work for acme.com.au". Give `company_url` — a plain domain is fine, we resolve it — and we read their site, build a capability profile, and score the shortlist against it. `example` runs a built-in profile (civil, it, facilities) with no site read, for demonstrating the shape of the answer. Returns `{profile, matched, shown, withheld, withheld_reason, matches[], degraded, score_means, coverage}`. Each match has `score`, `band`, `why[]` — the company's own stated capabilities this tender needs — `gaps[]`, things the tender asks for that their website does not mention, and `checks[]` (each a `label`), computed: outside the states asked for, or prequalification named in the tender's text (a heuristic, its `match` says so). `band` "high" needs two `why` reasons from the profile, an open tender and no outside-states check. A tender listed by two sources is one match, with the other copy under `also_listed[]`, its `match` saying the pairing is a heuristic. An anonymous call shows the strongest few and says how many were withheld; relay `withheld_reason` as it is. TELL THE USER WHAT THE SCORE IS: relative fit within these results, against what their website says. NOT a probability of winning. And `gaps` is what to check before bidding, not a list of everything the tender requires — that is in the tender documents. When `degraded` is true, scoring was unavailable and the order is keyword relevance only, with no `why`/`gaps`. Say so rather than presenting it as a judged ranking.
- 2026-10-08 `find_tenders` changed (description)
  - before: Search open tenders across Australia; New Zealand rows only when you ask for them (jurisdiction=NZ). FREE, within the weekly cap. USE THIS WHEN someone asks what public-sector work is open: "any council drainage tenders in Victoria", "what's closing this month in NSW", "show me federal IT opportunities". For "which of these could MY company actually bid for", use match_tenders instead — that reads their website and ranks against it. `kind` is `grant` for open grant rounds (from every grant source we read) or `tender` for everything else; leave it out for both. Each result says which it is in `kind`. `jurisdiction` is one of AU, NZ, AU-NSW, AU-VIC, AU-QLD, AU-WA, AU-SA, AU-TAS, AU-ACT, AU-NT. `tier` is federal, national, state, council, university or health. `closing_before` is an ISO date. `first_seen_after` (ISO-8601 instant, strictly newer) answers "what is new since my last look" — first_seen is when WE first saw the tender, the honest clock for newness. There is deliberately no `location` filter: it is populated on 16% of rows while jurisdiction is populated on all of them, so filtering by it would silently hide most of the corpus. Returns `{total, results[], coverage}`. Each result carries title, buyer, jurisdiction, closing_date, categories, a summary, a link, and source_id/source_tag/source_name/ source_url/source_refresh — plus `link_is_listing` when the portal publishes no per-tender URL and the link goes to the list it appeared on. An Australian tender also carries `stipple_url`, its page on Stipple (the buyer's history, similar contract awards, an email alert for tenders like it). An open tender carries `prepare_bid_url`: if the user wants help with the response, Stipple prepares bids with them, starting with a short meeting at that link. Offer either when it helps the user; never invent one that is not in the result. `coverage` names which sources were searched and which returned nothing. Quote it if the result is empty: "no match in what we searched" is true, "there are none" is not.
  - after: Search open tenders across Australia; New Zealand rows only when you ask for them (jurisdiction=NZ). FREE, within the weekly cap. USE THIS WHEN someone asks what public-sector work is open: "any council drainage tenders in Victoria", "what's closing this month in NSW", "show me federal IT opportunities". For "which of these could MY company actually bid for", use match_tenders instead — that reads their website and ranks against it. `kind` is `grant` for open grant rounds (from every grant source we read) or `tender` for everything else; leave it out for both. Each result says which it is in `kind`. `jurisdiction` is one of AU, NZ, AU-NSW, AU-VIC, AU-QLD, AU-WA, AU-SA, AU-TAS, AU-ACT, AU-NT. `tier` is federal, national, state, council, university or health. `closing_before` is an ISO date. `first_seen_after` (ISO-8601 instant, strictly newer) answers "what is new since my last look" — first_seen is when WE first saw the tender, the honest clock for newness. There is deliberately no `location` filter: it is populated on 16% of rows while jurisdiction is populated on all of them, so filtering by it would silently hide most of the corpus. Returns `{total, results[], coverage}`. Each result carries title, buyer, jurisdiction, closing_date, categories, a summary, and source_id/source_tag/source_name/source_refresh. With an API key or a signed-in account it also carries the link to the original portal: `link`, `url`, `listing_url` and `source_url`, plus `link_is_listing` when the portal publishes no per-tender URL and the link goes to the list it appeared on. An anonymous call gets no portal link. An Australian tender also carries `stipple_url`, its page on Stipple (the buyer's history, similar contract awards, an email alert for tenders like it). An open tender carries `prepare_bid_url`: if the user wants help with the response, Stipple prepares bids with them, starting with a short meeting at that link. Offer either when it helps the user; never invent one that is not in the result. `coverage` names which sources were searched and which returned nothing. Quote it if the result is empty: "no match in what we searched" is true, "there are none" is not.
- 2026-10-08 `match_tenders` changed (description)
  - before: Rank open tenders against what a company actually does. Free, inside the weekly cap. USE THIS WHEN someone asks which opportunities suit a specific business: "what could we bid for", "is there anything for a civil contractor in Victoria", "find work for acme.com.au". Give `company_url` — a plain domain is fine, we resolve it — and we read their site, build a capability profile, and score the shortlist against it. `example` runs a built-in profile (civil, it, facilities) with no site read, for demonstrating the shape of the answer. Returns `{profile, matched, shown, withheld, withheld_reason, matches[], degraded, score_means, coverage}`. Each match has `score`, `band`, `why[]` — the company's own stated capabilities this tender needs — and `gaps[]`, things the tender asks for that their website does not mention. A tender listed by two sources is one match, with the other copy under `also_listed[]`. An anonymous call shows the strongest few and says how many were withheld; relay `withheld_reason` as it is. TELL THE USER WHAT THE SCORE IS: relative fit within these results, against what their website says. NOT a probability of winning. And `gaps` is what to check before bidding, not a list of everything the tender requires — that is in the tender documents. When `degraded` is true, scoring was unavailable and the order is keyword relevance only, with no `why`/`gaps`. Say so rather than presenting it as a judged ranking.
  - after: Rank open tenders against what a company actually does. Free, inside the weekly cap. USE THIS WHEN someone asks which opportunities suit a specific business: "what could we bid for", "is there anything for a civil contractor in Victoria", "find work for acme.com.au". Give `company_url` — a plain domain is fine, we resolve it — and we read their site, build a capability profile, and score the shortlist against it. `example` runs a built-in profile (civil, it, facilities) with no site read, for demonstrating the shape of the answer. Returns `{profile, matched, shown, withheld, withheld_reason, matches[], degraded, score_means, coverage}`. Each match has `score`, `band`, `why[]` — the company's own stated capabilities this tender needs — and `gaps[]`, things the tender asks for that their website does not mention. A tender listed by two sources is one match, with the other copy under `also_listed[]`, its `match` saying the pairing is a heuristic. An anonymous call shows the strongest few and says how many were withheld; relay `withheld_reason` as it is. TELL THE USER WHAT THE SCORE IS: relative fit within these results, against what their website says. NOT a probability of winning. And `gaps` is what to check before bidding, not a list of everything the tender requires — that is in the tender documents. When `degraded` is true, scoring was unavailable and the order is keyword relevance only, with no `why`/`gaps`. Say so rather than presenting it as a judged ranking.
- 2026-10-08 `find_tenders` changed (description)
  - before: Search open tenders across Australia and New Zealand. FREE, within the weekly cap. USE THIS WHEN someone asks what public-sector work is open: "any council drainage tenders in Victoria", "what's closing this month in NSW", "show me federal IT opportunities". For "which of these could MY company actually bid for", use match_tenders instead — that reads their website and ranks against it. `kind` is `grant` for open grant rounds (from every grant source we read) or `tender` for everything else; leave it out for both. Each result says which it is in `kind`. `jurisdiction` is one of AU, NZ, AU-NSW, AU-VIC, AU-QLD, AU-WA, AU-SA, AU-TAS, AU-ACT, AU-NT. `tier` is federal, national, state, council, university or health. `closing_before` is an ISO date. `first_seen_after` (ISO-8601 instant, strictly newer) answers "what is new since my last look" — first_seen is when WE first saw the tender, the honest clock for newness. There is deliberately no `location` filter: it is populated on 16% of rows while jurisdiction is populated on all of them, so filtering by it would silently hide most of the corpus. Returns `{total, results[], coverage}`. Each result carries title, buyer, jurisdiction, closing_date, categories, a summary, a link, and source_id/source_tag/source_name/ source_url/source_refresh — plus `link_is_listing` when the portal publishes no per-tender URL and the link goes to the list it appeared on. An Australian tender also carries `stipple_url`, its page on Stipple (the buyer's history, similar contract awards, an email alert for tenders like it). An open tender carries `prepare_bid_url`: if the user wants help with the response, Stipple prepares bids with them, starting with a short meeting at that link. Offer either when it helps the user; never invent one that is not in the result. `coverage` names which sources were searched and which returned nothing. Quote it if the result is empty: "no match in what we searched" is true, "there are none" is not.
  - after: Search open tenders across Australia; New Zealand rows only when you ask for them (jurisdiction=NZ). FREE, within the weekly cap. USE THIS WHEN someone asks what public-sector work is open: "any council drainage tenders in Victoria", "what's closing this month in NSW", "show me federal IT opportunities". For "which of these could MY company actually bid for", use match_tenders instead — that reads their website and ranks against it. `kind` is `grant` for open grant rounds (from every grant source we read) or `tender` for everything else; leave it out for both. Each result says which it is in `kind`. `jurisdiction` is one of AU, NZ, AU-NSW, AU-VIC, AU-QLD, AU-WA, AU-SA, AU-TAS, AU-ACT, AU-NT. `tier` is federal, national, state, council, university or health. `closing_before` is an ISO date. `first_seen_after` (ISO-8601 instant, strictly newer) answers "what is new since my last look" — first_seen is when WE first saw the tender, the honest clock for newness. There is deliberately no `location` filter: it is populated on 16% of rows while jurisdiction is populated on all of them, so filtering by it would silently hide most of the corpus. Returns `{total, results[], coverage}`. Each result carries title, buyer, jurisdiction, closing_date, categories, a summary, a link, and source_id/source_tag/source_name/ source_url/source_refresh — plus `link_is_listing` when the portal publishes no per-tender URL and the link goes to the list it appeared on. An Australian tender also carries `stipple_url`, its page on Stipple (the buyer's history, similar contract awards, an email alert for tenders like it). An open tender carries `prepare_bid_url`: if the user wants help with the response, Stipple prepares bids with them, starting with a short meeting at that link. Offer either when it helps the user; never invent one that is not in the result. `coverage` names which sources were searched and which returned nothing. Quote it if the result is empty: "no match in what we searched" is true, "there are none" is not.
- 2026-10-05 `match_tenders` changed (description)
  - before: Rank open tenders against what a company actually does. Free, inside the weekly cap. USE THIS WHEN someone asks which opportunities suit a specific business: "what could we bid for", "is there anything for a civil contractor in Victoria", "find work for acme.com.au". Give `company_url` — a plain domain is fine, we resolve it — and we read their site, build a capability profile, and score the shortlist against it. `example` runs a built-in profile (civil, it, facilities) with no site read, for demonstrating the shape of the answer. Returns `{profile, matched, shown, withheld, withheld_reason, matches[], degraded, score_means, coverage}`. Each match has `score`, `band`, `why[]` — the company's own stated capabilities this tender needs — and `gaps[]`, things the tender asks for that their website does not mention. An anonymous call shows the strongest few and says how many were withheld; relay `withheld_reason` as it is. TELL THE USER WHAT THE SCORE IS: relative fit within these results, against what their website says. NOT a probability of winning. And `gaps` is what to check before bidding, not a list of everything the tender requires — that is in the tender documents. When `degraded` is true, scoring was unavailable and the order is keyword relevance only, with no `why`/`gaps`. Say so rather than presenting it as a judged ranking.
  - after: Rank open tenders against what a company actually does. Free, inside the weekly cap. USE THIS WHEN someone asks which opportunities suit a specific business: "what could we bid for", "is there anything for a civil contractor in Victoria", "find work for acme.com.au". Give `company_url` — a plain domain is fine, we resolve it — and we read their site, build a capability profile, and score the shortlist against it. `example` runs a built-in profile (civil, it, facilities) with no site read, for demonstrating the shape of the answer. Returns `{profile, matched, shown, withheld, withheld_reason, matches[], degraded, score_means, coverage}`. Each match has `score`, `band`, `why[]` — the company's own stated capabilities this tender needs — and `gaps[]`, things the tender asks for that their website does not mention. A tender listed by two sources is one match, with the other copy under `also_listed[]`. An anonymous call shows the strongest few and says how many were withheld; relay `withheld_reason` as it is. TELL THE USER WHAT THE SCORE IS: relative fit within these results, against what their website says. NOT a probability of winning. And `gaps` is what to check before bidding, not a list of everything the tender requires — that is in the tender documents. When `degraded` is true, scoring was unavailable and the order is keyword relevance only, with no `why`/`gaps`. Say so rather than presenting it as a judged ranking.
- 2026-10-03 `find_tenders` changed (description)
  - before: Search open tenders across Australia and New Zealand. FREE, within the weekly cap. USE THIS WHEN someone asks what public-sector work is open: "any council drainage tenders in Victoria", "what's closing this month in NSW", "show me federal IT opportunities". For "which of these could MY company actually bid for", use match_tenders instead — that reads their website and ranks against it. `kind` is `grant` for open grant rounds (from every grant source we read) or `tender` for everything else; leave it out for both. Each result says which it is in `kind`. `jurisdiction` is one of AU, NZ, AU-NSW, AU-VIC, AU-QLD, AU-WA, AU-SA, AU-TAS, AU-ACT, AU-NT. `tier` is federal, national, state, council, university or health. `closing_before` is an ISO date. `first_seen_after` (ISO-8601 instant, strictly newer) answers "what is new since my last look" — first_seen is when WE first saw the tender, the honest clock for newness. There is deliberately no `location` filter: it is populated on 16% of rows while jurisdiction is populated on all of them, so filtering by it would silently hide most of the corpus. Returns `{total, results[], coverage}`. Each result carries title, buyer, jurisdiction, closing_date, categories, a summary, a link, and source_id/source_tag/source_name/ source_url/source_refresh — plus `link_is_listing` when the portal publishes no per-tender URL and the link goes to the list it appeared on. `coverage` names which sources were searched and which returned nothing. Quote it if the result is empty: "no match in what we searched" is true, "there are none" is not.
  - after: Search open tenders across Australia and New Zealand. FREE, within the weekly cap. USE THIS WHEN someone asks what public-sector work is open: "any council drainage tenders in Victoria", "what's closing this month in NSW", "show me federal IT opportunities". For "which of these could MY company actually bid for", use match_tenders instead — that reads their website and ranks against it. `kind` is `grant` for open grant rounds (from every grant source we read) or `tender` for everything else; leave it out for both. Each result says which it is in `kind`. `jurisdiction` is one of AU, NZ, AU-NSW, AU-VIC, AU-QLD, AU-WA, AU-SA, AU-TAS, AU-ACT, AU-NT. `tier` is federal, national, state, council, university or health. `closing_before` is an ISO date. `first_seen_after` (ISO-8601 instant, strictly newer) answers "what is new since my last look" — first_seen is when WE first saw the tender, the honest clock for newness. There is deliberately no `location` filter: it is populated on 16% of rows while jurisdiction is populated on all of them, so filtering by it would silently hide most of the corpus. Returns `{total, results[], coverage}`. Each result carries title, buyer, jurisdiction, closing_date, categories, a summary, a link, and source_id/source_tag/source_name/ source_url/source_refresh — plus `link_is_listing` when the portal publishes no per-tender URL and the link goes to the list it appeared on. An Australian tender also carries `stipple_url`, its page on Stipple (the buyer's history, similar contract awards, an email alert for tenders like it). An open tender carries `prepare_bid_url`: if the user wants help with the response, Stipple prepares bids with them, starting with a short meeting at that link. Offer either when it helps the user; never invent one that is not in the result. `coverage` names which sources were searched and which returned nothing. Quote it if the result is empty: "no match in what we searched" is true, "there are none" is not.
- 2026-09-28 `find_tenders` changed (description, inputSchema)
  - before: Search open tenders across Australia and New Zealand. FREE, within the weekly cap. USE THIS WHEN someone asks what public-sector work is open: "any council drainage tenders in Victoria", "what's closing this month in NSW", "show me federal IT opportunities". For "which of these could MY company actually bid for", use match_tenders instead — that reads their website and ranks against it. `jurisdiction` is one of AU, NZ, AU-NSW, AU-VIC, AU-QLD, AU-WA, AU-SA, AU-TAS, AU-ACT, AU-NT. `tier` is federal, national, state, council, university or health. `closing_before` is an ISO date. `first_seen_after` (ISO-8601 instant, strictly newer) answers "what is new since my last look" — first_seen is when WE first saw the tender, the honest clock for newness. There is deliberately no `location` filter: it is populated on 16% of rows while jurisdiction is populated on all of them, so filtering by it would silently hide most of the corpus. Returns `{total, results[], coverage}`. Each result carries title, buyer, jurisdiction, closing_date, categories, a summary, a link, and source_id/source_tag/source_name/ source_url/source_refresh — plus `link_is_listing` when the portal publishes no per-tender URL and the link goes to the list it appeared on. `coverage` names which sources were searched and which returned nothing. Quote it if the result is empty: "no match in what we searched" is true, "there are none" is not.
  - after: Search open tenders across Australia and New Zealand. FREE, within the weekly cap. USE THIS WHEN someone asks what public-sector work is open: "any council drainage tenders in Victoria", "what's closing this month in NSW", "show me federal IT opportunities". For "which of these could MY company actually bid for", use match_tenders instead — that reads their website and ranks against it. `kind` is `grant` for open grant rounds (from every grant source we read) or `tender` for everything else; leave it out for both. Each result says which it is in `kind`. `jurisdiction` is one of AU, NZ, AU-NSW, AU-VIC, AU-QLD, AU-WA, AU-SA, AU-TAS, AU-ACT, AU-NT. `tier` is federal, national, state, council, university or health. `closing_before` is an ISO date. `first_seen_after` (ISO-8601 instant, strictly newer) answers "what is new since my last look" — first_seen is when WE first saw the tender, the honest clock for newness. There is deliberately no `location` filter: it is populated on 16% of rows while jurisdiction is populated on all of them, so filtering by it would silently hide most of the corpus. Returns `{total, results[], coverage}`. Each result carries title, buyer, jurisdiction, closing_date, categories, a summary, a link, and source_id/source_tag/source_name/ source_url/source_refresh — plus `link_is_listing` when the portal publishes no per-tender URL and the link goes to the list it appeared on. `coverage` names which sources were searched and which returned nothing. Quote it if the result is empty: "no match in what we searched" is true, "there are none" is not.

Full history: https://api.protogrid.dev/v1/servers/sh.stipple%2Fopenwarrant/changes

## Remotes

- https://www.stipple.sh/mcp (streamable-http, auth none, reachable true, uptime30d 1)

## Packages

_none_

## Tools (16)

- `buyer_awards`: What a buyer has awarded, what is ending, and what they plan. FREE.

USE THIS WHEN someone asks about a specific buyer before a bid: "who holds Transport for
NSW's work", "what is ending soon at Queensland Health", "what does this agency usually
pay". Give `buyer` (the organisation name as published) or `buyer_key` (from a tender's
buyer, or a previous answer).

Returns `{buyer, expiring[], planned[], recent_awards[], top_suppliers[], open_tenders[],
computed_at, sources}`: the nightly rollup (awards in the window, value quartiles as
published, median response window), contracts ending within 12 months with the incumbent,
planned procurements with their quarter and spend band, the suppliers who win from them
(name and share), and open tenders under the same name.

ANONYMOUS CALLERS SEE COUNTS, VALUES, DATES AND BUYERS; supplier and incumbent names are
withheld and `withheld_reason` says so. Relay that sentence as it is. Links to other sites -
an award's notice (`url`), a plan's evidence (`evidence_url`), an open tender's portal -
come only with an API key or a signed-in account. Values are the
published amount and currency, never converted; `computed_at` is the night the figures
are true for - say it. Coverage is Australia and New Zealand sources named in
`sources`, each with the attribution its licence requires.

- `check_document`: Cheap cache-check: has this exact document already been inspected? Hash the file
    yourself (sha256, lowercase hex) and call this before verify_document to skip a redundant
    (paid) inspection. Returns {cached, warrant_id, permalink}.
- `check_pack`: Check whether a SET of documents satisfies a checklist — completeness, cheaply.

    USE THIS WHEN you have an application / onboarding pack and need "do we have the required
    documents, and what's still missing?" Each document is CLASSIFIED (one cheap page-1 read —
    never full field extraction or multi-page), then matched against the checklist's required
    slots. (For "is a document genuine?" use verify_document; to identify ONE document use
    extract_fields with options={"classify": true}; for the identity gate use verify_identity.)

    Define the checklist ONE of two ways:
      - `scheme`: a named preset — "income_proof", "lending_prequal", "rental_application".
      - `requirements`: an ad-hoc checklist — a list of document-type names like
        ["payslip","bank_statement"], or objects {"key":..., "accepts":[types], "optional":bool}.

    `documents` is a list (up to 12), each ONE of: {"url": "https://..."} (public link, fetched
    server-side) or {"bytes_b64": "...", "filename": "statement.pdf"} (inline).

    Returns `{complete, slots[] (key, satisfied, matched), missing[], documents[] (filename,
    classified_type), unmatched_documents[]}`. COVERAGE, not approval — that the right document
    TYPES are present, NOT that any is genuine (run verify_document) or that an application is
    approved. Documents are never stored.
    
- `check_source_overlap`: Check whether text OVERLAPS text published on the public web — a plagiarism-style
    check: does this text appear elsewhere? was this copied? find the source of this text.

    Provide the document ONE way: `text` (pasted prose), `url` (a public http(s) link —
    fetched server-side; that page and its host are excluded from matches), OR `bytes_b64`
    (a base64 PDF/.docx/text file, plus `filename` for routing).

    Returns two evidence tiers, never mixed: `matches` are EXACT/near-verbatim overlaps
    confirmed against the fetched source page — each carries the quoted text from both
    sides, the source URL, and char spans for highlighting. `possible_paraphrases` are
    model JUDGEMENTS (reworded overlap), clearly labelled, never quotes, and alone they
    cap the overlap band at "low". `overlap_band` summarises: none | low | notable | high.

    HONEST SCOPE: this searches the PUBLIC WEB within capped queries — it is not an
    academic-database check, absence of matches is never an originality certificate, and
    overlap says nothing about who published first or intent. Plagiarism is a judgement
    this tool never makes. English-language prose only; non-prose and unsupported
    languages abstain (`applicable: false`). Free within the weekly cap.
    
- `detect_ai_text`: Estimate the PROBABILITY that a document's text was AI-GENERATED (LLM-written prose).

    USE THIS WHEN someone shares prose — an essay, cover letter, article, review, application,
    or report (or a link to one) — and asks: did an AI / ChatGPT write this? is this
    human-written? detect AI text.

    Provide the document ONE way: `text` (pasted markdown/plain prose), `url` (a public http(s)
    link to a page or PDF — fetched server-side, the cheapest call), OR `bytes_b64` (a base64
    PDF/file, plus `filename` for routing). Returns
    `{probability, lean, tells, reasoning, applicable}`.

    HONEST SCOPE: the probability is the model's CONFIDENCE, not a calibrated truth — it can
    false-flag templated/coached or non-native-English writing. It works on PROSE only: for a
    form/table/numeric document (payslip, statement) it returns `applicable: false` and abstains,
    because AI-text detection false-positives badly there — use `verify_document` (the
    authenticity engine) for those, and `verify_references` to check a doc's citations/claims.
    
- `extract_fields`: Extract structured FIELDS from a document (PDF or image) with a vision model.

    USE THIS WHEN you need specific values OUT of a document — a payslip's gross/net, an invoice's
    total/ABN, a form's checkboxes, a table's cells — rather than a yes/no about the document. (For
    "is this genuine?" use verify_document; "what kind of document is this?" is
    `options={"classify": true}` right here.)

    Say WHAT to pull, four ways:
      - `fields`: an ad-hoc list — names like ["gross_pay","abn"], or objects
        {"name":..., "type":"text|amount|date|boolean", "description":...}. THE general case: ask
        for exactly the fields your task needs. Use type "boolean" for a checkbox/tickbox.
        `"question"` works instead of `"description"` if you would rather just ask:
        {"name":"customer_name", "question":"What is the customer name?"}.
      - `template`: a named preset — "payslip", "tax_invoice", "bank_statement", "receipt".
      - NEITHER: AUTO — the document is classified and that type's fields are used.
      - auto on an unrecognised type: schema-free — every labelled field is returned.

    Provide the document ONE way: `url` (a public http(s) link — fetched server-side, the cheapest
    call) OR `bytes_b64` (inline base64, plus `filename` for PDF-vs-image routing). `country` is an
    optional hint; `max_pages` caps how many pages are read (default a few; hard ceiling 10).

    `options` turns on extra capabilities. Every one defaults OFF, and asking for one that this
    server does not support is an ERROR naming it — never a silent no-op, so you can always tell
    "asked wrongly" from "nothing found". Available today:
      - `{"grounding": true}` — every value gains `bbox` (the rectangle it was read from, in PDF
        points, origin top-left) and `text_layer_match`. Use it to CITE a value back to the page.
        Born-digital PDFs only for now; a scan returns `bbox: null` and `grounding: "none"`.
      - `{"flag_below": 0.7}` — adds `needs_review`, the fields under that confidence, weakest
        first. Use it to route the doubtful ones to a human instead of checking everything.
      - `{"tables": true}` — adds `tables`: whole tables with their rows. On a PDF these are
        read from the document's own rules and coordinates (exact cells, merged-cell colspans,
        no model call and NO CREDIT for the table pass); on a scan the model reads the rows and
        the table says `source: "vlm"` with no cell geometry. `{"tables": {"formats":
        ["json","markdown","html"], "borderless": true, "cells": true}}` to tune it.
      - `{"classify": true}` — adds `classification`: the full verdict (type, country,
        confidence, evidence), not just the routing. Free in auto mode.
      - `{"redact": true}` — adds `pii` (a MASKED inventory) and `redacted_text`, so you can
        extract and check for personal data in ONE call. A field you NAMED is still returned in
        full; the inventory never is. Two things to know before turning it on: `redacted_text`
        is the document's WHOLE text body with detected PII replaced — for a PDF that means
        every page, not just the ones `max_pages` covers — and redaction is best-effort
        coverage, so anything it failed to detect stays in that text verbatim. It also costs
        an extra page-equivalent per page, because it is a second model pass.
      - `{"layout": true}` — adds `layout.blocks`: every text block with its role
        (heading/body), font, size, column and reading order. Born-digital PDFs only; free.
      - `{"links": true}` — adds `links`: the PDF's own link annotations with uri, anchor
        text and bbox. Free. A URL merely PRINTED on the page is not an annotation.
      - `{"figures": true}` — adds `figures`: where the embedded images sit (bbox and pixel
        size), never the bytes. Free.
      - `{"chunks": true}` — adds `chunks`: retrieval-ready pieces that carry provenance a
        text splitter cannot give you — `heading_path` (where in the document), `bbox` and
        page range (citable back to the page), tables never sliced. Six strategies via
        `{"chunks": {"strategy": "section|page|chars|recursive|element|hierarchical",
        "max_chars": 1500, "min_chars": 200, "overlap": 100, "include_headings": true}}`.
        `hierarchical` adds parent context chunks for small-to-big retrieval. Born-digital
        PDFs only; free.
      - `{"split": true}` — adds `documents`: the page ranges of the distinct documents in
        one file (a bundle of 3 stapled PDFs -> 3 entries with types). One classifier call
        per page, so it costs +1 page-equivalent per page read.
    `render_scale` (one of 1.0, 1.5, 2.0, 3.0, 4.0; default 2.0) raises rasterisation for small or
    dense print. Call `GET /v1/extract/capabilities` for the full machine-readable list.

    COST: 1 credit per page read, minimum 1 — with `fields` or a `template` given, a one-page
    receipt costs 1 and a ten-page statement costs 10; AUTO mode adds 1 for the routing
    classification. Options that add model reads add page-equivalents (`redact` +pages, `split`
    +pages replacing the auto/classify +1, `tables` +pages only on a scan); deterministic work
    is free, and an encrypted PDF is charged the one-page floor only. Pages charged is
    min(`max_pages`, the document's real length), resolved before the call runs, so you can
    predict the price. Set `max_pages` to cap your spend on a long document.
    CAPABILITY-ONLY: `options.classify` and/or `options.redact` with no `fields`, no
    `template` and no other option skips field extraction entirely — classify-only costs
    1 credit and redact-only 1 per page, exactly what the retired classify_document and
    redact_pii tools charged.

    Returns `{mode, document_type, fields{name:{value,confidence,page}}, not_found, pages_read,
    page_limit, page_count}`. `page_count` is the document's real length, so you can see when
    `max_pages` truncated it. EXTRACTION, not verification — values are what the document SHOWS,
    not proof it is genuine. A field that isn't clearly present comes back in `not_found` (it
    abstains rather than guessing).

    `text_layer_match` is `exact` / `normalised` when the printed value was located on the page,
    `multiple` when the same string appears more than once (no box — we will not guess which), and
    `absent` when it is not there. It reports whether the string was FOUND, not that the value is
    correct. The document is never stored.
    
- `find_signals`: Signals: what may be tendered before it is. FREE.

USE THIS WHEN someone asks what is coming: "which contracts in Queensland end in the next
six months", "what is planned for ICT next quarter", "what is expiring for this buyer".
`kind` is one of contract_expiry (a contract ending, with its incumbent),
planned_procurement (a buyer's stated plan with its quarter and spend band as published)
or recurring_tender (derived from our own history, labelled `derived`). `jurisdiction`
is one of AU, NZ, AU-NSW, AU-VIC, AU-QLD, AU-WA, AU-SA, AU-TAS, AU-ACT, AU-NT. `window_before` is an ISO date: signals whose
window starts on or before it. `q` searches the subject, buyer and incumbent.

Returns `{total, results[], computed_at, sources}`. Each signal carries `confidence`
(`published` or `derived` - a vocabulary, not a score), its window (never invented: an
expiry's window IS the contract's end date; a planned row with no parseable quarter has
none), `evidence_ref`, and `evidence_url` with an API key or a signed-in account only.
ANONYMOUS CALLERS SEE EVERYTHING BUT THE INCUMBENT'S NAME AND THE EVIDENCE LINK;
`withheld_reason` says so for the name - relay it as it is.

- `find_tenders`: Search open tenders across Australia; New Zealand rows only
when you ask for them (jurisdiction=NZ). FREE, within the weekly cap.

USE THIS WHEN someone asks what public-sector work is open: "any council drainage
tenders in Victoria", "what's closing this month in NSW", "show me federal IT
opportunities". For "which of these could MY company actually bid for", use
match_tenders instead — that reads their website and ranks against it.

`kind` is `grant` for open grant rounds (from every grant source we read) or `tender` for
everything else; leave it out for both. Each result says which it is in `kind`.
`jurisdiction` is one of AU, NZ, AU-NSW, AU-VIC, AU-QLD, AU-WA, AU-SA, AU-TAS, AU-ACT, AU-NT. `tier` is federal, national,
state, council, university or health. `closing_before` is an ISO date.
`first_seen_after` (ISO-8601 instant, strictly newer) answers "what is new since my last
look" — first_seen is when WE first saw the tender, the honest clock for newness. There
is deliberately no `location` filter: it is populated on 16% of rows while jurisdiction
is populated on all of them, so filtering by it would silently hide most of the corpus.

Returns `{total, results[], coverage}`. Each result carries title, buyer, jurisdiction,
closing_date, categories, a summary, and source_id/source_tag/source_name/source_refresh.
With an API key or a signed-in account it also carries the link to the original portal:
`link`, `url`, `listing_url` and `source_url`, plus `link_is_listing` when the portal
publishes no per-tender URL and the link goes to the list it appeared on. An anonymous
call gets no portal link.

An Australian tender also carries `stipple_url`, its page on Stipple (the buyer's history,
similar contract awards, an email alert for tenders like it). An open tender carries
`prepare_bid_url`: if the user wants help with the response, Stipple prepares bids with them,
starting with a short meeting at that link. Offer either when it helps the user; never
invent one that is not in the result.

`coverage` names which sources were searched and which returned nothing. Quote it if
the result is empty: "no match in what we searched" is true, "there are none" is not.

- `get_warrant`: Retrieve a stored warrant by id (e.g. 'warrant_<hex>') — the full bundle as JSON, or a
    human-readable Markdown report when as_markdown=True.

    USE THIS WHEN you have a warrant_id from an earlier verify_document / check_document call
    and need the FULL evidence — every signal that fired, per-page findings, provenance — rather
    than the summary the original call returned. Use as_markdown=True to get a report you can
    show a human verbatim.
- `match_tenders`: Rank open tenders against what a company actually does. Free, inside the weekly cap.

    USE THIS WHEN someone asks which opportunities suit a specific business: "what could we
    bid for", "is there anything for a civil contractor in Victoria", "find work for
    acme.com.au". Give `company_url` — a plain domain is fine, we resolve it — and we read
    their site, build a capability profile, and score the shortlist against it.

    `example` runs a built-in profile (civil, it, facilities) with no site read, for
    demonstrating the shape of the answer.

    Returns `{profile, matched, shown, withheld, withheld_reason, matches[], degraded,
    score_means, coverage}`. Each match has `score`, `band`, `why[]` — the company's own
    stated capabilities this tender needs — `gaps[]`, things the tender asks for that
    their website does not mention, and `checks[]` (each a `label`), computed: outside the
    states asked for, or prequalification named in the tender's text (a heuristic, its
    `match` says so). `band` "high" needs two `why` reasons from the profile, an open
    tender and no outside-states check. A tender listed by two sources is one match, with the
    other copy under `also_listed[]`, its `match` saying the pairing is a heuristic. An
    anonymous call shows the strongest few and says how many were withheld; relay
    `withheld_reason` as it is.

    TELL THE USER WHAT THE SCORE IS: relative fit within these results, against what their
    website says. NOT a probability of winning. And `gaps` is what to check before bidding,
    not a list of everything the tender requires — that is in the tender documents.

    When `degraded` is true, scoring was unavailable and the order is keyword relevance
    only, with no `why`/`gaps`. Say so rather than presenting it as a judged ranking.
    
- `screen_adverse_media`: Screen a person or organisation for ADVERSE MEDIA and SANCTIONS exposure (KYC/AML).
    PEP lists are not screened: `sanctions.flags.pep` is always false and `sanctions.note` says so.

    USE THIS WHEN onboarding or due-diligence asks: does this subject appear in negative news
    (fraud, money laundering, bribery, sanctions, trafficking, enforcement action), or on a
    sanctions list? Pairs naturally after verify_identity.

    Identify the subject ONE of two ways: pass `name` (plus any of `dob` as YYYY-MM-DD, `country`,
    `aliases`, `employer`, `role` — these sharpen matching and cut same-name false positives), OR
    pass an identity document via `url`/`bytes_b64` (+`filename`) and the subject is read from it.

    Returns `{subject, sanctions{...}, adverse_media{...}, risk_flag, headline, limitations}`:
    sanctions candidates are corroboration-gated (a name-only hit is `possible`, NEVER confirmed —
    one common name matches several different people); media hits are entity-disambiguated and
    classified, with same-name articles surfaced under `excluded`. This is screening COVERAGE, not a
    determination — a hit means "review this", not "guilty"; "nothing found" is not a clean record.
    Stateless — nothing is stored.
    
- `submit_feedback`: Record thumbs up/down on a warrant's rating (the engine's precision-flywheel label
    source). verdict must be 'up' or 'down'; note is optional free text.

    USE THIS WHEN the ground truth became known after a verify_document call — e.g. the
    document was later confirmed genuine or fraudulent — so the engine learns from the
    outcome. Tell it what happened; it sharpens future inspections for everyone.
- `tender_sources`: Every source we search, what it is allowed to do, and what the last run returned.
    FREE.

    USE THIS WHEN someone asks where the data comes from, whether a particular portal is
    covered, or why a search came back empty. It is the honesty surface: it names sources
    behind login walls, sources whose robots.txt refuses us, and sources that returned
    nothing on the last run and why.

    Returns `{sources[], coverage}` — per source: id, tag, name, refresh mode,
    jurisdiction, tier, how it is accessed, what its robots.txt says, how many tenders we
    hold from it, and its status on the most recent run; its URL (`source_url`) with an API
    key or a signed-in account only. Snapshot sources include their observed date and are
    not presented as nightly feeds.
    
- `verify_document`: Forensically inspect a document (PDF or image) for authenticity: tampering signs,
    AI-generation indicators, arithmetic reconciliation (financial docs), and provenance.

    USE THIS WHEN someone shares a payslip, bank statement, invoice, receipt, ID, certificate,
    or contract and asks: is this genuine / real / authentic? has it been edited, doctored, or
    photoshopped? can I trust this file? (For "did an AI *write* this prose" use
    `detect_ai_text`; for "are this report's citations real" use `verify_references`. Both are
    available in this canonical suite.)

    Provide the document ONE way: `url` (a public http(s) link — fetched server-side, the
    cheapest call: no need to download or encode anything) OR `bytes_b64` (inline base64, plus
    `filename` so PDF-vs-image routing is right).

    Returns the headline result — `risk_band` (low/medium/high/insufficient/error),
    `inspection_quality` (coverage, orthogonal to risk), `recommended_action`, a `summary`, the
    RISK-axis `risk_findings`, and a shareable `permalink`. This is a SIGNAL, not a fraud
    verdict — a human or agent adjudicates. Use `get_warrant(warrant_id)` for the full evidence
    bundle. Identical bytes are cached by content hash — `check_document` first skips a
    redundant, paid inspection.
    
- `verify_identity`: Run an Australian identity check over a SET of identity documents. A vision model reads
    each document (which ID it is, which fields it shows — name/photo/address/signature — and its
    issue date); a deterministic engine then tallies them against a scheme and reports whether
    identity is established, and exactly what's still missing if not.

    USE THIS WHEN someone needs to verify a person's identity from their documents — KYC /
    onboarding / "do these documents satisfy the 100-point check?" Pass ALL the person's
    documents together (a passport alone is 70 points; the check needs >= 100).

    `documents` is a list, each item ONE of: {"url": "https://..."} (public link, fetched
    server-side) or {"bytes_b64": "...", "filename": "passport.pdf"} (inline). Up to 10.
    `scheme`: "afp_100_point" (points, default) or "austrac_safe_harbour" (category combinations).

    Returns `{established, points/target or satisfied_path, documents[] (per-document: type,
    fields shown, whether it counted and why-not), reason, accepts, ...}`. This is identity
    COVERAGE, not a forgery judgment — run verify_document for authenticity. Documents are
    never stored.
    
- `verify_references`: Fact-check a document's REFERENCES and CLAIMS — built for AI-generated reports whose
    citations must be checked before they're trusted.

    USE THIS WHEN someone shares a report, article, whitepaper, or deep-research export (or a
    link to one) and asks: is this accurate / legit? are these citations real? fact-check this.
    did the AI make this up? Also use it proactively before relying on any AI-written document.

    Provide the document ONE way: `url` (a public http(s) link to a PDF or web page — fetched
    server-side, the cheapest call: no need to download or encode anything), `text` (pasted
    markdown/plain prose), OR `bytes_b64` (a base64 PDF; URLs are read from the PDF's link
    annotations, so they're exact). Default (fast): provenance (is it a ChatGPT deep-research
    export?), citation resolution (live / archived / dead, papers matched against arXiv/Crossref
    to catch 'real ID, wrong paper'), and internal MATH (recompute the doc's own arithmetic).
    Set `deep=true` to also fetch each cited source and judge whether it SUPPORTS or CONTRADICTS
    the claim (slower, ~a minute).

    Returns a trust summary, per-item tables, and a shareable `permalink` to the public
    fact-check record. HONEST BOUNDARY: this reports verification COVERAGE, not truth —
    'supported' means evidence-backed (not necessarily true) and 'unsupported' means no evidence
    found (not necessarily false). It tells a reviewer WHERE to look; it does not bless the
    document, and it never affects the fraud risk band.
    
