Endpoints: 28,729MCP servers: 18,414Payout addresses: 2,071Paid calls: 1,566Letters: 14Defects: 1,338counted just now
teppi

Server definition

Hash
sha256:cbb3f032e43dd0c4ef299af8bd4063d23e3a1b938e8e98687e0cb6d42221eaff
What it is
What a remote MCP server returned when asked what it offers: 101 tools

The blob, as servednamed by its sha256

{ "instructions": "TunnelMind Data API — surveillance intelligence. Use search() to find domains/entities, get_domain() for full records, intel_* for live probes. Pass Authorization: Bearer <key> for authenticated access. The tunnelmind_analyst prompt (prompts/get) returns the full BYOM config bundle to configure any LLM as a TunnelMind analyst.", "tools": [ { "description": "P75 registry aggregation: the cross-lens join applied to agent identity.\nIncumbent providers each consult only their own registry; this endpoint\nchecks every registry TunnelMind can reach and labels each answer with\nan explicit state, so a gap can never be mistaken for a clean result:\n\n- `observed` — the subject IS in this registry (record attached)\n- `not_present` — checked, and it isn't (an observation, not a gap)\n- `not_applicable` — the registry doesn't key on this subject type\n- `degraded` — the check failed (timeout, upstream error)\n- `unavailable` — the registry is not publicly consultable (closed /\n platform-scoped); stated in-band because silence would read as clean\n\nRegistries (v0): `crawler_ranges` (operator-published IP feeds —\nGooglebot, GPTBot, PerplexityBot…), `wba_directory` (RFC 9421\nSignature-Agent JWKS at the subject domain), `mcp_registry`\n(registry.modelcontextprotocol.io), `tunnelmind_known_agents` (curated\nverifiable/claim-only set), plus honest `unavailable` rows for Visa TAP,\nMastercard Agent Pay, and Cloudflare Verified Bots.\n\nUse this tool when:\n- You are deciding whether an agent, bot, or MCP server is registered\n anywhere that vouches for it — in one call instead of five.\n- You need the blind spots stated: which registries could NOT be\n consulted for this subject, and why.\n\nInputs: subject — an IP (registry membership by published ranges), a\ndomain (WBA directory + MCP registry), or an agent name/UA fragment\n(e.g. `gptbot`, `claudebot`). `?receipt=true` attaches a signed\nReceipt v1.0 committed to the transparency log.\n\nLatency: remote registry checks are KV-cached for 1h; a warm call is\nedge-fast, a cold one bounded by 5s per-registry timeouts.\n", "inputSchema": { "properties": { "receipt": { "description": "Attach a signed TunnelMind Receipt v1.0 over the aggregation.", "enum": [ "true" ], "type": "string" }, "subject": { "description": "IP address, domain, or agent name / User-Agent fragment.", "type": "string" } }, "required": [ "subject" ], "type": "object" }, "name": "agent_registries_lookup", "outputSchema": null }, { "description": "P73 fast attributes endpoint (PIP-PLAN P3): a full `POST /v1/verify`\nresolve fans out across four lenses (~2s) — fine for preflight, fatal\ninside a per-request authorization loop. This endpoint serves the\nlast-known signed bundle from a single KV read, with the P69 freshness\ncontract deciding how much to trust it.\n\nUse this tool when:\n- A policy decision point (OPA, Cerbos, Cedar) needs node attributes\n on its hot path and can tolerate `valid_until`-bounded staleness.\n- An agent re-checks a node it (or anyone) verified recently.\n\nInputs:\n- `node` (path, required): IPv4 address, domain, ASN (`AS64500`), or\n entity_slug — same grammar as /v1/verify.\n\nReturns:\n- The exact verify bundle last cached for the node (lens blocks,\n `cross_lens` verdict, `coverage` with `valid_until` /\n `stale_if_error`, signed `receipt`), plus `attributes_meta`:\n `cached_at` and `freshness` — `fresh` (inside `valid_until`) or\n `stale` (past it, still inside the `stale_if_error` window; the\n contract says a consumer may use it rather than fail closed).\n- `404` when nothing is cached — the node was never verified, or its\n bundle aged past `stale_if_error`. POST /v1/verify to (re)observe.\n- The short-lived `sigil_token` from the original verify is never\n included: bearer capabilities are not re-served.\n\nCost:\n- Counts as one request against the daily rate limit.\n\nLatency:\n- Typical: <100ms (one KV read, no lens fan-out).\n", "inputSchema": { "properties": { "node": { "type": "string" } }, "required": [ "node" ], "type": "object" }, "name": "attributes_lookup", "outputSchema": null }, { "description": "Returns NDJSON (one JSON object per line) of audit log entries. Each entry records\nthe operation called, the identity, hashes of the request and response, duration,\nand an Ed25519 signature over the canonical entry JSON. Entries are hash-chained:\neach entry's `prev_entry_hash` is SHA-256 of the previous entry's signature,\nmaking deletion of any entry detectable offline.\n\nAuthenticated callers receive only their own entries (`identity_sub` match).\nAdmin key holders receive all entries.\n\nUse this tool when:\n- You want a tamper-evident record of your own API calls.\n- You are auditing a sequence of requests for compliance or debugging.\n- You want to verify the audit chain integrity offline.\n\nDo NOT use this tool when:\n- You are anonymous — authentication is required.\n- You want task status — use `get_task` instead.\n\nInputs:\n- `from` (query, optional): ISO 8601 start datetime. Default: 7 days ago.\n- `to` (query, optional): ISO 8601 end datetime. Default: now.\n- `limit` (query, optional): Max entries. 1–5000, default 1000.\n\nReturns:\n- NDJSON stream, one `AuditEntry` per line.\n- `X-Total-Count` response header with entry count.\n- `X-Took-Ms` response header.\n\nVerify the chain offline:\n- For each consecutive pair (A, B): `SHA-256(A.signature) == B.prev_entry_hash`.\n- For each entry: verify Ed25519 signature against public key in `/.well-known/atap.json`.\n\nCost:\n- Counts as one request against the daily limit.\n\nLatency:\n- Typical: <300ms for 1000 entries, p99: <1s.\n", "inputSchema": { "properties": { "from": { "example": "2026-04-17T00:00:00Z", "format": "date-time", "type": "string" }, "limit": { "default": 1000, "maximum": 5000, "minimum": 1, "type": "integer" }, "to": { "format": "date-time", "type": "string" } }, "type": "object" }, "name": "audit_export", "outputSchema": null }, { "description": "Marks the task as `cancelled`. If the task is already in a terminal state\n(`complete`, `failed`, `expired`), returns 409 Conflict. Only the identity\nthat created the task may cancel it.\n\nUse this tool when:\n- You submitted a probe with `?async=true` and no longer need the result.\n- You want to free up a pending task before it expires.\n\nDo NOT use this tool when:\n- The task is already complete — cancellation is not possible.\n\nInputs:\n- `task_id` (path, required): 26-char ULID.\n\nReturns:\n- `task_id` and `status: cancelled`.\n\nCost:\n- Free.\n\nLatency:\n- Typical: <150ms.\n", "inputSchema": { "properties": { "task_id": { "pattern": "^[A-Z0-9]{26}$", "type": "string" } }, "required": [ "task_id" ], "type": "object" }, "name": "cancel_task", "outputSchema": null }, { "description": "Single-item revocation lookup per Receipt Format v1.0 §8.2. Verifiers that\ndo not want to maintain a local mirror of `/.well-known/receipt-revocations.json`\ncall this endpoint instead. The response includes `feed_version` for cache\ncoherence.\n\nUse this tool when:\n- You are verifying a receipt and need to confirm its `signature.key_id` is still trusted.\n- You are verifying a receipt and need to confirm the specific `receipt_id` was not retracted by its issuer.\n- You hold receipts long-term and want to recheck trust before acting on them.\n\nDo NOT use this tool when:\n- You want the full revocation set — fetch `/.well-known/receipt-revocations.json` directly.\n- You want to *publish* a revocation — that is operator-controlled and not exposed via this API.\n\nInputs:\n- `key_id` (query, optional): Receipt-format key_id (e.g., `tm-receipt-2026-05`). Provide one of `key_id` or `id`.\n- `id` (query, optional): UUIDv7 of a specific receipt. Provide one of `key_id` or `id`.\n\nReturns:\n- `revoked`: boolean.\n- When revoked: `revoked_at` (ISO 8601), `reason` (human-readable), `replacement_key_id` (for keys).\n- Always: `checked_at` (ISO 8601), `feed_version` (integer).\n\nCost:\n- Free; rate-limited like the rest of the data API. Edge-cached 60s.\n\nLatency:\n- Typical <100ms (warm cache); p99 <500ms (cold fetch from well-known).\n", "inputSchema": { "properties": { "id": { "description": "UUIDv7 of a specific receipt to check.", "example": "019e8054-4449-7a36-869f-cb76a3447d5a", "format": "uuid", "type": "string" }, "key_id": { "description": "Receipt-format signing key_id to check.", "example": "tm-receipt-2026-05", "type": "string" } }, "type": "object" }, "name": "check_receipt_revoked", "outputSchema": null }, { "description": "Set the customizable knob: which regulatory regime your auditor maps to,\nhow long to retain decision content, and which export formats to offer.\nBody: { enabled?, regime?, retention_days?, export_formats? }. retention_days\nis 1..3650; regime is one of the catalog ids; export_formats is a non-empty\nsubset of [signed_json, csv, eat, stix]. No bespoke engineering — you pick,\nthe ledger adapts.\n", "inputSchema": { "properties": { "enabled": { "example": true, "type": "boolean" }, "export_formats": { "example": [ "signed_json", "csv", "eat" ], "items": { "type": "string" }, "type": "array" }, "regime": { "example": "ai_act_art12", "type": "string" }, "retention_days": { "example": 365, "type": "integer" } }, "type": "object" }, "name": "compliance_configure", "outputSchema": null }, { "description": "Generates a signed export bundle of your ledger over an optional time\nwindow, mapped to your regime's field names and citation, with a manifest\n+ chain-integrity proof + the latest signed checkpoint. Choose the format\nwith ?format= (signed_json | csv | eat | stix; defaults to your profile's\nfirst) and override the regime with ?regime=. The response is a downloadable\nartifact your auditor can verify independently against the spec.\n", "inputSchema": { "properties": { "format": { "description": "signed_json | csv | eat | stix.", "type": "string" }, "from": { "description": "ISO8601 lower bound.", "type": "string" }, "regime": { "description": "Override the profile regime for this export.", "type": "string" }, "to": { "description": "ISO8601 upper bound.", "type": "string" } }, "type": "object" }, "name": "compliance_export", "outputSchema": null }, { "description": "Returns your hash-chained decision records — one per verdict-bearing call\n(/v1/verify, /v1/explain, /v1/preflight, /v1/profile) made while compliance\nis enabled. Each entry carries its node, verdict, scores, receipt_id, the\nfull decision record, and the chain hashes (prev_hash, entry_hash). Filter\nwith from/to (ISO8601) and page with cursor (a seq) + limit (≤1000).\n", "inputSchema": { "properties": { "cursor": { "description": "Resume after this seq.", "type": "integer" }, "from": { "description": "ISO8601 lower bound (inclusive).", "type": "string" }, "limit": { "description": "Page size, max 1000.", "type": "integer" }, "to": { "description": "ISO8601 upper bound (inclusive).", "type": "string" } }, "type": "object" }, "name": "compliance_ledger", "outputSchema": null }, { "description": "Returns your current compliance configuration (regime, retention_days,\nexport_formats, enabled) and the catalog of supported regimes (EU AI Act\nArt.12, DORA, NYDFS 500, HIPAA, PCI DSS, SOC 2, generic) and export\nformats (signed_json, csv, eat, stix). Authenticated. The compliance\nledger is a tamper-evident, retained record of every verdict you make —\nconfigure it once, then it self-maintains.\n", "inputSchema": { "properties": {}, "type": "object" }, "name": "compliance_profile", "outputSchema": null }, { "description": "Recomputes your entire hash chain server-side and reports integrity\n({ intact, entry_count, chain_head_hash } — plus reason + first_break_seq\nif a record was altered or deleted), alongside the most recent Ed25519\ncheckpoint signed with the TunnelMind receipt key. This is the auditor's\n\"prove it\" button — and even TunnelMind cannot rewrite history before a\nsigned checkpoint without detection.\n", "inputSchema": { "properties": {}, "type": "object" }, "name": "compliance_verify", "outputSchema": null }, { "description": "Self-serve free tier — the rung between anonymous access and paid\nblocks. One email in, one API key out, shown exactly once.\n\nUse this tool when:\n- You are calling anonymously and hitting the anonymous rate limit.\n- You want your calls identified so usage survives IP changes.\n\nLimits:\n- 50 requests/day (same endpoints as anonymous, higher ceiling).\n- One active free key per email; 3 signups per IP per day.\n- The raw key is returned once and stored only as a SHA-256 hash —\n it cannot be recovered, only revoked and reissued.\n\nCost: free. No card, no account — the email is the revocation\nhandle, nothing more.\n", "inputSchema": { "properties": { "email": { "example": "[email protected]", "format": "email", "type": "string" } }, "required": [ "email" ], "type": "object" }, "name": "create_free_key", "outputSchema": null }, { "description": "Subscribe to a node (ip, domain, asn, or entity slug). On a recurring\nsweep (~20 min) TunnelMind re-runs the fused `POST /v1/verify` verdict and,\nwhen the *material* result changes — the verdict label flips, the trust\nscore crosses a band, or the signal set changes — POSTs a signed event to\nyour `callback_url`.\n\nWebhook authenticity: every delivery carries an `X-TunnelMind-Signature:\nsha256=<hex>` header, an HMAC-SHA256 over the raw request body keyed by the\n`signing_key` returned ONCE at creation. Recompute and compare to trust it.\n\nDelivery body: `{ subscription_id, node, event: \"verdict_change\",\nprevious, current, delivered_ms }` where `previous`/`current` are compact\nverdict summaries `{ verdict, trust_score, signals }`.\n\nInputs (JSON body):\n- `node` (required): the node to watch.\n- `callback_url` (required): an https URL to receive deliveries.\n- `events` (optional): reserved; defaults to `[\"verdict_change\"]`.\n\nRequires an API key. The baseline verdict is captured at creation, so the\nfirst webhook fires on the first genuine change, not the initial state.\n", "inputSchema": { "properties": { "callback_url": { "example": "https://hooks.example.com/tunnelmind", "format": "uri", "type": "string" }, "events": { "items": { "enum": [ "verdict_change" ], "type": "string" }, "type": "array" }, "node": { "example": "example.com", "type": "string" } }, "required": [ "node", "callback_url" ], "type": "object" }, "name": "create_subscription", "outputSchema": null }, { "description": "Returns all three lens views for a single node key without computing a\nfused verdict. Use this when you want raw transparency — the Tracker\ncatalog presence, Scry attacker observations, and Sigil supply-graph\nposition — and intend to make your own decision. For an opinionated\nverdict, call `cross_lens_verify` instead. For an agent-side\nallow/caution/deny gate plus signed consultation receipt, call\n`preflight_should_i_act`.\n\nCoverage block exposes which lenses responded so agents can reason about\npartial-data verdicts. `issued_by` carries the OAI of the answering\nwitness so the response is attributable.\n", "inputSchema": { "properties": { "node": { "description": "IPv4/IPv6 address, domain, ASN with optional `AS` prefix, or entity_slug.\nType is auto-detected.\n", "type": "string" } }, "required": [ "node" ], "type": "object" }, "name": "cross_lens_lookup", "outputSchema": null }, { "description": "A2 — the cross-lens join. TunnelMind owns multiple halves of the\nopen-web graph: Scry sees who is on every IP (attacker intelligence,\nactor class, Augur threat-intel overlap); Sigil sees the supply graph\n(publishers, SSPs, DSPs, ads.txt + sellers.json + SupplyChain Object);\nGhostRoute sees routing integrity & sovereignty (RPKI origin validity,\nBGP prefix, claimed sovereign zone, sanctions, AI-infrastructure\nownership, certificate CA). This endpoint fuses them into one verdict\non a single node key.\n\nStreaming mode (P56): send `Accept: application/x-ndjson` and the\nsame verdict computation streams as one JSON object per line — a\n`{\"t\":\"lens\",...,\"state\":\"start\"}` line when each lens query is\ndispatched, a `\"state\":\"result\"` line as each lens actually resolves\n(real completion order, never reordered or paced), then the final\n`{\"t\":\"verdict\",...}` line with the fused verdict, trust score, and\nattestation tier. The default single-JSON response is unchanged and\nthe two modes return the identical verdict for the same node.\n\nThe response leads with a base record, then the lens views:\n- `ip_intel` — the BASE: the commodity IP-intelligence + WHOIS record\n (geo/ASN/company/WHOIS/routing/cert), every field provenance-tagged\n `{value, tier, source}` (verified/derived/trusted) with a behaviour axis\n from Scry. The lens blocks below are augmentation beside it. Committed in\n the receipt payload. See `docs/IP-INTEL-RECORD.md`.\n- `scry` — the single-lens Scry view (transparency).\n- `sigil` — the single-lens Sigil view (transparency).\n- `ghostroute` — the single-lens GhostRoute view (transparency).\n- `cross_lens` — the fused verdict (the moat).\n\nFusion math: weighted-mean over evaluated components plus a\n`co_observation_bonus` when both lenses independently flag the node.\nGhostRoute adds a routing-integrity component with two hard safety\nfloors that cannot be averaged away: an RPKI-INVALID origin (a BGP\nhijack signal) caps its trust at 0.15, and a sanctions match zeroes it.\nWeights and thresholds are per-request overridable.\n\nLens unavailability is reported in-band: each lens fails\nindependently and the cross_lens block reflects degraded confidence\nwhen fewer lenses have data (0.55 one lens / 0.80 two / 0.94 three).\nGhostRoute has no routing surface for a bare entity_slug, so it drops\nout and the remaining weights re-normalise. Returns 503 only when ALL\nlenses are unavailable.\n\nv1 lens coverage matrix:\n- IP node — Scry: full; Sigil: not_indexed (v2 will reverse-DNS); GhostRoute: full.\n- Domain node — Scry: deferred; Sigil: full (publisher/ssp/dsp + entity); GhostRoute: full (resolves to IP).\n- entity_slug node — Scry: n/a; Sigil: full (entity + sell/buy presence); GhostRoute: n/a (no routing surface).\n- ASN node — Scry: deferred (v2); Sigil: not_indexed; GhostRoute: origin-AS lookup.\n", "inputSchema": { "properties": { "ait": { "description": "Optional ATAP AIT id (`AIT-<uuidv7>`). When present, the\nverdict is wrapped in a witness-tier `cross_lens:verified`\nevent chained onto the AIT and signed by Sigil\n(witness OAI-2026-0000201). Independent of the AIT, a\nshort-lived signed `sigil_token` is always issued on a\nsuccessful verify, and a durable TunnelMind `receipt`\n(v1.0) commits to the verdict for long-term audit.\n", "example": "AIT-0192f5d3-2c1e-7af6-bd84-9c4a3e8b7d12", "type": "string" }, "claimed_zone": { "description": "Caller-asserted sovereign zone for the subject (e.g. `EU`) —\n\"the vendor's contract says EU-only; score the routing\nagainst that claim.\" Validated against the sovereign-zone\nreference; an unknown code is ignored with caveat\n`claimed_zone_unrecognised_ignored` (garbage input never\ncreates penalties). Takes precedence over the corpus's\npublic claim; the response and signed receipt record who\nasserted it in `ghostroute.claimed_sovereign_zone_source`\n(`caller` | `corpus`). Claim-bearing calls bypass the\nshared lens cache and are never written back to the\ncorpus (ADR-012).\n", "example": "EU", "type": "string" }, "node": { "description": "The node to verify. Type is auto-detected: IPv4/IPv6 address, domain,\nASN with optional `AS` prefix, or entity_slug.\n", "type": "string" }, "thresholds": { "description": "{ pass, fail } verdict cutoffs (defaults 0.7 / 0.3)", "type": "object" }, "weights": { "description": "Per-component weight overrides", "type": "object" } }, "required": [ "node" ], "type": "object" }, "name": "cross_lens_verify", "outputSchema": null }, { "description": "Cancel a subscription.", "inputSchema": { "properties": { "id": { "type": "string" } }, "required": [ "id" ], "type": "object" }, "name": "delete_subscription", "outputSchema": null }, { "description": "Call this when you need to ACT ON a verdict and prove why. It returns the\nexact verdict `/v1/verify/{node}` computes (same fusion, same weights)\nPLUS a traced evidence chain: every claim is attributed to where it came\nfrom — the attested sensor fleet (with attestation tier), a named Augur\nthreat feed, sellers.json/ads.txt supply-graph presence, the cross-lens\nco-observation join, the DDG/IAB tracker corpus — and how much each item\nmoved the verdict (`weight`; null = supplementary, not scored).\n\nThe response is committed to by a P38 signed receipt via\n`evidence_digest` (a hash of the exact evidence array), so an agent can\nact on the verdict and leave behind a cryptographically verifiable trail\nof the reasoning in the same request. Empty/`none` evidence is the honest\n\"no corpus presence\", never a fabricated reason.\n\n`node` is an IPv4/IPv6, ASN, domain, or entity_slug — the same key space as\n`/v1/verify`.\n", "inputSchema": { "properties": { "node": { "description": "IPv4/IPv6, ASN (AS####), domain, or entity_slug.", "type": "string" } }, "required": [ "node" ], "type": "object" }, "name": "explain_verdict", "outputSchema": null }, { "description": "Looks up each submitted domain in the TunnelMind tracker database, aggregates risk\nmetrics (avg score, max score, fingerprinters, high-risk domains, entity ownership),\nand issues a signed surveillance receipt. The receipt is stored in the public registry\nand can be verified at `/verify/{receipt_id}`.\n\nUse this tool when:\n- You want a verifiable record of which trackers were observed in a context (page, app, session).\n- You need a signed evidence artifact for a privacy audit or compliance report.\n- You want to know the overall surveillance exposure level for a set of domains.\n- You are generating a receipt to share with a user as evidence of tracker presence.\n\nDo NOT use this tool when:\n- You want full tracker details per domain — use `get_domain` instead.\n- You want to look up an existing receipt — use `get_receipt` instead.\n- You need live probes (HTTP headers, stack detection) — use `/v1/intel/*` instead.\n\nInputs:\n- `domains` (body, required): Array of 1–50 fully qualified domain names.\n Duplicates are deduplicated. URLs are stripped to host component.\n- `domain` (body, alternative): Single domain string (shorthand for `domains: [domain]`).\n\nReturns:\n- `receipt_id`: Unique receipt ID (e.g. `rcpt_01JXYZ...`).\n- `receipt`: Full receipt document including domains submitted, tracker findings,\n high-risk domains, fingerprinters, unique entities, and exposure metrics.\n- `content_hash`: SHA-256 of the canonical receipt JSON.\n- `signature`: Base64 Ed25519 signature (empty string if signing key not configured).\n- `signed`: Boolean — true if the receipt is cryptographically signed.\n- `verify_url`: Path to retrieve this receipt from the public registry.\n\nExposure levels: `minimal` / `moderate` / `high` / `critical`\nBased on average tracker score and proportion of high-risk domains (score ≥ 70).\n\nCost:\n- Counts as one request against the daily limit regardless of domain count.\n\nLatency:\n- Typical: <100ms (pure D1 lookup, no outbound probing). p99: <300ms.\n", "inputSchema": { "properties": { "domain": { "description": "Single domain shorthand (alternative to `domains`)", "type": "string" }, "domains": { "description": "Domain names to look up (1–50)", "example": [ "doubleclick.net", "google-analytics.com", "facebook.com" ], "items": { "type": "string" }, "maxItems": 50, "minItems": 1, "type": "array" } }, "type": "object" }, "name": "generate_receipt", "outputSchema": null }, { "description": "Returns the TunnelMind analyst config bundle. Configures any LLM\n(Claude, GPT, Gemini, local) to behave as a TunnelMind analyst that\nknows the data graph, follows the 5-call golden path, and surfaces\nattestation_tier on every claim.\n\nThe bundle is signed inline (Ed25519, key_id from\n/.well-known/receipt-signing-key.json). Add `?receipt=true` to wrap\nthe response in a Receipt v1.0 envelope for end-to-end audit.\n\nUse this tool when:\n- You want to configure a new LLM runtime to act as a TunnelMind analyst\n- You want to verify the system prompt you're running matches what TunnelMind serves\n- You're building a BYOM (bring-your-own-model) deployment and need the canonical config\n\nDo NOT use this tool when:\n- You want to call individual TunnelMind data tools — use the tools directly\n- You want to verify a specific receipt — use check_receipt_revoked or @tunnelmindai/receipt-verify\n\nInputs (all optional):\n- `surface` (query): \"data\" (default, full surface), \"scry\", or \"sigil\"\n- `version` (query): pin a specific bundle version (e.g. \"1.0.0\" or \"1\" for latest 1.x.y)\n- `receipt` (query): \"true\" to wrap the response in a signed Receipt v1.0 envelope\n\nContent negotiation (via Accept header):\n- `application/json` (default) — full bundle JSON\n- `text/markdown` — system prompt only (Anthropic flavor)\n- `application/vnd.anthropic.config+json` — Anthropic-shaped subset\n- `application/vnd.openai.config+json` — OpenAI-shaped subset\n\nReturns:\n- `version`, `schema`, `issuer`, `surface`, `surface_label`\n- `system_prompts.{anthropic,openai,generic}` — three encodings of the same semantic prompt\n- `tools.surface_subset` — array of operationIds for this surface (null = all)\n- `response_format` — JSON Schema the analyst's verdicts must conform to\n- `attestation_tiers` — the 4-tier vocabulary (self_asserted → silicon_root)\n- `graph_state` — live corpus counts at serve time\n- `references` — URLs to the rest of the open-protocol layer\n- `bundle_signature` — inline Ed25519 signature for offline verification\n- `pin_recommended` — stable supply-chain identifier (survives hourly graph_state updates)\n\nHeaders: `X-Bundle-Version`, `X-Pin-Recommended`, `ETag`, `X-RateLimit-*`.\n\nCost:\n- Free, anonymous-accessible. Rate-limited on a SEPARATE counter from data-API calls\n (`cfg:ip:<ip>` identity) so a config refetch loop can't burn your data quota.\n\nLatency:\n- Typical <100ms (cached); cold fetch <500ms (live Supabase counts).\n", "inputSchema": { "properties": { "receipt": { "default": "false", "description": "When true, wrap the bundle in a Receipt v1.0 envelope.", "enum": [ "true", "false" ], "type": "string" }, "surface": { "default": "data", "enum": [ "data", "scry", "sigil" ], "type": "string" }, "version": { "description": "Pin a specific bundle version. Omit for latest.", "example": "1.0.0", "type": "string" } }, "type": "object" }, "name": "get_analyst_config", "outputSchema": null }, { "description": "Returns the tier, label, masked owner email, creation date, last-used timestamp,\ntoday's request count, and daily request limit for the API key used in this request.\nUseful for agents that need to monitor their own quota consumption.\n\nUse this tool when:\n- You want to check how many requests your key has used today.\n- You need to know your current tier or daily limit.\n- You want to confirm that your API key is active.\n\nDo NOT use this tool when:\n- You want to manage multiple keys — this endpoint only reflects the calling key.\n- You need tracker data — use the tracker endpoints instead.\n\nInputs:\n- No body or query parameters. Auth is from the `Authorization: Bearer` header.\n\nReturns:\n- `tier`: free, supporter, pro, or enterprise.\n- `requests_today`: integer count from KV (best-effort; resets at UTC midnight).\n- `limit_per_day`: null for enterprise (unlimited).\n- `last_used`: ISO 8601 timestamp, may be null if never used.\n\nCost:\n- Free. Does not count against the daily request limit.\n\nLatency:\n- Typical: <150ms, p99: <400ms.\n", "inputSchema": { "properties": {}, "type": "object" }, "name": "get_api_key", "outputSchema": null }, { "description": "Returns the routing anomalies the bgp-monitor has observed against\nTunnelMind's BGP watchlist — the witnessability layer's routing\ndimension. The monitor polls RIPEstat (RIPE NCC) on a cron, self-baselines\neach watched prefix's origin set on first sight, then records an event\nwhenever a later poll deviates from that baseline.\n\nUse this to check whether a prefix or ASN you depend on (an SSP's egress,\na publisher's network, your own infrastructure) has shown a hijack-shaped\nrouting event. `event_type` is one of:\n- `origin_change` — an origin AS not in the baseline is announcing the\n prefix (severity `critical` if that announcement also fails RPKI,\n else `high`).\n- `rpki_invalid` — a current announcement fails RPKI ROA validation.\n- `withdrawn` — a previously-announced prefix is no longer visible.\n- `new_more_specific` / `visibility_drop` — reserved for a later monitor pass.\n\n`prev_origins` is the baseline the event deviated from. `count` is the\nfull filtered set; `events` is bounded by `limit`, newest first. An empty\n`events` array means no anomalies in the window — the honest \"all clear\".\n", "inputSchema": { "properties": { "limit": { "default": 100, "description": "Max events returned (default 100, hard cap 500).", "maximum": 500, "minimum": 1, "type": "integer" }, "resource": { "description": "Filter to one watched resource — a CIDR prefix (e.g. 45.32.0.0/24) or an ASN (e.g. AS13335). Omit for all.", "type": "string" }, "since_ms": { "description": "Unix epoch milliseconds lower bound on observed_at.", "format": "int64", "type": "integer" } }, "type": "object" }, "name": "get_bgp_events", "outputSchema": null }, { "description": "Weekly public aggregate of demand: what callers asked this API for that it\ndid not have or rejected (ghost routes, rejected arguments, ghost MCP tools, tools/list counts). One ISO week, Monday 00:00 UTC to the next Monday\n00:00 UTC (`?week=` picks the week containing a date; default is the current\nweek). Aggregate rows only: a row is published only when at least\n`n_threshold` (3) distinct actors produced it in the window. Rows below that\nare omitted, and their count is published in `suppressed` ({rows, events}).\nNo actor identifier, IP, raw path, query string, timestamp or per-row user\nagent is ever returned. `name` and `path_shape` are caller-supplied request\ntext, marked `caller_supplied: true`; they are not TunnelMind statements.\n`valid_until` equals `window_end`. Add `?receipt=true` for a signed Receipt\nv1.0 over the same payload.\nTotals cover published rows only. `ghost_tool_per_list_ratio` is ghost tool\nasks per tools/list, because only unknown-tool calls are recorded.\n", "inputSchema": { "properties": { "receipt": { "default": false, "description": "When true, attach a signed Receipt v1.0 committed to the transparency log. Additive — a signing failure never costs you the observation (ADR-014).", "type": "boolean" }, "week": { "description": "Any date (YYYY-MM-DD) inside the wanted ISO week. Defaults to the current week.", "format": "date", "type": "string" } }, "type": "object" }, "name": "get_demand_aggregate", "outputSchema": null }, { "description": "Returns the complete surveillance intelligence record for a domain name. If the\ndomain is in TunnelMind's tracker database (80,000+ entries), the response includes\ntracker category, risk score, fingerprinting data, cookie persistence, IAB TCF\npurposes, and the owning corporate entity. If the domain is not in the database,\na live probe is automatically run: RDAP registration data, DNS records (MX, SPF,\nTXT verification tokens), HTTP headers, and CSP third-party actors are fetched\nfresh from the edge and returned.\n\nUse this tool when:\n- You need to know whether a specific domain tracks users, and how aggressively.\n- You are researching who owns a domain and what corporate entity controls it.\n- You want to check HTTP security headers and third-party services embedded in a site.\n- You are building a risk score for a domain before routing traffic through it.\n\nDo NOT use this tool when:\n- You want to search by keyword or category — use `search` instead.\n- You want all domains for an entity — use `get_entity` instead.\n\nInputs:\n- `domain` (path, required): Domain name. Strip `www.` prefix — it is removed automatically.\n Subdomains are resolved to the parent: `ads.doubleclick.net` → `doubleclick.net`.\n Examples: `doubleclick.net`, `google-analytics.com`, `intercom.io`.\n\nReturns:\n- Full `DomainRecord`. Free tier returns the domain, category, score, prevalence, and\n entity name. Pro/enterprise additionally return `tcf_vendor_id`, `tcf_purposes`,\n `tcf_features`, and `disconnect_cats`.\n- If the domain is not in the tracker database, `live_lookup: true` is set and\n RDAP/DNS/HTTP probe results are returned instead of tracker fields.\n- 404 if the domain cannot be found via live probe either (unknown TLD, unreachable).\n\nCost:\n- Free tier: included in 50 req/day limit. Pro/enterprise: included in plan.\n\nLatency:\n- Database hit: typical <100ms, p99 <300ms.\n- Live probe: typical 2-5s, p99 10s (external DNS/HTTP calls).\n", "inputSchema": { "properties": { "domain": { "description": "Domain name to look up (www. prefix stripped automatically)", "example": "doubleclick.net", "type": "string" } }, "required": [ "domain" ], "type": "object" }, "name": "get_domain", "outputSchema": null }, { "description": "Returns an entity record for a surveillance company or data broker, including its\nindustry, estimated annual data value per user (in USD), categories of personal data\ncollected, and the full list of domains it controls. Free tier returns 5 domains,\npaid returns up to 200.\n\nUse this tool when:\n- You want to understand what corporate entity owns or controls a tracker domain.\n- You need to assess the total surveillance footprint of a company (e.g., Alphabet,\n Meta, Oracle).\n- You are building a corporate surveillance graph and need domain-to-entity mapping.\n\nDo NOT use this tool when:\n- You have a domain and need its category — use `get_domain` instead.\n- You want to browse entities by industry — use `list_entities` instead.\n- You are searching for an entity by name — use `search` instead.\n\nInputs:\n- `slug` (path, required): URL-safe entity identifier (lowercase, hyphens). Examples:\n `alphabet`, `meta`, `oracle-data-cloud`, `the-trade-desk`.\n\nReturns:\n- Full `EntityRecord` with data categories, estimated data cost, and associated domains.\n- `domains`: array of top-scoring domains (5 for free tier, 200 for paid).\n- Pro/enterprise additionally return `website` and `description` fields.\n\nCost:\n- Free tier: included in 50 req/day limit. Pro/enterprise: included in plan.\n\nLatency:\n- Typical: <150ms, p99: <400ms.\n", "inputSchema": { "properties": { "slug": { "example": "alphabet", "pattern": "^[a-z0-9\\-]+$", "type": "string" } }, "required": [ "slug" ], "type": "object" }, "name": "get_entity", "outputSchema": null }, { "description": "Public read of the crowd-sourced outcome aggregate for a node — how\ncallers reported their real-world results after acting on its verdict.\nAdvisory signal, not a trust verdict. An empty aggregate returns cleanly\nwith `total: 0` and `signal: none`.\n\n`signal` is derived: `none` (no reports), `insufficient` (<3),\n`positive` / `negative` (score past ±0.3), or `mixed`.\n", "inputSchema": { "properties": { "node": { "description": "ip, domain, asn, or entity slug.", "type": "string" } }, "required": [ "node" ], "type": "object" }, "name": "get_feedback", "outputSchema": null }, { "description": "D4 — the freshness contract a PDP can gate on. For each lens (Scry /\nSigil / Tracker / GhostRoute) this reports the newest observation\ntimestamp in the corpus, the declared ingest cadence (taken from the\ningester's own code and cron schedules, never asserted), the published\nSLO, the current corpus age in seconds, and whether the SLO holds.\nGhostRoute reports its three corpus workers (CT hourly, RPKI 6-hourly,\nASN daily) individually.\n\nSLO rule: 2x the declared cadence — one fully missed ingest cycle trips\nit — except where an estate monitor already publishes a threshold, in\nwhich case the SLO matches the monitor.\n\nEvery source is independently null-tolerant: a momentarily-unmeasurable\nlens reports `last_observation_at: null` and `slo_met: null` — never a\nfabricated timestamp, never a silent pass. Cached ~5 minutes (unlike the\nweekly /v1/stats snapshot — freshness that was itself a week stale would\nbe self-refuting).\n", "inputSchema": { "properties": {}, "type": "object" }, "name": "get_freshness", "outputSchema": null }, { "description": "Spec 097 / ADR-035 Amendment C8. Returns the usage-tiered price schedule\nfor paid calls. Prices are integer strings of USDC atomic units\n(6 decimals). Rows are `{tier, from, to, price_atomic}`; `to` is null for\nthe open tier. `anonymous` is the price a call without an API key pays.\nNo database or KV read: the schedule is compiled into the running Worker.\n\n`counting_rule`: the tier is set by settled paid calls per API key in the\ncurrent UTC calendar month; a call without a key pays the top-tier price;\na call counts only after a successful settle; the 402 response quotes the\nprice of the caller's next call. `consistency_note`: the count is kept in\nKV, which is eventually consistent, so a tier boundary can drift by a few\ncalls.\n\nFreshness: `observed_at` is the response time, `valid_until` is 24 hours\nlater, `stale_if_error` is 86400 seconds.\nAdd `?receipt=true` for a signed Receipt v1.0 over the same payload.\n", "inputSchema": { "properties": { "receipt": { "default": false, "description": "When true, attach a signed Receipt v1.0 committed to the transparency log. Additive — a signing failure never costs you the observation (ADR-014).", "type": "boolean" } }, "type": "object" }, "name": "get_pricing", "outputSchema": null }, { "description": "Returns metadata for a TunnelMind surveillance receipt — a signed document proving\nthat a specific user's surveillance exposure was observed, measured, and recorded at\na specific time. Does NOT return the receipt's signature (anti-phishing protection).\nTo verify a receipt's content integrity, use `verify_receipt` with the hash and\nsignature from the receipt document itself.\n\nUse this tool when:\n- You have a receipt ID and want to confirm it was genuinely issued by TunnelMind.\n- You need the issuance timestamp and signing key ID for a receipt.\n- You want to check whether a receipt exists before attempting content verification.\n\nDo NOT use this tool when:\n- You have the full receipt document and want to verify it hasn't been tampered with —\n use `verify_receipt` instead.\n\nInputs:\n- `receipt_id` (path, required): The receipt ID from the receipt document. Alphanumeric\n with hyphens, max 128 characters.\n\nReturns:\n- `status`: `FOUND` if the receipt is in the registry.\n- `generated_at`: ISO 8601 timestamp of receipt issuance.\n- `signing_key_id`: identifier of the Ed25519 key used to sign.\n- `schema_version`: receipt schema version.\n- `message`: human-readable summary with instructions for content verification.\n- 404 if the receipt ID is not in the registry.\n\nCost:\n- Free. No API key required.\n\nLatency:\n- Typical: <100ms, p99: <300ms.\n", "inputSchema": { "properties": { "receipt_id": { "maxLength": 128, "pattern": "^[a-zA-Z0-9\\-]+$", "type": "string" } }, "required": [ "receipt_id" ], "type": "object" }, "name": "get_receipt", "outputSchema": null }, { "description": "For a capability TunnelMind does not provide itself, returns the destination's\nendpoint and schema URL from a reviewed catalog, plus facts TunnelMind\nitself observed: when its own probe last reached the destination, whether the\ndestination advertises x402 or Web Bot Auth, and the origin ASN and RPKI state\nof the host. Every fact carries `{value, tier, source}` and a coverage state.\nThe response carries a signed Receipt v1.0.\nThe signature attests what TunnelMind recorded, not that the destination's\nclaims are true. TunnelMind never calls the destination on your behalf and\nnever carries your traffic or data to it. Payment always goes to\nTunnelMind's own x402 address and nothing the destination says can change that.\nPriced per call in x402 USDC by the caller's monthly tier (anonymous callers\npay the base price); the 402 challenge quotes the price for this call. Demo\npayments are refused. When the paid tools flag is off the route answers 503\nand issues no challenge. Unknown capabilities answer 404 with no charge.\n", "inputSchema": { "properties": { "X-PAYMENT": { "description": "base64(JSON) x402 payment. Absent on the first call, which returns the 402 challenge.", "type": "string" }, "capability": { "description": "Capability slug from the referral catalog, for example whois_history.", "type": "string" } }, "required": [ "capability" ], "type": "object" }, "name": "get_referral", "outputSchema": null }, { "description": "Weekly public aggregate of demand: what callers asked this API for that it\ndid not have or rejected on paid referrals (kinds referral and ghost_referral only). One ISO week, Monday 00:00 UTC to the next Monday\n00:00 UTC (`?week=` picks the week containing a date; default is the current\nweek). Aggregate rows only: a row is published only when at least\n`n_threshold` (3) distinct actors produced it in the window. Rows below that\nare omitted, and their count is published in `suppressed` ({rows, events}).\nNo actor identifier, IP, raw path, query string, timestamp or per-row user\nagent is ever returned. `name` and `path_shape` are caller-supplied request\ntext, marked `caller_supplied: true`; they are not TunnelMind statements.\n`valid_until` equals `window_end`. Add `?receipt=true` for a signed Receipt\nv1.0 over the same payload.\nReferral rows carry `status`; 404 (unknown capability) and 503 (asked while\noff) are separate rows.\n", "inputSchema": { "properties": { "receipt": { "default": false, "description": "When true, attach a signed Receipt v1.0 committed to the transparency log. Additive — a signing failure never costs you the observation (ADR-014).", "type": "boolean" }, "week": { "description": "Any date (YYYY-MM-DD) inside the wanted ISO week. Defaults to the current week.", "format": "date", "type": "string" } }, "type": "object" }, "name": "get_referral_log", "outputSchema": null }, { "description": "P83 Gate 1. The caller is the subject: every fact here comes from the\nTLS handshake and headers the caller has already sent, so there is no\nrender, no browser, and nothing to authorize.\n\nThree surfaces:\n- `client` — user-agent, HTTP protocol, TLS version/cipher, ClientHello\n length, the pre-hashed JA3/JA4 input components, header order.\n- `state` — how many cookies were sent (never their values), Referer,\n DNT, Global Privacy Control.\n- `network` — address, ASN and operator, coarse geography, edge colo,\n and the four-lens verdict on the caller's own IP.\n\nEvery field carries a coverage state from the same three-value\nvocabulary as `/v1/verify`: `observed_clean`, `never_observed`,\n`degraded`. There is no fourth state. Fields that run inside a page —\nlocalStorage, canvas fingerprinting, cookie values — are reported\n`never_observed` with reason `not_observable_server_side`, because they\nare outside a server's vantage rather than missing.\n\n`claim_vs_conduct` compares the claimed user-agent against the shape of\nthe request itself and returns `consistent`, `mismatch`, or\n`unverifiable`, with the evidence listed. It is deliberately narrow:\nJA4 requires Cloudflare Enterprise + Bot Management, so there is no\nportable fingerprint to look up in a public corpus, and this check only\nreports contradictions it can demonstrate from the request in hand.\n`unverifiable` is the honest default and is never dressed up as a pass.\n\nUse this tool when:\n- You want to know what a server learns about your client without\n asking you anything.\n- You are checking whether a client's user-agent claim matches its\n conduct.\n\nDo NOT use this tool when:\n- You need facts about some OTHER host — that is `POST /v1/verify/{node}`.\n\nMust be called directly at `data.tunnelmind.ai`. Behind a proxy, the\nconnection properties describe the proxy, not the caller.\n\n`?receipt=true` attaches a signed Receipt v1.0 committed to the\ntransparency log.\n", "inputSchema": { "properties": { "receipt": { "default": false, "type": "boolean" } }, "type": "object" }, "name": "get_self_view", "outputSchema": null }, { "description": "One public \"state of the corpus\" readout — the whole graph in a single\ncall. Distinct from the Scry-only sensor stats at\napi.tunnelmind.ai/v1/stats (which this reuses for the `scry` block): this\nspans Scry, Sigil, and Tracker plus the attestation and routing layers.\n\nUse it to cite live coverage — how many publishers / SSPs / DSPs / sell\npaths / sellers.json seats are in the Sigil supply graph, how many tracker\nentities and domains Tracker holds, how many ATAP witness events and OAIs\nthe attestation layer carries, and how many BGP watchlist resources and\nrouting events the monitor has recorded.\n\nEvery count is independent and null-tolerant: a momentarily-unavailable\nlens reports `null`, never a silent zero. Cacheable for ~10 minutes.\n", "inputSchema": { "properties": {}, "type": "object" }, "name": "get_stats", "outputSchema": null }, { "description": "Read one of your subscriptions (signing_key redacted).", "inputSchema": { "properties": { "id": { "type": "string" } }, "required": [ "id" ], "type": "object" }, "name": "get_subscription", "outputSchema": null }, { "description": "Returns the current status of a task created by an `?async=true` intel request.\nPoll this endpoint until `status` is one of: `complete`, `failed`, `cancelled`,\n`expired`. On `complete`, the `result` field contains the same payload the sync\nendpoint would have returned. On `failed`, `error.message` explains the failure.\n\nUse this tool when:\n- You submitted an intel probe with `?async=true` and need to retrieve the result.\n- You want to check whether a background task finished without opening an SSE stream.\n\nDo NOT use this tool when:\n- You want real-time event streaming — use `stream_task` instead.\n- You have no task_id — submit a probe with `?async=true` first.\n\nInputs:\n- `task_id` (path, required): 26-char ULID returned in the 202 response.\n\nReturns:\n- `status`: `pending` | `running` | `complete` | `failed` | `cancelled` | `expired`.\n- `result`: populated when status is `complete`. Null otherwise.\n- `error`: populated when status is `failed`. Null otherwise.\n- `expires_at`: tasks expire 1 hour after creation.\n\nCost:\n- Free. Does not count against rate limits.\n\nLatency:\n- Typical: <100ms.\n", "inputSchema": { "properties": { "task_id": { "example": "01KPFC524XASR404D436DX60AP", "pattern": "^[A-Z0-9]{26}$", "type": "string" } }, "required": [ "task_id" ], "type": "object" }, "name": "get_task", "outputSchema": null }, { "description": "Spec 097 FR-010 / ADR-034. Returns the tool registry generated from\nopenapi.yaml: one entry per operation with its version, status\n(active / deprecated / retired), lens and schema hash, plus the\n`registry_hash` over the whole set. Retired entries stay listed.\nNo database read: the registry is compiled into the running Worker.\n\nFreshness: `observed_at` is the response time, `valid_until` is 24 hours\nlater, `stale_if_error` is 86400 seconds. `deployed_at` is the Worker\nversion timestamp, or null when the runtime does not expose it.\nAdd `?receipt=true` for a signed Receipt v1.0 over the same payload.\n", "inputSchema": { "properties": { "receipt": { "default": false, "description": "When true, attach a signed Receipt v1.0 committed to the transparency log. Additive — a signing failure never costs you the observation (ADR-014).", "type": "boolean" } }, "type": "object" }, "name": "get_tool_registry", "outputSchema": null }, { "description": "The over-time layer behind the site's website map (the radar's\nevolution). Every domain verify appends the domain's machinery tuple\n— origin AS, RPKI state, announced prefix, network country, CDN,\ncertificate authority, registrar, owning entity, and the per-lens\ncoverage tri-states — to an append-only change-log, one row per\nobserved change (plus a daily heartbeat row per looked-up domain).\n\nHonesty contract: `first_recorded` is when the observatory first\nlooked at this domain — never presented as when the machinery came to\nexist. History accretes from real lookups starting 2026-08-04; a\ndomain nobody has verified has zero rows, which is itself the honest\nanswer.\n", "inputSchema": { "properties": { "domain": { "type": "string" } }, "required": [ "domain" ], "type": "object" }, "name": "get_website_history", "outputSchema": null }, { "description": "Checks whether a domain or ASN belongs to a known AI company's\ninfrastructure and what sovereignty it CLAIMS (program, zone, HQ), the\nbaseline GhostRoute scores routing reality against.\n\nUse this tool when:\n- You want to know \"whose AI infrastructure is this, and what does it claim?\"\n- You are enriching an endpoint before deciding whether to send it inference.\n\nInputs:\n- `entity` (path, required): a domain or ASN (AS####).\n\nReturns:\n- `matched`, `match_basis` (domain|asn), `ai_company`, `ai_product`,\n `sovereign_ai_program`, `claimed_sovereign_zone`, `hq_country`, `verified_sovereign`.\n\nLatency:\n- Typical <300ms (cached corpus read).\n", "inputSchema": { "properties": { "entity": { "type": "string" } }, "required": [ "entity" ], "type": "object" }, "name": "ghostroute_ai_lookup", "outputSchema": null }, { "description": "Returns GhostRoute's ownership-graph record for an autonomous system: the\nregistrant/parent organisation, its HQ country and sovereign zone, RIR,\nand cloud/AI-infrastructure flags. The long-term moat — who actually owns\nthe network a route originates from.\n\nUse this tool when:\n- You have an origin ASN and need its corporate owner + jurisdiction.\n- You are assessing whether an ASN belongs to a cloud front or the real operator.\n\nInputs:\n- `asn` (path, required): AS#### or a bare AS number.\n\nReturns:\n- `registrant_org`, `parent_org`, `parent_org_country`, `sovereign_zone`,\n `rir`, `is_cloud_provider`, `is_ai_infrastructure`, or `{matched:false}`.\n\nLatency:\n- Typical <300ms (cached corpus read, RDAP fallback on a miss).\n", "inputSchema": { "properties": { "asn": { "type": "string" } }, "required": [ "asn" ], "type": "object" }, "name": "ghostroute_asn_lookup", "outputSchema": null }, { "description": "GhostRoute is TunnelMind's fourth lens: routing-integrity / sovereignty\nverification. It answers \"is this infrastructure where it claims to be,\nowned by who it claims, routing where it says — and does that match the\nsovereign jurisdiction it asserts?\" It resolves the originating ASN owner,\nRPKI validity, the certificate-issuing CA's jurisdiction, and matches the\nsubject against a curated AI-infrastructure corpus to recover any\nsovereignty CLAIM (e.g. an \"EU-sovereign\" AI service), then scores reality\nagainst claim.\n\nUse this tool when:\n- An agent is about to route data/inference to an endpoint that claims a\n jurisdiction (e.g. EU data residency, FedRAMP, sovereign-AI).\n- You want to detect a US-fronted (Cloudflare/AWS/GCP) endpoint masquerading\n as sovereign-EU infrastructure, an RPKI-invalid origin (possible hijack),\n or a sanctioned operator.\n\nInputs:\n- `entity` (path, required): an IPv4/IPv6, domain, ASN (AS####), or cert SHA-1/256.\n- `receipt` (query, optional): when `true`, issues a signed, persisted\n GhostRoute receipt (GR-YYYY-NNNNNNN) instead of an ephemeral verdict.\n\nReturns:\n- `sovereign_tier`: VERIFIED | PLAUSIBLE | MISMATCH | CRITICAL_MISMATCH (or null if no claim).\n- `sovereign_integrity`: [0,1] score; `origin_as`, `rpki_status`, `cert_ca`,\n `claimed_sovereign_zone`, `is_ai_infrastructure`, `ai_owner`, `sanctions_match`.\n- `_meta.caveats` / `_meta.penalties`: what was and wasn't determinable.\n\nLatency:\n- Typical 300-900ms on a cold subject (live BGP/RPKI/cert lookups), faster when cached.\n", "inputSchema": { "properties": { "entity": { "description": "An IPv4/IPv6 address, domain, ASN (`AS####`), or cert SHA-1/256 to check.", "type": "string" }, "receipt": { "default": false, "description": "When `true`, issues a signed, persisted GhostRoute receipt (`GR-YYYY-NNNNNNN`) instead of an ephemeral verdict.", "type": "boolean" } }, "required": [ "entity" ], "type": "object" }, "name": "ghostroute_check", "outputSchema": null }, { "description": "Returns the durable, deduplicated ledger of CT equivocation events the\nGhostRoute witness worker detects and pushes — a tree_size_rewind (an\nappend-only log shrank), a root_fork (one tree_size witnessed with two\ndifferent Merkle roots = a split-view log), or an sth_signature_invalid\n(a log's latest Signed Tree Head failed signature verification). Where\n`/v1/ghostroute/witness` shows live computed health, this is the immutable\nfirst-detection log: each entry's `detected_at` is when TunnelMind first\nraised the alarm. A healthy CT ecosystem returns an empty feed — any row\nhere is a serious trust event.\n\nUse this tool when:\n- You want a chronological record of CT trust violations, not live state.\n- You're polling for new equivocation events (check `summary.last_detected_at`).\n\nInputs:\n- `limit` (query, optional): max recent alerts, 1–200, default 50.\n\nReturns:\n- `summary`: `total`, `undelivered`, `rewinds`, `forks`, `bad_signatures`,\n `last_detected_at`.\n- `alerts[]`: each `kind`, `severity`, `log_url`, `log_operator`,\n `from_tree_size`, `to_tree_size`, `distinct_roots`, `event_observed_at`,\n `detected_at`, `delivered`.\n\nLatency:\n- Typical <200ms (KV-cached 1m).\n", "inputSchema": { "properties": { "limit": { "default": 50, "maximum": 200, "minimum": 1, "type": "integer" } }, "type": "object" }, "name": "ghostroute_ct_alerts", "outputSchema": null }, { "description": "Returns GhostRoute's per-cert inclusion proofs: each is a cryptographic\ndemonstration that the exact certificate a host serves is included in an\nappend-only CT log whose root TunnelMind signature-verified — upgrading\n\"a monitor said this cert exists\" to \"proven in a log we witness\". Failed\nattempts are included with a `reason`; a cert that suddenly cannot be\nproven is itself a signal.\n\nUse this tool when:\n- You want to know whether a specific AI host's live cert is provably\n logged (pass `domain`), or\n- You want the corpus-wide proof rollup across watched hosts (omit `domain`).\n\nInputs:\n- `domain` (query, optional): a hostname to filter to; omit for corpus-wide.\n- `limit` (query, optional): max recent rows, 1–200, default 50.\n\nReturns:\n- `domain` (echo, null when corpus-wide).\n- `summary`: `total_attempts`, `proven`, `unproven`, `domains`, `last_observed_at`.\n- `recent[]`: recent attempts (`log_operator`, `leaf_index`, `tree_size`,\n `sth_root_hash`, `inclusion_proven`, `reason`, ...).\n- `by_domain[]`: per-host `attempts` / `proven` rollup.\n\nLatency:\n- Typical <300ms (KV-cached 5m).\n", "inputSchema": { "properties": { "domain": { "type": "string" }, "limit": { "default": 50, "maximum": 200, "minimum": 1, "type": "integer" } }, "type": "object" }, "name": "ghostroute_ct_proofs", "outputSchema": null }, { "description": "Returns GhostRoute's first-party Certificate-Transparency witness state:\nthe latest signature-verified Signed Tree Head (STH) for every trusted,\nnon-Google CT log TunnelMind independently witnesses, plus a regression\nscan over our own append-only history. Proof the platform holds its own\nsignature-checked roots rather than reselling crt.sh/certspotter.\n\nUse this tool when:\n- You want corpus-wide CT witness health, not one cert.\n- You need to know whether any CT log misbehaved (rewound, forked, or\n served an STH whose signature did not verify) — a serious trust event.\n\nInputs:\n- none.\n\nReturns:\n- `summary`: `logs_witnessed`, `verified_logs`, `unverified_logs`,\n `all_verified`, `total_snapshots`, `regressions`, `last_observed_at`.\n- `logs[]`: per-log latest STH (`log_url`, `log_operator`, `tree_size`,\n `sth_timestamp`, `root_hash`, `signature_verified`, `snapshots`).\n- `regressions[]`: detected violations — `kind` is `tree_size_rewind`,\n `root_fork`, or `sth_signature_invalid` (empty array = healthy).\n\nLatency:\n- Typical <300ms (KV-cached 5m; the witness worker updates twice a day).\n", "inputSchema": { "properties": {}, "type": "object" }, "name": "ghostroute_ct_witness", "outputSchema": null }, { "description": "Retrieves a previously-issued, signed GhostRoute receipt by its\nGR-YYYY-NNNNNNN id, for independent audit of a past sovereignty verdict.\n\nUse this tool when:\n- You hold a GhostRoute receipt id and want to confirm its contents/signature.\n- You are reconciling an agent's action log against the attestation layer.\n\nInputs:\n- `receipt_id` (path, required): GR-YYYY-NNNNNNN.\n\nReturns:\n- The full persisted receipt row (routing, cert, sovereignty fields + signature).\n\nLatency:\n- Typical <200ms (single indexed read).\n", "inputSchema": { "properties": { "receipt_id": { "type": "string" } }, "required": [ "receipt_id" ], "type": "object" }, "name": "ghostroute_verify", "outputSchema": null }, { "description": "Returns a minimal status object confirming the API is alive. Use this to verify\nconnectivity before chaining other calls, or as a liveness check in a workflow.\n\nUse this tool when:\n- You need to verify the API is reachable before starting a multi-step investigation.\n- A prior call failed with a 503 or 504 and you want to confirm the service recovered.\n- You are debugging connectivity from a new environment.\n\nDo NOT use this tool when:\n- You want actual tracker data — use `get_domain` or `search` instead.\n- You want to check a specific domain — this returns nothing domain-specific.\n\nInputs:\n- None.\n\nReturns:\n- `ok`: always true if the API is up.\n- `ts`: ISO 8601 timestamp of the server's current time.\n\nCost:\n- Free. No API key required. Not rate-limited.\n\nLatency:\n- Typical: <50ms, p99: <200ms.\n", "inputSchema": { "properties": {}, "type": "object" }, "name": "health_check", "outputSchema": null }, { "description": "Probes a domain for known AI agent integration signals: `llms.txt`, `ai.txt`,\n`/.well-known/ai-plugin.json`, `openapi.json`, `swagger.json`, MCP manifest, MCP\nSSE endpoint. Returns a score based on the count of signals detected. Use this to\nassess whether a domain is ready for agent-to-agent interaction.\n\nUse this tool when:\n- You want to know whether a domain exposes an MCP server or OpenAPI spec for agents.\n- You are cataloguing the AI-agent-ready surface of a set of domains.\n- You need to decide whether to attempt programmatic API access to a domain.\n\nDo NOT use this tool when:\n- You need tracker/surveillance data about the domain — use `get_domain` instead.\n- You need the robots.txt AI crawler policy — use `intel_robots` instead.\n- You need HTTP security posture — use `intel_http` instead.\n\nInputs:\n- `domain` (query, required): Domain to probe.\n\nReturns:\n- Boolean flags per signal (`llms_txt`, `ai_plugin`, `openapi`, `mcp_manifest`,\n `mcp_endpoint`, `mcp_sse`).\n- `agent_surface_score`: integer 0-8, count of signals detected.\n\nCost:\n- Free. No API key required.\n\nLatency:\n- Typical: 2-5s (parallel probes), p99: 8s.\n", "inputSchema": { "properties": { "async": { "default": false, "description": "When true, return a task handle immediately instead of blocking. Poll get_task for the result.", "type": "boolean" }, "domain": { "example": "stripe.com", "type": "string" }, "receipt": { "default": false, "description": "When true, attach a signed Receipt v1.0 committed to the transparency log. Additive — a signing failure never costs you the observation (ADR-014).", "type": "boolean" } }, "required": [ "domain" ], "type": "object" }, "name": "intel_agent", "outputSchema": null }, { "description": "Makes a live HEAD request to the target domain from the Cloudflare edge, follows\nup to 5 redirects, and returns the full redirect chain, final HTTP status, key\nresponse headers, a security header score, and any third-party surveillance\nactors referenced in the Content-Security-Policy header.\n\nUse this tool when:\n- You want to verify whether a site enforces HTTPS and HSTS.\n- You need to inspect what third-party scripts a site loads via its CSP header.\n- You are assessing a domain's security posture before trusting it.\n- You want to detect surveillance actors embedded in a site's CSP.\n\nDo NOT use this tool when:\n- You need tracker database data (category, score, entity) — use `get_domain` instead.\n- You need the technology stack (CMS, framework) — use `intel_stack` instead.\n- You need robots.txt AI crawler policy — use `intel_robots` instead.\n\nInputs:\n- `domain` (query, required): Domain to probe. Can include or omit `https://`.\n Examples: `nytimes.com`, `https://example.com`.\n\nReturns:\n- `reachable`: false if the domain did not respond within 6 seconds.\n- `redirect_chain`: each hop with URL, status code, and Location header.\n- `security_headers.score`: 0-100 based on presence of HSTS, CSP, X-Content-Type,\n X-Frame-Options, Referrer-Policy.\n- `security_headers.missing`: list of headers absent.\n- `csp_actors`: known surveillance actors detected in the CSP header.\n- `error`: set if the connection failed.\n\nCost:\n- Free. No API key required.\n\nLatency:\n- Typical: 1-3s (outbound fetch), p99: 6s (timeout). Plan for async if chaining calls.\n", "inputSchema": { "properties": { "async": { "default": false, "description": "When true, return a task handle immediately instead of blocking. Poll get_task for the result.", "type": "boolean" }, "domain": { "example": "nytimes.com", "type": "string" }, "receipt": { "default": false, "description": "When true, attach a signed Receipt v1.0 committed to the transparency log. Additive — a signing failure never costs you the observation (ADR-014).", "type": "boolean" } }, "required": [ "domain" ], "type": "object" }, "name": "intel_http", "outputSchema": null }, { "description": "Fetches a domain's homepage and checks for content patterns that could constitute\nprompt injection attacks against AI agents that visit and ingest the page. Signals\ninclude hidden text, invisible divs, `<!-- AI: ignore -->` style comments, and\nknown injection patterns.\n\nUse this tool when:\n- You are vetting a domain before feeding its content into an LLM context.\n- You want to assess the prompt injection risk of a URL before browsing it with an agent.\n- You are auditing a set of domains for adversarial AI content.\n\nDo NOT use this tool when:\n- You want tracker surveillance data — use `get_domain` instead.\n- You want AI training opt-out signals — use `intel_optout` instead.\n- You want the agent surface (MCP/OpenAPI) — use `intel_agent` instead.\n\nInputs:\n- `domain` (query, required): Domain to scan.\n\nReturns:\n- `injection_signals`: list of signal types detected (e.g., `hidden_text`,\n `ai_instruction_comment`, `invisible_div`).\n- `risk_level`: `none`, `low`, `medium`, or `high` based on signal count and type.\n\nCost:\n- Free. No API key required.\n\nLatency:\n- Typical: 2-4s (HTML fetch), p99: 7s.\n", "inputSchema": { "properties": { "async": { "default": false, "description": "When true, return a task handle immediately instead of blocking. Poll get_task for the result.", "type": "boolean" }, "domain": { "example": "example.com", "type": "string" }, "receipt": { "default": false, "description": "When true, attach a signed Receipt v1.0 committed to the transparency log. Additive — a signing failure never costs you the observation (ADR-014).", "type": "boolean" } }, "required": [ "domain" ], "type": "object" }, "name": "intel_inject", "outputSchema": null }, { "description": "Checks a domain for all known AI training data opt-out mechanisms beyond robots.txt:\nTDM (Text and Data Mining) reservation headers, `<meta name=\"ai\">` tags, Creative\nCommons NonCommercial licenses, and other machine-readable opt-out signals.\n\nUse this tool when:\n- You need to determine whether a domain has opted out of AI training data collection.\n- You are checking compliance before using a domain's content in a training dataset.\n- You want a comprehensive opt-out status (robots.txt + TDM + meta tags combined).\n\nDo NOT use this tool when:\n- You only need robots.txt crawler policy — use `intel_robots` instead (faster).\n- You need tracker data — use `get_domain` instead.\n- You want injection risk assessment — use `intel_inject` instead.\n\nInputs:\n- `domain` (query, required): Domain to probe.\n\nReturns:\n- `tdm_reservation`: true if the domain sends a `TDM-Reservation: 1` header.\n- `noai_meta`: true if the HTML contains `<meta name=\"robots\" content=\"noai\">`.\n- `license_detected`: string if a CC NonCommercial or similar license is detected,\n otherwise null.\n- `opted_out`: true if any opt-out signal is present.\n\nCost:\n- Free. No API key required.\n\nLatency:\n- Typical: 2-4s, p99: 7s.\n", "inputSchema": { "properties": { "async": { "default": false, "description": "When true, return a task handle immediately instead of blocking. Poll get_task for the result.", "type": "boolean" }, "domain": { "example": "nytimes.com", "type": "string" }, "receipt": { "default": false, "description": "When true, attach a signed Receipt v1.0 committed to the transparency log. Additive — a signing failure never costs you the observation (ADR-014).", "type": "boolean" } }, "required": [ "domain" ], "type": "object" }, "name": "intel_optout", "outputSchema": null }, { "description": "Retrieves the target domain's `robots.txt` file and parses it for AI crawler\ndisallow rules. Specifically detects policies for known AI crawlers (GPTBot,\nClaudeBot, CCBot, Bytespider, etc.) and returns a structured summary of the\ncrawling policy.\n\nUse this tool when:\n- You need to know whether a domain has opted out of AI training data collection.\n- You want to check if a specific AI crawler is blocked before citing the domain.\n- You are building a dataset of AI-accessible vs AI-blocked domains.\n\nDo NOT use this tool when:\n- You want training opt-out signals beyond robots.txt (TDM reservation, noai meta) —\n use `intel_optout` instead.\n- You want the full technology stack — use `intel_stack` instead.\n- You need tracker database data — use `get_domain` instead.\n\nInputs:\n- `domain` (query, required): Domain to probe.\n\nReturns:\n- `robots_txt_found`: false if the domain returned 404 or the file is empty.\n- `ai_crawlers_blocked`: list of AI crawler user-agent names that are disallowed.\n- `all_blocked`: true if `User-agent: *` with `Disallow: /` is present.\n- `raw`: first 4096 characters of the robots.txt file.\n\nCost:\n- Free. No API key required.\n\nLatency:\n- Typical: 1-2s, p99: 6s.\n", "inputSchema": { "properties": { "async": { "default": false, "description": "When true, return a task handle immediately instead of blocking. Poll get_task for the result.", "type": "boolean" }, "domain": { "example": "openai.com", "type": "string" }, "receipt": { "default": false, "description": "When true, attach a signed Receipt v1.0 committed to the transparency log. Additive — a signing failure never costs you the observation (ADR-014).", "type": "boolean" } }, "required": [ "domain" ], "type": "object" }, "name": "intel_robots", "outputSchema": null }, { "description": "Fetches up to 32KB of the domain's HTML and response headers from the edge, then\nfingerprints the content for known CMS platforms, JavaScript frameworks, CDN\nproviders, and analytics tools. Detection is based on meta generator tags, script\nsrc patterns, response headers, and cookie names.\n\nUse this tool when:\n- You need to know what CMS (WordPress, Drupal, Shopify) a site runs.\n- You are assessing a domain's infrastructure before a security review.\n- You want to identify analytics or marketing tools a site embeds.\n\nDo NOT use this tool when:\n- You want HTTP headers and security posture — use `intel_http` instead.\n- You want tracker database classification — use `get_domain` instead.\n- You need robots.txt AI policy — use `intel_robots` instead.\n\nInputs:\n- `domain` (query, required): Domain to fingerprint.\n\nReturns:\n- `cms`: detected content management system, or null.\n- `frameworks`: JavaScript/backend frameworks detected.\n- `cdn`: CDN provider detected, or null.\n- `analytics`: analytics and tracking tools detected.\n- `meta_generators`: raw meta generator tag values.\n\nCost:\n- Free. No API key required.\n\nLatency:\n- Typical: 2-4s (HTML fetch), p99: 7s.\n", "inputSchema": { "properties": { "async": { "default": false, "description": "When true, return a task handle immediately instead of blocking. Poll get_task for the result.", "type": "boolean" }, "domain": { "example": "wordpress.org", "type": "string" }, "receipt": { "default": false, "description": "When true, attach a signed Receipt v1.0 committed to the transparency log. Additive — a signing failure never costs you the observation (ADR-014).", "type": "boolean" } }, "required": [ "domain" ], "type": "object" }, "name": "intel_stack", "outputSchema": null }, { "description": "Returns a paginated list of domains from the tracker database. Results are ordered\nalphabetically by domain name and support cursor-based pagination for full traversal.\nFiltering by category and minimum score allows targeted data extraction.\n\nUse this tool when:\n- You want to enumerate all known ad-tech or analytics domains above a risk threshold.\n- You need a dataset of tracker domains for offline analysis.\n- You are paginating through a category to build a block list.\n\nDo NOT use this tool when:\n- You need data for a specific domain — use `get_domain` instead.\n- You are searching by keyword — use `search` instead.\n- You want domains belonging to a specific company — use `get_entity` instead.\n\nInputs:\n- `category` (query, optional): Filter by surveillance category. One of: `ad_tech`,\n `analytics`, `social`, `fingerprinting`, `content`, `cdn`, `other`.\n- `min_score` (query, optional): Integer 0-100. Exclude domains scoring below this value.\n- `limit` (query, optional): Number of results per page. Max 100 (paid), 20 (free). Default 50.\n- `cursor` (query, optional): Pagination cursor from the previous response's `next_cursor` field.\n\nReturns:\n- Array of domain list items (domain, category, score, prevalence, entity summary).\n- `meta.has_more`: true if more pages exist.\n- `meta.next_cursor`: pass as `cursor` to get the next page.\n- `meta.count`: number of results in this page.\n\nCost:\n- Free tier: up to 20 results/page, 50 req/day. Pro/enterprise: up to 100 results/page.\n\nLatency:\n- Typical: <200ms, p99: <500ms.\n", "inputSchema": { "properties": { "category": { "enum": [ "ad_tech", "analytics", "social", "fingerprinting", "content", "cdn", "other" ], "type": "string" }, "cursor": { "type": "string" }, "limit": { "default": 50, "maximum": 100, "minimum": 1, "type": "integer" }, "min_score": { "maximum": 100, "minimum": 0, "type": "integer" } }, "type": "object" }, "name": "list_domains", "outputSchema": null }, { "description": "Returns a paginated list of corporate entities in the TunnelMind surveillance\ndatabase. Includes data categories, estimated data value, and industry classification.\nUseful for enumerating the surveillance ecosystem by sector.\n\nUse this tool when:\n- You want to enumerate all entities in a specific industry (e.g., all ad-tech companies).\n- You need a dataset of surveillance entities for analysis or reporting.\n- You are building a comprehensive surveillance landscape map.\n\nDo NOT use this tool when:\n- You need the full profile of a specific entity — use `get_entity` instead.\n- You are searching by entity name — use `search` instead.\n- You need domain-level data — use `list_domains` instead.\n\nInputs:\n- `industry` (query, optional): Filter by industry classification. Examples:\n `ad_tech`, `analytics`, `data_broker`, `social`, `crm`.\n- `limit` (query, optional): Results per page. Max 100 (paid), 20 (free). Default 50.\n- `cursor` (query, optional): Pagination cursor from previous response's `next_cursor`.\n\nReturns:\n- Array of entity list items (slug, name, parent_company, industry, data_categories,\n data_cost_usd).\n- `meta.has_more` and `meta.next_cursor` for pagination.\n\nCost:\n- Free tier: up to 20 results/page, 50 req/day. Pro/enterprise: up to 100 results/page.\n\nLatency:\n- Typical: <150ms, p99: <400ms.\n", "inputSchema": { "properties": { "cursor": { "type": "string" }, "industry": { "example": "ad_tech", "type": "string" }, "limit": { "default": 50, "maximum": 100, "minimum": 1, "type": "integer" } }, "type": "object" }, "name": "list_entities", "outputSchema": null }, { "description": "Returns the caller's active and inactive subscriptions (signing_key redacted). Requires an API key.", "inputSchema": { "properties": {}, "type": "object" }, "name": "list_subscriptions", "outputSchema": null }, { "description": "The single call an agent makes before transacting with a destination\non the open web. Composes the cross-lens verdict with a bounded\nTracker-presence bonus, maps the adjusted trust score to a tri-state\ndecision (`allow` / `caution` / `deny`), and returns a 5-minute signed\nconsultation receipt (`sigil_token` with `sub: preflight:consulted`).\n\nThe receipt is the load-bearing artifact: the agent attaches it to\nits action log as cryptographic proof that the destination was\nconsulted before action. The decision itself is commodity-shaped; the\n*receipt of having asked* is what accountability requires.\n\nWhen `ait` is supplied, the consultation additionally chains a\nwitness-tier `preflight:consulted` event onto the ATAP AIT, signed by\nOAI-2026-0000201 — turning the consultation into a hash-chained,\nreplayable artifact.\n\nTracker presence applies a bounded `+0.05` trust bonus before decision\nmapping (capped at 1.0). Absence is never a penalty — most of the open\nweb is not in the tracker corpus and that's expected.\n\nDefaults: `allow >= 0.70`, `caution >= 0.40`, else `deny`. Thresholds\nare overridable per request; weights are inherited from cross_lens_verify.\n", "inputSchema": { "properties": { "agent_id": { "description": "Caller's stable agent identifier, recorded in the receipt. Validated against /^[A-Za-z0-9._:-]{1,128}$/.", "example": "agent.acme.bidder.v1", "type": "string" }, "ait": { "description": "Optional ATAP AIT id. When present, chains a witness-tier\n`preflight:consulted` event onto the AIT.\n", "example": "AIT-0192f5d3-2c1e-7af6-bd84-9c4a3e8b7d12", "type": "string" }, "intent": { "description": "Free-form context — recorded in the receipt, never affects the decision. Validated against /^[A-Za-z0-9._:-]{1,64}$/.", "example": "bid.submit", "type": "string" }, "node": { "description": "IPv4/IPv6 address, domain, ASN with optional `AS` prefix, or entity_slug.", "example": "nytimes.com", "type": "string" }, "thresholds": { "description": "Optional overrides; must satisfy 0 <= caution < allow <= 1.\n", "properties": { "allow": { "example": 0.7, "type": "number" }, "caution": { "example": 0.4, "type": "number" } }, "type": "object" } }, "required": [ "node" ], "type": "object" }, "name": "preflight_should_i_act", "outputSchema": null }, { "description": "Call this before routing traffic, bidding on inventory, or trusting a\ncounterparty. It fuses ALL THREE TunnelMind lenses for one subject —\nScry (attacker intelligence + threat feeds + open ports), Sigil\n(ad-supply-chain position + trust score + ATAP witness count), and\nTracker (DDG/IAB catalog + prevalence + categories) — into a single\nconfidence-scored profile plus a signed P38 receipt.\n\nThe `cross_lens.hits` field tells you if the same infrastructure\nappears in attack data AND supply-chain data — that's your\nhighest-confidence signal, and the one no siloed competitor can give\nyou. `cross_lens.flags` surfaces the actionable highlights\n(`cross_lens_overlap:scry+sigil`, `in_threat_intel:...`,\n`high_prevalence_tracker`, `corroborated_by_N_lenses`).\n\nConfidence weighting: each lens contributes a base score; a 1.5×\nmultiplier applies when ≥2 lenses corroborate the same subject; and the\nScry contribution is weighted by the attestation tier of the sensors\nthat observed it (silicon_root 1.0 → self_asserted 0.5). Bounded [0,1]\nand carried into the receipt.\n\nUnlike `cross_lens_verify` (one node → one verdict) and\n`cross_lens_lookup` (one node → raw three-lens view), profile_entity\ntakes the SUBJECT as any combination of ip / domain / entity and returns\nthe richest fused detail for a pre-transaction decision. At least one of\nip / domain / entity is required.\n", "inputSchema": { "properties": { "domain": { "description": "Domain of the subject (Sigil + Tracker lenses).", "example": "pubmatic.com", "type": "string" }, "entity": { "description": "entity_slug of the subject (Sigil + Tracker lenses).", "example": "google-doubleclick", "type": "string" }, "ip": { "description": "IPv4 or IPv6 address of the subject (Scry lens).", "example": "8.8.8.8", "type": "string" } }, "type": "object" }, "name": "profile_entity", "outputSchema": null }, { "description": "Proves the log at size `second` is an append-only extension of the log\nat size `first` — history was never rewritten. Returns both roots and\nthe proof path. Verify offline with\n`scripts/verify-log.mjs consistency <proof.json>`.\n", "inputSchema": { "properties": { "first": { "minimum": 1, "type": "integer" }, "second": { "minimum": 2, "type": "integer" } }, "required": [ "first", "second" ], "type": "object" }, "name": "receipt_log_consistency_proof", "outputSchema": null }, { "description": "Proves a specific receipt (by unified `receipt_id`, lens alias, or raw\n`leaf_index`) is included in the tree at `tree_size` (default: the\nlatest STH's). Returns `leaf_hash`, the `audit_path`, the recomputed\n`root_hash`, and the matching STH. What this proves: the receipt in\nyour hand is byte-identical to the one sequenced into the log — not\nthat the observation inside it was correct (ADR-010).\n\nVerify offline with `scripts/verify-log.mjs inclusion <proof.json>`.\n", "inputSchema": { "properties": { "leaf_index": { "minimum": 0, "type": "integer" }, "receipt_id": { "type": "string" }, "tree_size": { "minimum": 1, "type": "integer" } }, "type": "object" }, "name": "receipt_log_inclusion_proof", "outputSchema": null }, { "description": "P72 RFC 6962 transparency log over the unified receipt ledger\n(ADR-010). The STH commits to the entire log: `tree_size`, `root_hash`\n(`0x` + SHA-256), `timestamp`, and an Ed25519 signature (with `key_id`\nand embedded public key) over the RFC 8785 canonicalization of the\nbody. Hashes only — receipt bodies are never on this surface.\n\nVerify offline with `scripts/verify-log.mjs sth` (zero TunnelMind\nlibrary code) against the published receipt-signing key.\n", "inputSchema": { "properties": {}, "type": "object" }, "name": "receipt_log_sth", "outputSchema": null }, { "description": "P72 unified receipt ledger (ADR-010): every receipt-issuing surface\n(cross-lens verify, tracker verify, verdict, profile, explain,\nGhostRoute, Sigil/ATAP, compliance export) records the exact signed\ndocument it returned, keyed by one ID space.\n\nUse this tool when:\n- An agent holds a receipt and wants to confirm TunnelMind logged it\n (existence + canonical hash) before trusting it in an audit trail.\n- The owning customer wants to re-fetch a receipt body by id.\n\nInputs:\n- `id` (path, required): the unified `receipt_id` (UUIDv7,\n `GR-YYYY-NNNNNNN`, or `ATAP-RCPT-…`) or a lens-native alias.\n\nReturns:\n- Always: `receipt_id`, `lens`, `payload_hash` (`0x` + SHA-256 of the\n RFC 8785 canonicalization of the stored document), `key_id`,\n `attestation_strength`, `issued_at`, and `leaf_index` (null until the\n transparency-log sequencer enrolls the row).\n- Owner only (authenticated caller matching the receipt's customer):\n `subject` and the full stored `receipt` document. Receipt bodies are\n never public.\n\nCost:\n- Counts as one request against the daily rate limit.\n\nLatency:\n- Typical: <300ms (one Supabase read).\n", "inputSchema": { "properties": { "id": { "type": "string" } }, "required": [ "id" ], "type": "object" }, "name": "receipt_lookup", "outputSchema": null }, { "description": "Permanently deactivates the API key used to make this request. This action is\nirreversible. After revocation, the key will return 401 on all subsequent calls.\nIf you have an active Stripe subscription, you must separately cancel it at\nstripe.com — revoking the key does not cancel billing.\n\nUse this tool when:\n- You want to rotate your API key (revoke old, then provision a new one).\n- You believe your key has been compromised.\n\nDo NOT use this tool when:\n- You want to check quota — use `get_api_key` instead.\n- You intend to keep using the API — this is permanent.\n\nInputs:\n- No body or query parameters. Auth is from the `Authorization: Bearer` header.\n\nReturns:\n- `revoked`: true.\n- `note`: reminder about Stripe subscription cancellation.\n\nCost:\n- Free. Does not count against the daily request limit.\n\nLatency:\n- Typical: <150ms, p99: <400ms.\n", "inputSchema": { "properties": {}, "type": "object" }, "name": "revoke_api_key", "outputSchema": null }, { "description": "Runs a curated signature corpus over a piece of untrusted text — content\nan agent is about to consume, a retrieved document, a tool result, an\nemail body — and returns the matched injection patterns plus a bounded\n0..1 risk score. This is a signal, never a policy decision: the caller\ndecides what to do with a flagged input.\n\nDetected classes: instruction_override (ignore/override previous rules),\nrole_reassignment (you are now DAN / developer mode), exfiltration (leak\nthe system prompt or a secret to a URL), tool_smuggling (covertly invoke\na tool, delete/destroy data), boundary_spoof (fake system/assistant turn\ndelimiters). Input is normalized first to blunt cheap evasions (zero-width\ncharacters, smart quotes, whitespace padding).\n\nUse this tool when:\n- You are an agent about to feed retrieved or third-party text into a model\n and want to check it for embedded instructions first.\n- You are triaging why a tool description or web page looks suspicious.\n\nDo NOT use this tool when:\n- You want a trust verdict on a domain or entity — use `cross_lens_verify`.\n- You want to scan a whole MCP server's tools — use `scan_mcp`.\n\nInputs:\n- `text` (body, required): the untrusted text to scan. Max 200,000 chars.\n\nReturns:\n- `flagged`: true if any signature matched.\n- `score`: bounded 0..1 risk score (saturating — one high-severity hit is\n already strongly flagged; many hits approach but never exceed 1).\n- `severity_max`: highest severity among matches (`high`/`medium`/`low`) or null.\n- `classes`: distinct injection classes matched.\n- `matches`: each matched signature `{ id, class, severity, excerpt }`.\n\nCost:\n- Free. No API key required. Pure edge computation, no external calls.\n\nLatency:\n- Typical <20ms.\n", "inputSchema": { "properties": { "text": { "description": "Untrusted text to scan for injection signatures.", "maxLength": 200000, "type": "string" } }, "required": [ "text" ], "type": "object" }, "name": "scan_injection", "outputSchema": null }, { "description": "Connect to a caller-supplied MCP server (Streamable-HTTP transport),\nread its advertised tools, and run the injection corpus over every tool\nname / description / input schema — plus a capability heuristic that\nflags broad, dangerous powers (shell execution, filesystem write,\ncredential access, arbitrary network, destructive DB ops). Returns a\nper-tool safety report. A caution to review, never a verdict.\n\nThis is a single-target, caller-initiated scan. It is NOT a crawler and\ndoes not follow links or enumerate other servers. Loopback / private /\ninternal hosts are rejected.\n\nUse this tool when:\n- You are about to connect an agent to a third-party MCP server and want\n to inspect its tools for embedded instructions or excessive powers first.\n\nDo NOT use this tool when:\n- You only have a blob of text — use `scan_injection`.\n- You want a trust verdict on a domain or entity — use `cross_lens_verify`.\n\nInputs:\n- `url` (body, required): the MCP server endpoint (http/https).\n\nReturns:\n- `server`: `{ name, version }` reported by the server, if any.\n- `tools_scanned`: number of tools inspected.\n- `flagged_count`: tools with an injection hit or a flagged capability.\n- `risk`: worst per-tool risk across the server (`high`/`medium`/`low`/`none`).\n- `score`: max injection score across tools (0..1).\n- `tools`: per tool `{ name, risk, injection{...}, capabilities[] }`.\n\nCost:\n- Free. No API key required.\n\nLatency:\n- Bounded by the target server's handshake; typically <2s.\n", "inputSchema": { "properties": { "url": { "description": "MCP server endpoint (Streamable-HTTP). http or https.", "format": "uri", "type": "string" } }, "required": [ "url" ], "type": "object" }, "name": "scan_mcp", "outputSchema": null }, { "description": "Searches both the domains table and the entities table simultaneously. Returns\nmatching domains (by domain name) and entities (by name or slug) in a single\nresponse. Minimum 2 characters, maximum 100 characters.\n\nUse this tool when:\n- You have a partial name and need to identify what tracker or entity it belongs to.\n- You want to find all TunnelMind records related to a company name like \"Google\" or \"Oracle\".\n- You are resolving an ambiguous domain (e.g., does `criteo.com` appear in the tracker DB?).\n\nDo NOT use this tool when:\n- You know the exact domain — use `get_domain` instead (faster, more complete).\n- You know the exact entity slug — use `get_entity` instead.\n- You want to browse by category or industry — use `list_domains` or `list_entities`.\n\nInputs:\n- `q` (query, required): Search string, 2-100 characters. Matched against domain names\n and entity names/slugs.\n\nReturns:\n- `domains`: array of matching domain records (list item format).\n- `entities`: array of matching entity records (list item format).\n- Both arrays may be empty if no matches found. No pagination — results are capped\n at 20 per type.\n\nCost:\n- Free tier: included in 50 req/day. Pro/enterprise: included in plan.\n\nLatency:\n- Typical: <200ms, p99: <500ms.\n", "inputSchema": { "properties": { "q": { "example": "google", "maxLength": 100, "minLength": 2, "type": "string" } }, "required": [ "q" ], "type": "object" }, "name": "search", "outputSchema": null }, { "description": "Returns a publisher's ads.txt change log — one entry per crawl in which\nits authorized-seller set changed. A publisher quietly adding a reseller\nline is a real fraud signal; this is how a buyer audits supply over time.\n\nInputs:\n- `domain` (path, required): publisher domain.\n- `since` (query, optional): ISO date / date-time lower bound on `observed_at`.\n- `limit` (query, optional): max entries — default 50, max 200.\n\nReturns `changes[]`, newest first — each with `observed_at`,\n`added_count`, `removed_count`, `additions`, `removals`,\n`directive_changes`.\n", "inputSchema": { "properties": { "domain": { "type": "string" }, "limit": { "default": 50, "maximum": 200, "type": "integer" }, "since": { "format": "date-time", "type": "string" } }, "required": [ "domain" ], "type": "object" }, "name": "sigil_ads_txt_history", "outputSchema": null }, { "description": "Returns an AIT's status, chain head hash, event count, pending-event\ncount, per-tier event counts, and the anchored-bid coverage ratio.\n", "inputSchema": { "properties": { "id": { "type": "string" } }, "required": [ "id" ], "type": "object" }, "name": "sigil_atap_ait_status", "outputSchema": null }, { "description": "Registers an ATAP v0.1 AIT for a media-buying agent under the\n`sigil:media_buyer:v1` profile. Sigil validates the capability set and\nconstraints against the published profile, signs the AIT as the witness\n(`OAI-2026-0000201`), stores it, and returns the signed token.\n\nSigil is the ATAP witness — there is no kernel observer. See\nhttps://github.com/TunnelMind/atap-profiles.\n", "inputSchema": { "properties": { "agent_type": { "default": "media-buyer", "type": "string" }, "attestation_policy": { "type": "object" }, "capabilities": { "items": { "type": "string" }, "type": "array" }, "constraints": { "type": "object" }, "expires_at": { "format": "date-time", "type": "string" }, "operator": { "description": "The agent operator's canonical OAI.", "type": "string" }, "profile": { "example": "sigil:media_buyer:v1", "type": "string" } }, "required": [ "profile", "operator", "capabilities", "constraints", "attestation_policy", "expires_at" ], "type": "object" }, "name": "sigil_atap_register_ait", "outputSchema": null }, { "description": "Rolls every not-yet-blocked Witness Event for an AIT into one signed\nATAP Attestation Block with a profile `period_summary`, chained onto the\nprior block.\n", "inputSchema": { "properties": { "ait": { "type": "string" } }, "required": [ "ait" ], "type": "object" }, "name": "sigil_atap_roll_block", "outputSchema": null }, { "description": "Ingests one agent-reported event (`bid:submitted`, `bid:won`,\n`bid:lost`, `budget:decremented`) into an AIT's hash-chained\nattestation log. Sigil validates the payload (rejecting any PII per\nATAP §7.6), classifies the evidence tier — `anchored` if a\n`bid:submitted` cites a valid Sigil token issued for this AIT and\nmatching the bid's supply path, otherwise `asserted` — derives any\n`constraint:violated` events, then chains and signs each event.\n\n`supply:verified` / `supply:rejected` are witness-emitted by\n`sigil_verify_supply_path`, never accepted here — that is what makes\nthe `witnessed` tier non-bypassable.\n", "inputSchema": { "properties": { "ait": { "type": "string" }, "event_type": { "enum": [ "bid:submitted", "bid:won", "bid:lost", "budget:decremented" ], "type": "string" }, "payload": { "type": "object" } }, "required": [ "ait", "event_type", "payload" ], "type": "object" }, "name": "sigil_atap_witness", "outputSchema": null }, { "description": "Assembles the ATAP v0.1 §7.5 Receipt ZIP for an AIT — the signed\nReceipt (`manifest.json`), the AIT, the Attestation Block chain, the\nwitness public key, a tier-graded `summary.json`, the bundled\n`verify.sh` reference verifier, and the witness events + sigil_tokens\nas profile artifacts. Any pending events are rolled into a final block\nfirst.\n\nThe ZIP verifies offline — unpack it and run `verify.sh`; keys are at\nhttps://tunnelmind.ai/atap/keys. The summary grades every event as\n`witnessed`, `anchored`, or `asserted` and reports the anchored-bid\ncoverage ratio.\n", "inputSchema": { "properties": { "ait": { "type": "string" }, "format": { "default": "full", "enum": [ "full", "summary" ], "type": "string" } }, "required": [ "ait" ], "type": "object" }, "name": "sigil_receipt_generate", "outputSchema": null }, { "description": "Scores up to 200 entities in one round-trip — built for agents\nevaluating many supply sources during campaign setup. Per-item parse\nfailures are returned inline; the batch never fails as a whole.\n\nAn optional `weights` object re-weights every entity in the call.\n", "inputSchema": { "properties": { "entity_ids": { "example": [ "publisher:nytimes.com", "ssp:pubmatic.com" ], "items": { "type": "string" }, "maxItems": 200, "type": "array" }, "weights": { "description": "Optional custom weights: an object of `{ type: { component: weight } }`.", "type": "object" } }, "required": [ "entity_ids" ], "type": "object" }, "name": "sigil_score_batch", "outputSchema": null }, { "description": "Returns the pre-computed 0.0–1.0 trust score for one entity, its\ncomponent breakdown, and the 14-day trend. Scores are refreshed daily\nby a database job — this endpoint never recomputes from raw data, so it\nis fast and deterministic.\n\n`entity_id` is `{entity_type}:{key}` — e.g. `publisher:nytimes.com` or\n`ssp:pubmatic.com`. Entity types: `publisher`, `ssp`, `dsp`,\n`app_bundle` (publishers and SSPs are scored today).\n\nv1 evaluates structural components only (`ads_txt_health`,\n`supply_chain_directness`, `historical_stability` for publishers;\n`supply_reach`, `directness` for SSPs). The `not_evaluated` list names\nspec components without an enrichment path yet.\n\nOptional `weights` query param (URL-encoded JSON) re-weights the stored\ncomponents for this call.\n", "inputSchema": { "properties": { "entity_id": { "type": "string" }, "weights": { "description": "URL-encoded JSON: an object of `{ type: { component: weight } }`.", "type": "string" } }, "required": [ "entity_id" ], "type": "object" }, "name": "sigil_score_entity", "outputSchema": null }, { "description": "Returns the active, versioned default weights used to combine an\nentity's trust-score components, plus the list of spec components that\nare not yet evaluated. Pass a custom `weights` object to\n`sigil_score_batch` to re-weight without changing the defaults.\n", "inputSchema": { "properties": {}, "type": "object" }, "name": "sigil_score_weights", "outputSchema": null }, { "description": "Reconstructs the supply paths for a publisher domain from Sigil's own\ncrawl and returns them ITEMIZED — distinct from `sigil_verify_supply_chain`\n(which verifies a schain the caller brings) and from `signal_dark_pool_risk`\n(which returns only aggregate counts). Every SSP the publisher declares it\nsells through is joined to that SSP's identity and classified two-sided\nagainst the SSP's sellers.json: `corroborated` (seat present),\n`contradicted` (SSP crawled but seller_id absent — real risk), `unchecked`\n(SSP not yet crawled — not risk). Each returned path also carries\n`resells_to`, one level of downstream reseller expansion.\n\nThe list is ordered riskiest-first (contradicted, then reseller) so a\ntruncated page is still the most useful; the `supply_paths` counts are\nalways over the FULL set. `in_supply_graph:false` when the domain is not\na known publisher.\n", "inputSchema": { "properties": { "domain": { "description": "Publisher hostname to traverse.", "type": "string" }, "limit": { "default": 200, "description": "Max paths returned (default 200, hard cap 500).", "maximum": 500, "minimum": 1, "type": "integer" } }, "required": [ "domain" ], "type": "object" }, "name": "sigil_traverse", "outputSchema": null }, { "description": "Confirms whether an SSP/exchange is authorized to sell a publisher's\ninventory according to that publisher's ads.txt. This is a cache lookup\nagainst ads.txt files crawled daily across the top 10,000 publisher\ndomains — it does NOT fetch the publisher's ads.txt live, so it is fast\nand adds no latency to a real-time bidding decision.\n\nUse this tool when:\n- You are an ad-buying agent and want to confirm, pre-bid, that a supply\n path (publisher → exchange → seller_id) is legitimate.\n- You are detecting domain spoofing or unauthorized resale in a bid stream.\n- You want to check whether a seller is listed DIRECT or RESELLER.\n\nDo NOT use this tool when:\n- You want a full supply-path trust score — that endpoint is Sigil P31.\n- You want surveillance tracker data for the domain — use `get_domain`.\n\nInputs:\n- `publisher_domain` (body, required): Publisher domain, e.g. `nytimes.com`.\n A `www.` prefix and scheme/path are stripped automatically.\n- `exchange_domain` (body, required): The exchange/SSP domain as it appears\n in ads.txt, e.g. `google.com`, `amazon-adsystem.com`.\n- `seller_id` (body, required): The publisher's seller/account ID at that\n exchange, e.g. `pub-4177862836555934`. Matched exactly.\n- `seller_type` (body, optional): `DIRECT` or `RESELLER`. When supplied it\n is checked against the ads.txt entry; a mismatch is reported as a warning.\n- `resolve_chain` (body, optional): When true, a matched RESELLER entry is\n cross-checked against the exchange's sellers.json (one authoritative hop).\n\nReturns:\n- `verified`: true (entry found), false (confidently not listed), or null\n (ads.txt could not be retrieved — indeterminate).\n- `confidence`: `high` | `degraded` | `low` | `unknown`.\n- `seller_entry`: the matched ads.txt line (line number, raw text, parsed\n fields) when `verified` is true; otherwise null.\n- `ads_txt_parse_status`, `ads_txt_last_parsed`, `stale`: provenance of the\n cached crawl this answer is derived from.\n- `reseller_chain`: empty unless `resolve_chain: true` and the matched entry\n is RESELLER — then it carries the sellers.json cross-check for the seller.\n- `warnings`: actionable flags, e.g. `publisher_not_in_corpus`,\n `publisher_has_no_ads_txt`, `seller_type_mismatch`, `ads_txt_cache_stale`.\n\nCost:\n- Counts as one request against the daily rate limit.\n\nLatency:\n- Typical: <50ms (single cache lookup, no outbound fetch). p99: <120ms.\n", "inputSchema": { "properties": { "exchange_domain": { "description": "Exchange/SSP domain as listed in ads.txt", "example": "amazon-adsystem.com", "type": "string" }, "publisher_domain": { "description": "Publisher domain (www. prefix and scheme stripped)", "example": "nytimes.com", "type": "string" }, "receipt": { "default": false, "description": "When true, attach a signed Receipt v1.0 committed to the transparency log. Additive — the response shape is otherwise unchanged, and a signing failure never costs you the verdict (ADR-014).", "type": "boolean" }, "resolve_chain": { "default": false, "description": "When true, a matched RESELLER entry is cross-checked against the exchange's sellers.json", "type": "boolean" }, "seller_id": { "description": "Publisher's seller/account ID at the exchange", "example": "3030", "maxLength": 128, "type": "string" }, "seller_type": { "description": "Optional — checked against the ads.txt entry", "enum": [ "DIRECT", "RESELLER" ], "type": "string" } }, "required": [ "publisher_domain", "exchange_domain", "seller_id" ], "type": "object" }, "name": "sigil_verify_ads_txt", "outputSchema": null }, { "description": "Runs up to 100 ads.txt verifications in a single call — the endpoint an\nad-buying agent uses for pre-bid checks across a whole campaign's supply.\nEach item is the same shape as `sigil_verify_ads_txt`. Per-item\nvalidation failures are reported inline; the batch never fails as a\nwhole. Publisher records are fetched once per unique domain.\n\nUse this tool when:\n- You are evaluating many supply paths at once (campaign setup, SPO sweep).\n- You want one round-trip instead of N calls to `sigil_verify_ads_txt`.\n\nInputs:\n- `items` (body, required): Array of 1–100 verification requests, each\n `{ publisher_domain, exchange_domain, seller_id, seller_type? }`.\n- `resolve_chain` (body, optional): Applies to every item — when true, a\n matched RESELLER entry is cross-checked against the exchange's sellers.json.\n\nReturns:\n- `count`: number of result entries (matches `items` length, in order).\n- `verified_count`: how many resolved to `verified: true`.\n- `results`: array aligned to `items`. Each entry is either a verification\n result with `ok: true` and `input_index`, or `{ ok: false, input_index,\n error, message }` for an invalid item.\n\nCost:\n- Counts as one request against the daily rate limit.\n\nLatency:\n- Typical: <150ms. With `resolve_chain: true`, add one sellers.json fetch\n per unique exchange (edge-cached 12h after the first fetch).\n", "inputSchema": { "properties": { "items": { "description": "1–100 verification requests", "items": { "properties": { "exchange_domain": { "example": "amazon-adsystem.com", "type": "string" }, "publisher_domain": { "example": "nytimes.com", "type": "string" }, "seller_id": { "example": "3030", "maxLength": 128, "type": "string" }, "seller_type": { "enum": [ "DIRECT", "RESELLER" ], "type": "string" } }, "required": [ "publisher_domain", "exchange_domain", "seller_id" ], "type": "object" }, "maxItems": 100, "minItems": 1, "type": "array" }, "resolve_chain": { "default": false, "description": "Resolve reseller chains for every RESELLER item", "type": "boolean" } }, "required": [ "items" ], "type": "object" }, "name": "sigil_verify_ads_txt_batch", "outputSchema": null }, { "description": "Reports whether a domain publishes ads.cert (IAB Tech Lab Authenticated\nConnections) DNS records — a readiness signal showing the domain\nsupports cryptographically authenticated ad-tech connections. This is\nnot signature verification: ads.cert is pairwise, so verifying a signed\nbid request requires Sigil to be a delegated participant (a future\nbuild). DNS-only and stateless.\n\nInputs:\n- `domain` (query, required): Domain to check.\n\nReturns:\n- `adscert_ready`: true | false | null (DNS lookup failed).\n- `adscert_records`: TXT values at `_adscert.{domain}`.\n- `delegation_records`: TXT values at `_delegated._adscert.{domain}`.\n", "inputSchema": { "properties": { "domain": { "type": "string" } }, "required": [ "domain" ], "type": "object" }, "name": "sigil_verify_adscert", "outputSchema": null }, { "description": "Verifies that a mobile or CTV app bundle ID actually exists in the\nrelevant app store — used to detect bundle spoofing in bid requests.\n\nPlatform support (v1):\n- `ios`: verified live via Apple's iTunes Lookup API.\n- `android`: verified live via the Google Play store listing page.\n- `ctv_*` / `web`: no public store API — returns verified=null.\n\nInputs:\n- `bundle_id` (body, required): e.g. `com.nytimes.NYTimes`.\n- `platform` (body, required): ios | android | ctv_roku | ctv_fire |\n ctv_samsung | ctv_lg | ctv_vizio | web.\n- `claimed_developer` (body, optional): checked against the store listing.\n\nReturns:\n- `verified`: true | false | null. null means one of two things: the\n platform has no store API (confidence `low`, warning\n `no_store_api_available`), or the store lookup failed (confidence\n `degraded`, warning `store_api_unavailable`, with `reason`).\n- `reason`: why the store lookup failed — http_<status> | timeout |\n network_<error name> | bad_response. Present only on the degraded path.\n When the relay was also tried and failed it is\n `<worker reason>+relay_<relay reason>`, e.g. `http_403+relay_timeout`.\n- `source` (iOS only): `worker` | `relay`. When the Worker's own iTunes\n lookup ends in http_403, http_429 or network_* and the relay is\n configured, the lookup is retried once through TunnelMind's relay;\n `relay` means the relay was consulted (success or failure).\n- `store_listing`: name, developer, developer_match, store_url.\n", "inputSchema": { "properties": { "bundle_id": { "example": "com.nytimes.NYTimes", "maxLength": 255, "type": "string" }, "claimed_developer": { "example": "The New York Times Company", "type": "string" }, "platform": { "enum": [ "ios", "android", "ctv_roku", "ctv_fire", "ctv_samsung", "ctv_lg", "ctv_vizio", "web" ], "type": "string" } }, "required": [ "bundle_id", "platform" ], "type": "object" }, "name": "sigil_verify_app_bundle", "outputSchema": null }, { "description": "Confirms a publisher controls a domain by checking for a DNS TXT record\nthe owner publishes under `_tunnelmind.{domain}`. A DNS record can only\nbe set by whoever controls the zone, so its presence proves control — a\nstronger signal than ads.txt, which is just a file anything in the\nrequest path can serve.\n\nUse this tool when:\n- You want proof a publisher actually owns the domain it claims.\n- You are distinguishing publishers who have opted into Sigil verification.\n\nInputs:\n- `domain` (query, required): Publisher domain. `www.` and scheme stripped.\n\nReturns:\n- `verified`: true (record found), false (absent), or null (DNS lookup failed).\n- `expected`: the exact TXT record the owner must publish to verify.\n- `found_records`: TXT values currently present at `_tunnelmind.{domain}`.\n- `checked_at`: ISO 8601 timestamp of the live DNS lookup.\n\nCost:\n- Counts as one request against the daily rate limit.\n\nLatency:\n- Typical: <300ms (one DNS-over-HTTPS lookup).\n", "inputSchema": { "properties": { "domain": { "type": "string" } }, "required": [ "domain" ], "type": "object" }, "name": "sigil_verify_domain", "outputSchema": null }, { "description": "Classifies an IPv4 or IPv6 address by network type — the high-value ad-fraud\nsignal being datacenter traffic posing as residential or living-room\n(CTV) devices. IP→ASN resolution uses Team Cymru's public service; the\nASN is then classified by its registered organization name.\n\nIt also cross-references the Scry attacker-observation corpus to detect\nanonymizing EGRESS — the thing a rotating-residential proxy provider is\nbuilt to hide. A residential- or mobile-looking IP that Scry has observed\nacting as a hostile actor is a residential-proxy exit node (home devices\ndon't scan honeypots); tor and vpn egress are named outright.\n\nIt also identifies the proxy COMPANY by network: if the IP's ASN belongs\nto a known VPN/anonymizing-egress provider (X4BNet's curated list), the\nverdict is `vpn` and `scry_signals` carries `vpn_provider_asn` — even\nwhen Scry has never observed the IP acting. Datacenter and residential\nproxy verdicts still require observed conduct.\n\nPRIVACY: the IP is used for lookup only — never logged, never stored. The\nScry cross-reference is likewise a read-only corpus lookup.\n\nInputs:\n- `ip` (query, required): IPv4 or IPv6 address.\n\nReturns:\n- `ip_type`: datacenter | residential | mobile | unknown.\n- `confidence`: high | medium | low.\n- `asn`, `asn_name`: the resolved autonomous system.\n- `proxy_suspected`: boolean — the IP is an anonymizing egress.\n- `proxy_type`: tor | vpn | residential_proxy | datacenter_proxy | null.\n- `scry_signals`: evidence strings from the corpus (actor_class, threat\n feeds, observation counts); empty when the IP is unknown to Scry.\n\nLatency:\n- Typical: 100-250ms (DNS + a parallel corpus lookup).\n", "inputSchema": { "properties": { "ip": { "type": "string" } }, "required": [ "ip" ], "type": "object" }, "name": "sigil_verify_ip_type", "outputSchema": null }, { "description": "The bid-time contract. Pass the SupplyChain object from an OpenRTB bid\nrequest (`source.ext.schain`) verbatim, plus the originating site domain\nor app bundle. Sigil verifies, per node and in aggregate:\n\n- origin ads.txt — the publisher's ads.txt authorizes node[0] (asi + sid).\n- per node — the node's `asi` sellers.json declares the node's `sid`.\n- owner-domain — node[0]'s sellers.json seller `domain` matches the\n publisher's ads.txt OWNERDOMAIN / MANAGERDOMAIN (spec §3.5.1).\n- `schain.complete` — an incomplete chain caps the verdict at `warn`.\n\nOpenRTB field mapping: `site.domain` → `site_domain`; `app.bundle` →\n`app_bundle`; `source.ext.schain` → `schain`. An app_bundle origin's\nads.txt check is `not_evaluated` pending app-ads.txt resolution.\n\nReturns a per-node result array, an aggregate `verdict`\n(pass/warn/fail/unknown), `recommendations`, and a signed `sigil_token`.\n", "inputSchema": { "properties": { "app_bundle": { "example": "com.example.app", "type": "string" }, "buyer": { "description": "Optional. When present and the verdict is not `fail`, Sigil\nopportunistically records a `buys_through` edge linking the\nbuyer entity to the resolved DSP. Side-effect persistence\nonly — never affects the verdict or response shape, silent\non every failure path. Requires `entity_slug` plus one of\n`dsp_domain` / `dsp_id`.\n", "properties": { "dsp_domain": { "example": "thetradedesk.com", "type": "string" }, "dsp_id": { "example": 42, "type": "integer" }, "entity_slug": { "example": "trade-desk", "type": "string" } }, "required": [ "entity_slug" ], "type": "object" }, "schain": { "properties": { "complete": { "enum": [ 0, 1 ], "type": "integer" }, "nodes": { "items": { "properties": { "asi": { "example": "exchange-a.com", "type": "string" }, "hp": { "enum": [ 0, 1 ], "type": "integer" }, "sid": { "example": "12345", "type": "string" } }, "required": [ "asi", "sid" ], "type": "object" }, "maxItems": 20, "minItems": 1, "type": "array" } }, "required": [ "nodes" ], "type": "object" }, "site_domain": { "example": "example.com", "type": "string" } }, "required": [ "schain" ], "type": "object" }, "name": "sigil_verify_supply_chain", "outputSchema": null }, { "description": "The core Sigil pre-bid call. Submit a supply path; Sigil composes its\nindividual checks into one trust verdict and returns a signed\n`sigil_token` the agent can attach to its bid as proof of verification.\n\nChecks composed:\n- `ads_txt` — exchange authorized in the publisher's ads.txt.\n- `datacenter_ip` — is the IP a datacenter posing as a real user.\n- `fraud_signals` — is the IP in Scry's attacker-intelligence corpus.\n- `bundle_verified` — does the app bundle exist in its store.\n- `domain_authenticity` / `entity_reputation` — reserved, not evaluated in v1.\n\nEach evaluated check yields pass/warn/fail; `trust_score` is their\nweighted mean (override `weights` per request); `verdict` is\npass/warn/fail/unknown (override `thresholds`).\n\nPRIVACY: `ip_address` is used for lookup only — never logged, never\nstored, never placed in the sigil_token. `geo` is accepted but unused.\n\nReturns: `trust_score` (0-1 or null), `verdict`, `checks`,\n`recommendations`, `sigil_token` (signed, 5-minute lifetime).\n", "inputSchema": { "properties": { "buyer": { "description": "Optional. When present and the verdict is not `fail`, Sigil\nopportunistically records a `buys_through` edge linking the\nbuyer entity to the resolved DSP. Side-effect persistence\nonly — never affects the verdict or response shape, silent\non every failure path. Requires `entity_slug` plus one of\n`dsp_domain` / `dsp_id`.\n", "properties": { "dsp_domain": { "example": "thetradedesk.com", "type": "string" }, "dsp_id": { "example": 42, "type": "integer" }, "entity_slug": { "example": "trade-desk", "type": "string" } }, "required": [ "entity_slug" ], "type": "object" }, "receipt": { "default": false, "description": "When true, attach a signed Receipt v1.0 committed to the transparency log. Additive — the response shape is otherwise unchanged, and a signing failure never costs you the verdict (ADR-014).", "type": "boolean" }, "supply_path": { "properties": { "app_bundle": { "properties": { "bundle_id": { "type": "string" }, "claimed_developer": { "type": "string" }, "platform": { "type": "string" } }, "type": "object" }, "device_type": { "example": "desktop", "type": "string" }, "exchange": { "example": "amazon-adsystem.com", "type": "string" }, "ip_address": { "example": "203.0.113.42", "type": "string" }, "publisher_domain": { "example": "nytimes.com", "type": "string" }, "seller_id": { "example": "3030", "type": "string" }, "seller_type": { "enum": [ "DIRECT", "RESELLER" ], "type": "string" } }, "required": [ "publisher_domain" ], "type": "object" }, "thresholds": { "description": "{ pass, fail } verdict cutoffs", "type": "object" }, "weights": { "description": "Per-check weight overrides", "type": "object" } }, "required": [ "supply_path" ], "type": "object" }, "name": "sigil_verify_supply_path", "outputSchema": null }, { "description": "Verifies the authenticity and expiry of a `sigil_token` returned by\n`sigil_verify_supply_path`. Anyone can call this — no key needed; Sigil\nverifies the Ed25519 signature server-side. Tokens live 5 minutes.\n\nReturns `valid` (boolean), `reason` (when invalid: malformed / expired /\nbad_signature / unsigned), and the decoded `payload`.\n", "inputSchema": { "properties": { "token": { "type": "string" } }, "required": [ "token" ], "type": "object" }, "name": "sigil_verify_token", "outputSchema": null }, { "description": "Reconciles every sell path a publisher declares (`sells_through`) against\neach SSP's own sellers.json (`exchange_seat`) and keeps three classes\nstrictly separate: `corroborated` (seat present), `contradicted` (SSP\ncrawled but seller_id absent — real risk), and `unchecked` (SSP not yet\ncrawled — excluded from risk, lowers confidence). Combined with\npublisher-side ads.txt opacity. Two-sided corroboration is the cross-lens\nmoat — it catches unauthorized resale a one-sided ads.txt read cannot.\n", "inputSchema": { "properties": { "domain": { "description": "Publisher hostname.", "type": "string" } }, "required": [ "domain" ], "type": "object" }, "name": "signal_dark_pool_risk", "outputSchema": null }, { "description": "Scores an entity by the trust character of its neighbours — the SSPs its\npublishers sell through and the DSPs it buys through. Reports neighbour\ncounts, mean/min neighbour trust, and how many neighbours are\nadversary-classified (P46). `derived.halo_score` (0–100, or null when no\nneighbour has a computed trust) is mean neighbour trust dragged down by\nadversary-neighbour share. Evidence about an entity's company, not a\npersisted verdict — no profile poisoning.\n", "inputSchema": { "properties": { "entity_slug": { "description": "Stable kebab-case entity identifier.", "type": "string" } }, "required": [ "entity_slug" ], "type": "object" }, "name": "signal_halo_score", "outputSchema": null }, { "description": "Surfaces other entities that operate as a coordinated team with this one:\nthey share a NARROWLY-held direct seller account (2–8 entities — network\nhouse accounts shared by hundreds are separated into\n`house_accounts_excluded`, not counted) or co-own an exchange seat.\n`derived.team_signal` (0–100) is a coordination magnitude over teammate\ncount, shared-account breadth, and co-owned seats.\n", "inputSchema": { "properties": { "entity_slug": { "description": "Stable kebab-case entity identifier.", "type": "string" } }, "required": [ "entity_slug" ], "type": "object" }, "name": "signal_team_signal", "outputSchema": null }, { "description": "Observed component counts first, a labelled derived roll-up second. The\ncomponents — `data_categories`, supply-surface counts (ssp + publisher +\ndsp + owns_seat + buys_through), and corroborating `sources` — are facts.\n`derived.tracker_density` (0–100) is a weighted blend of those counts, not\na measurement; `data_cost_usd` is deliberately excluded (non-zero only for\na curated seed, so weighting by it would fabricate precision). Anchors the\n`surveillance_bigtech` adversary class for the cross-lens classifier.\n", "inputSchema": { "properties": { "entity_slug": { "description": "Stable kebab-case entity identifier ([a-z0-9-], 1–255 chars).", "type": "string" } }, "required": [ "entity_slug" ], "type": "object" }, "name": "signal_tracker_density", "outputSchema": null }, { "description": "The exact bytes the manifest's sha256 commits to. Content-Type\n`application/x-ndjson`; rows ordered by domain. Verify:\n`sha256(body) == manifest.sha256`.\n", "inputSchema": { "properties": { "date": { "type": "string" } }, "required": [ "date" ], "type": "object" }, "name": "snapshot_data", "outputSchema": null }, { "description": "JSONL diff vs the previous snapshot — apply +/~/- lines instead of re-pulling the corpus.", "inputSchema": { "properties": { "date": { "type": "string" } }, "required": [ "date" ], "type": "object" }, "name": "snapshot_diff", "outputSchema": null }, { "description": "P4 corpus replication, the OPA \"push data into the PDP\" pattern. A\ndaily snapshot of the domain corpus (domain, score, category,\nfingerprinting, entity) is published as deterministic JSONL with a\nmanifest carrying row_count, sha256 over the exact bytes, a diff\nsummary vs the previous day, and an Ed25519-signed Receipt v1.0\ncommitted to the transparency log — a PDP that replicates the data\ncan verify offline that it loaded exactly what was published.\n\n`date` is `YYYY-MM-DD` or `latest`. Retention: 14 days. Fetch the\nrows from `data_url`, apply increments from `diff_url`\n(`{\"op\":\"+\"|\"~\"|\"-\"}` per line), re-pull the full file when the\nmanifest marks the diff truncated.\n", "inputSchema": { "properties": { "date": { "type": "string" } }, "required": [ "date" ], "type": "object" }, "name": "snapshot_manifest", "outputSchema": null }, { "description": "One sample per 20-minute monitor sweep. `uptime_pct` is the share of\nsweeps in which every fail point was green (the strictest read);\n`per_monitor` lists only monitors that failed at least once in the\nwindow. History begins at feature deploy and is never extrapolated\nbackwards — an empty window returns `uptime_pct: null`, not 100.\n", "inputSchema": { "properties": { "days": { "default": 30, "maximum": 90, "minimum": 1, "type": "integer" } }, "type": "object" }, "name": "status_history", "outputSchema": null }, { "description": "Opens a persistent SSE connection that emits events as the task progresses.\nThe stream closes automatically when the task reaches a terminal state or after\n~90 seconds (timeout). Heartbeat comments are sent every ~15 seconds to keep\nthe connection alive through proxies.\n\nEvent types:\n- `status` — emitted when status changes (pending → running → complete/failed)\n- `result` — emitted on `complete` with the full result payload\n- `error` — emitted on `failed`, `cancelled`, or `expired` with error info\n- SSE comment (`: heartbeat`) — keepalive, no data\n\nUse this tool when:\n- You want real-time progress without polling.\n- You are in an environment that supports SSE (EventSource API).\n\nDo NOT use this tool when:\n- You want a simple one-shot status check — use `get_task` instead.\n- Your HTTP client doesn't support streaming responses.\n\nInputs:\n- `task_id` (path, required): 26-char ULID.\n\nReturns:\n- SSE stream (`text/event-stream`). Each event is `event: <type>\\\\ndata: <json>\\\\n\\\\n`.\n\nCost:\n- Free. Counts as one request against rate limits when the stream opens.\n\nLatency:\n- First event: <200ms. Stream duration: up to 90s.\n", "inputSchema": { "properties": { "task_id": { "pattern": "^[A-Z0-9]{26}$", "type": "string" } }, "required": [ "task_id" ], "type": "object" }, "name": "stream_task", "outputSchema": null }, { "description": "Close the loop: after you acted on a TunnelMind verdict, tell us how it\nwent. Reports aggregate per node into an advisory second opinion that any\ncaller can read back via `GET /v1/feedback/{node}`.\n\nAdvisory only. In v0 a negative aggregate does NOT silently lower the\nfused trust score — it's a human-weighable signal beside the verdict, not\nan automatic reweight.\n\nUse this tool when:\n- You acted on a verdict and want to record the real-world outcome\n (honored, defrauded, no issue) to help future callers.\n\nInputs:\n- `node` (body, required): the subject — ip, domain, asn, or entity slug.\n- `outcome` (body, required): one of `positive`, `negative`, `neutral`.\n- `receipt_id` (body, optional): the verdict receipt this outcome refers to.\n- `note` (body, optional): free-text context, max 500 chars.\n\nReturns the updated advisory aggregate `{ node, counts, total, score, signal }`.\n\nCost:\n- Free. Requires an API key (authenticated callers only).\n", "inputSchema": { "properties": { "node": { "example": "doubleclick.net", "type": "string" }, "note": { "maxLength": 500, "type": "string" }, "outcome": { "enum": [ "positive", "negative", "neutral" ], "example": "negative", "type": "string" }, "receipt_id": { "example": "rcpt_abc123", "type": "string" } }, "required": [ "node", "outcome" ], "type": "object" }, "name": "submit_feedback", "outputSchema": null }, { "description": "Free bulk read of the commons — the raw record is never paywalled. Every\nrow is a tollbooth document exactly\nas its site signed it (Ed25519 over RFC 8785 JCS, key = the row's own\n`site`), wrapped in a `_commons` envelope naming the tier and vouching\ndomain. Nothing in a row requires trusting TunnelMind.\n\nUse this tool when:\n- You want the raw record behind the stats, or to verify it yourself.\n- You are building your own exhibit or comparison over attested sites.\n\nReturns:\n- `rows[]`: `{_commons: {tier, domain, received_at}, receipt | snapshot}`.\n- `rows_returned`, `limit`, `capped` (true when the day has more than `limit`).\n\nCost:\n- Counts as one request against the daily rate limit. Past days cached 1h.\n\nLatency:\n- Typical: <200ms cached; up to ~1s on a cache miss for a busy day.\n", "inputSchema": { "properties": { "day": { "description": "UTC day, YYYY-MM-DD. Defaults to yesterday.", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "type": "string" }, "format": { "default": "json", "description": "json for the {ok,data} envelope (what this tool reads); omit for the NDJSON download.", "enum": [ "json" ], "type": "string" }, "kind": { "default": "receipts", "enum": [ "receipts", "reports" ], "type": "string" }, "limit": { "default": 200, "description": "Rows to return (JSON form defaults to 200; the NDJSON download at the same URL defaults to 5000).", "maximum": 5000, "minimum": 1, "type": "integer" }, "tier": { "default": "attested", "enum": [ "attested", "all" ], "type": "string" } }, "type": "object" }, "name": "tollbooth_export", "outputSchema": null }, { "description": "Membership of the commons: every signing key that has reported, the\ndomain that vouched for it (by serving the key in its\n/.well-known/tollbooth-site.json), and when it was last re-checked.\nAttested only by default; tier=all adds unattested keys with the domain\nthey CLAIMED but that did not (yet) vouch for them.\n\nUse this tool when:\n- You want to know whose data is in the exhibit, or whether a given site reports.\n- You are verifying an export row's `site` key against a domain.\n\nReturns:\n- `sites[]`: site (public key), domain, status, attested_at, last_checked_at, first_seen_at.\n\nCost:\n- Counts as one request against the daily rate limit.\n\nLatency:\n- Typical: <100ms.\n", "inputSchema": { "properties": { "tier": { "default": "attested", "enum": [ "attested", "all" ], "type": "string" } }, "type": "object" }, "name": "tollbooth_sites", "outputSchema": null }, { "description": "The public read over the Conduct Log Commons: which agents knocked on\nattested tollbooth sites in the last 7 days, what they did when offered\npaid access, and what they would have paid. First-party monitors and\ncredential-scanning recon are classified and EXCLUDED from the headline\n(reported separately, never conflated). Attested tier only — keys a\ndomain has vouched for via /.well-known/tollbooth-site.json.\n\nUse this tool when:\n- You want to know how AI crawlers actually behave when a site asks them to pay.\n- You need the current commons membership (sites by tier) and the export pointers.\n\nReturns:\n- `headline`: agents, requests, would_have_paid_usd, robots_respecting_agents.\n- `named_ai` / `other` / `attack_recon`: per-agent rows with sampled paths.\n- `receipts`: identity-bearing conduct receipts by type.\n- `commons`: tier, sites {attested, unattested}, export + attest pointers.\n\nCost:\n- Counts as one request against the daily rate limit. Not cached.\n\nLatency:\n- Typical: 300–1200ms (two D1 reads over the last 7 days).\n", "inputSchema": { "properties": {}, "type": "object" }, "name": "tollbooth_stats", "outputSchema": null }, { "description": "The Tracker lens-owned verify surface: a per-node verdict over the\nnormalized DDG Tracker Radar / IAB TCF / Disconnect.me corpus, with an\noptional signed TunnelMind Receipt v1.0. This is the single-lens ground\ntruth the fused `POST /v1/verify` cites for its tracker block.\n\nUse this tool when:\n- You need to know whether a domain is tracking/surveillance infrastructure\n and which entity operates it, without the full cross-lens fusion.\n- You want a signed, offline-verifiable receipt for that single-lens answer.\n\nInputs:\n- `node` (path, required): a domain (e.g. `doubleclick.net`) or an entity\n slug (e.g. `google`). IPs and ASNs are not indexable by this lens.\n- `receipt` (query, optional): `true` attaches a Receipt v1.0 envelope.\n\nReturns:\n- `tracking`: true (in the tracker corpus), false (queried, absent), or\n null (not answerable — ip/asn node or backend unavailable; see `reason`).\n- `tracker`: the lens record — domain {category, prevalence, score 0-100}\n plus operating entity {slug, name, parent_company, industry, sources},\n or entity + top_domains when queried by slug.\n- `checked_at`: ISO 8601 timestamp of the corpus read.\n- `receipt`: TunnelMind Receipt v1.0 (Ed25519, JCS) when requested.\n\nCost:\n- Counts as one request against the daily rate limit.\n\nLatency:\n- Typical: <100ms (one or two D1 reads at the edge).\n", "inputSchema": { "properties": { "node": { "type": "string" }, "receipt": { "default": false, "type": "boolean" } }, "required": [ "node" ], "type": "object" }, "name": "tracker_verify", "outputSchema": null }, { "description": "Live traction numbers computed from sources the Worker owns: the\nhash-chained D1 audit log (7-day call volume, distinct identified\ncallers, top operations), the stored-receipt table, and Stripe\n(succeeded charges → paying customers, gross USD). Ed25519-signed\nwith the same attestation envelope as /v1/status so the numbers can\nbe replayed to an auditor.\n\nUse this tool when:\n- You are evaluating whether anyone actually uses and pays for this API.\n- You need a signed, re-checkable statement of usage rather than a claim.\n\nReturns:\n- `traction.usage`: calls_7d, identified_callers_7d, anonymous_calls_7d,\n top_operations_7d — or available:false with a reason.\n- `traction.receipts`: stored receipt counts (total / 7d).\n- `traction.revenue`: paying_customers, succeeded_charges, gross_usd,\n `truncated` flag when the Stripe page is partial.\n- `attestation`: Ed25519 signature over the canonicalized traction block.\n\nCost:\n- Counts as one request against the daily rate limit. Cached 1h.\n\nLatency:\n- Typical: <100ms cached; up to ~2s on a cache miss (one Stripe read).\n", "inputSchema": { "properties": {}, "type": "object" }, "name": "traction", "outputSchema": null }, { "description": "The reconciliation layer in one call. Where `cross_lens_verify` answers\n\"what is this network destination,\" `verdict_lookup` answers a different,\nsharper question about a key-addressed ACTOR: **does what this key claims\nabout itself match what the network has seen it do?**\n\nIt fuses two sides:\n- **claim** — what the key can prove about itself: its `attestation_tier`\n across roots of trust (bare Ed25519 self-attestation → a RATS/EAT\n hardware/platform attestation). TunnelMind owns no silicon and reads\n every root; the tier is always *measured/anchored*, never self-asserted\n (a token claiming a higher tier than its trust anchor is trusted to\n assert is capped down).\n- **conduct** — what the graph has seen the key's subject do (Scry × Sigil\n × GhostRoute), supplied via the optional `subject` parameter.\n\nThe response carries `reconciliation.contradictions` (e.g. a key that\nattests `silicon-root` but behaves as a low-trust node →\n`claim_exceeds_conduct`; a presented claim that fails to verify →\n`unverified_claim`; claims presented with no proof of key control →\n`key_control_unproven`), a `claim_vs_conduct_delta`, and a\n`verdict {tier, reputation, flags, confidence}`.\n\nKeys are linked to an identity ONLY when the actor cryptographically\nproves control — never inferred from behavioral correlation. An EAT that\nattests a *different* subject key is rejected, not silently merged.\n\nThe verdict is published as a self-verifying receipt: given the receipt\nbytes + the witness public keys carried inline, anyone re-derives the\nverdict and checks log inclusion OFFLINE with `scripts/verify-verdict.mjs`\n— no call back to TunnelMind. A bare, unattested key still gets a verdict\n(at `self-asserted` tier); attestation is never required to participate.\n", "inputSchema": { "properties": { "claims": { "description": "URL-encoded JSON array of raw claim objects, e.g.\n`[{\"type\":\"ed25519-self\",\"signature\":\"…\",\"nonce\":\"…\"},{\"type\":\"eat\",\"token\":\"…\"}]`.\nOverrides the `nonce`/`sig`/`eat` convenience params when present.\n", "type": "string" }, "eat": { "description": "A RATS/EAT compact JWS (EdDSA) attesting this key, signed by a trusted anchor.", "type": "string" }, "key": { "description": "The actor's Ed25519 public key, as hex (64 chars, optional 0x),\nbase64url (43 chars, unpadded), or did:key (did:key:z6Mk…).\n", "type": "string" }, "nonce": { "description": "Binding nonce for a bare-Ed25519 self-attestation (paired with `sig`).", "type": "string" }, "sig": { "description": "Base64 Ed25519 signature over `nonce`, proving control of the key.", "type": "string" }, "subject": { "description": "An ip / domain / ASN / entity_slug the key claims to act as. Drives the\nconduct (graph behavior) side of the reconciliation. Omit for a\nclaim-only verdict.\n", "type": "string" } }, "required": [ "key" ], "type": "object" }, "name": "verdict_lookup", "outputSchema": null }, { "description": "Reconciles a claimed bot User-Agent against the operator's OWN published\nIP-range feed (Googlebot, GPTBot, OAI-SearchBot, ChatGPT-User,\nPerplexityBot, Perplexity-User, Bingbot). A User-Agent is trivial to\nforge; membership in the operator's published CIDR ranges is not. This\nexposes the common attack: a scraper sending `User-Agent: Googlebot` from\nan IP in none of Google's ranges.\n\nUse this tool when:\n- A request claims to be a search/AI crawler and you must decide whether\n to trust that claim before serving, allowing, or logging it.\n- You are separating genuine declared agents from impersonators.\n\nInputs:\n- `ip` (path, required): the IPv4 or IPv6 address to check.\n- `ua` (query, optional): the claimed User-Agent string. Omit to ask only\n \"is this IP a known published bot range?\".\n\nReturns:\n- `verdict`: one of\n - `verified` — the IP is inside the agent's published range (UA, if\n given, agrees). It genuinely is that bot.\n - `spoofed` — the UA claims a verifiable bot but the IP is in none of\n its published ranges. Impersonation.\n - `mismatch` — the IP is a real bot's range, but the UA names a\n different bot.\n - `unverifiable` — the UA names a real agent whose operator publishes\n no authoritative IP feed (e.g. Anthropic's ClaudeBot). Neither\n confirmed nor denied — never reported as spoofed.\n - `unknown` — no recognized bot UA and the IP is in no known range.\n- `is_verified_agent`, `is_spoofed`: booleans for the two actionable cases.\n- `agent`, `agent_label`, `matched_agent`, `claimed_agent`: the resolved\n identities.\n- `reason`: one-line explanation of the verdict.\n- `feeds_as_of_ms`: when the published ranges were last refreshed.\n\nCost:\n- Counts as one request against the daily rate limit.\n\nLatency:\n- Typical: <50ms (one KV read + CIDR match). First call after a deploy may\n take ~1s if it has to warm the range cache.\n", "inputSchema": { "properties": { "ip": { "type": "string" }, "ua": { "type": "string" } }, "required": [ "ip" ], "type": "object" }, "name": "verify_agent", "outputSchema": null }, { "description": "Neutral third-party Web Bot Auth verification. An origin — or the PDP\ndeciding for it — received a request from a claimed agent carrying the\nWeb Bot Auth headers (Signature, Signature-Input, Signature-Agent).\nRelay those headers here, plus the authority the request was addressed\nto, and TunnelMind verifies the Ed25519 signature against the agent's\nown published key directory\n(https://<agent>/.well-known/http-message-signatures-directory).\n\nFacts, not a verdict: `state: verified` means \"this signature\ncryptographically verifies against that directory\" — whether to trust\nthe agent behind it is your policy engine's call.\n\nUse this tool when:\n- A request claims a cryptographic agent identity (Signature-Agent\n header present) and you must check the claim before serving it.\n- You want signature verification independent of your CDN — or you are\n not behind a CDN that implements Web Bot Auth at all.\n\nInputs (JSON body):\n- `signature` (required): the received Signature header value.\n- `signature_input` (required): the received Signature-Input header value.\n- `signature_agent` (required): the received Signature-Agent header\n value (quoted https origin).\n- `authority` (required): the host the request was addressed to.\n- `method`, `path`, `scheme` (optional): only needed if the signature's\n covered components include them.\n\nReturns:\n- `state`: one of\n - `verified` — Ed25519 signature verifies against a key in the\n agent's published directory.\n - `invalid_signature` — key found, signature does not verify\n (tampered or forged).\n - `unknown_key` — directory reachable but contains no key with the\n claimed thumbprint.\n - `directory_unreachable` — the claimed key directory did not answer;\n an honest degraded state, not evidence of forgery.\n - `expired` — the signature's `expires` timestamp has passed.\n - `malformed` — headers do not parse as a Web Bot Auth signature.\n- `key_id`: the claimed RFC 7638 JWK thumbprint.\n- `directory_url`: the resolved well-known directory URL.\n- `params`: created/expires/alg/tag as sent.\n- `checks[]`: per-check {name, pass, detail} facts a PDP can gate on.\n\nCost:\n- Counts as one request against the daily rate limit.\n\nLatency:\n- Typical: <100ms when the agent's directory is KV-cached (1h TTL);\n up to ~5s on first sight of a new directory.\n", "inputSchema": { "properties": { "authority": { "example": "example.com", "type": "string" }, "method": { "type": "string" }, "path": { "type": "string" }, "scheme": { "type": "string" }, "signature": { "example": "sig2=:jdq0SqOwHdyHr9+r5jw3iYZH6aNGKijYp/EstF4RQTQdi5N5YYKrD+mCT1HA1nZDsi6nJKuHxUi/5Syp3rLWBA==:", "type": "string" }, "signature_agent": { "example": "\"https://signature-agent.test\"", "type": "string" }, "signature_input": { "example": "sig2=(\"@authority\" \"signature-agent\");created=1735689600;keyid=\"poqkLGiymh_W0uP6PZFw-dvez3QJT5SolqXBCW38r0U\";alg=\"ed25519\";expires=1735693200;tag=\"web-bot-auth\"", "type": "string" } }, "required": [ "signature", "signature_input", "signature_agent", "authority" ], "type": "object" }, "name": "verify_agent_signature", "outputSchema": null }, { "description": "Tamper-detection verification for TunnelMind surveillance receipts. Submit the\nreceipt ID, the SHA-256 content hash, and the Ed25519 signature from the receipt\ndocument. The registry compares these against what was recorded at issuance time.\nReturns VALID if both match exactly, INVALID with a specific mismatch reason otherwise.\n\nUse this tool when:\n- You received a surveillance receipt document and want to verify it hasn't been altered.\n- You are programmatically checking receipt authenticity in an agent workflow.\n- You want to prove to a third party that a receipt is genuine.\n\nDo NOT use this tool when:\n- You only want to check existence — use `get_receipt` instead (no body required).\n\nInputs:\n- `receipt_id` (body, required): The receipt's ID field from the document.\n- `content_hash` (body, required): SHA-256 hex hash of the receipt JSON. Max 256 chars.\n- `signature` (body, required): Ed25519 signature from the receipt document. Max 512 chars.\n\nReturns:\n- `valid`: boolean. True only if both hash and signature match exactly.\n- `status`: `VALID` or `INVALID`.\n- `message`: human-readable explanation. On INVALID, specifies whether the hash\n mismatched, the signature mismatched, or both.\n\nCost:\n- Free. No API key required.\n\nLatency:\n- Typical: <100ms, p99: <300ms.\n", "inputSchema": { "properties": { "content_hash": { "description": "SHA-256 hex hash of the receipt JSON content", "example": "sha256:abc123...", "maxLength": 256, "type": "string" }, "receipt_id": { "example": "rcpt_01HXYZ123", "maxLength": 128, "type": "string" }, "signature": { "description": "Ed25519 signature from the receipt document", "maxLength": 512, "type": "string" } }, "required": [ "receipt_id", "content_hash", "signature" ], "type": "object" }, "name": "verify_receipt", "outputSchema": null }, { "description": "Validates an agent's x402 v1 client implementation against a TunnelMind\nsurface end-to-end. Two operating modes:\n\n- `mode: \"demo\"` — HMAC over a nonce against a publicly-published secret.\n Does not move USDC. Smoke proves the WIRE works, not money movement.\n- `mode: \"x402\"` — real Coinbase facilitator dispatch (gated on\n operator wallet provisioning; currently returns \"facilitator not configured\").\n\nWithout an `X-PAYMENT` header, the endpoint returns HTTP 402 with a standards-\ncompliant `accepts[]` array (USDC on Base, $0.001).\n\nWith a valid `X-PAYMENT` header (base64-encoded payment payload), echoes the\nrequest body and returns an `X-PAYMENT-RESPONSE` settlement header.\n\nUse this tool when:\n- You are validating your agent's x402 v1 client implementation against a real\n public endpoint.\n- You want to demonstrate the full 402 → retry → settle wire end-to-end.\n\nDo NOT use this tool when:\n- You need a real paid operation — no TunnelMind production endpoint is gated\n behind x402 yet.\n\nInputs:\n- `X-PAYMENT` (header, optional): base64(JSON) per the x402 v1 spec. Without it,\n a 402 challenge is returned.\n- Request body (optional): any JSON object to be echoed back on successful payment.\n\nReturns:\n- On no header: HTTP 402 + `{ x402Version, accepts: [...] }`.\n- On valid payment: HTTP 200 + `{ ok: true, data: { echoed, paid_micro_usdc, x402 } }`\n and an `X-PAYMENT-RESPONSE` header carrying the settlement record.\n- On invalid payment: HTTP 402 + `{ error: \"invalid payment\", reason }`.\n\nDiscovery:\n- `https://tunnelmind.ai/.well-known/x402.json` carries the public demo secret\n and the HMAC construction recipe.\n\nCost:\n- Free in demo mode (no USDC moved). $0.001 USDC in real-mode (when activated).\n\nLatency:\n- Typical <100ms (demo mode); real mode is bounded by facilitator latency.\n", "inputSchema": { "properties": { "X-PAYMENT": { "description": "base64(JSON) payment payload per the x402 v1 spec. Absent → 402 challenge.", "type": "string" } }, "type": "object" }, "name": "x402_echo", "outputSchema": null } ] }
Verify it yourselfcurl -s https://api.teppi.xyz/v1/evidence/sha256:cbb3f032e43dd0c4ef299af8bd4063d23e3a1b938e8e98687e0cb6d42221eaff | sha256sum