# OpenWarrant — Document Verification Suite (remote · www.stipple.sh)

Document forensics: tamper/AI checks, extract, identity, PII, adverse media. No API key needed.

- Trust score: 64/100 (medium)
- Change this week: +4
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-03

## Components

- remote · `www.stipple.sh`: 64/100 (this document), [markdown](https://verifymcp.io/servers/sh-stipple-openwarrant/www.md), [page](https://verifymcp.io/servers/sh-stipple-openwarrant/www)

## Channel facts

- Endpoint: `https://www.stipple.sh/mcp`
- Transports: `streamable-http`
- Auth: `none`
- Version: `0.2.2`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-08-03.

- **Endpoint Security**: 57/100
  - The endpoint's TLS certificate is valid, in date, and uses a strong key.
  - Authorisation not fully verified: no authorisation is required to call this server, and 12 tool(s) never declared a destructiveHint. The MCP spec treats an absent hint as destructive by default, so we cannot call this surface safe.
  - HTTPS is enforced; there's no plaintext access path.
  - HSTS check failed: the Strict-Transport-Security header is absent.
  - DNSSEC check failed: this domain isn't protected by DNSSEC.
- **Transport & Reachability**: 100/100
  - Verified streamable-http transport via a live MCP handshake.
- **Schema Quality & AI Usability**: 76/100
  - 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 3588 tokens (~299/item across 12 items; 12 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 27/100
  - Stability observed for 8 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 71/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 0% of tool parameters carry a description.
  - Structured output schemas are declared (92% of tools); any adoption earns full credit.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### Claude

```bash
claude mcp add --transport http sh-stipple-openwarrant https://www.stipple.sh/mcp
```

### Codex

```toml
[mcp_servers.sh-stipple-openwarrant]
url = "https://www.stipple.sh/mcp"
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "sh-stipple-openwarrant": {
      "type": "remote",
      "url": "https://www.stipple.sh/mcp",
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add sh-stipple-openwarrant --url https://www.stipple.sh/mcp --transport streamable-http
```

### Hermes

```yaml
mcp_servers:
  sh-stipple-openwarrant:
    url: "https://www.stipple.sh/mcp"
```

### Other

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

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-08-02 (score 64, +1)

No change was recorded against any check on this day. Stability & Change Management went from 20 to 23. That category is still filling its 30-day observation window: 6 days of observed history at the previous scan, 7 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-07-31 (score 63, +1)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-30 (score 62, +1)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-29 (score 61, +1)

No change was recorded against any check on this day. Stability & Change Management went from 7 to 10. That category is still filling its 30-day observation window: 2 days of observed history at the previous scan, 3 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-07-27 (score 60, +1)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-26 (score 59)

First indexed and scored.

## MCP tools (12)

### `verify_document` (~350 tokens)

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
    on /mcp-aitext; for "are this report's citations real" use verify_references on /mcp-verify.)

    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.

Input parameters:

- `bytes_b64`
- `filename` (string)
- `fresh` (boolean)
- `url`

### `check_document` (~67 tokens)

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}.

Input parameters:

- `sha256` (string, required)

### `get_warrant` (~131 tokens)

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.

Input parameters:

- `as_markdown` (boolean)
- `warrant_id` (string, required)

### `submit_feedback` (~118 tokens)

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.

Input parameters:

- `note`
- `verdict` (string, required)
- `warrant_id` (string, required)

### `classify_document` (~265 tokens)

Classify a FINANCIAL document's type and issuing country. Specialised in
    financial-services documents: payslip, tax_invoice, bank_statement, salary_certificate,
    payg_summary, receipt.

    USE THIS WHEN someone shares a document (or a link to one) and asks: what kind of
    document is this? is this a payslip / invoice / bank statement? route this document.
    Also use it as the FIRST step before verify_document, so the right checks run.

    Provide the document ONE way: `url` (a public http(s) link to a PDF or image — fetched
    server-side, the cheapest call) OR `bytes_b64` (inline base64, plus `filename` for
    PDF-vs-image routing). Returns `{document_type, country_code, confidence,
    is_financial_document, evidence, ...}`.

    HONEST SCOPE: type classification only — NOT an authenticity or fraud judgment (use
    verify_document for that). Below the confidence threshold it abstains with 'unknown'
    rather than guessing; non-financial documents classify as 'other'. The document is
    never stored.

Input parameters:

- `bytes_b64`
- `filename` (string)
- `url`

### `extract_fields` (~442 tokens)

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; for "what kind of document is this?" classify_document.)

    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.
      - `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).

    Returns `{mode, document_type, fields{name:{value,confidence,page}}, not_found, pages_read,
    page_limit}`. 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). The document is never stored.

Input parameters:

- `bytes_b64`
- `country`
- `fields`
- `filename` (string)
- `max_pages`
- `template`
- `url`

### `verify_identity` (~300 tokens)

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.

Input parameters:

- `documents` (array, required)
- `scheme` (string)

### `check_pack` (~334 tokens)

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
    classify_document; 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.

Input parameters:

- `documents` (array, required)
- `requirements`
- `scheme`

### `redact_pii` (~288 tokens)

Detect and MASK personally identifiable information in a document (PDF or image).

    USE THIS WHEN you need to know what PII a document contains, or to get a redacted copy before
    forwarding / logging / passing it to another model. Two layers: a deterministic regex+checksum
    pass for structured identifiers (emails, payment cards, SSN, PAN, ABN) and a vision model for
    the unstructured PII — names, addresses, dates of birth, phone numbers, and photo/signature
    presence.

    Provide the document ONE way: `url` (a public http(s) link, fetched server-side) or `bytes_b64`
    (inline base64, plus `filename`). `max_pages` caps how many pages are read (default a few;
    ceiling 10).

    Returns `{pii_found, by_type, items[] (type, masked preview, method), redacted_text, has_photo,
    has_signature}`. Values are MASKED in the response — the raw PII is never returned. DETECTION
    coverage, not a guarantee: it may miss PII or over-flag, so review before relying on it for
    compliance. The document is never stored.

Input parameters:

- `bytes_b64`
- `filename` (string)
- `max_pages`
- `url`

### `screen_adverse_media` (~333 tokens)

Screen a person or organisation for ADVERSE MEDIA and SANCTIONS/PEP exposure (KYC/AML).

    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 / politically-exposed-person 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.

Input parameters:

- `aliases`
- `bytes_b64`
- `country`
- `dob`
- `employer`
- `filename` (string)
- `name`
- `role`
- `url`

### `detect_ai_text` (~304 tokens)

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.

Input parameters:

- `bytes_b64`
- `filename` (string)
- `text`
- `url`

### `verify_references` (~405 tokens)

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.

Input parameters:

- `bytes_b64`
- `deep` (boolean)
- `filename` (string)
- `text`
- `url`

## Diagnostics

Captured diagnostic sections: TLS, DNSSEC, Authorisation, Transports. The full working is on the page: https://verifymcp.io/servers/sh-stipple-openwarrant/www#diagnostics

## Score history

- 2026-08-03: 64
- 2026-08-02: 64
- 2026-08-01: 63
- 2026-07-31: 63
- 2026-07-30: 62
- 2026-07-29: 61
- 2026-07-28: 60
- 2026-07-27: 60
- 2026-07-26: 59

## Links

- Remote endpoint: https://www.stipple.sh/mcp
- Repository: https://github.com/Sketchjar/openwarrant
- Changelog RSS feed: https://verifymcp.io/servers/sh-stipple-openwarrant/www/changelog.xml
- Changelog JSON feed: https://verifymcp.io/servers/sh-stipple-openwarrant/www/changelog.json
- HTML version of this page: https://verifymcp.io/servers/sh-stipple-openwarrant/www
