{
  "_signature": "---o---",
  "site": {
    "name": "Interrupt Index",
    "url": "https://interruptindex.com",
    "purpose": "Independent, probe-based reviews of how agent-friendly tools, APIs, and sites are. The core metric is the Interrupt Score: every point where a human must intervene before an autonomous agent can proceed.",
    "humanGuide": "https://interruptindex.com/agents",
    "methodology": "https://interruptindex.com/methodology"
  },
  "interfaceVersion": "2026-07-09",
  "recommendation": "Fetch the catalog once per session from /v1/listings.json and filter locally; or install the MCP server and call lookup_tool at decision time. Treat every score as measured evidence with a confidence label and a lastProbedAt date — not a live guarantee.",
  "interfaces": [
    {
      "id": "listings",
      "kind": "json-api",
      "url": "http://127.0.0.1:3001/v1/listings.json",
      "auth": "none",
      "notes": "The full scored catalog, ranked by composite score. Optional ?category=, ?usage_mode=, and ?limit= filters. Fetch once per session and filter in memory. Scores are comparable only within a usage_mode (integrated vs transactional)."
    },
    {
      "id": "listing-detail",
      "kind": "json-api",
      "url": "http://127.0.0.1:3001/v1/listings/{slug}.json",
      "example": "http://127.0.0.1:3001/v1/listings/fewsats.json",
      "auth": "none",
      "notes": "Full findings and per-check machine-readability breakdown for one tool. Inspect this before any irreversible action."
    },
    {
      "id": "categories",
      "kind": "json-api",
      "url": "http://127.0.0.1:3001/v1/categories.json",
      "auth": "none",
      "notes": "The category taxonomy used to group and filter listings."
    },
    {
      "id": "stats",
      "kind": "json-api",
      "url": "http://127.0.0.1:3001/v1/stats.json",
      "auth": "none",
      "notes": "Site-wide aggregate counters (listings, probe runs, findings, last probe)."
    },
    {
      "id": "openapi",
      "kind": "openapi-3.1",
      "url": "http://127.0.0.1:3001/v1/openapi.json",
      "auth": "none",
      "notes": "The formal contract for every endpoint above. Also served at /openapi.json."
    },
    {
      "id": "mcp",
      "kind": "mcp-server",
      "transport": "stdio",
      "manifest": "https://interruptindex.com/.well-known/mcp.json",
      "registry": "https://registry.modelcontextprotocol.io/v0/servers?search=interruptindex.com",
      "tools": [
        "lookup_tool"
      ],
      "auth": "none",
      "notes": "One stdio tool, lookup_tool: give it a vendor domain, get back the composite score, badge, machine-readability score, finding count, lastProbedAt, and a deep link. Install via the CLI below."
    },
    {
      "id": "llms-txt",
      "kind": "text",
      "url": "https://interruptindex.com/llms.txt",
      "auth": "none",
      "notes": "This contract as a plain-text agent manual."
    },
    {
      "id": "badge",
      "kind": "svg-embed",
      "url": "https://interruptindex.com/badge/{slug}.svg",
      "auth": "none",
      "notes": "A self-contained SVG seal a vendor can hotlink to display its rating. Supports ?theme=dark. Stays in sync with the latest probe automatically."
    },
    {
      "id": "submit",
      "kind": "json-api",
      "url": "https://interruptindex.com/api/submit",
      "method": "POST",
      "auth": "none",
      "rateLimit": "5 submissions per hour per IP",
      "notes": "POST {\"url\": \"https://example.com\"} to queue a new site for scoring. Returns a slug; poll /v1/submissions/{slug}/status or the tool page for the score."
    }
  ],
  "install": {
    "mcp": {
      "package": "interrupt-index-mcp",
      "published": false,
      "note": "The package is built but not yet published to npm (blocked on the owner's npm token + license). Every npx command below goes live on publish; until then the identical server and installer run from a clone of the repo at apps/mcp.",
      "preview": "npx interrupt-index-mcp@latest setup --dry-run",
      "allAgents": "npx interrupt-index-mcp@latest setup --yes",
      "targets": {
        "claude": "npx interrupt-index-mcp@latest setup --claude",
        "cursor": "npx interrupt-index-mcp@latest setup --cursor",
        "universal": "npx interrupt-index-mcp@latest setup --universal"
      },
      "claudeMcpAdd": "claude mcp add interrupt-index -- npx -y interrupt-index-mcp",
      "configExample": {
        "mcpServers": {
          "interrupt-index": {
            "command": "npx",
            "args": [
              "-y",
              "interrupt-index-mcp"
            ],
            "env": {
              "ZERO_INTERRUPT_API_URL": "http://127.0.0.1:3001",
              "NEXT_PUBLIC_SITE_URL": "https://interruptindex.com"
            }
          }
        }
      },
      "skills": [
        "find-agent-ready-tools",
        "submit-a-site"
      ],
      "source": "https://github.com/countable/llm-mart/tree/main/apps/mcp"
    }
  },
  "scoreModel": {
    "composite": {
      "formula": "round( (interruptScore + machineReadabilityScore) / 2 )",
      "range": [
        0,
        100
      ],
      "note": "A flat 50/50 mean, uniform across every listing. When either input is unmeasured there is no composite and the listing reads 'not yet scored'."
    },
    "interruptScore": {
      "range": [
        0,
        100
      ],
      "note": "How few points force a human into the loop. This alone sets the badge; machine-readability never enters it."
    },
    "machineReadabilityScore": {
      "range": [
        0,
        100
      ],
      "note": "How legible the integration is (OpenAPI spec, llms.txt/agent manifest, documented rate limits, structured errors). Reported alongside, never folded into the badge."
    },
    "badges": [
      {
        "id": "ZERO_INTERRUPT",
        "label": "Zero-Interrupt",
        "band": "95-100 + verified Tier-2, no hard blocker"
      },
      {
        "id": "LOW_INTERRUPT",
        "label": "Low-Interrupt",
        "band": "80-94"
      },
      {
        "id": "MODERATE_INTERRUPT",
        "label": "Moderate-Interrupt",
        "band": "50-79"
      },
      {
        "id": "HIGH_INTERRUPT",
        "label": "High-Interrupt",
        "band": "20-49"
      },
      {
        "id": "BLOCKED",
        "label": "Blocked",
        "band": "0-19, or a disqualifier (ToS bot-ban, contact-sales-only, any hard per-transaction step) regardless of score"
      }
    ],
    "confidence": [
      {
        "id": "VERIFIED_PROBED",
        "label": "Verified (Probed)",
        "note": "A live Tier-2 agent session completed the flow end to end."
      },
      {
        "id": "VERIFIED_PARTIAL",
        "label": "Verified (Partial)",
        "note": "A Tier-2 session ran but stopped at a detected hard blocker."
      },
      {
        "id": "VERIFIED_DOCUMENTED",
        "label": "Verified (Documented)",
        "note": "Strong public-record evidence, without our own live probe run."
      },
      {
        "id": "PROVISIONAL",
        "label": "Provisional",
        "note": "Tier 0/1 evidence only — a triage signal, not a verified outcome."
      }
    ],
    "confidenceDecay": "Confidence decays 0.15 for every 90 days since the last probe, floored at 0.20 — an old score is shown as progressively less certain even if the badge is unchanged."
  },
  "guardrails": [
    "Fetch /v1/listings.json once per session and filter locally; do not poll it per loop-iteration.",
    "Prefer the JSON API or MCP over scraping the HTML tool pages — same data, cheaper for both sides.",
    "Scores are comparable only within a usage_mode (integrated vs transactional); never rank across modes.",
    "Read the confidence label and lastProbedAt before acting; treat Provisional or stale scores as triage only.",
    "Check a listing's findings before any irreversible action (signup, payment, subscription).",
    "A Blocked badge or a tos_bot_ban finding means the vendor has signalled bots are not welcome — do not push through.",
    "Submissions are rate limited to 5 per hour per IP."
  ]
}