{
  "meta": {
    "attribution": "Anchor Terminal (https://www.anchorterminal.com)",
    "docs": "https://www.anchorterminal.com/docs/",
    "generatedAt": "2026-10-04",
    "license": "CC-BY-4.0",
    "method": "https://www.anchorterminal.com/benchmark/",
    "methodology": "0.3",
    "openapi": "https://www.anchorterminal.com/openapi.json",
    "preview": false,
    "run": "2026-10-01",
    "runLabel": "October 2026 research run"
  },
  "tool": {
    "category": "email",
    "endpoint": "https://api.contrastcyber.com/mcp/",
    "jsonUrl": "https://www.anchorterminal.com/api/v1/tools/contrastcyber-api.json",
    "kind": "mcp",
    "listed": "indexed",
    "liveUrl": "https://www.anchorterminal.com/api/v1/live/contrastcyber-api.json",
    "markdownUrl": "https://www.anchorterminal.com/tools/contrastcyber-api.md",
    "mcpTools": {
      "check": {
        "checker": "anchor-check/1.0",
        "totalTokens": 177970,
        "counts": {
          "error": 0,
          "note": 1,
          "warn": 59
        },
        "findings": [
          {
            "rule": "TC07",
            "severity": "warn",
            "tool": "cve_lookup",
            "message": "the description is about 536 tokens",
            "fix": "Keep the description to what a model needs to choose and call the tool; move the manual to a resource or the docs."
          },
          {
            "rule": "TC13",
            "severity": "warn",
            "tool": "check_dependencies",
            "message": "packages[] (object with no properties)",
            "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
          },
          {
            "rule": "TC14",
            "severity": "warn",
            "tool": "cwe_lookup",
            "message": "allowed values are in the description, not an enum: cwe_id",
            "fix": "Move them into enum."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "asn_lookup",
            "message": "the definition is about 2,174 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "atlas_case_study_lookup",
            "message": "the definition is about 2,263 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "atlas_case_study_search",
            "message": "the definition is about 2,598 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "atlas_technique_lookup",
            "message": "the definition is about 2,811 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "atlas_technique_search",
            "message": "the definition is about 2,894 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "audit_domain",
            "message": "the definition is about 9,235 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "brand_assets",
            "message": "the definition is about 2,793 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "bulk_atlas_technique_lookup",
            "message": "the definition is about 3,571 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "bulk_cve_lookup",
            "message": "the definition is about 6,267 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "bulk_ioc_lookup",
            "message": "the definition is about 2,841 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "bulk_sigma_rule_lookup",
            "message": "the definition is about 3,511 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "calculate_risk_score",
            "message": "the definition is about 2,522 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "check_dependencies",
            "message": "the definition is about 2,680 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "check_headers",
            "message": "the definition is about 3,087 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "check_injection",
            "message": "the definition is about 2,495 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "check_secrets",
            "message": "the definition is about 2,476 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "contrast_scan",
            "message": "the definition is about 2,929 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "cve_leading",
            "message": "the definition is about 4,180 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "cve_lookup",
            "message": "the definition is about 5,930 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "cve_search",
            "message": "the definition is about 5,368 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "cwe_lookup",
            "message": "the definition is about 3,228 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "d3fend_attack_coverage",
            "message": "the definition is about 2,259 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "d3fend_defense_for_attack",
            "message": "the definition is about 2,954 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "d3fend_defense_lookup",
            "message": "the definition is about 2,472 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "d3fend_defense_search",
            "message": "the definition is about 2,716 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "dns_lookup",
            "message": "the definition is about 2,780 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "domain_report",
            "message": "the definition is about 8,530 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "email_disposable",
            "message": "the definition is about 2,351 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "email_mx",
            "message": "the definition is about 2,339 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "email_security_posture",
            "message": "the definition is about 3,188 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "email_verify",
            "message": "the definition is about 2,715 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "exploit_lookup",
            "message": "the definition is about 2,879 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "geo_audit",
            "message": "the definition is about 3,305 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "get_cvss_details",
            "message": "the definition is about 2,730 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "hash_lookup",
            "message": "the definition is about 2,183 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "ioc_lookup",
            "message": "the definition is about 3,415 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "ip_lookup",
            "message": "the definition is about 5,371 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "kev_detail",
            "message": "the definition is about 2,952 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "password_check",
            "message": "the definition is about 2,133 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "phishing_check",
            "message": "the definition is about 2,515 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "phone_lookup",
            "message": "the definition is about 2,789 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "redirect_chain",
            "message": "the definition is about 2,678 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "robots_txt",
            "message": "the definition is about 2,621 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "scan_headers",
            "message": "the definition is about 3,084 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "seo_audit",
            "message": "the definition is about 3,345 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "sigma_rule_lookup",
            "message": "the definition is about 2,993 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "ssl_check",
            "message": "the definition is about 3,278 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "subdomain_enum",
            "message": "the definition is about 2,588 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "tech_fingerprint",
            "message": "the definition is about 2,071 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "tech_stack_cve_audit",
            "message": "the definition is about 2,376 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "threat_intel",
            "message": "the definition is about 2,150 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "threat_report",
            "message": "the definition is about 4,849 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "username_lookup",
            "message": "the definition is about 2,384 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "wayback_lookup",
            "message": "the definition is about 2,497 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC22",
            "severity": "warn",
            "tool": "whois_lookup",
            "message": "the definition is about 2,443 tokens",
            "fix": "Trim the description and parameter docs, or split the tool."
          },
          {
            "rule": "TC23",
            "severity": "warn",
            "message": "55 tools, about 177,786 tokens of definitions",
            "fix": "Split the server by job, or offer a smaller default toolset (a read-only set, or a search-then-call pattern)."
          },
          {
            "rule": "TC29",
            "severity": "note",
            "message": "about 12,703 tokens (7% of the definitions) are titles that repeat property or function names",
            "fix": "Strip \"title\" keys that only restate a name before listing tools."
          }
        ]
      },
      "checkedAt": "2026-10-04T22:22:27Z",
      "count": 55,
      "schemaTokens": 177970,
      "status": "ok",
      "tools": [
        {
          "name": "domain_report",
          "title": "Domain Report",
          "description": "Query DNS, WHOIS, SSL, subdomains, and threat intel for a domain in one call. By default dns.txt is filtered to security-relevant entries (SPF, DMARC, DKIM, MTA-STS, TLS-RPT) and dns.total_txt_records reports the honest pre-filter count; pass include_all_txt=true for the raw TXT list. Use as a starting point for domain investigations; use audit_domain for live headers + tech stack. Response carries next_calls — chain with subdomain_enum (always emitted), ssl_check + tech_fingerprint (when an A record resolves) for the standard recon depth without re-prompting. Free: 30/hr, Pro: 500/hr. Returns domain report with DNS records, WHOIS data, SSL cert, risk score, email config, threat status, recommendation, and next_calls.",
          "inputSchema": {
            "properties": {
              "domain": {
                "description": "Root domain to analyze, without protocol or path (e.g. 'example.com', 'shopify.com')",
                "title": "Domain",
                "type": "string"
              },
              "include_all_txt": {
                "default": false,
                "description": "Return every TXT record (default: False, only SPF/DMARC/DKIM/MTA-STS/TLS-RPT kept). dns.total_txt_records is always emitted with the honest pre-filter count. Default filter strips vendor verification strings (google-site-verification, ms=, facebook-domain-verification, etc.) that bloat the response without security signal. Set True only when you need the raw TXT inventory.",
                "title": "Include All Txt",
                "type": "boolean"
              }
            },
            "required": [
              "domain"
            ],
            "title": "domain_reportArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "AbuseIpdbInfo": {
                "description": "AbuseIPDB reputation check (Pro tier only).",
                "properties": {
                  "abuse_score": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "AbuseIPDB confidence-of-abuse score (0-100). Only present when status='ok'.",
                    "title": "Abuse Score"
                  },
                  "country": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 3166-1 alpha-2 country code from AbuseIPDB geolocation (may differ from RIPE).",
                    "title": "Country"
                  },
                  "is_tor": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "AbuseIPDB's Tor exit flag (cross-reference with top-level tor_exit field).",
                    "title": "Is Tor"
                  },
                  "isp": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISP name as reported by AbuseIPDB.",
                    "title": "Isp"
                  },
                  "reason": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Human-readable reason string. Present when status is skipped/rate_limited/error/pro_only.",
                    "title": "Reason"
                  },
                  "status": {
                    "description": "'ok' = data fetched; 'skipped' = API key not configured; 'rate_limited' = AbuseIPDB quota exceeded; 'error' = transient HTTP/network failure; 'pro_only' = returned on Free tier as upsell hint (see upgrade_url).",
                    "enum": [
                      "ok",
                      "skipped",
                      "rate_limited",
                      "error",
                      "pro_only"
                    ],
                    "title": "Status",
                    "type": "string"
                  },
                  "total_reports": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Number of reports submitted against this IP in the last 90 days.",
                    "title": "Total Reports"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Upgrade link returned when status='pro_only'.",
                    "title": "Upgrade Url"
                  },
                  "usage_type": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "AbuseIPDB usage classification: 'Data Center/Web Hosting/Transit', 'ISP', 'Mobile ISP', etc.",
                    "title": "Usage Type"
                  }
                },
                "required": [
                  "status"
                ],
                "title": "AbuseIpdbInfo",
                "type": "object"
              },
              "CertificateSummary": {
                "additionalProperties": true,
                "description": "Single cert entry inside CertificatesInfo.certificates.",
                "properties": {
                  "common_name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Cert Subject CN.",
                    "title": "Common Name"
                  },
                  "issuer": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Cert issuer CN or O.",
                    "title": "Issuer"
                  },
                  "not_after": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "notAfter timestamp.",
                    "title": "Not After"
                  },
                  "not_before": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "notBefore timestamp.",
                    "title": "Not Before"
                  }
                },
                "title": "CertificateSummary",
                "type": "object"
              },
              "CertificatesInfo": {
                "additionalProperties": true,
                "properties": {
                  "certificates": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/CertificateSummary"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Up to CT_MAX_CERTS recent unique certs (deduped by serial).",
                    "title": "Certificates"
                  },
                  "crtsh_status": {
                    "anyOf": [
                      {
                        "enum": [
                          "ok",
                          "timeout",
                          "rate_limited",
                          "unavailable",
                          "error"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Status of the crt.sh fetch behind certificates. Mirrors subdomains.crtsh_status so both halves of a domain_report agree on whether CT logs delivered. 'ok' means the upstream responded — total_certificates=0 with status='ok' is a real empty result. Anything else (timeout / rate_limited / unavailable / error) means the upstream did not deliver and the cert list may be missing entries.",
                    "title": "Crtsh Status"
                  },
                  "error": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Populated when the crt.sh fetch failed (e.g. 'crt_sh_timeout', 'crt_sh_rate_limited', 'crt_sh_unavailable'). Distinguishes 'no certs found' from 'fetch failed'; risk_score skips the CT factor when this is set.",
                    "title": "Error"
                  },
                  "total_certificates": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Total cert count from crt.sh (pre-dedup).",
                    "title": "Total Certificates"
                  }
                },
                "title": "CertificatesInfo",
                "type": "object"
              },
              "DomainDnsInfo": {
                "additionalProperties": true,
                "description": "DNS records per type. Keys are omitted (not null) when the lookup for that type fails.",
                "properties": {
                  "a": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "A records (IPv4 addresses).",
                    "title": "A"
                  },
                  "aaaa": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "AAAA records (IPv6 addresses).",
                    "title": "Aaaa"
                  },
                  "cname": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CNAME records.",
                    "title": "Cname"
                  },
                  "mx": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/MxDnsRecord"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "MX records as {priority, host} list.",
                    "title": "Mx"
                  },
                  "ns": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "NS records (nameserver hostnames).",
                    "title": "Ns"
                  },
                  "soa": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/SoaInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "SOA record (zone authority)."
                  },
                  "total_txt_records": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Honest pre-filter TXT record count. Always emitted (domain_report, audit_domain, /v1/dns). Equals len(txt) when include_all_txt=true or on /v1/dns/{domain} (raw, unfiltered). 0 when no TXT records exist. Null only when the field is absent (older cached entries).",
                    "title": "Total Txt Records"
                  },
                  "txt": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "TXT records. By default in domain_report, filtered to security-relevant entries (SPF v=spf, DMARC v=DMARC, DKIM v=DKIM, MTA-STS v=STSv, TLS-RPT v=TLSRPTv). Pass ?include_all_txt=true to return every TXT including vendor verification strings.",
                    "title": "Txt"
                  }
                },
                "title": "DomainDnsInfo",
                "type": "object"
              },
              "DomainReportResponse": {
                "properties": {
                  "certificates": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/CertificatesInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Certificate transparency log entries from crt.sh. Skipped in lite mode."
                  },
                  "dns": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/DomainDnsInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Forward DNS record set (A/AAAA/MX/NS/TXT/CNAME/SOA). Empty dict when all lookups fail."
                  },
                  "domain": {
                    "description": "Queried domain (echoed, lowercased).",
                    "title": "Domain",
                    "type": "string"
                  },
                  "email_security": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/EmailSecurityInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "SPF/DMARC/DKIM posture of the domain (email authentication grade)."
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "reputation": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/DomainReputationInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "IP-level reputation of the domain's resolved A record. Absent in lite mode AND when no A record resolves. On Free tier inner blocks carry {status:'pro_only'} stubs (agents should not treat as clean)."
                  },
                  "reverse_dns": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/ReverseDnsInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Reverse-DNS resolution of the domain's primary IPv4 (PTR + shared-hosting signal)."
                  },
                  "risk": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/RiskInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Composite risk scoring (0-100) with per-factor breakdown — drives the top-level risk_score alias."
                  },
                  "ssl": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/SslInfoEmbedded"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "SSL/TLS certificate subset (CN, issuer, validity, grade). Full shape at top-level /v1/ssl/{domain}."
                  },
                  "subdomains": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/SubdomainsInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Subdomain enumeration (wordlist + crt.sh). Skipped in lite mode (returns {subdomains:[], count:0})."
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line human summary aggregating IP, grade, WAF, and subdomain count.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "threat": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/ThreatInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "URLhaus threat intelligence for the domain (malware / phishing URL listings). Skipped in lite mode."
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  },
                  "waf": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/WafInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "WAF detection from live response headers (Cloudflare, AWS CloudFront, Akamai, Sucuri, etc.)."
                  },
                  "whois": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/WhoisInfoEmbedded"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "WHOIS extract (registrar, dates, nameservers, EPP status). Skipped in lite mode. Error branch populates `error`."
                  }
                },
                "required": [
                  "domain"
                ],
                "title": "DomainReportResponse",
                "type": "object"
              },
              "DomainReputationInfo": {
                "additionalProperties": true,
                "description": "Reputation block inside DomainReportResponse (IP-level enrichment of the resolved A record).\n\nDiffers from IpLookupResponse.reputation: no firehol block here (FireHOL is IP-only).",
                "properties": {
                  "abuseipdb": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/AbuseIpdbInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "AbuseIPDB enrichment for the domain's resolved IP. Pro tier only — free tier returns {status:'pro_only', reason, upgrade_url} stub."
                  },
                  "shodan": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/ShodanRepInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Shodan enrichment for the domain's resolved IP. Pro tier only — free tier returns {status:'pro_only', reason, upgrade_url} stub."
                  }
                },
                "title": "DomainReputationInfo",
                "type": "object"
              },
              "EmailSecurityInfo": {
                "additionalProperties": true,
                "properties": {
                  "dkim_selectors": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "DKIM selectors that responded to probing (e.g. ['google', 'selector1']). Empty when none found.",
                    "title": "Dkim Selectors"
                  },
                  "dkim_status": {
                    "anyOf": [
                      {
                        "enum": [
                          "verified",
                          "unverifiable"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Honest evidence label for DKIM. 'verified' when at least one selector responded (see dkim_selectors). 'unverifiable' when no probed selector matched — DKIM keys live at arbitrary operator-chosen selector names, so absence under common+date-based probes does not prove absence. Grade does not penalize 'unverifiable'.",
                    "title": "Dkim Status"
                  },
                  "dmarc": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "DMARC record string (v=DMARC1; p=...; ...). Null when no DMARC record is published at _dmarc.\u003cdomain\u003e.",
                    "title": "Dmarc"
                  },
                  "grade": {
                    "anyOf": [
                      {
                        "enum": [
                          "A",
                          "B",
                          "C",
                          "F"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Email-auth grade. When DKIM is verified: A=SPF+DMARC+DKIM, B=2 of 3, C=1 of 3. When DKIM is unverifiable: A=SPF+DMARC, B=one of SPF/DMARC, F=neither — DKIM absence is not penalized because it cannot be proven without selector knowledge.",
                    "title": "Grade"
                  },
                  "issues": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Human-readable issues (missing SPF, weak DMARC policy, etc.).",
                    "title": "Issues"
                  },
                  "spf": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "SPF record string (v=spf1 ...). Null when no SPF is published.",
                    "title": "Spf"
                  }
                },
                "title": "EmailSecurityInfo",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "MxDnsRecord": {
                "description": "Single MX record embedded inside DomainReportResponse.dns.mx.",
                "properties": {
                  "host": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "MX hostname (trailing dot stripped).",
                    "title": "Host"
                  },
                  "priority": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "MX preference (lower = higher priority).",
                    "title": "Priority"
                  }
                },
                "title": "MxDnsRecord",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "ReverseDnsInfo": {
                "additionalProperties": true,
                "properties": {
                  "ip": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Resolved IPv4 for the domain. Null when DNS fails or IP is private.",
                    "title": "Ip"
                  },
                  "ptr": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "PTR (reverse-DNS) hostname for the IP. Null when no PTR is published.",
                    "title": "Ptr"
                  },
                  "shared_hosting": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "True when PTR hostname differs from the queried domain (shared hosting signal). Absent when PTR lookup fails.",
                    "title": "Shared Hosting"
                  }
                },
                "title": "ReverseDnsInfo",
                "type": "object"
              },
              "RiskFactor": {
                "properties": {
                  "detail": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Human-readable justification for the score.",
                    "title": "Detail"
                  },
                  "max": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Maximum possible points for this factor.",
                    "title": "Max"
                  },
                  "name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Factor label (e.g. 'SSL/TLS', 'Email Security', 'IP Reputation').",
                    "title": "Name"
                  },
                  "score": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Points earned by this factor (can be negative for penalties).",
                    "title": "Score"
                  }
                },
                "title": "RiskFactor",
                "type": "object"
              },
              "RiskInfo": {
                "additionalProperties": true,
                "properties": {
                  "factors": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/RiskFactor"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Per-factor scoring breakdown (typically 8-9 factors).",
                    "title": "Factors"
                  },
                  "grade": {
                    "anyOf": [
                      {
                        "enum": [
                          "A",
                          "B",
                          "C",
                          "D",
                          "F"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Letter grade derived from score.",
                    "title": "Grade"
                  },
                  "max_score": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Maximum achievable score, 100 by default. It drops by a factor's max when that signal could not be measured, so grade reflects the available signals instead of penalizing the domain for our blind spot. Observed values are 100, 95, 90, 85, 80 and 75: a crt.sh failure excludes the 10-point CT factor, an unverifiable DKIM selector trims the email factor 25-\u003e20, and wildcard DNS can exclude the 10-point subdomain factor. ALWAYS compute percentages against this field, never against a literal 100.",
                    "title": "Max Score"
                  },
                  "score": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Cumulative risk score (0-100).",
                    "title": "Score"
                  }
                },
                "title": "RiskInfo",
                "type": "object"
              },
              "ShodanRepInfo": {
                "description": "Shodan full API enrichment (Pro tier only). Richer than InternetDB fields at top level.",
                "properties": {
                  "asn": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ASN string per Shodan (e.g. 'AS13335'); may differ from top-level asn int.",
                    "title": "Asn"
                  },
                  "city": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "City name per Shodan geolocation.",
                    "title": "City"
                  },
                  "country_name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Country name per Shodan geolocation.",
                    "title": "Country Name"
                  },
                  "hostnames": {
                    "description": "Hostnames observed pointing to this IP per Shodan.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Hostnames",
                    "type": "array"
                  },
                  "isp": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISP per Shodan (may differ from AbuseIPDB/RIPE).",
                    "title": "Isp"
                  },
                  "last_update": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 timestamp of Shodan's most recent data point for this IP.",
                    "title": "Last Update"
                  },
                  "org": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Organization name owning the IP per Shodan.",
                    "title": "Org"
                  },
                  "os": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Shodan-detected operating system (fingerprint-based, best-effort).",
                    "title": "Os"
                  },
                  "ports": {
                    "description": "Open ports observed by Shodan full scan (superset of top-level InternetDB ports).",
                    "items": {
                      "type": "integer"
                    },
                    "title": "Ports",
                    "type": "array"
                  },
                  "reason": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Human-readable reason. Present when status is skipped/restricted/rate_limited/error/pro_only.",
                    "title": "Reason"
                  },
                  "status": {
                    "description": "'ok' = data fetched; 'skipped' = API key not configured; 'restricted' = 403 (IP not available on free Shodan tier); 'rate_limited' = 429 quota exceeded; 'error' = transient HTTP/network failure; 'pro_only' = returned on Free tier as upsell hint.",
                    "enum": [
                      "ok",
                      "skipped",
                      "restricted",
                      "rate_limited",
                      "error",
                      "pro_only"
                    ],
                    "title": "Status",
                    "type": "string"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Upgrade link returned when status='pro_only'.",
                    "title": "Upgrade Url"
                  },
                  "vulns": {
                    "description": "CVE IDs Shodan has associated with banners on this IP.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Vulns",
                    "type": "array"
                  }
                },
                "required": [
                  "status"
                ],
                "title": "ShodanRepInfo",
                "type": "object"
              },
              "SoaInfo": {
                "additionalProperties": true,
                "description": "SOA record embedded inside DomainDnsInfo.soa.",
                "properties": {
                  "mname": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Primary nameserver (SOA MNAME).",
                    "title": "Mname"
                  },
                  "rname": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Responsible party mailbox (SOA RNAME).",
                    "title": "Rname"
                  },
                  "serial": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Zone serial number.",
                    "title": "Serial"
                  }
                },
                "title": "SoaInfo",
                "type": "object"
              },
              "SslInfoEmbedded": {
                "additionalProperties": true,
                "description": "SSL subset embedded in the domain report. See top-level SslResponse for live SSL endpoint shape.",
                "properties": {
                  "alpn": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Negotiated ALPN protocol (e.g. 'http/1.1', 'h2').",
                    "title": "Alpn"
                  },
                  "cert_valid": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "True only when chain verified AND hostname matches AND not expired. False when cert is readable but fails one or more validation checks (see validation_errors).",
                    "title": "Cert Valid"
                  },
                  "common_name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Leaf cert Subject CN.",
                    "title": "Common Name"
                  },
                  "days_remaining": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Days until expiry. Negative when already expired.",
                    "title": "Days Remaining"
                  },
                  "error": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Populated only on probe failure (timeout, connection refused, no port 443). Cert validation issues are NOT errors here — see cert_valid + validation_errors instead.",
                    "title": "Error"
                  },
                  "grade": {
                    "anyOf": [
                      {
                        "enum": [
                          "A",
                          "B",
                          "C",
                          "D",
                          "F"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "SSL grade. A/B/C: cert_valid AND TLS modern. D: cert readable but invalid (self-signed, hostname mismatch, untrusted root). F: probe failure, expired, or legacy TLS.",
                    "title": "Grade"
                  },
                  "issuer": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Leaf cert issuer organization name.",
                    "title": "Issuer"
                  },
                  "not_after": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "notAfter (expiry) timestamp (ISO 8601 / UTC).",
                    "title": "Not After"
                  },
                  "not_before": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "notBefore timestamp (ISO 8601 / UTC).",
                    "title": "Not Before"
                  },
                  "san": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Subject Alternative Names.",
                    "title": "San"
                  },
                  "serial_number": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Hex-encoded cert serial number.",
                    "title": "Serial Number"
                  },
                  "tls_version": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Negotiated TLS protocol (e.g. 'TLSv1.3', 'TLSv1.2'). Empty on handshake failure.",
                    "title": "Tls Version"
                  },
                  "validation_errors": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Canonical validation failure tags when cert_valid is False. Values: 'expired', 'self_signed', 'hostname_mismatch', 'untrusted_root', 'chain_incomplete'. Empty/null when cert_valid is True.",
                    "title": "Validation Errors"
                  },
                  "version": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "X.509 version as returned by the ssl module (int 3 for v3; empty string on some parse paths).",
                    "title": "Version"
                  }
                },
                "title": "SslInfoEmbedded",
                "type": "object"
              },
              "SubdomainsInfo": {
                "additionalProperties": true,
                "properties": {
                  "count": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Total subdomains discovered.",
                    "title": "Count"
                  },
                  "found_via_crtsh": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Count discovered via crt.sh CT log query.",
                    "title": "Found Via Crtsh"
                  },
                  "found_via_wordlist": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Count discovered via DNS brute-force wordlist.",
                    "title": "Found Via Wordlist"
                  },
                  "sources": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Sources that produced hits (subset of ['wordlist', 'crt_sh']).",
                    "title": "Sources"
                  },
                  "subdomains": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Sorted unique subdomain list.",
                    "title": "Subdomains"
                  },
                  "summary": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "One-line human-readable summary.",
                    "title": "Summary"
                  },
                  "warnings": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Non-fatal warnings (e.g. 'crt.sh timeout', 'result truncated').",
                    "title": "Warnings"
                  },
                  "wildcard_status": {
                    "anyOf": [
                      {
                        "enum": [
                          "absent",
                          "present",
                          "undetermined"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Wildcard-DNS probe result; anything other than 'absent' means count is unverified.",
                    "title": "Wildcard Status"
                  }
                },
                "title": "SubdomainsInfo",
                "type": "object"
              },
              "ThreatInfo": {
                "additionalProperties": true,
                "properties": {
                  "tags": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Deduped list of tags (up to 20).",
                    "title": "Tags"
                  },
                  "threat_types": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Deduped list of threat classes across all URLs.",
                    "title": "Threat Types"
                  },
                  "url_count": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Total URLs URLhaus has seen for this domain.",
                    "title": "Url Count"
                  },
                  "urlhaus_status": {
                    "anyOf": [
                      {
                        "enum": [
                          "clean",
                          "listed",
                          "error",
                          "skipped"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "URLhaus lookup outcome. 'skipped' in lite mode; 'error' on API failure (treat as unavailable, not clean).",
                    "title": "Urlhaus Status"
                  },
                  "urls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/ThreatUrlEntry"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Up to 20 offending URL entries.",
                    "title": "Urls"
                  },
                  "urls_online": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Subset of url_count currently marked online.",
                    "title": "Urls Online"
                  }
                },
                "title": "ThreatInfo",
                "type": "object"
              },
              "ThreatUrlEntry": {
                "additionalProperties": true,
                "description": "Single offending URL entry inside ThreatInfo.urls.",
                "properties": {
                  "date_added": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When URLhaus first saw this URL.",
                    "title": "Date Added"
                  },
                  "status": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "URLhaus status for this URL ('online', 'offline').",
                    "title": "Status"
                  },
                  "tags": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Tags assigned by URLhaus (malware family, kit, etc.).",
                    "title": "Tags"
                  },
                  "threat": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Threat class (e.g. 'malware_download', 'phishing').",
                    "title": "Threat"
                  },
                  "url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Offending URL observed in URLhaus.",
                    "title": "Url"
                  }
                },
                "title": "ThreatUrlEntry",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              },
              "WafInfo": {
                "additionalProperties": true,
                "properties": {
                  "detected": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "WAF product names detected from response headers (e.g. ['Cloudflare', 'AWS CloudFront']).",
                    "title": "Detected"
                  },
                  "waf_present": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "True when `detected` is non-empty.",
                    "title": "Waf Present"
                  }
                },
                "title": "WafInfo",
                "type": "object"
              },
              "WhoisInfoEmbedded": {
                "additionalProperties": true,
                "description": "WHOIS subset embedded in the domain report. Fields are best-effort regex extracts from the raw WHOIS text.",
                "properties": {
                  "creation_date": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Domain creation date (format depends on registrar).",
                    "title": "Creation Date"
                  },
                  "error": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Populated when the WHOIS TCP query failed (e.g. no WHOIS server for TLD, socket timeout).",
                    "title": "Error"
                  },
                  "expiry_date": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Domain expiry date (format depends on registrar).",
                    "title": "Expiry Date"
                  },
                  "name_servers": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Authoritative nameservers per WHOIS.",
                    "title": "Name Servers"
                  },
                  "raw_length": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Byte length of raw WHOIS response (sanity indicator).",
                    "title": "Raw Length"
                  },
                  "registrar": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Registrar name as reported by the WHOIS server.",
                    "title": "Registrar"
                  },
                  "status": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "EPP domain status (e.g. 'clientTransferProhibited'). String or list depending on registrar.",
                    "title": "Status"
                  },
                  "updated_date": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Last-updated timestamp from WHOIS.",
                    "title": "Updated Date"
                  }
                },
                "title": "WhoisInfoEmbedded",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/DomainReportResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "domain_reportOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "audit_domain",
          "title": "Audit Domain",
          "description": "Perform comprehensive domain audit: combines domain_report + live HTTP security headers + technology fingerprinting. By default report.dns.txt is filtered to security-relevant entries (SPF, DMARC, DKIM, MTA-STS, TLS-RPT) and report.dns.total_txt_records reports the honest pre-filter count; pass include_all_txt=true for the raw TXT list. Use when you need the full picture (recon + active checks); use domain_report for passive-only assessment. Response carries next_calls — chain with subdomain_enum (always emitted) and ssl_check (when an A record resolves) for the residual recon depth (tech_fingerprint already inline as `technologies`). Free: 30/hr (costs 6 tokens), Pro: 500/hr. Returns {domain, report, technologies, live_headers, summary, next_calls}.",
          "inputSchema": {
            "properties": {
              "domain": {
                "description": "Root domain to audit, without protocol or path (e.g. 'example.com', 'shopify.com')",
                "title": "Domain",
                "type": "string"
              },
              "include_all_txt": {
                "default": false,
                "description": "Return every TXT record under report.dns.txt (default: False, only SPF/DMARC/DKIM/MTA-STS/TLS-RPT kept). report.dns.total_txt_records is always emitted with the honest pre-filter count. Default filter strips vendor verification strings (google-site-verification, ms=, facebook-domain-verification, etc.) that bloat the response without security signal. Set True only when you need the raw TXT inventory.",
                "title": "Include All Txt",
                "type": "boolean"
              }
            },
            "required": [
              "domain"
            ],
            "title": "audit_domainArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "AbuseIpdbInfo": {
                "description": "AbuseIPDB reputation check (Pro tier only).",
                "properties": {
                  "abuse_score": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "AbuseIPDB confidence-of-abuse score (0-100). Only present when status='ok'.",
                    "title": "Abuse Score"
                  },
                  "country": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 3166-1 alpha-2 country code from AbuseIPDB geolocation (may differ from RIPE).",
                    "title": "Country"
                  },
                  "is_tor": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "AbuseIPDB's Tor exit flag (cross-reference with top-level tor_exit field).",
                    "title": "Is Tor"
                  },
                  "isp": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISP name as reported by AbuseIPDB.",
                    "title": "Isp"
                  },
                  "reason": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Human-readable reason string. Present when status is skipped/rate_limited/error/pro_only.",
                    "title": "Reason"
                  },
                  "status": {
                    "description": "'ok' = data fetched; 'skipped' = API key not configured; 'rate_limited' = AbuseIPDB quota exceeded; 'error' = transient HTTP/network failure; 'pro_only' = returned on Free tier as upsell hint (see upgrade_url).",
                    "enum": [
                      "ok",
                      "skipped",
                      "rate_limited",
                      "error",
                      "pro_only"
                    ],
                    "title": "Status",
                    "type": "string"
                  },
                  "total_reports": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Number of reports submitted against this IP in the last 90 days.",
                    "title": "Total Reports"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Upgrade link returned when status='pro_only'.",
                    "title": "Upgrade Url"
                  },
                  "usage_type": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "AbuseIPDB usage classification: 'Data Center/Web Hosting/Transit', 'ISP', 'Mobile ISP', etc.",
                    "title": "Usage Type"
                  }
                },
                "required": [
                  "status"
                ],
                "title": "AbuseIpdbInfo",
                "type": "object"
              },
              "AuditResponse": {
                "properties": {
                  "domain": {
                    "description": "Queried domain (lowercased, no scheme).",
                    "title": "Domain",
                    "type": "string"
                  },
                  "live_headers": {
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Filtered HTTP response headers from the origin (lowercased keys). Sensitive headers (Set-Cookie, Authorization, etc.) are stripped before serialization.",
                    "title": "Live Headers",
                    "type": "object"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "report": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/DomainReportResponse"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Full domain intelligence report — same shape as /v1/domain/{domain}. Contains DNS, WHOIS, SSL, subdomains, threat intel, reputation, and verdict. See DomainReportResponse."
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line audit summary combining domain report summary + technology count.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "technologies": {
                    "$ref": "#/$defs/AuditTechInfo",
                    "description": "Technology fingerprint detected from live response headers. See AuditTechInfo."
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "domain"
                ],
                "title": "AuditResponse",
                "type": "object"
              },
              "AuditTechInfo": {
                "description": "Technology fingerprint subset embedded in /v1/audit (no domain echo — outer AuditResponse carries it).",
                "properties": {
                  "categories": {
                    "additionalProperties": {
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "description": "Technologies grouped by category (e.g. {'cdn': ['Cloudflare'], 'webserver': ['nginx']}).",
                    "title": "Categories",
                    "type": "object"
                  },
                  "count": {
                    "default": 0,
                    "description": "Total number of detected technologies (== sum of categories).",
                    "title": "Count",
                    "type": "integer"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line summary of the detected stack.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "technologies": {
                    "description": "Detected technologies (name + category) inferred from response headers (e.g. Server, X-Powered-By).",
                    "items": {
                      "$ref": "#/$defs/TechItem"
                    },
                    "title": "Technologies",
                    "type": "array"
                  }
                },
                "title": "AuditTechInfo",
                "type": "object"
              },
              "CertificateSummary": {
                "additionalProperties": true,
                "description": "Single cert entry inside CertificatesInfo.certificates.",
                "properties": {
                  "common_name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Cert Subject CN.",
                    "title": "Common Name"
                  },
                  "issuer": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Cert issuer CN or O.",
                    "title": "Issuer"
                  },
                  "not_after": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "notAfter timestamp.",
                    "title": "Not After"
                  },
                  "not_before": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "notBefore timestamp.",
                    "title": "Not Before"
                  }
                },
                "title": "CertificateSummary",
                "type": "object"
              },
              "CertificatesInfo": {
                "additionalProperties": true,
                "properties": {
                  "certificates": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/CertificateSummary"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Up to CT_MAX_CERTS recent unique certs (deduped by serial).",
                    "title": "Certificates"
                  },
                  "crtsh_status": {
                    "anyOf": [
                      {
                        "enum": [
                          "ok",
                          "timeout",
                          "rate_limited",
                          "unavailable",
                          "error"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Status of the crt.sh fetch behind certificates. Mirrors subdomains.crtsh_status so both halves of a domain_report agree on whether CT logs delivered. 'ok' means the upstream responded — total_certificates=0 with status='ok' is a real empty result. Anything else (timeout / rate_limited / unavailable / error) means the upstream did not deliver and the cert list may be missing entries.",
                    "title": "Crtsh Status"
                  },
                  "error": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Populated when the crt.sh fetch failed (e.g. 'crt_sh_timeout', 'crt_sh_rate_limited', 'crt_sh_unavailable'). Distinguishes 'no certs found' from 'fetch failed'; risk_score skips the CT factor when this is set.",
                    "title": "Error"
                  },
                  "total_certificates": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Total cert count from crt.sh (pre-dedup).",
                    "title": "Total Certificates"
                  }
                },
                "title": "CertificatesInfo",
                "type": "object"
              },
              "DomainDnsInfo": {
                "additionalProperties": true,
                "description": "DNS records per type. Keys are omitted (not null) when the lookup for that type fails.",
                "properties": {
                  "a": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "A records (IPv4 addresses).",
                    "title": "A"
                  },
                  "aaaa": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "AAAA records (IPv6 addresses).",
                    "title": "Aaaa"
                  },
                  "cname": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CNAME records.",
                    "title": "Cname"
                  },
                  "mx": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/MxDnsRecord"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "MX records as {priority, host} list.",
                    "title": "Mx"
                  },
                  "ns": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "NS records (nameserver hostnames).",
                    "title": "Ns"
                  },
                  "soa": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/SoaInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "SOA record (zone authority)."
                  },
                  "total_txt_records": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Honest pre-filter TXT record count. Always emitted (domain_report, audit_domain, /v1/dns). Equals len(txt) when include_all_txt=true or on /v1/dns/{domain} (raw, unfiltered). 0 when no TXT records exist. Null only when the field is absent (older cached entries).",
                    "title": "Total Txt Records"
                  },
                  "txt": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "TXT records. By default in domain_report, filtered to security-relevant entries (SPF v=spf, DMARC v=DMARC, DKIM v=DKIM, MTA-STS v=STSv, TLS-RPT v=TLSRPTv). Pass ?include_all_txt=true to return every TXT including vendor verification strings.",
                    "title": "Txt"
                  }
                },
                "title": "DomainDnsInfo",
                "type": "object"
              },
              "DomainReportResponse": {
                "properties": {
                  "certificates": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/CertificatesInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Certificate transparency log entries from crt.sh. Skipped in lite mode."
                  },
                  "dns": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/DomainDnsInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Forward DNS record set (A/AAAA/MX/NS/TXT/CNAME/SOA). Empty dict when all lookups fail."
                  },
                  "domain": {
                    "description": "Queried domain (echoed, lowercased).",
                    "title": "Domain",
                    "type": "string"
                  },
                  "email_security": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/EmailSecurityInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "SPF/DMARC/DKIM posture of the domain (email authentication grade)."
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "reputation": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/DomainReputationInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "IP-level reputation of the domain's resolved A record. Absent in lite mode AND when no A record resolves. On Free tier inner blocks carry {status:'pro_only'} stubs (agents should not treat as clean)."
                  },
                  "reverse_dns": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/ReverseDnsInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Reverse-DNS resolution of the domain's primary IPv4 (PTR + shared-hosting signal)."
                  },
                  "risk": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/RiskInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Composite risk scoring (0-100) with per-factor breakdown — drives the top-level risk_score alias."
                  },
                  "ssl": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/SslInfoEmbedded"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "SSL/TLS certificate subset (CN, issuer, validity, grade). Full shape at top-level /v1/ssl/{domain}."
                  },
                  "subdomains": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/SubdomainsInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Subdomain enumeration (wordlist + crt.sh). Skipped in lite mode (returns {subdomains:[], count:0})."
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line human summary aggregating IP, grade, WAF, and subdomain count.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "threat": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/ThreatInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "URLhaus threat intelligence for the domain (malware / phishing URL listings). Skipped in lite mode."
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  },
                  "waf": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/WafInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "WAF detection from live response headers (Cloudflare, AWS CloudFront, Akamai, Sucuri, etc.)."
                  },
                  "whois": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/WhoisInfoEmbedded"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "WHOIS extract (registrar, dates, nameservers, EPP status). Skipped in lite mode. Error branch populates `error`."
                  }
                },
                "required": [
                  "domain"
                ],
                "title": "DomainReportResponse",
                "type": "object"
              },
              "DomainReputationInfo": {
                "additionalProperties": true,
                "description": "Reputation block inside DomainReportResponse (IP-level enrichment of the resolved A record).\n\nDiffers from IpLookupResponse.reputation: no firehol block here (FireHOL is IP-only).",
                "properties": {
                  "abuseipdb": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/AbuseIpdbInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "AbuseIPDB enrichment for the domain's resolved IP. Pro tier only — free tier returns {status:'pro_only', reason, upgrade_url} stub."
                  },
                  "shodan": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/ShodanRepInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Shodan enrichment for the domain's resolved IP. Pro tier only — free tier returns {status:'pro_only', reason, upgrade_url} stub."
                  }
                },
                "title": "DomainReputationInfo",
                "type": "object"
              },
              "EmailSecurityInfo": {
                "additionalProperties": true,
                "properties": {
                  "dkim_selectors": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "DKIM selectors that responded to probing (e.g. ['google', 'selector1']). Empty when none found.",
                    "title": "Dkim Selectors"
                  },
                  "dkim_status": {
                    "anyOf": [
                      {
                        "enum": [
                          "verified",
                          "unverifiable"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Honest evidence label for DKIM. 'verified' when at least one selector responded (see dkim_selectors). 'unverifiable' when no probed selector matched — DKIM keys live at arbitrary operator-chosen selector names, so absence under common+date-based probes does not prove absence. Grade does not penalize 'unverifiable'.",
                    "title": "Dkim Status"
                  },
                  "dmarc": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "DMARC record string (v=DMARC1; p=...; ...). Null when no DMARC record is published at _dmarc.\u003cdomain\u003e.",
                    "title": "Dmarc"
                  },
                  "grade": {
                    "anyOf": [
                      {
                        "enum": [
                          "A",
                          "B",
                          "C",
                          "F"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Email-auth grade. When DKIM is verified: A=SPF+DMARC+DKIM, B=2 of 3, C=1 of 3. When DKIM is unverifiable: A=SPF+DMARC, B=one of SPF/DMARC, F=neither — DKIM absence is not penalized because it cannot be proven without selector knowledge.",
                    "title": "Grade"
                  },
                  "issues": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Human-readable issues (missing SPF, weak DMARC policy, etc.).",
                    "title": "Issues"
                  },
                  "spf": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "SPF record string (v=spf1 ...). Null when no SPF is published.",
                    "title": "Spf"
                  }
                },
                "title": "EmailSecurityInfo",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "MxDnsRecord": {
                "description": "Single MX record embedded inside DomainReportResponse.dns.mx.",
                "properties": {
                  "host": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "MX hostname (trailing dot stripped).",
                    "title": "Host"
                  },
                  "priority": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "MX preference (lower = higher priority).",
                    "title": "Priority"
                  }
                },
                "title": "MxDnsRecord",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "ReverseDnsInfo": {
                "additionalProperties": true,
                "properties": {
                  "ip": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Resolved IPv4 for the domain. Null when DNS fails or IP is private.",
                    "title": "Ip"
                  },
                  "ptr": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "PTR (reverse-DNS) hostname for the IP. Null when no PTR is published.",
                    "title": "Ptr"
                  },
                  "shared_hosting": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "True when PTR hostname differs from the queried domain (shared hosting signal). Absent when PTR lookup fails.",
                    "title": "Shared Hosting"
                  }
                },
                "title": "ReverseDnsInfo",
                "type": "object"
              },
              "RiskFactor": {
                "properties": {
                  "detail": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Human-readable justification for the score.",
                    "title": "Detail"
                  },
                  "max": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Maximum possible points for this factor.",
                    "title": "Max"
                  },
                  "name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Factor label (e.g. 'SSL/TLS', 'Email Security', 'IP Reputation').",
                    "title": "Name"
                  },
                  "score": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Points earned by this factor (can be negative for penalties).",
                    "title": "Score"
                  }
                },
                "title": "RiskFactor",
                "type": "object"
              },
              "RiskInfo": {
                "additionalProperties": true,
                "properties": {
                  "factors": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/RiskFactor"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Per-factor scoring breakdown (typically 8-9 factors).",
                    "title": "Factors"
                  },
                  "grade": {
                    "anyOf": [
                      {
                        "enum": [
                          "A",
                          "B",
                          "C",
                          "D",
                          "F"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Letter grade derived from score.",
                    "title": "Grade"
                  },
                  "max_score": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Maximum achievable score, 100 by default. It drops by a factor's max when that signal could not be measured, so grade reflects the available signals instead of penalizing the domain for our blind spot. Observed values are 100, 95, 90, 85, 80 and 75: a crt.sh failure excludes the 10-point CT factor, an unverifiable DKIM selector trims the email factor 25-\u003e20, and wildcard DNS can exclude the 10-point subdomain factor. ALWAYS compute percentages against this field, never against a literal 100.",
                    "title": "Max Score"
                  },
                  "score": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Cumulative risk score (0-100).",
                    "title": "Score"
                  }
                },
                "title": "RiskInfo",
                "type": "object"
              },
              "ShodanRepInfo": {
                "description": "Shodan full API enrichment (Pro tier only). Richer than InternetDB fields at top level.",
                "properties": {
                  "asn": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ASN string per Shodan (e.g. 'AS13335'); may differ from top-level asn int.",
                    "title": "Asn"
                  },
                  "city": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "City name per Shodan geolocation.",
                    "title": "City"
                  },
                  "country_name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Country name per Shodan geolocation.",
                    "title": "Country Name"
                  },
                  "hostnames": {
                    "description": "Hostnames observed pointing to this IP per Shodan.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Hostnames",
                    "type": "array"
                  },
                  "isp": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISP per Shodan (may differ from AbuseIPDB/RIPE).",
                    "title": "Isp"
                  },
                  "last_update": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 timestamp of Shodan's most recent data point for this IP.",
                    "title": "Last Update"
                  },
                  "org": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Organization name owning the IP per Shodan.",
                    "title": "Org"
                  },
                  "os": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Shodan-detected operating system (fingerprint-based, best-effort).",
                    "title": "Os"
                  },
                  "ports": {
                    "description": "Open ports observed by Shodan full scan (superset of top-level InternetDB ports).",
                    "items": {
                      "type": "integer"
                    },
                    "title": "Ports",
                    "type": "array"
                  },
                  "reason": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Human-readable reason. Present when status is skipped/restricted/rate_limited/error/pro_only.",
                    "title": "Reason"
                  },
                  "status": {
                    "description": "'ok' = data fetched; 'skipped' = API key not configured; 'restricted' = 403 (IP not available on free Shodan tier); 'rate_limited' = 429 quota exceeded; 'error' = transient HTTP/network failure; 'pro_only' = returned on Free tier as upsell hint.",
                    "enum": [
                      "ok",
                      "skipped",
                      "restricted",
                      "rate_limited",
                      "error",
                      "pro_only"
                    ],
                    "title": "Status",
                    "type": "string"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Upgrade link returned when status='pro_only'.",
                    "title": "Upgrade Url"
                  },
                  "vulns": {
                    "description": "CVE IDs Shodan has associated with banners on this IP.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Vulns",
                    "type": "array"
                  }
                },
                "required": [
                  "status"
                ],
                "title": "ShodanRepInfo",
                "type": "object"
              },
              "SoaInfo": {
                "additionalProperties": true,
                "description": "SOA record embedded inside DomainDnsInfo.soa.",
                "properties": {
                  "mname": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Primary nameserver (SOA MNAME).",
                    "title": "Mname"
                  },
                  "rname": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Responsible party mailbox (SOA RNAME).",
                    "title": "Rname"
                  },
                  "serial": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Zone serial number.",
                    "title": "Serial"
                  }
                },
                "title": "SoaInfo",
                "type": "object"
              },
              "SslInfoEmbedded": {
                "additionalProperties": true,
                "description": "SSL subset embedded in the domain report. See top-level SslResponse for live SSL endpoint shape.",
                "properties": {
                  "alpn": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Negotiated ALPN protocol (e.g. 'http/1.1', 'h2').",
                    "title": "Alpn"
                  },
                  "cert_valid": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "True only when chain verified AND hostname matches AND not expired. False when cert is readable but fails one or more validation checks (see validation_errors).",
                    "title": "Cert Valid"
                  },
                  "common_name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Leaf cert Subject CN.",
                    "title": "Common Name"
                  },
                  "days_remaining": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Days until expiry. Negative when already expired.",
                    "title": "Days Remaining"
                  },
                  "error": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Populated only on probe failure (timeout, connection refused, no port 443). Cert validation issues are NOT errors here — see cert_valid + validation_errors instead.",
                    "title": "Error"
                  },
                  "grade": {
                    "anyOf": [
                      {
                        "enum": [
                          "A",
                          "B",
                          "C",
                          "D",
                          "F"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "SSL grade. A/B/C: cert_valid AND TLS modern. D: cert readable but invalid (self-signed, hostname mismatch, untrusted root). F: probe failure, expired, or legacy TLS.",
                    "title": "Grade"
                  },
                  "issuer": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Leaf cert issuer organization name.",
                    "title": "Issuer"
                  },
                  "not_after": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "notAfter (expiry) timestamp (ISO 8601 / UTC).",
                    "title": "Not After"
                  },
                  "not_before": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "notBefore timestamp (ISO 8601 / UTC).",
                    "title": "Not Before"
                  },
                  "san": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Subject Alternative Names.",
                    "title": "San"
                  },
                  "serial_number": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Hex-encoded cert serial number.",
                    "title": "Serial Number"
                  },
                  "tls_version": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Negotiated TLS protocol (e.g. 'TLSv1.3', 'TLSv1.2'). Empty on handshake failure.",
                    "title": "Tls Version"
                  },
                  "validation_errors": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Canonical validation failure tags when cert_valid is False. Values: 'expired', 'self_signed', 'hostname_mismatch', 'untrusted_root', 'chain_incomplete'. Empty/null when cert_valid is True.",
                    "title": "Validation Errors"
                  },
                  "version": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "X.509 version as returned by the ssl module (int 3 for v3; empty string on some parse paths).",
                    "title": "Version"
                  }
                },
                "title": "SslInfoEmbedded",
                "type": "object"
              },
              "SubdomainsInfo": {
                "additionalProperties": true,
                "properties": {
                  "count": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Total subdomains discovered.",
                    "title": "Count"
                  },
                  "found_via_crtsh": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Count discovered via crt.sh CT log query.",
                    "title": "Found Via Crtsh"
                  },
                  "found_via_wordlist": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Count discovered via DNS brute-force wordlist.",
                    "title": "Found Via Wordlist"
                  },
                  "sources": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Sources that produced hits (subset of ['wordlist', 'crt_sh']).",
                    "title": "Sources"
                  },
                  "subdomains": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Sorted unique subdomain list.",
                    "title": "Subdomains"
                  },
                  "summary": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "One-line human-readable summary.",
                    "title": "Summary"
                  },
                  "warnings": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Non-fatal warnings (e.g. 'crt.sh timeout', 'result truncated').",
                    "title": "Warnings"
                  },
                  "wildcard_status": {
                    "anyOf": [
                      {
                        "enum": [
                          "absent",
                          "present",
                          "undetermined"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Wildcard-DNS probe result; anything other than 'absent' means count is unverified.",
                    "title": "Wildcard Status"
                  }
                },
                "title": "SubdomainsInfo",
                "type": "object"
              },
              "TechItem": {
                "properties": {
                  "category": {
                    "title": "Category",
                    "type": "string"
                  },
                  "name": {
                    "title": "Name",
                    "type": "string"
                  },
                  "source": {
                    "title": "Source",
                    "type": "string"
                  },
                  "version": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Version"
                  }
                },
                "required": [
                  "name",
                  "category",
                  "source"
                ],
                "title": "TechItem",
                "type": "object"
              },
              "ThreatInfo": {
                "additionalProperties": true,
                "properties": {
                  "tags": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Deduped list of tags (up to 20).",
                    "title": "Tags"
                  },
                  "threat_types": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Deduped list of threat classes across all URLs.",
                    "title": "Threat Types"
                  },
                  "url_count": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Total URLs URLhaus has seen for this domain.",
                    "title": "Url Count"
                  },
                  "urlhaus_status": {
                    "anyOf": [
                      {
                        "enum": [
                          "clean",
                          "listed",
                          "error",
                          "skipped"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "URLhaus lookup outcome. 'skipped' in lite mode; 'error' on API failure (treat as unavailable, not clean).",
                    "title": "Urlhaus Status"
                  },
                  "urls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/ThreatUrlEntry"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Up to 20 offending URL entries.",
                    "title": "Urls"
                  },
                  "urls_online": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Subset of url_count currently marked online.",
                    "title": "Urls Online"
                  }
                },
                "title": "ThreatInfo",
                "type": "object"
              },
              "ThreatUrlEntry": {
                "additionalProperties": true,
                "description": "Single offending URL entry inside ThreatInfo.urls.",
                "properties": {
                  "date_added": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When URLhaus first saw this URL.",
                    "title": "Date Added"
                  },
                  "status": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "URLhaus status for this URL ('online', 'offline').",
                    "title": "Status"
                  },
                  "tags": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Tags assigned by URLhaus (malware family, kit, etc.).",
                    "title": "Tags"
                  },
                  "threat": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Threat class (e.g. 'malware_download', 'phishing').",
                    "title": "Threat"
                  },
                  "url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Offending URL observed in URLhaus.",
                    "title": "Url"
                  }
                },
                "title": "ThreatUrlEntry",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              },
              "WafInfo": {
                "additionalProperties": true,
                "properties": {
                  "detected": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "WAF product names detected from response headers (e.g. ['Cloudflare', 'AWS CloudFront']).",
                    "title": "Detected"
                  },
                  "waf_present": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "True when `detected` is non-empty.",
                    "title": "Waf Present"
                  }
                },
                "title": "WafInfo",
                "type": "object"
              },
              "WhoisInfoEmbedded": {
                "additionalProperties": true,
                "description": "WHOIS subset embedded in the domain report. Fields are best-effort regex extracts from the raw WHOIS text.",
                "properties": {
                  "creation_date": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Domain creation date (format depends on registrar).",
                    "title": "Creation Date"
                  },
                  "error": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Populated when the WHOIS TCP query failed (e.g. no WHOIS server for TLD, socket timeout).",
                    "title": "Error"
                  },
                  "expiry_date": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Domain expiry date (format depends on registrar).",
                    "title": "Expiry Date"
                  },
                  "name_servers": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Authoritative nameservers per WHOIS.",
                    "title": "Name Servers"
                  },
                  "raw_length": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Byte length of raw WHOIS response (sanity indicator).",
                    "title": "Raw Length"
                  },
                  "registrar": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Registrar name as reported by the WHOIS server.",
                    "title": "Registrar"
                  },
                  "status": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "EPP domain status (e.g. 'clientTransferProhibited'). String or list depending on registrar.",
                    "title": "Status"
                  },
                  "updated_date": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Last-updated timestamp from WHOIS.",
                    "title": "Updated Date"
                  }
                },
                "title": "WhoisInfoEmbedded",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/AuditResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "audit_domainOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "contrast_scan",
          "title": "Contrast Scan",
          "description": "Active website security scan: runs the ContrastScan C engine (11 modules — HTTP security headers, SSL/TLS, DNS, redirect chain, information disclosure, cookie flags, DNSSEC, HTTP methods, CORS, HTML hygiene, deep CSP analysis) against the live site and enriches the raw result with severity-ranked vulnerability findings and a letter grade. Use for a hands-on misconfiguration scan; use audit_domain for passive recon (DNS/WHOIS/SSL/threat intel) and scan_headers for headers only. Active outbound fetch — a per-target eTLD+1 throttle (60 req/min) applies. Free: 30/hr (costs 6 tokens), Pro: 500/hr. Returns {domain, resolved_ip, total_score, max_score, grade, findings, findings_count, headers, ssl, dns, redirect, disclosure, cookies, dnssec, methods, cors, html, csp_analysis, enterprise, summary, next_calls}.",
          "inputSchema": {
            "properties": {
              "domain": {
                "description": "Root domain to scan, without protocol or path (e.g. 'example.com'). Bare IPs and private-resolving domains are rejected.",
                "title": "Domain",
                "type": "string"
              }
            },
            "required": [
              "domain"
            ],
            "title": "contrast_scanArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "ScanResponse": {
                "description": "Envelope for the ContrastScan engine result (scan/engine.py contrast_scan()).\n\nMirrors the engine dict 1:1. The eleven section blocks are dict-typed —\ntheir inner shape ({score, max, details, ...}) is owned by the C binary\n(scanner/src/contrastscan.c); findings-enrichment fields come from\nscan/findings.py. `verdict` + `next_calls` are inherited from\nBaseSuccessResponse.",
                "properties": {
                  "cookies": {
                    "additionalProperties": true,
                    "description": "Cookie-flags module block (score, max, details).",
                    "title": "Cookies",
                    "type": "object"
                  },
                  "cors": {
                    "additionalProperties": true,
                    "description": "CORS-policy module block (score, max, details).",
                    "title": "Cors",
                    "type": "object"
                  },
                  "csp_analysis": {
                    "additionalProperties": true,
                    "description": "Deep CSP-analysis module block (score, max, details).",
                    "title": "Csp Analysis",
                    "type": "object"
                  },
                  "disclosure": {
                    "additionalProperties": true,
                    "description": "Information-disclosure module block (score, max, details).",
                    "title": "Disclosure",
                    "type": "object"
                  },
                  "dns": {
                    "additionalProperties": true,
                    "description": "DNS / email-security module block (score, max, details).",
                    "title": "Dns",
                    "type": "object"
                  },
                  "dnssec": {
                    "additionalProperties": true,
                    "description": "DNSSEC module block (score, max, details).",
                    "title": "Dnssec",
                    "type": "object"
                  },
                  "domain": {
                    "description": "Scanned domain (lowercased, no scheme/path/port).",
                    "title": "Domain",
                    "type": "string"
                  },
                  "enterprise": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Present only for known enterprise domains: {is_enterprise, company, note} scoring caveat (large-org infra legitimately omits some checks).",
                    "title": "Enterprise"
                  },
                  "findings": {
                    "description": "Vulnerability findings sorted by severity (critical first). Each entry carries severity/category/title plus category-specific detail fields.",
                    "items": {
                      "additionalProperties": true,
                      "type": "object"
                    },
                    "title": "Findings",
                    "type": "array"
                  },
                  "findings_count": {
                    "additionalProperties": {
                      "type": "integer"
                    },
                    "description": "Finding counts keyed by severity: {critical, high, medium, low}.",
                    "title": "Findings Count",
                    "type": "object"
                  },
                  "grade": {
                    "default": "",
                    "description": "Letter grade (A-F) derived from total_score/max_score.",
                    "title": "Grade",
                    "type": "string"
                  },
                  "headers": {
                    "additionalProperties": true,
                    "description": "HTTP security-headers module block (score, max, details).",
                    "title": "Headers",
                    "type": "object"
                  },
                  "html": {
                    "additionalProperties": true,
                    "description": "HTML-hygiene module block (score, max, details).",
                    "title": "Html",
                    "type": "object"
                  },
                  "max_score": {
                    "default": 0,
                    "description": "Maximum achievable score for the modules that ran.",
                    "title": "Max Score",
                    "type": "integer"
                  },
                  "methods": {
                    "additionalProperties": true,
                    "description": "HTTP-methods module block (score, max, details).",
                    "title": "Methods",
                    "type": "object"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "redirect": {
                    "additionalProperties": true,
                    "description": "Redirect-chain module block (score, max, details).",
                    "title": "Redirect",
                    "type": "object"
                  },
                  "resolved_ip": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "IP the scanner pinned for the scan (SSRF defense — DNS resolved once, pre-validated; '127.0.0.1' for the self-domain bypass).",
                    "title": "Resolved Ip"
                  },
                  "ssl": {
                    "additionalProperties": true,
                    "description": "SSL/TLS module block (score, max, details).",
                    "title": "Ssl",
                    "type": "object"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line scan summary (reserved — empty until a summarizer is wired).",
                    "title": "Summary",
                    "type": "string"
                  },
                  "total_score": {
                    "default": 0,
                    "description": "Aggregate security score across all scanner modules.",
                    "title": "Total Score",
                    "type": "integer"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "domain"
                ],
                "title": "ScanResponse",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/ScanResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "contrast_scanOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "tech_stack_cve_audit",
          "title": "Tech Stack CVE Audit",
          "description": "Composite tech-stack + CVE audit (MCP-only, no REST endpoint). Detects technologies on the target domain, queries CVE database for known vulnerabilities per product, enriches top-10 CVE candidates with CISA KEV federal patch deadlines, and checks public exploit / PoC availability. Identical for every tier — all data is sourced from local DB mirrors (no Shodan/AbuseIPDB), so there is no tier gating. CVE candidate batch: 50. Cost: 10 tokens per call — Free 30/hr ≈ 3 audits, Pro 500/hr ≈ 50 audits. Returns {domain, technologies, cves_by_tech, kev_findings, exploit_findings, summary, next_calls}.",
          "inputSchema": {
            "properties": {
              "domain": {
                "description": "Target domain to fingerprint and CVE-audit (e.g. 'example.com'). IPs and internal hostnames are rejected.",
                "maxLength": 253,
                "minLength": 1,
                "title": "Domain",
                "type": "string"
              }
            },
            "required": [
              "domain"
            ],
            "title": "tech_stack_cve_auditArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "TechStackCveAuditResponse": {
                "additionalProperties": true,
                "description": "Response envelope for the MCP-only composite `tech_stack_cve_audit`.\n\nCombines technology fingerprint, per-tech CVE candidates, KEV matches,\nand exploit findings in a single agentic response. No tier gating — all\nfields (including `exploit_findings`) are sourced from local DB mirrors\nand are always present on the wire for every tier.",
                "properties": {
                  "cves_by_tech": {
                    "additionalProperties": {
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "description": "Map of `name/version` → list of CVE IDs for that product.",
                    "title": "Cves By Tech",
                    "type": "object"
                  },
                  "domain": {
                    "description": "Normalized input domain (clean_domain applied).",
                    "title": "Domain",
                    "type": "string"
                  },
                  "exploit_findings": {
                    "description": "Public exploit / PoC availability per matched CVE (local ExploitDB mirror). Always present; empty list when none found.",
                    "items": {
                      "additionalProperties": true,
                      "type": "object"
                    },
                    "title": "Exploit Findings",
                    "type": "array"
                  },
                  "kev_findings": {
                    "description": "CISA KEV records for matched CVEs. Empty when no KEV matches.",
                    "items": {
                      "additionalProperties": true,
                      "type": "object"
                    },
                    "title": "Kev Findings",
                    "type": "array"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "summary": {
                    "description": "Human-readable triage summary — N techs, M CVEs, K KEV-listed.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "technologies": {
                    "additionalProperties": true,
                    "description": "Tech fingerprint payload — {technologies, categories, count, summary}.",
                    "title": "Technologies",
                    "type": "object"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "domain",
                  "technologies",
                  "summary"
                ],
                "title": "TechStackCveAuditResponse",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/TechStackCveAuditResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "tech_stack_cve_auditOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "threat_report",
          "title": "Threat Report",
          "description": "Query comprehensive threat profile for an IP: Shodan host data, AbuseIPDB reputation, ASN/geolocation, and open ports. Use for IP investigation and SOC alert triage; for domain data use domain_report. Note: nested asn block always returns at most 50 IPv4/IPv6 prefixes — call asn_lookup with include_full_prefixes=True for the full announced-prefixes list. enrichment.vulns is severity-aware list[VulnInfo] (cve_id + severity + cvss_v3) — Phase 2 v1.16.0 BREAKING; pre-1.16 it was list[str] of CVE IDs. Free: 30/hr (costs 6 tokens), Pro: 500/hr. Returns {ip, enrichment, abuseipdb, shodan, asn, threat_level}.",
          "inputSchema": {
            "properties": {
              "ip": {
                "description": "Public IPv4 or IPv6 address to investigate (e.g. '8.8.8.8', '1.1.1.1'). Private/reserved IPs are rejected.",
                "title": "Ip",
                "type": "string"
              }
            },
            "required": [
              "ip"
            ],
            "title": "threat_reportArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "AbuseIpdbInfo": {
                "description": "AbuseIPDB reputation check (Pro tier only).",
                "properties": {
                  "abuse_score": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "AbuseIPDB confidence-of-abuse score (0-100). Only present when status='ok'.",
                    "title": "Abuse Score"
                  },
                  "country": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 3166-1 alpha-2 country code from AbuseIPDB geolocation (may differ from RIPE).",
                    "title": "Country"
                  },
                  "is_tor": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "AbuseIPDB's Tor exit flag (cross-reference with top-level tor_exit field).",
                    "title": "Is Tor"
                  },
                  "isp": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISP name as reported by AbuseIPDB.",
                    "title": "Isp"
                  },
                  "reason": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Human-readable reason string. Present when status is skipped/rate_limited/error/pro_only.",
                    "title": "Reason"
                  },
                  "status": {
                    "description": "'ok' = data fetched; 'skipped' = API key not configured; 'rate_limited' = AbuseIPDB quota exceeded; 'error' = transient HTTP/network failure; 'pro_only' = returned on Free tier as upsell hint (see upgrade_url).",
                    "enum": [
                      "ok",
                      "skipped",
                      "rate_limited",
                      "error",
                      "pro_only"
                    ],
                    "title": "Status",
                    "type": "string"
                  },
                  "total_reports": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Number of reports submitted against this IP in the last 90 days.",
                    "title": "Total Reports"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Upgrade link returned when status='pro_only'.",
                    "title": "Upgrade Url"
                  },
                  "usage_type": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "AbuseIPDB usage classification: 'Data Center/Web Hosting/Transit', 'ISP', 'Mobile ISP', etc.",
                    "title": "Usage Type"
                  }
                },
                "required": [
                  "status"
                ],
                "title": "AbuseIpdbInfo",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "IpEnrichmentInfo": {
                "description": "Shodan InternetDB enrichment subset (free, no API key) embedded in /v1/threat_report.\n\nMirrors the {ports, hostnames, vulns, cpes, tags} block at the top of ip_lookup,\nplus an internetdb_status field that surfaces the upstream fetch outcome —\nextracted as a sub-model so MCP clients see a typed schema instead of an opaque dict slot.",
                "properties": {
                  "cpes": {
                    "description": "CPE 2.3 strings for services detected on this IP per Shodan InternetDB.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Cpes",
                    "type": "array"
                  },
                  "hostnames": {
                    "description": "Hostnames Shodan InternetDB has observed pointing to this IP.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Hostnames",
                    "type": "array"
                  },
                  "internetdb_status": {
                    "anyOf": [
                      {
                        "enum": [
                          "ok",
                          "error"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Outcome of the InternetDB fetch. 'error' indicates upstream failure; absent on cached/legacy paths.",
                    "title": "Internetdb Status"
                  },
                  "ports": {
                    "description": "Open ports observed by Shodan InternetDB. Empty on upstream failure (treat as 'no data', not 'closed').",
                    "items": {
                      "type": "integer"
                    },
                    "title": "Ports",
                    "type": "array"
                  },
                  "tags": {
                    "description": "Shodan InternetDB classification tags (e.g. 'cdn', 'cloud', 'vpn', 'tor', 'self-signed').",
                    "items": {
                      "type": "string"
                    },
                    "title": "Tags",
                    "type": "array"
                  },
                  "vulns": {
                    "description": "CVEs Shodan InternetDB has associated with banners on this IP, enriched with severity + cvss_v3 from local cve.db (Phase 2 IP enrichment, v1.16.0 BREAKING). Pre-1.16 this was a flat list[str] of CVE IDs. Unknown CVEs emit severity='UNKNOWN'.",
                    "items": {
                      "$ref": "#/$defs/VulnInfo"
                    },
                    "title": "Vulns",
                    "type": "array"
                  }
                },
                "title": "IpEnrichmentInfo",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "ShodanRepInfo": {
                "description": "Shodan full API enrichment (Pro tier only). Richer than InternetDB fields at top level.",
                "properties": {
                  "asn": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ASN string per Shodan (e.g. 'AS13335'); may differ from top-level asn int.",
                    "title": "Asn"
                  },
                  "city": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "City name per Shodan geolocation.",
                    "title": "City"
                  },
                  "country_name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Country name per Shodan geolocation.",
                    "title": "Country Name"
                  },
                  "hostnames": {
                    "description": "Hostnames observed pointing to this IP per Shodan.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Hostnames",
                    "type": "array"
                  },
                  "isp": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISP per Shodan (may differ from AbuseIPDB/RIPE).",
                    "title": "Isp"
                  },
                  "last_update": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 timestamp of Shodan's most recent data point for this IP.",
                    "title": "Last Update"
                  },
                  "org": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Organization name owning the IP per Shodan.",
                    "title": "Org"
                  },
                  "os": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Shodan-detected operating system (fingerprint-based, best-effort).",
                    "title": "Os"
                  },
                  "ports": {
                    "description": "Open ports observed by Shodan full scan (superset of top-level InternetDB ports).",
                    "items": {
                      "type": "integer"
                    },
                    "title": "Ports",
                    "type": "array"
                  },
                  "reason": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Human-readable reason. Present when status is skipped/restricted/rate_limited/error/pro_only.",
                    "title": "Reason"
                  },
                  "status": {
                    "description": "'ok' = data fetched; 'skipped' = API key not configured; 'restricted' = 403 (IP not available on free Shodan tier); 'rate_limited' = 429 quota exceeded; 'error' = transient HTTP/network failure; 'pro_only' = returned on Free tier as upsell hint.",
                    "enum": [
                      "ok",
                      "skipped",
                      "restricted",
                      "rate_limited",
                      "error",
                      "pro_only"
                    ],
                    "title": "Status",
                    "type": "string"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Upgrade link returned when status='pro_only'.",
                    "title": "Upgrade Url"
                  },
                  "vulns": {
                    "description": "CVE IDs Shodan has associated with banners on this IP.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Vulns",
                    "type": "array"
                  }
                },
                "required": [
                  "status"
                ],
                "title": "ShodanRepInfo",
                "type": "object"
              },
              "ThreatReportResponse": {
                "properties": {
                  "abuseipdb": {
                    "$ref": "#/$defs/AbuseIpdbInfo",
                    "description": "AbuseIPDB abuse-confidence enrichment. Pro tier returns live data; Free tier returns a {status:'pro_only', reason, upgrade_url} upsell stub (NOT an error). Pro failure paths emit status='error' / 'rate_limited' / 'skipped'. See AbuseIpdbInfo."
                  },
                  "asn": {
                    "additionalProperties": true,
                    "description": "ASN ownership from RIPE Stat network-info: {asn: int, prefix: str}. Empty dict when RIPE has no allocation; {error:'lookup_failed'} on fetch failure.",
                    "title": "Asn",
                    "type": "object"
                  },
                  "asn_name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ASN holder name from RIPE Stat as-overview, or null.",
                    "title": "Asn Name"
                  },
                  "cloud_provider": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Cloud / hosting provider name when the IP sits in a known CIDR or maps to a tier-1 ASN.",
                    "title": "Cloud Provider"
                  },
                  "country": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Country code from RIPE Stat rir-stats-country, or null.",
                    "title": "Country"
                  },
                  "enrichment": {
                    "$ref": "#/$defs/IpEnrichmentInfo",
                    "description": "Shodan InternetDB free-tier enrichment (ports, hostnames, vulns, cpes, tags). Available on all tiers. See IpEnrichmentInfo for the exact field shape. Returned with all-empty lists on upstream failure — treat as 'no data', not 'clean'."
                  },
                  "firehol": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "FireHOL Level1 listing status: {status, listed, lists_matched}. Available on all tiers.",
                    "title": "Firehol"
                  },
                  "ip": {
                    "description": "Queried IP address (IPv4 or IPv6, echoed back verbatim).",
                    "title": "Ip",
                    "type": "string"
                  },
                  "is_datacenter": {
                    "default": false,
                    "description": "True if IP is hosted on a known datacenter / cloud provider (parity with ip_lookup.is_datacenter). Same two-tier detection — cloud_provider hit OR tier-1 datacenter ASN. Always present — never null.",
                    "title": "Is Datacenter",
                    "type": "boolean"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "ptr": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Reverse DNS PTR for the IP, or null when unresolvable.",
                    "title": "Ptr"
                  },
                  "risk_score": {
                    "default": 0,
                    "description": "Composite 0-100 score (parity with ip_lookup.risk_score). v1.17.0 additive components: ports (10 * min(count, 5) = 0-50), tor_exit (+30), firehol.listed (+20), AbuseIPDB confidence (round(15 * score / 100) = 0-15), is_datacenter (+10), known vulns (5 * min(count, 4) = 0-20). Use severity_label for thresholding.",
                    "title": "Risk Score",
                    "type": "integer"
                  },
                  "severity_label": {
                    "default": "low",
                    "description": "Coarse risk band derived from risk_score (parity with ip_lookup.severity_label). Pre-1.17 the route emitted this field and advertised it in verdict.falsifiable_fields but the schema didn't declare it, so Pydantic silently dropped it from the wire. Same thresholds: \u003e=75 critical, \u003e=50 high, \u003e=25 medium, else low.",
                    "enum": [
                      "low",
                      "medium",
                      "high",
                      "critical"
                    ],
                    "title": "Severity Label",
                    "type": "string"
                  },
                  "shodan": {
                    "$ref": "#/$defs/ShodanRepInfo",
                    "description": "Shodan full-API enrichment (richer than the InternetDB enrichment block). Pro tier returns live data; Free tier returns a {status:'pro_only', reason, upgrade_url} upsell stub. Pro failure paths emit status='error' / 'rate_limited' / 'restricted' / 'skipped'. See ShodanRepInfo."
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line human summary combining threat_level, port count, vuln count, and abuse signal.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "threat_level": {
                    "default": "none",
                    "description": "Heuristic threat tier. 'high' when any vulns present OR abuse_score\u003e=50; 'medium' when abuse_score\u003e=25; 'low' when open ports observed; 'none' otherwise. On Free tier threat_level is necessarily conservative — abuse_score is unknown.",
                    "enum": [
                      "none",
                      "low",
                      "medium",
                      "high"
                    ],
                    "title": "Threat Level",
                    "type": "string"
                  },
                  "tor_exit": {
                    "default": false,
                    "description": "True if IP appears in the Tor Project bulk exit list (verdict.sources_unavailable['tor'] when fetch failed).",
                    "title": "Tor Exit",
                    "type": "boolean"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "ip"
                ],
                "title": "ThreatReportResponse",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              },
              "VulnInfo": {
                "description": "Severity-enriched CVE entry attached to /v1/ip and /v1/threat_report.\n\nPhase 2 IP enrichment (v1.16.0 BREAKING): Shodan InternetDB returns a flat\nlist of CVE IDs with no severity context, forcing agents to fan out\ncve_lookup calls for triage. We resolve severity + cvss_v3 against the\nlocal cve.db in a single SQL batch so the agent can prioritise without\nextra round-trips. Unknown CVEs are emitted with severity='UNKNOWN' /\ncvss_v3=null so the ID is preserved (the agent must not infer 'benign'\nfrom the absence of a row).",
                "properties": {
                  "cve_id": {
                    "description": "CVE identifier (e.g. 'CVE-2021-44228').",
                    "title": "Cve Id",
                    "type": "string"
                  },
                  "cvss_v3": {
                    "anyOf": [
                      {
                        "maximum": 10,
                        "minimum": 0,
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CVSS v3 base score (0.0-10.0). Null when severity='UNKNOWN' or NVD has no v3 score.",
                    "title": "Cvss V3"
                  },
                  "severity": {
                    "description": "NVD CVSS v3 severity bucket from local cve.db. 'UNKNOWN' when the CVE is not in our database (NVD may not have classified it yet, or the ID is reserved). Treat UNKNOWN as 'do not assume benign — call cve_lookup for fresh upstream data.'",
                    "enum": [
                      "CRITICAL",
                      "HIGH",
                      "MEDIUM",
                      "LOW",
                      "UNKNOWN"
                    ],
                    "title": "Severity",
                    "type": "string"
                  }
                },
                "required": [
                  "cve_id",
                  "severity"
                ],
                "title": "VulnInfo",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/ThreatReportResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "threat_reportOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "dns_lookup",
          "title": "DNS Lookup",
          "description": "Query all DNS record types (A, AAAA, MX, NS, TXT, CNAME, SOA) for a domain. Use for mail routing inspection, nameserver verification, or SPF/DMARC checks; for full overview use domain_report. TXT records are returned raw (no filter) — `total_txt_records` always carries the honest count (use domain_report for the security-only filtered TXT view). Free: 30/hr, Pro: 500/hr. Returns {domain, records: {a, aaaa, mx, ns, txt, total_txt_records, cname, soa}, summary}.",
          "inputSchema": {
            "properties": {
              "domain": {
                "description": "Root domain to query, without protocol or path (e.g. 'example.com', 'cloudflare.com')",
                "title": "Domain",
                "type": "string"
              }
            },
            "required": [
              "domain"
            ],
            "title": "dns_lookupArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "DnsResponse": {
                "properties": {
                  "domain": {
                    "description": "Queried domain (lowercased, no scheme).",
                    "title": "Domain",
                    "type": "string"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "records": {
                    "$ref": "#/$defs/DomainDnsInfo",
                    "description": "DNS records keyed by type (a, aaaa, mx, ns, txt, cname, soa). Keys are omitted (not null) when the lookup for that type fails. Same shape as DomainReportResponse.dns."
                  },
                  "summary": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "One-line human-readable record summary (e.g. 'A, MX, TXT records for example.com').",
                    "title": "Summary"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "domain",
                  "records"
                ],
                "title": "DnsResponse",
                "type": "object"
              },
              "DomainDnsInfo": {
                "additionalProperties": true,
                "description": "DNS records per type. Keys are omitted (not null) when the lookup for that type fails.",
                "properties": {
                  "a": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "A records (IPv4 addresses).",
                    "title": "A"
                  },
                  "aaaa": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "AAAA records (IPv6 addresses).",
                    "title": "Aaaa"
                  },
                  "cname": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CNAME records.",
                    "title": "Cname"
                  },
                  "mx": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/MxDnsRecord"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "MX records as {priority, host} list.",
                    "title": "Mx"
                  },
                  "ns": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "NS records (nameserver hostnames).",
                    "title": "Ns"
                  },
                  "soa": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/SoaInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "SOA record (zone authority)."
                  },
                  "total_txt_records": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Honest pre-filter TXT record count. Always emitted (domain_report, audit_domain, /v1/dns). Equals len(txt) when include_all_txt=true or on /v1/dns/{domain} (raw, unfiltered). 0 when no TXT records exist. Null only when the field is absent (older cached entries).",
                    "title": "Total Txt Records"
                  },
                  "txt": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "TXT records. By default in domain_report, filtered to security-relevant entries (SPF v=spf, DMARC v=DMARC, DKIM v=DKIM, MTA-STS v=STSv, TLS-RPT v=TLSRPTv). Pass ?include_all_txt=true to return every TXT including vendor verification strings.",
                    "title": "Txt"
                  }
                },
                "title": "DomainDnsInfo",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "MxDnsRecord": {
                "description": "Single MX record embedded inside DomainReportResponse.dns.mx.",
                "properties": {
                  "host": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "MX hostname (trailing dot stripped).",
                    "title": "Host"
                  },
                  "priority": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "MX preference (lower = higher priority).",
                    "title": "Priority"
                  }
                },
                "title": "MxDnsRecord",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "SoaInfo": {
                "additionalProperties": true,
                "description": "SOA record embedded inside DomainDnsInfo.soa.",
                "properties": {
                  "mname": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Primary nameserver (SOA MNAME).",
                    "title": "Mname"
                  },
                  "rname": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Responsible party mailbox (SOA RNAME).",
                    "title": "Rname"
                  },
                  "serial": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Zone serial number.",
                    "title": "Serial"
                  }
                },
                "title": "SoaInfo",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/DnsResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "dns_lookupOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "whois_lookup",
          "title": "WHOIS Lookup",
          "description": "Retrieve WHOIS registration data: registrar, creation/expiry dates, nameservers, status. Use to verify domain ownership, age, expiration; for full audit use domain_report. Free: 30/hr, Pro: 500/hr. Returns {domain, whois: {registrar, creation_date, expiry_date, updated_date, name_servers, status, raw_length, error}, summary}.",
          "inputSchema": {
            "properties": {
              "domain": {
                "description": "Root domain to query WHOIS for (e.g. 'example.com', 'github.com')",
                "title": "Domain",
                "type": "string"
              }
            },
            "required": [
              "domain"
            ],
            "title": "whois_lookupArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              },
              "WhoisInfoEmbedded": {
                "additionalProperties": true,
                "description": "WHOIS subset embedded in the domain report. Fields are best-effort regex extracts from the raw WHOIS text.",
                "properties": {
                  "creation_date": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Domain creation date (format depends on registrar).",
                    "title": "Creation Date"
                  },
                  "error": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Populated when the WHOIS TCP query failed (e.g. no WHOIS server for TLD, socket timeout).",
                    "title": "Error"
                  },
                  "expiry_date": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Domain expiry date (format depends on registrar).",
                    "title": "Expiry Date"
                  },
                  "name_servers": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Authoritative nameservers per WHOIS.",
                    "title": "Name Servers"
                  },
                  "raw_length": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Byte length of raw WHOIS response (sanity indicator).",
                    "title": "Raw Length"
                  },
                  "registrar": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Registrar name as reported by the WHOIS server.",
                    "title": "Registrar"
                  },
                  "status": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "EPP domain status (e.g. 'clientTransferProhibited'). String or list depending on registrar.",
                    "title": "Status"
                  },
                  "updated_date": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Last-updated timestamp from WHOIS.",
                    "title": "Updated Date"
                  }
                },
                "title": "WhoisInfoEmbedded",
                "type": "object"
              },
              "WhoisResponse": {
                "properties": {
                  "domain": {
                    "description": "Queried domain (lowercased, no scheme).",
                    "title": "Domain",
                    "type": "string"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line human-readable summary (registrar + expiry hint).",
                    "title": "Summary",
                    "type": "string"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  },
                  "whois": {
                    "$ref": "#/$defs/WhoisInfoEmbedded",
                    "description": "WHOIS extract — registrar, dates, nameservers, EPP status. Same shape as DomainReportResponse.whois. Populates `error` when the WHOIS query failed (no WHOIS server for TLD, socket timeout, etc.)."
                  }
                },
                "required": [
                  "domain",
                  "whois"
                ],
                "title": "WhoisResponse",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/WhoisResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "whois_lookupOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "ssl_check",
          "description": "(not repeated here: it reads like a rating or a usage claim)",
          "inputSchema": {
            "properties": {
              "domain": {
                "description": "Domain to check SSL/TLS certificate for (e.g. 'example.com', 'api.stripe.com')",
                "title": "Domain",
                "type": "string"
              }
            },
            "required": [
              "domain"
            ],
            "title": "ssl_checkArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "CipherInfo": {
                "additionalProperties": true,
                "properties": {
                  "bits": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Effective symmetric key length in bits (e.g. 256 for AES-256-GCM). Null on handshake failure.",
                    "title": "Bits"
                  },
                  "name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Cipher suite name as reported by OpenSSL, e.g. 'TLS_AES_256_GCM_SHA384' (TLS 1.3) or 'ECDHE-RSA-AES256-GCM-SHA384' (TLS 1.2). Null on handshake failure.",
                    "title": "Name"
                  },
                  "protocol": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "TLS protocol version negotiated for this cipher, e.g. 'TLSv1.3', 'TLSv1.2'. Mirrors SslResponse.protocol and is null on handshake failure.",
                    "title": "Protocol"
                  }
                },
                "title": "CipherInfo",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "SslChainItem": {
                "properties": {
                  "issuer": {
                    "default": "",
                    "description": "Issuer DN of the chain certificate (the CA that signed it).",
                    "title": "Issuer",
                    "type": "string"
                  },
                  "not_after": {
                    "default": "",
                    "description": "Certificate's expiry timestamp (ISO 8601, UTC).",
                    "title": "Not After",
                    "type": "string"
                  },
                  "source": {
                    "default": "handshake",
                    "description": "How this chain entry was discovered: 'handshake' (server-sent) or 'aia_fetch' (AIA chase-up).",
                    "title": "Source",
                    "type": "string"
                  },
                  "subject": {
                    "default": "",
                    "description": "Subject DN of the chain certificate, e.g. 'CN=*.example.com'.",
                    "title": "Subject",
                    "type": "string"
                  }
                },
                "title": "SslChainItem",
                "type": "object"
              },
              "SslResponse": {
                "properties": {
                  "chain": {
                    "description": "Full cert chain from leaf upward (excluding system root). Includes AIA-fetched intermediates when needed.",
                    "items": {
                      "$ref": "#/$defs/SslChainItem"
                    },
                    "title": "Chain",
                    "type": "array"
                  },
                  "cipher": {
                    "$ref": "#/$defs/CipherInfo",
                    "description": "Negotiated cipher suite with name, negotiated TLS protocol, and key length. All fields are null on handshake failure (empty CipherInfo)."
                  },
                  "days_remaining": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Days until leaf cert expires (negative if already expired). Null when not_after could not be parsed.",
                    "title": "Days Remaining"
                  },
                  "domain": {
                    "description": "Queried domain (echoed). SNI-matched against the leaf cert.",
                    "title": "Domain",
                    "type": "string"
                  },
                  "grade": {
                    "default": "F",
                    "description": "Overall SSL configuration grade. 'A' (cert_valid + TLSv1.3 + \u003e=30 days remaining), 'B' (cert_valid + (TLSv1.3 \u003c30d OR TLSv1.2 healthy)), 'C' (cert_valid + (TLSv1.2 \u003c14d OR TLSv1.3 \u003c7d OR unknown protocol)), 'D' (cert readable but invalid: hostname_mismatch / untrusted_root / self_signed), 'F' (probe failure, expired, OR TLSv1/TLSv1.1). Canonical grader is _ssl_grade() in domain/recon.py; same helper powers /v1/domain/ ssl section (single source of truth).",
                    "enum": [
                      "A",
                      "B",
                      "C",
                      "D",
                      "F"
                    ],
                    "title": "Grade",
                    "type": "string"
                  },
                  "issuer": {
                    "default": "",
                    "description": "Issuer DN of the leaf cert, e.g. \"CN=Let's Encrypt R3, O=Let's Encrypt, C=US\".",
                    "title": "Issuer",
                    "type": "string"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "not_after": {
                    "default": "",
                    "description": "Leaf cert's notAfter timestamp (ISO 8601, UTC) — expiry moment.",
                    "title": "Not After",
                    "type": "string"
                  },
                  "not_before": {
                    "default": "",
                    "description": "Leaf cert's notBefore timestamp (ISO 8601, UTC) — earliest valid moment.",
                    "title": "Not Before",
                    "type": "string"
                  },
                  "protocol": {
                    "default": "",
                    "description": "Negotiated TLS protocol version string as reported by OpenSSL: 'TLSv1.3', 'TLSv1.2', 'TLSv1.1', 'TLSv1'. Empty on handshake failure. Grade F is forced for TLSv1/TLSv1.1.",
                    "title": "Protocol",
                    "type": "string"
                  },
                  "san": {
                    "description": "Subject Alternative Names — all DNS names the cert is valid for (including CN when distinct).",
                    "items": {
                      "type": "string"
                    },
                    "title": "San",
                    "type": "array"
                  },
                  "serial_number": {
                    "default": "",
                    "description": "Hex-encoded leaf cert serial number.",
                    "title": "Serial Number",
                    "type": "string"
                  },
                  "signature_algorithm": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Signature algorithm name, e.g. 'sha256WithRSAEncryption', 'ecdsa-with-SHA384'.",
                    "title": "Signature Algorithm"
                  },
                  "subject": {
                    "default": "",
                    "description": "Subject DN of the leaf cert, e.g. 'CN=example.com'.",
                    "title": "Subject",
                    "type": "string"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line human summary, e.g. 'example.com valid until 2026-07-04 (71 days) · TLSv1.3 · grade A'.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "valid": {
                    "default": false,
                    "description": "True when TLS handshake succeeded AND cert is unexpired AND chain verified. False on any failure (handshake error, expired, hostname mismatch, untrusted CA).",
                    "title": "Valid",
                    "type": "boolean"
                  },
                  "validation_errors": {
                    "description": "Canonical cert validation failure tags when cert is readable but invalid. Values: 'expired', 'self_signed', 'hostname_mismatch', 'untrusted_root', 'chain_incomplete'. Empty when cert validates cleanly. See also: 'valid' (boolean overall) and 'warnings' (human-readable).",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 10,
                    "title": "Validation Errors",
                    "type": "array"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  },
                  "warnings": {
                    "description": "Human-readable warnings: deprecated protocol, near-expiry, self-signed chain, weak signature algorithm, etc.",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 10,
                    "title": "Warnings",
                    "type": "array"
                  }
                },
                "required": [
                  "domain"
                ],
                "title": "SslResponse",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/SslResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "ssl_checkOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "subdomain_enum",
          "title": "Subdomain Enum",
          "description": "Discover subdomains using passive methods: Certificate Transparency logs + DNS brute-force (no active probing). Use to map organization's attack surface; non-intrusive. Response carries next_calls — capped at 5 ssl_check hints (one per first-five subdomain) so triage scales to large enumerations without token bloat; pull tail entries by name when needed. Free: 30/hr, Pro: 500/hr. Returns {domain, count, subdomains, sources, found_via_wordlist, found_via_crtsh, wildcard_status, crtsh_status, warnings, summary, next_calls}. Always check wildcard_status FIRST: 'absent' means the DNS brute-force plane was meaningful; 'present' means the zone answers every name (wildcard DNS) so wordlist results were discarded and count is a certificate-transparency LOWER BOUND — report the surface as UNKNOWN, not small, and never infer low exposure from it; 'undetermined' means a negative-control probe went unanswered, so count is unverified. Then check crtsh_status: 'ok' means the CT lookup completed (so a low count is real); 'timeout' / 'rate_limited' / 'unavailable' / 'error' means CT logs did not respond and the count is wordlist-only — the actual attack surface is likely larger, retry later or surface the limitation to the user.",
          "inputSchema": {
            "properties": {
              "domain": {
                "description": "Root domain to enumerate subdomains for (e.g. 'example.com', 'tesla.com')",
                "title": "Domain",
                "type": "string"
              }
            },
            "required": [
              "domain"
            ],
            "title": "subdomain_enumArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "SubdomainsResponse": {
                "properties": {
                  "count": {
                    "default": 0,
                    "title": "Count",
                    "type": "integer"
                  },
                  "crtsh_status": {
                    "default": "ok",
                    "description": "Status of the crt.sh certificate-transparency lookup that feeds found_via_crtsh. 'ok' means the upstream responded — found_via_crtsh=0 with status='ok' is a real empty result. Anything else means the upstream did not deliver (timeout / rate_limited / unavailable / error); count and subdomains are then wordlist-only and an unknown number of CT-log subdomains may be missing.",
                    "enum": [
                      "ok",
                      "timeout",
                      "rate_limited",
                      "unavailable",
                      "error"
                    ],
                    "title": "Crtsh Status",
                    "type": "string"
                  },
                  "domain": {
                    "title": "Domain",
                    "type": "string"
                  },
                  "found_via_crtsh": {
                    "default": 0,
                    "title": "Found Via Crtsh",
                    "type": "integer"
                  },
                  "found_via_wordlist": {
                    "default": 0,
                    "title": "Found Via Wordlist",
                    "type": "integer"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "sources": {
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources",
                    "type": "array"
                  },
                  "subdomains": {
                    "items": {
                      "type": "string"
                    },
                    "title": "Subdomains",
                    "type": "array"
                  },
                  "summary": {
                    "default": "",
                    "title": "Summary",
                    "type": "string"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  },
                  "warnings": {
                    "items": {
                      "type": "string"
                    },
                    "title": "Warnings",
                    "type": "array"
                  },
                  "wildcard_status": {
                    "default": "absent",
                    "description": "Result of two synthetic negative-control DNS probes. 'absent' = no catch-all, the wordlist plane is trustworthy. 'present' = wildcard DNS (*.domain) answers every name, so brute-force cannot distinguish a real host from the catch-all; wordlist results are discarded (found_via_wordlist=0) and count is a certificate-transparency LOWER BOUND — the real surface is UNKNOWN, not small. 'undetermined' = a probe went unanswered or the target name was too long to probe, so the count is unverified and may contain artefacts. Treat anything other than 'absent' as a measurement caveat.",
                    "enum": [
                      "absent",
                      "present",
                      "undetermined"
                    ],
                    "title": "Wildcard Status",
                    "type": "string"
                  }
                },
                "required": [
                  "domain"
                ],
                "title": "SubdomainsResponse",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/SubdomainsResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "subdomain_enumOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "tech_fingerprint",
          "title": "Tech Fingerprint",
          "description": "Detect website technology stack: CMS, frameworks, CDN, analytics tools, web servers, languages (via HTTP headers + HTML analysis). Use for passive reconnaissance; for full audit use audit_domain. Free: 30/hr, Pro: 500/hr. Returns {technologies: [{name, category, confidence%, version}]}.",
          "inputSchema": {
            "properties": {
              "domain": {
                "description": "Domain to fingerprint (e.g. 'example.com', 'shopify.com')",
                "title": "Domain",
                "type": "string"
              }
            },
            "required": [
              "domain"
            ],
            "title": "tech_fingerprintArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "TechItem": {
                "properties": {
                  "category": {
                    "title": "Category",
                    "type": "string"
                  },
                  "name": {
                    "title": "Name",
                    "type": "string"
                  },
                  "source": {
                    "title": "Source",
                    "type": "string"
                  },
                  "version": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Version"
                  }
                },
                "required": [
                  "name",
                  "category",
                  "source"
                ],
                "title": "TechItem",
                "type": "object"
              },
              "TechResponse": {
                "properties": {
                  "categories": {
                    "additionalProperties": {
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "title": "Categories",
                    "type": "object"
                  },
                  "count": {
                    "default": 0,
                    "title": "Count",
                    "type": "integer"
                  },
                  "domain": {
                    "title": "Domain",
                    "type": "string"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "summary": {
                    "default": "",
                    "title": "Summary",
                    "type": "string"
                  },
                  "technologies": {
                    "items": {
                      "$ref": "#/$defs/TechItem"
                    },
                    "title": "Technologies",
                    "type": "array"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "domain"
                ],
                "title": "TechResponse",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/TechResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "tech_fingerprintOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "threat_intel",
          "title": "Threat Intel",
          "description": "Check domain against abuse.ch URLhaus for known malware-distribution URLs (single source — for multi-feed correlation use ioc_lookup which adds ThreatFox and, for IPs, Feodo Tracker). Use for fast domain-level threat assessment; use phishing_check for specific URLs. Free: 30/hr, Pro: 500/hr. Returns {malware_urls, threat_tags, threat_status, summary}.",
          "inputSchema": {
            "properties": {
              "domain": {
                "description": "Domain to check for threats (e.g. 'suspicious-site.com', 'example.com')",
                "title": "Domain",
                "type": "string"
              }
            },
            "required": [
              "domain"
            ],
            "title": "threat_intelArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "ThreatResponse": {
                "properties": {
                  "domain": {
                    "title": "Domain",
                    "type": "string"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "summary": {
                    "default": "",
                    "title": "Summary",
                    "type": "string"
                  },
                  "tags": {
                    "items": {
                      "type": "string"
                    },
                    "title": "Tags",
                    "type": "array"
                  },
                  "threat_types": {
                    "items": {
                      "type": "string"
                    },
                    "title": "Threat Types",
                    "type": "array"
                  },
                  "url_count": {
                    "default": 0,
                    "title": "Url Count",
                    "type": "integer"
                  },
                  "urlhaus_status": {
                    "title": "Urlhaus Status",
                    "type": "string"
                  },
                  "urls": {
                    "items": {
                      "$ref": "#/$defs/ThreatUrl"
                    },
                    "title": "Urls",
                    "type": "array"
                  },
                  "urls_online": {
                    "default": 0,
                    "title": "Urls Online",
                    "type": "integer"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "domain",
                  "urlhaus_status"
                ],
                "title": "ThreatResponse",
                "type": "object"
              },
              "ThreatUrl": {
                "properties": {
                  "date_added": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Date Added"
                  },
                  "status": {
                    "default": "unknown",
                    "title": "Status",
                    "type": "string"
                  },
                  "tags": {
                    "items": {
                      "type": "string"
                    },
                    "title": "Tags",
                    "type": "array"
                  },
                  "threat": {
                    "default": "unknown",
                    "title": "Threat",
                    "type": "string"
                  },
                  "url": {
                    "default": "",
                    "title": "Url",
                    "type": "string"
                  }
                },
                "title": "ThreatUrl",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/ThreatResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "threat_intelOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "wayback_lookup",
          "title": "Wayback Lookup",
          "description": "Retrieve Wayback Machine snapshots for a domain: first capture, latest, total count, snapshot list. Use to investigate domain history and age; for full audit use domain_report. Free: 30/hr, Pro: 500/hr. status='ok' means the count is authoritative (even when 0 → confirmed no archives). status='unavailable' means CDX timed out/rate-limited/5xx — total_snapshots is OMITTED (unknown, NOT zero) and the agent should NOT report \"no snapshots\"; the warnings[] array carries the cdx_* error code (cdx_timeout/cdx_rate_limited/cdx_unavailable/cdx_error/cdx_parse_error/cdx_body_too_large). Heavy domains (kernel.org, microsoft.com, archive.org itself) frequently time out the CDX endpoint despite having millions of snapshots — fall back to archive_url for manual inspection. Returns {domain, status, total_snapshots, first_seen, last_seen, years_online, snapshots, archive_url, summary, warnings}.",
          "inputSchema": {
            "properties": {
              "domain": {
                "description": "Domain to look up in web archives (e.g. 'example.com', 'archive.org')",
                "title": "Domain",
                "type": "string"
              }
            },
            "required": [
              "domain"
            ],
            "title": "wayback_lookupArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              },
              "WaybackResponse": {
                "properties": {
                  "archive_url": {
                    "default": "",
                    "title": "Archive Url",
                    "type": "string"
                  },
                  "domain": {
                    "title": "Domain",
                    "type": "string"
                  },
                  "first_seen": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "First Seen"
                  },
                  "last_seen": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Last Seen"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "snapshots": {
                    "items": {
                      "$ref": "#/$defs/WaybackSnapshot"
                    },
                    "title": "Snapshots",
                    "type": "array"
                  },
                  "status": {
                    "default": "ok",
                    "description": "'ok' when the CDX request returned a parseable response (even if zero snapshots); 'unavailable' when CDX timed out, rate-limited, 5xx-failed, or returned malformed data. On 'unavailable' total_snapshots is omitted (unknown) — DO NOT interpret absence as zero. See warnings[] for the specific cdx_* error code.",
                    "enum": [
                      "ok",
                      "unavailable"
                    ],
                    "title": "Status",
                    "type": "string"
                  },
                  "summary": {
                    "default": "",
                    "title": "Summary",
                    "type": "string"
                  },
                  "total_snapshots": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Snapshot count when status='ok'. Omitted (null) when status='unavailable' — the count is unknown, NOT zero. Use the archive_url to check manually in that case.",
                    "title": "Total Snapshots"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  },
                  "warnings": {
                    "items": {
                      "type": "string"
                    },
                    "title": "Warnings",
                    "type": "array"
                  },
                  "years_online": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Years between first_seen and last_seen. Omitted when status='unavailable'.",
                    "title": "Years Online"
                  }
                },
                "required": [
                  "domain"
                ],
                "title": "WaybackResponse",
                "type": "object"
              },
              "WaybackSnapshot": {
                "properties": {
                  "date": {
                    "title": "Date",
                    "type": "string"
                  },
                  "mimetype": {
                    "title": "Mimetype",
                    "type": "string"
                  },
                  "status": {
                    "title": "Status",
                    "type": "string"
                  },
                  "timestamp": {
                    "title": "Timestamp",
                    "type": "string"
                  },
                  "url": {
                    "title": "Url",
                    "type": "string"
                  }
                },
                "required": [
                  "timestamp",
                  "date",
                  "status",
                  "mimetype",
                  "url"
                ],
                "title": "WaybackSnapshot",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/WaybackResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "wayback_lookupOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "scan_headers",
          "title": "Scan Headers",
          "description": "Perform live HTTP GET and analyze security headers: CSP, HSTS, X-Frame-Options, X-Content-Type-Options, Permissions-Policy, Referrer-Policy. Use to audit live website headers; use check_headers to validate headers you already have. Free: 30/hr, Pro: 500/hr. By default header values are truncated to 500 chars (CSP can exceed 4 KB on large sites); pass include='full' for the full raw value. Returns {headers_present, headers_missing, findings, total_score}.",
          "inputSchema": {
            "properties": {
              "domain": {
                "description": "Domain to scan live HTTP headers for (e.g. 'example.com', 'api.github.com')",
                "title": "Domain",
                "type": "string"
              },
              "include": {
                "default": "",
                "description": "Detail level. Default ('') returns slim findings — raw header values capped at 500 chars with total_value_length carrying the honest pre-truncation length. Pass 'full' to restore the full raw value (useful for inspecting full CSP directives on sites like GitHub where the CSP header exceeds 4 KB). Allowed: '' or 'full'.",
                "enum": [
                  "",
                  "full"
                ],
                "title": "Include",
                "type": "string"
              }
            },
            "required": [
              "domain"
            ],
            "title": "scan_headersArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "HeaderFinding": {
                "properties": {
                  "description": {
                    "default": "",
                    "description": "Human-readable explanation of what this header protects against.",
                    "title": "Description",
                    "type": "string"
                  },
                  "header": {
                    "description": "Canonical header name as defined by the ruleset (e.g. 'Strict-Transport-Security', 'Content-Security-Policy').",
                    "title": "Header",
                    "type": "string"
                  },
                  "issues": {
                    "description": "Machine-readable issue codes emitted by the validator for present-but-invalid headers (e.g. 'hsts_max_age_too_short', 'csp_wildcard_script_src', 'xfo_allowall'). Empty when the header is absent, valid, or has no validator.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Issues",
                    "type": "array"
                  },
                  "present": {
                    "description": "True when the response sent this header at all (regardless of whether the value is valid).",
                    "title": "Present",
                    "type": "boolean"
                  },
                  "reference": {
                    "default": "",
                    "description": "URL to authoritative spec/documentation (MDN, OWASP, RFC).",
                    "title": "Reference",
                    "type": "string"
                  },
                  "remediation": {
                    "default": "",
                    "description": "Concrete recommended header value or configuration snippet.",
                    "title": "Remediation",
                    "type": "string"
                  },
                  "severity": {
                    "description": "Impact weight assigned by the ruleset: 'high' (25 pts), 'medium' (15 pts), 'low' (10 pts). Drives the overall score/grade — missing a 'high' header costs more than missing a 'low' one.",
                    "enum": [
                      "high",
                      "medium",
                      "low"
                    ],
                    "title": "Severity",
                    "type": "string"
                  },
                  "total_value_length": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Honest pre-truncation char length of the raw header value. Only emitted when the value was actually truncated (raw length \u003e 500). Null when no truncation occurred, when no validator applies, or when the header is absent.",
                    "title": "Total Value Length"
                  },
                  "valid": {
                    "default": false,
                    "description": "Value-level validation result. True when the header is present AND its value passes the header-specific validator (e.g. HSTS max-age \u003e= 1 year + includeSubDomains; CSP has no wildcard source in script-src). True also when the header is present but no validator exists for it. False when the header is absent, or present-but-invalid. Inspect `issues` for the specific reasons a present-but-invalid header failed.",
                    "title": "Valid",
                    "type": "boolean"
                  },
                  "value": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Raw header value as sent by the origin, when the header is present AND a validator exists for it. Null when the header is absent, or when it's present but no validator applies to it. By default the value is capped at the first 500 chars (CSP headers can exceed 4 KB); inspect total_value_length to see if truncation occurred and refetch with include=full to restore the full value.",
                    "title": "Value"
                  }
                },
                "required": [
                  "header",
                  "severity",
                  "present"
                ],
                "title": "HeaderFinding",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "ScanHeadersResponse": {
                "properties": {
                  "domain": {
                    "description": "Queried domain (lowercased, no scheme).",
                    "title": "Domain",
                    "type": "string"
                  },
                  "findings": {
                    "description": "Per-header validation findings — one entry per header in the ruleset (present or missing).",
                    "items": {
                      "$ref": "#/$defs/HeaderFinding"
                    },
                    "title": "Findings",
                    "type": "array"
                  },
                  "grade": {
                    "default": "F",
                    "description": "Letter grade derived from score: A=90+, B=75+, C=60+, D=40+, else F.",
                    "enum": [
                      "A",
                      "B",
                      "C",
                      "D",
                      "F"
                    ],
                    "title": "Grade",
                    "type": "string"
                  },
                  "headers_missing": {
                    "description": "Names of security-relevant headers the origin did NOT send.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Headers Missing",
                    "type": "array"
                  },
                  "headers_present": {
                    "description": "Names of security-relevant headers the origin actually sent.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Headers Present",
                    "type": "array"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "score": {
                    "default": 0,
                    "description": "Aggregate header-posture score (0-100) summed from per-finding severity weights.",
                    "title": "Score",
                    "type": "integer"
                  },
                  "status_code": {
                    "default": 0,
                    "description": "HTTP status code returned by the live origin during the header probe.",
                    "title": "Status Code",
                    "type": "integer"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line human-readable summary of grade + key gaps.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "url": {
                    "default": "",
                    "description": "Final URL the probe landed on (after redirects).",
                    "title": "Url",
                    "type": "string"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "domain"
                ],
                "title": "ScanHeadersResponse",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/ScanHeadersResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "scan_headersOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "email_mx",
          "title": "Email MX",
          "description": "Analyze email security: MX records, SPF policy, DMARC policy, DKIM probe across common+date-based selectors, mail provider, grade. Use to verify email-auth setup and phishing risk; for full audit use domain_report. Free: 30/hr, Pro: 500/hr. email_security.dkim_status reports honest evidence: 'verified' iff at least one selector responded, else 'unverifiable' (custom selectors cannot be discovered without prior knowledge). Grade: when DKIM verified, A=SPF+DMARC+DKIM/B=2of3/C=1of3; when DKIM unverifiable, A=SPF+DMARC/B=one/F=neither — DKIM absence is NOT penalized because it is unprovable in DNS. Returns {mx_records, mail_provider, email_security:{spf, dmarc, dkim_selectors, dkim_status, grade, issues}, summary}.",
          "inputSchema": {
            "properties": {
              "domain": {
                "description": "Domain to analyze email configuration for (e.g. 'example.com', 'google.com')",
                "title": "Domain",
                "type": "string"
              }
            },
            "required": [
              "domain"
            ],
            "title": "email_mxArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "EmailMxResponse": {
                "properties": {
                  "domain": {
                    "title": "Domain",
                    "type": "string"
                  },
                  "email_security": {
                    "$ref": "#/$defs/EmailSecurityDetail"
                  },
                  "mail_provider": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Mail Provider"
                  },
                  "mx_records": {
                    "items": {
                      "$ref": "#/$defs/MxRecord"
                    },
                    "title": "Mx Records",
                    "type": "array"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "summary": {
                    "default": "",
                    "title": "Summary",
                    "type": "string"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "domain"
                ],
                "title": "EmailMxResponse",
                "type": "object"
              },
              "EmailSecurityDetail": {
                "properties": {
                  "dkim_selectors": {
                    "items": {
                      "type": "string"
                    },
                    "title": "Dkim Selectors",
                    "type": "array"
                  },
                  "dkim_status": {
                    "anyOf": [
                      {
                        "enum": [
                          "verified",
                          "unverifiable"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "'verified' when at least one DKIM selector responded; 'unverifiable' when none of the probed common/date-based selectors matched. Custom selectors cannot be discovered without prior knowledge.",
                    "title": "Dkim Status"
                  },
                  "dmarc": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Dmarc"
                  },
                  "grade": {
                    "default": "F",
                    "title": "Grade",
                    "type": "string"
                  },
                  "issues": {
                    "items": {
                      "type": "string"
                    },
                    "title": "Issues",
                    "type": "array"
                  },
                  "spf": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Spf"
                  }
                },
                "title": "EmailSecurityDetail",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "MxRecord": {
                "properties": {
                  "host": {
                    "title": "Host",
                    "type": "string"
                  },
                  "priority": {
                    "title": "Priority",
                    "type": "integer"
                  }
                },
                "required": [
                  "priority",
                  "host"
                ],
                "title": "MxRecord",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/EmailMxResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "email_mxOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "email_security_posture",
          "title": "Email Security Posture",
          "description": "Analyze domain email authentication posture: SPF, DMARC, DKIM with numeric score and findings. Dual-use: red-team (spoofing feasibility) + blue-team (posture audit). Score 0-100, grades A+-F. DKIM probing tests common selectors + recent dates; custom selectors must be supplied. Passive DNS-only; no SMTP probe. Free: 30/hr, Pro: 500/hr.",
          "inputSchema": {
            "properties": {
              "domain": {
                "description": "Domain to audit email authentication posture for (e.g. 'example.com')",
                "title": "Domain",
                "type": "string"
              },
              "selectors": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Optional comma-separated custom DKIM selectors to probe",
                "title": "Selectors"
              }
            },
            "required": [
              "domain"
            ],
            "title": "email_security_postureArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "DkimPosture": {
                "description": "DKIM posture — selector discovery and verification.",
                "properties": {
                  "findings": {
                    "items": {
                      "$ref": "#/$defs/Finding"
                    },
                    "title": "Findings",
                    "type": "array"
                  },
                  "status": {
                    "description": "Verification status",
                    "enum": [
                      "verified",
                      "unverifiable"
                    ],
                    "title": "Status",
                    "type": "string"
                  },
                  "tested_selectors": {
                    "description": "All selectors probed",
                    "items": {
                      "type": "string"
                    },
                    "title": "Tested Selectors",
                    "type": "array"
                  },
                  "verified_selectors": {
                    "items": {
                      "type": "string"
                    },
                    "title": "Verified Selectors",
                    "type": "array"
                  }
                },
                "required": [
                  "status"
                ],
                "title": "DkimPosture",
                "type": "object"
              },
              "DmarcPosture": {
                "description": "DMARC posture analysis.",
                "properties": {
                  "adkim": {
                    "anyOf": [
                      {
                        "enum": [
                          "s",
                          "r"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "DKIM alignment mode",
                    "title": "Adkim"
                  },
                  "aspf": {
                    "anyOf": [
                      {
                        "enum": [
                          "s",
                          "r"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "SPF alignment mode",
                    "title": "Aspf"
                  },
                  "findings": {
                    "items": {
                      "$ref": "#/$defs/Finding"
                    },
                    "title": "Findings",
                    "type": "array"
                  },
                  "fo": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Failure reporting options",
                    "title": "Fo"
                  },
                  "pct": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Rollout percentage",
                    "title": "Pct"
                  },
                  "policy": {
                    "anyOf": [
                      {
                        "enum": [
                          "none",
                          "quarantine",
                          "reject"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Policy"
                  },
                  "present": {
                    "description": "DMARC record exists",
                    "title": "Present",
                    "type": "boolean"
                  },
                  "record": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Record"
                  },
                  "rua_uris": {
                    "description": "Aggregate report URIs",
                    "items": {
                      "type": "string"
                    },
                    "title": "Rua Uris",
                    "type": "array"
                  },
                  "ruf_uris": {
                    "description": "Forensic report URIs",
                    "items": {
                      "type": "string"
                    },
                    "title": "Ruf Uris",
                    "type": "array"
                  },
                  "subdomain_policy": {
                    "anyOf": [
                      {
                        "enum": [
                          "none",
                          "quarantine",
                          "reject"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Subdomain Policy"
                  }
                },
                "required": [
                  "present"
                ],
                "title": "DmarcPosture",
                "type": "object"
              },
              "EmailSecurityPostureResponse": {
                "description": "Email authentication posture: SPF + DMARC + DKIM with score and findings.",
                "properties": {
                  "all_findings": {
                    "description": "Flattened findings",
                    "items": {
                      "$ref": "#/$defs/Finding"
                    },
                    "title": "All Findings",
                    "type": "array"
                  },
                  "dkim": {
                    "$ref": "#/$defs/DkimPosture",
                    "description": "DKIM posture"
                  },
                  "dmarc": {
                    "$ref": "#/$defs/DmarcPosture",
                    "description": "DMARC posture"
                  },
                  "domain": {
                    "description": "Domain analyzed",
                    "title": "Domain",
                    "type": "string"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "posture_grade": {
                    "description": "Grade A+-F",
                    "enum": [
                      "A+",
                      "A",
                      "B",
                      "C",
                      "D",
                      "F"
                    ],
                    "title": "Posture Grade",
                    "type": "string"
                  },
                  "posture_score": {
                    "description": "Score 0-100",
                    "title": "Posture Score",
                    "type": "integer"
                  },
                  "spf": {
                    "$ref": "#/$defs/SpfPosture",
                    "description": "SPF posture"
                  },
                  "summary": {
                    "description": "Summary",
                    "title": "Summary",
                    "type": "string"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "domain",
                  "spf",
                  "dmarc",
                  "dkim",
                  "posture_score",
                  "posture_grade",
                  "all_findings",
                  "summary"
                ],
                "title": "EmailSecurityPostureResponse",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "Finding": {
                "description": "Discrete audit finding.",
                "properties": {
                  "check": {
                    "description": "What was checked",
                    "title": "Check",
                    "type": "string"
                  },
                  "description": {
                    "description": "Finding description",
                    "title": "Description",
                    "type": "string"
                  },
                  "fix_hint": {
                    "description": "Remediation hint",
                    "title": "Fix Hint",
                    "type": "string"
                  },
                  "severity": {
                    "description": "Severity",
                    "enum": [
                      "critical",
                      "high",
                      "medium",
                      "low"
                    ],
                    "title": "Severity",
                    "type": "string"
                  },
                  "status": {
                    "description": "Outcome",
                    "enum": [
                      "pass",
                      "warn",
                      "fail"
                    ],
                    "title": "Status",
                    "type": "string"
                  }
                },
                "required": [
                  "check",
                  "status",
                  "severity",
                  "description",
                  "fix_hint"
                ],
                "title": "Finding",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "SpfMechanism": {
                "description": "Single SPF mechanism (a, mx, include, ip4, ip6, ptr, exists, redirect).",
                "properties": {
                  "qualifier": {
                    "description": "Qualifier: + (pass), - (fail), ~ (softfail), ? (neutral)",
                    "enum": [
                      "+",
                      "-",
                      "~",
                      "?"
                    ],
                    "title": "Qualifier",
                    "type": "string"
                  },
                  "type": {
                    "description": "Mechanism type",
                    "title": "Type",
                    "type": "string"
                  },
                  "value": {
                    "description": "Mechanism value",
                    "title": "Value",
                    "type": "string"
                  }
                },
                "required": [
                  "type",
                  "value",
                  "qualifier"
                ],
                "title": "SpfMechanism",
                "type": "object"
              },
              "SpfPosture": {
                "description": "SPF posture analysis.",
                "properties": {
                  "all_policy": {
                    "anyOf": [
                      {
                        "enum": [
                          "permissive",
                          "soft_fail",
                          "strict",
                          "neutral"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "All Policy"
                  },
                  "findings": {
                    "items": {
                      "$ref": "#/$defs/Finding"
                    },
                    "title": "Findings",
                    "type": "array"
                  },
                  "has_spf_all": {
                    "description": "Has 'all' mechanism",
                    "title": "Has Spf All",
                    "type": "boolean"
                  },
                  "lookup_count": {
                    "description": "DNS lookups needed",
                    "title": "Lookup Count",
                    "type": "integer"
                  },
                  "mechanisms": {
                    "items": {
                      "$ref": "#/$defs/SpfMechanism"
                    },
                    "title": "Mechanisms",
                    "type": "array"
                  },
                  "present": {
                    "description": "SPF record exists",
                    "title": "Present",
                    "type": "boolean"
                  },
                  "record": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Record"
                  },
                  "redirect_target": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Redirect Target"
                  }
                },
                "required": [
                  "present",
                  "lookup_count",
                  "has_spf_all"
                ],
                "title": "SpfPosture",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/EmailSecurityPostureResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "email_security_postureOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "email_disposable",
          "title": "Email Disposable",
          "description": "Check if email address uses a known disposable/temporary provider (Guerrilla Mail, Temp Mail, Mailinator, etc.). Use for input validation to detect throwaway signups; for domain reputation use threat_intel. Companion email-investigation tools: email_mx (deliverability + MX trust), domain_report on the email's domain (full recon), threat_intel (malware-distribution signal on the domain). Free: 30/hr, Pro: 500/hr. Returns {disposable, domain, provider}.",
          "inputSchema": {
            "properties": {
              "email": {
                "description": "Full email address to check (e.g. 'user@tempmail.com', 'test@guerrillamail.com')",
                "title": "Email",
                "type": "string"
              }
            },
            "required": [
              "email"
            ],
            "title": "email_disposableArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "DisposableResponse": {
                "properties": {
                  "disposable": {
                    "default": false,
                    "description": "True when the domain matches the disposable-provider database.",
                    "title": "Disposable",
                    "type": "boolean"
                  },
                  "domain": {
                    "description": "Lowercased domain extracted from the email's right-of-@.",
                    "title": "Domain",
                    "type": "string"
                  },
                  "email": {
                    "description": "Echoed input email (local-part preserved; domain lowercased).",
                    "title": "Email",
                    "type": "string"
                  },
                  "mx_disposable": {
                    "default": false,
                    "description": "True when the domain's MX records point to a known disposable mail host (catches custom domains fronting disposable backends).",
                    "title": "Mx Disposable",
                    "type": "boolean"
                  },
                  "mx_records": {
                    "description": "Resolved MX records for the email's domain (priority + host).",
                    "items": {
                      "$ref": "#/$defs/MxRecord"
                    },
                    "title": "Mx Records",
                    "type": "array"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "provider": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Disposable-provider name when known (e.g. 'mailinator', 'tempmail.com'). Null when not disposable.",
                    "title": "Provider"
                  },
                  "risk_level": {
                    "default": "low",
                    "description": "Combined risk band. 'high' = domain is on the disposable list; 'medium' = MX points to a disposable backend but the domain itself is not listed; 'low' = neither match (legitimate).",
                    "enum": [
                      "low",
                      "medium",
                      "high"
                    ],
                    "title": "Risk Level",
                    "type": "string"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line human-readable summary including risk_level + provider hint.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "email",
                  "domain"
                ],
                "title": "DisposableResponse",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "MxRecord": {
                "properties": {
                  "host": {
                    "title": "Host",
                    "type": "string"
                  },
                  "priority": {
                    "title": "Priority",
                    "type": "integer"
                  }
                },
                "required": [
                  "priority",
                  "host"
                ],
                "title": "MxRecord",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/DisposableResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "email_disposableOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "email_verify",
          "title": "Email Verify",
          "description": "One-call email validation combining syntax + MX records + disposable check + role-address detection (admin@/info@/...) + free-provider classification (gmail/outlook/yahoo/...). Use BEFORE adding an email to a contact list, sending an outbound message, or auditing a lead-list dump — replaces 2-3 tool calls (email_mx + email_disposable + manual role parse) with one structured response. Deliberately does NOT do SMTP `RCPT TO` deliverability probing — Hunter.io / NeverBounce-style mailbox enumeration is an ethical grey area we declined; use those services if you need that specific signal. role_address=true on `admin@`, `info@`, `noreply@`, `support@`, etc. (Gmail-style `+tag` is stripped before classification). free_provider=true on consumer-mailbox domains (B2B detection signal — a 'work' email at `@gmail.com` likely isn't a corporate user). Free: 30/hr, Pro: 500/hr. Returns {email, domain, syntax_valid, mx_records, disposable, disposable_provider, role_address, role_type, free_provider, summary}.",
          "inputSchema": {
            "properties": {
              "email": {
                "description": "Full email address to verify (e.g. 'admin@example.com', 'user@gmail.com'). Must contain '@'.",
                "title": "Email",
                "type": "string"
              }
            },
            "required": [
              "email"
            ],
            "title": "email_verifyArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "EmailVerifyResponse": {
                "description": "Combined email validation: syntax + MX + disposable + role + free-provider.\n\nWhat we DO NOT do: SMTP `RCPT TO` deliverability probing. Hunter.io-style\nmailbox-existence checks are an ethical grey area (mailbox enumeration +\nHetzner ToS risk on unsolicited SMTP from datacenter IPs). Use Hunter.io /\nNeverBounce / ZeroBounce when you need that specific signal.",
                "properties": {
                  "disposable": {
                    "default": false,
                    "description": "True iff the domain matches our disposable-provider database OR a known disposable MX host.",
                    "title": "Disposable",
                    "type": "boolean"
                  },
                  "disposable_provider": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Name of the disposable provider when `disposable=true` (e.g. 'Mailinator'). Null otherwise.",
                    "title": "Disposable Provider"
                  },
                  "domain": {
                    "description": "The domain part (after `@`).",
                    "title": "Domain",
                    "type": "string"
                  },
                  "email": {
                    "description": "Echo of the input email (lowercased, control-chars stripped).",
                    "title": "Email",
                    "type": "string"
                  },
                  "free_provider": {
                    "default": false,
                    "description": "True iff the domain is a known consumer-mailbox provider (gmail/outlook/yahoo/proton/icloud). B2B detection signal.",
                    "title": "Free Provider",
                    "type": "boolean"
                  },
                  "mx_records": {
                    "description": "MX records for the domain, sorted by priority. Empty list = no MX = mail cannot be delivered.",
                    "items": {
                      "$ref": "#/$defs/MxDnsRecord"
                    },
                    "title": "Mx Records",
                    "type": "array"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "role_address": {
                    "default": false,
                    "description": "True iff the local-part is a generic role address (admin@, info@, support@, etc.) — not a specific person.",
                    "title": "Role Address",
                    "type": "boolean"
                  },
                  "role_type": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "The role keyword when role_address=true (e.g. 'admin', 'noreply'). Null otherwise.",
                    "title": "Role Type"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line human-readable summary.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "syntax_valid": {
                    "description": "True iff the email passes the same RFC-aware regex used by /v1/email/disposable.",
                    "title": "Syntax Valid",
                    "type": "boolean"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "email",
                  "domain",
                  "syntax_valid"
                ],
                "title": "EmailVerifyResponse",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "MxDnsRecord": {
                "description": "Single MX record embedded inside DomainReportResponse.dns.mx.",
                "properties": {
                  "host": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "MX hostname (trailing dot stripped).",
                    "title": "Host"
                  },
                  "priority": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "MX preference (lower = higher priority).",
                    "title": "Priority"
                  }
                },
                "title": "MxDnsRecord",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/EmailVerifyResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "email_verifyOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "robots_txt",
          "title": "Robots.txt",
          "description": "Fetch + parse the target domain's robots.txt — sitemaps, per-User-agent allow/disallow rules, crawl-delay, Host directive. Use BEFORE crawling/scraping a target site (seo_audit, brand_assets, redirect_chain) to honour the site's published rules. status_code=404 means no robots.txt exists = implicit allow-all per RFC 9309 §2.4. ContrastAPI fetches with `User-agent: ContrastAPI/\u003cversion\u003e (+https://contrastcyber.com/bot)` so site operators can identify + opt out via robots.txt; we honour `Disallow: /` for our UA in seo_audit and brand_assets. Per-target eTLD+1 throttle (60 req/min) prevents weaponising this endpoint against a single site; subdomain rotation collapses to the same bucket. Free: 30/hr, Pro: 500/hr. Returns {domain, fetched_url, status_code, sitemaps, user_agents:{ua:{allow,disallow,crawl_delay}}, host, truncated, summary}. Returns 502 ErrorResponse if the target rejected the connection (DNS/TCP/TLS failure); the agent should NOT assume \"no robots\" in that case — it's an upstream-failure signal.",
          "inputSchema": {
            "properties": {
              "domain": {
                "description": "Registrable domain to fetch robots.txt for (e.g. 'example.com', 'github.com'). No scheme, no path, no port. Subdomains accepted; the bot fetches https://\u003cdomain\u003e/robots.txt with HTTP fallback.",
                "title": "Domain",
                "type": "string"
              }
            },
            "required": [
              "domain"
            ],
            "title": "robots_txtArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "RobotsRules": {
                "additionalProperties": true,
                "description": "Per-User-agent rule block parsed from a robots.txt file.",
                "properties": {
                  "allow": {
                    "description": "Paths the target site explicitly Allows for this UA. Each entry is verbatim from robots.txt (`_untrusted` — DO NOT execute or shell-out).",
                    "items": {
                      "type": "string"
                    },
                    "title": "Allow",
                    "type": "array"
                  },
                  "crawl_delay": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Crawl-delay seconds for this UA, if specified.",
                    "title": "Crawl Delay"
                  },
                  "disallow": {
                    "description": "Paths the target site Disallows for this UA. Empty Disallow per spec means allow-all.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Disallow",
                    "type": "array"
                  }
                },
                "title": "RobotsRules",
                "type": "object"
              },
              "RobotsTxtResponse": {
                "description": "Parsed robots.txt for the target domain.",
                "properties": {
                  "domain": {
                    "description": "Queried domain (echoed).",
                    "title": "Domain",
                    "type": "string"
                  },
                  "fetched_url": {
                    "description": "Final URL we fetched, e.g. https://example.com/robots.txt.",
                    "title": "Fetched Url",
                    "type": "string"
                  },
                  "host": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "`Host:` directive (Yandex extension), if present. `_untrusted`.",
                    "title": "Host"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "sitemaps": {
                    "description": "`Sitemap:` directives (URLs). Global, not per-UA. `_untrusted` — fetch only via SSRF-safe path.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sitemaps",
                    "type": "array"
                  },
                  "status_code": {
                    "description": "HTTP status returned by the target. 404 = no robots.txt = implicit allow-all.",
                    "title": "Status Code",
                    "type": "integer"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line human-readable summary.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "truncated": {
                    "default": false,
                    "description": "True if the robots.txt body exceeded ROBOTS_MAX_BYTES and was truncated before parsing.",
                    "title": "Truncated",
                    "type": "boolean"
                  },
                  "user_agents": {
                    "additionalProperties": {
                      "$ref": "#/$defs/RobotsRules"
                    },
                    "description": "Per-`User-agent:` rule blocks. Wildcard `*` is one of the keys when present.",
                    "title": "User Agents",
                    "type": "object"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "domain",
                  "fetched_url",
                  "status_code"
                ],
                "title": "RobotsTxtResponse",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/RobotsTxtResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "robots_txtOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "redirect_chain",
          "title": "Redirect Chain",
          "description": "Walk an HTTP redirect chain hop-by-hop, returning per-hop {url, status_code, location, latency_ms}. Use to deobfuscate URL shorteners (bit.ly / t.co / lnkd.in), audit suspicious links from phishing investigations, or trace marketing tracking redirects. SSRF-guarded: each redirect target's resolved IP is re-validated before connecting (private IPs and non-HTTP schemes rejected). Up to 10 hops; loop_detected=true if a hop would revisit a previously-seen URL (we abort before the duplicate fetch); truncated=true if the chain still had a 30x at hop 10. Per-target eTLD+1 throttle (60 req/min) consumed once for the start host AND once per new host reached — a chain across 11 unrelated domains cannot bypass the cap. Free: 30/hr, Pro: 500/hr. Returns {start_url, final_url, hops, hop_count, final_status, loop_detected, truncated, summary}. Returns 502 ErrorResponse on hard fetch failure (timeout / TLS / connect); 429 with Retry-After if a hop's eTLD+1 throttle is exceeded mid-chain.",
          "inputSchema": {
            "properties": {
              "url": {
                "description": "Full URL whose redirect chain to walk, e.g. 'https://bit.ly/3xyz' or 'http://example.com/old-path'. Must start with http:// or https://. Pass the URL exactly as you'd `curl -L` it; the server handles encoding.",
                "title": "Url",
                "type": "string"
              }
            },
            "required": [
              "url"
            ],
            "title": "redirect_chainArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "RedirectChainResponse": {
                "description": "Manual hop-by-hop walk through HTTP redirects. SSRF-guarded at each hop.",
                "properties": {
                  "final_status": {
                    "description": "HTTP status of the last hop, or 0 if the chain failed before any successful response.",
                    "title": "Final Status",
                    "type": "integer"
                  },
                  "final_url": {
                    "description": "The URL of the terminal (non-redirect) response, or the last redirect target reached if the chain was truncated. `_untrusted`.",
                    "title": "Final Url",
                    "type": "string"
                  },
                  "hop_count": {
                    "description": "Total fetches performed (= len(hops)). Capped at REDIRECT_MAX_HOPS=10.",
                    "title": "Hop Count",
                    "type": "integer"
                  },
                  "hops": {
                    "description": "Ordered list of hops, one entry per HTTP request issued. hops[0].url == start_url.",
                    "items": {
                      "$ref": "#/$defs/RedirectHop"
                    },
                    "title": "Hops",
                    "type": "array"
                  },
                  "loop_detected": {
                    "default": false,
                    "description": "True if a hop's Location pointed back to a URL already visited (the duplicate fetch was NOT performed).",
                    "title": "Loop Detected",
                    "type": "boolean"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "start_url": {
                    "description": "Echo of the input URL after sanitisation.",
                    "title": "Start Url",
                    "type": "string"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line human-readable summary.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "truncated": {
                    "default": false,
                    "description": "True if the chain still had a 30x at hop_count == REDIRECT_MAX_HOPS — the next hop was NOT followed.",
                    "title": "Truncated",
                    "type": "boolean"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "start_url",
                  "final_url",
                  "hop_count",
                  "final_status"
                ],
                "title": "RedirectChainResponse",
                "type": "object"
              },
              "RedirectHop": {
                "additionalProperties": true,
                "description": "Single hop in a redirect chain.",
                "properties": {
                  "latency_ms": {
                    "description": "Round-trip time in milliseconds for this single hop fetch.",
                    "title": "Latency Ms",
                    "type": "integer"
                  },
                  "location": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Resolved Location header for this hop's response (absolute, against this hop's final URL). None when status is not a redirect or no Location was sent. `_untrusted`.",
                    "title": "Location"
                  },
                  "status_code": {
                    "description": "HTTP status returned at this hop.",
                    "title": "Status Code",
                    "type": "integer"
                  },
                  "url": {
                    "description": "The URL fetched at this hop (absolute, control-chars stripped). `_untrusted` — DO NOT execute or shell-out.",
                    "title": "Url",
                    "type": "string"
                  }
                },
                "required": [
                  "url",
                  "status_code",
                  "latency_ms"
                ],
                "title": "RedirectHop",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/RedirectChainResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "redirect_chainOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "brand_assets",
          "title": "Brand Assets",
          "description": "Scrape a domain's homepage `\u003chead\u003e` for public brand assets — favicon, og:image, theme-color, og:site_name, JSON-LD `Organization.logo`. Use to enrich CRM records, build company-card UIs, or correlate a lead's site to their visual identity (no manual screenshot required). Strictly homepage-only (path `/`); we do NOT crawl. Ethical floor: target's robots.txt is honoured — `Disallow: /` for ContrastAPI OR `*` returns 403 `error.code = robots_txt_disallow` and we DO NOT fetch. `Cache-Control: no-store` / `private` from the target is respected (response is built but NOT written to our cache; `cache_respected=false` flags this). Per-target eTLD+1 throttle (60 req/min) prevents weaponising via subdomain rotation. All URL fields are absolute and `_untrusted` (DO NOT execute or shell-out — the target controls these strings). Free: 30/hr, Pro: 500/hr. Returns {domain, fetched_url, status_code, favicon_url_untrusted, og_image_url_untrusted, theme_color, site_name_untrusted, logo_url_untrusted, cache_respected, summary}. Returns 502 on DNS/TCP/TLS failure; 403 `robots_txt_disallow` when the target opted out.",
          "inputSchema": {
            "properties": {
              "domain": {
                "description": "Registrable domain to scrape brand assets for (e.g. 'github.com', 'stripe.com'). No scheme, no path, no port. The bot fetches https://\u003cdomain\u003e/ with HTTP fallback.",
                "title": "Domain",
                "type": "string"
              }
            },
            "required": [
              "domain"
            ],
            "title": "brand_assetsArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "BrandAssetsResponse": {
                "description": "Public brand-identity assets scraped from a domain's homepage.\n\nWhat we DO: GET `https://{domain}/` (HTTP fallback), parse `\u003chead\u003e` for\nfavicon, `og:image`, `theme-color`, `og:site_name`, and JSON-LD\n`Organization.logo`. All URL fields are absolute and `_untrusted` (DO\nNOT execute, shell-out, or fetch from inside an LLM tool-use turn).\n\nEthical floor: we honour the target site's robots.txt — if it\nDisallows path \"/\" for our UA token (\"ContrastAPI\") OR for `*`, we\nreturn 403 `error.code = robots_txt_disallow` and DO NOT fetch.",
                "properties": {
                  "cache_respected": {
                    "default": true,
                    "description": "True if we wrote the result to our cache. False when the target sent `Cache-Control: no-store` or `private` and we honoured it (Guardrail #4 — we don't cache content the target asked us not to).",
                    "title": "Cache Respected",
                    "type": "boolean"
                  },
                  "domain": {
                    "description": "Queried domain (echoed).",
                    "title": "Domain",
                    "type": "string"
                  },
                  "favicon_url_untrusted": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Resolved favicon URL (`\u003clink rel='icon'\u003e`, `shortcut icon`, `apple-touch-icon`, then `/favicon.ico` fallback). Absolute. `_untrusted`.",
                    "title": "Favicon Url Untrusted"
                  },
                  "fetched_url": {
                    "description": "Final URL we fetched, e.g. https://example.com/ (post-redirects).",
                    "title": "Fetched Url",
                    "type": "string"
                  },
                  "logo_url_untrusted": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "`Organization.logo` from the first matching JSON-LD block (`\u003cscript type='application/ld+json'\u003e`). Resolved to absolute URL. `_untrusted`.",
                    "title": "Logo Url Untrusted"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "og_image_url_untrusted": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "`\u003cmeta property='og:image'\u003e` resolved to an absolute URL. Used as the social-share thumbnail. `_untrusted`.",
                    "title": "Og Image Url Untrusted"
                  },
                  "site_name_untrusted": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "`\u003cmeta property='og:site_name'\u003e` (preferred) or `\u003ctitle\u003e` fallback. Capped at 200 chars. `_untrusted`.",
                    "title": "Site Name Untrusted"
                  },
                  "status_code": {
                    "description": "HTTP status returned by the homepage fetch.",
                    "title": "Status Code",
                    "type": "integer"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line human-readable summary.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "theme_color": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "`\u003cmeta name='theme-color'\u003e` value (verbatim, capped at 64 chars). Useful for matching brand chrome.",
                    "title": "Theme Color"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "domain",
                  "fetched_url",
                  "status_code"
                ],
                "title": "BrandAssetsResponse",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/BrandAssetsResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "brand_assetsOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "seo_audit",
          "title": "SEO Audit",
          "description": "One-shot SEO audit of a domain's homepage with a 0-100 composite score + a `missing_signals` list of concrete fixes. Use BEFORE pitching SEO work to a prospect, when triaging a lead's marketing maturity, or as a structured pre-flight before deeper auditing tools (Lighthouse / SEMrush). 10 audit rules each worth 10 pts: title present, title length 30-60 chars (Google SERP truncation window), meta description present, meta description length 50-160, exactly one H1, canonical link, \u003e=3 OG tags, JSON-LD present, image alt-text coverage (proportional), HTTPS. Strictly homepage-only — we do NOT crawl the site. Ethical floor: target's robots.txt is honoured — `Disallow: /` for ContrastAPI OR `*` returns 403 `error.code = robots_txt_disallow` and we DO NOT fetch. `Cache-Control: no-store`/`private` skips our cache write (`cache_respected=false` in the response). Per-target eTLD+1 throttle (60 req/min) prevents weaponising via subdomain rotation. All target-derived strings/lists are `_untrusted`. Free: 30/hr, Pro: 500/hr. Returns {domain, fetched_url, status_code, title_untrusted, meta_description_untrusted, canonical_url, h1_untrusted, h1_count, h2_count, h3_count, images_total, images_missing_alt, internal_link_count, external_link_count, og_tags, json_ld_present, score, missing_signals, cache_respected, summary}. Returns 502 on DNS/TCP/TLS failure; 403 `robots_txt_disallow` when the target opted out.",
          "inputSchema": {
            "properties": {
              "domain": {
                "description": "Registrable domain to audit SEO for (e.g. 'example.com', 'shopify.com'). No scheme, no path, no port. Strictly homepage-only — the bot fetches https://\u003cdomain\u003e/ with HTTP fallback and audits that single page (we do NOT crawl).",
                "title": "Domain",
                "type": "string"
              }
            },
            "required": [
              "domain"
            ],
            "title": "seo_auditArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "SeoAuditResponse": {
                "description": "One-page SEO audit of a domain's homepage with a 0-100 composite score.\n\nStrictly homepage-only (path `/`); we do NOT crawl the site. Same\nethical floor as `brand_assets`: target's robots.txt is honoured\n(Disallow `/` for our UA → 403, no fetch). All target-derived\nstring/list fields are `_untrusted` (DO NOT execute or shell-out —\nthe page author controls these contents).\n\nScore (0-100) is the sum of 10 audit rules, each worth 0-10 points.\n`missing_signals` lists the rule-IDs that did NOT fire so agents\ncan surface concrete fixes (\"title_missing\", \"h1_multiple\", etc.).",
                "properties": {
                  "cache_respected": {
                    "default": true,
                    "description": "True if we wrote the result to our cache. False when the target sent `Cache-Control: no-store` or `private` and we honoured it.",
                    "title": "Cache Respected",
                    "type": "boolean"
                  },
                  "canonical_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "`\u003clink rel='canonical'\u003e` href, resolved to an absolute URL.",
                    "title": "Canonical Url"
                  },
                  "domain": {
                    "description": "Queried domain (echoed).",
                    "title": "Domain",
                    "type": "string"
                  },
                  "external_link_count": {
                    "default": 0,
                    "description": "`\u003ca href\u003e` count to a different registrable domain. Excludes mailto:, tel:, javascript:, in-page anchors.",
                    "title": "External Link Count",
                    "type": "integer"
                  },
                  "fetched_url": {
                    "description": "Final URL we fetched (post-redirects).",
                    "title": "Fetched Url",
                    "type": "string"
                  },
                  "h1_count": {
                    "default": 0,
                    "description": "Total number of `\u003ch1\u003e` tags found (NOT capped — for scoring).",
                    "title": "H1 Count",
                    "type": "integer"
                  },
                  "h1_untrusted": {
                    "description": "Text of each `\u003ch1\u003e` (capped at 20 entries, 300 chars each). `_untrusted`.",
                    "items": {
                      "type": "string"
                    },
                    "title": "H1 Untrusted",
                    "type": "array"
                  },
                  "h2_count": {
                    "default": 0,
                    "description": "`\u003ch2\u003e` tag count, capped at 200.",
                    "title": "H2 Count",
                    "type": "integer"
                  },
                  "h3_count": {
                    "default": 0,
                    "description": "`\u003ch3\u003e` tag count, capped at 200.",
                    "title": "H3 Count",
                    "type": "integer"
                  },
                  "images_missing_alt": {
                    "default": 0,
                    "description": "Number of `\u003cimg\u003e` tags with no `alt` attribute OR an empty/whitespace `alt`. Counts toward the score's accessibility rule.",
                    "title": "Images Missing Alt",
                    "type": "integer"
                  },
                  "images_total": {
                    "default": 0,
                    "description": "Total `\u003cimg\u003e` tags on the page (parser bound: 1000).",
                    "title": "Images Total",
                    "type": "integer"
                  },
                  "internal_link_count": {
                    "default": 0,
                    "description": "`\u003ca href\u003e` count where the target host shares the registrable domain. Cheap eTLD-aware compare; not perfect on suffixes like .co.uk.",
                    "title": "Internal Link Count",
                    "type": "integer"
                  },
                  "json_ld_present": {
                    "default": false,
                    "description": "True if at least one `\u003cscript type='application/ld+json'\u003e` block exists (parser does NOT validate the JSON, only counts tag presence — score considers tag presence sufficient for structured-data signal).",
                    "title": "Json Ld Present",
                    "type": "boolean"
                  },
                  "meta_description_untrusted": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "`\u003cmeta name='description'\u003e` content, capped at 500 chars. `_untrusted`.",
                    "title": "Meta Description Untrusted"
                  },
                  "missing_signals": {
                    "description": "Rule-IDs that did NOT contribute their points. Subset of: title_missing, title_length_off, meta_description_missing, meta_description_length_off, h1_missing, h1_multiple, canonical_missing, og_tags_sparse, json_ld_missing, images_missing_alt, not_https.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Missing Signals",
                    "type": "array"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "og_tags": {
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "`\u003cmeta property='og:*'\u003e` map, capped at 50 entries. Values capped at 500 chars each. All `_untrusted`.",
                    "title": "Og Tags",
                    "type": "object"
                  },
                  "score": {
                    "description": "Composite 0-100 SEO score: 10 rules x 10 points each (title present, title length, meta description present, meta description length, single H1, canonical, \u003e=3 OG tags, JSON-LD present, image alt coverage proportional, HTTPS).",
                    "title": "Score",
                    "type": "integer"
                  },
                  "status_code": {
                    "description": "HTTP status returned by the homepage fetch.",
                    "title": "Status Code",
                    "type": "integer"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line human-readable summary.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "title_untrusted": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "`\u003ctitle\u003e` text, control-char stripped, capped at 300 chars. `_untrusted`.",
                    "title": "Title Untrusted"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "domain",
                  "fetched_url",
                  "status_code",
                  "score"
                ],
                "title": "SeoAuditResponse",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/SeoAuditResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "seo_auditOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "geo_audit",
          "title": "Geo Audit",
          "description": "Deterministic GEO / AI-visibility readiness audit of a domain's homepage with a 0-100 score + a `missing_signals` fix list. Answers \"can AI assistants (ChatGPT, Claude, Perplexity, Google AI) discover, crawl, and recommend this site?\" using STRUCTURAL signals ONLY — no LLM is queried, fully deterministic. 7 weighted rules: llms.txt present (15), AI-crawler robots.txt access — 9 crawlers incl. GPTBot/ClaudeBot/PerplexityBot/Google-Extended/CCBot (25 — the dominant signal; blocking = invisible to that AI surface), schema.org @type coverage Organization/Product/FAQPage (20), server-side rendering vs client-only SPA (15 — a JS-only SPA serves AI crawlers empty HTML), discovery signals og/canonical/sitemap (10), semantic headings single-H1 + H2 structure (10), competitor-comparison content (5). Use to triage why a brand is absent from AI recommendations, as a pre-flight before GEO/AEO content work, or to score a prospect's AI-readiness. Strictly homepage-only — we do NOT crawl. Ethical floor: target's robots.txt is honoured — `Disallow: /` for ContrastAPI returns 403 `error.code = robots_txt_disallow` and we DO NOT fetch. `Cache-Control: no-store`/`private` skips our cache write (`cache_respected=false`). Per-target eTLD+1 throttle (60 req/min). Free: 30/hr, Pro: 500/hr. Returns {domain, fetched_url, status_code, llms_txt_present, ai_crawlers_total, ai_crawlers_allowed, ai_crawlers_blocked, schema_types, client_side_rendered, render_framework, has_canonical, og_tag_count, sitemap_count, h1_count, h2_count, comparison_content, score, missing_signals, cache_respected, summary}. Returns 502 on DNS/TCP/TLS failure; 403 `robots_txt_disallow` when the target opted out.",
          "inputSchema": {
            "properties": {
              "domain": {
                "description": "Registrable domain to audit for AI-visibility / GEO readiness (e.g. 'example.com', 'shopify.com'). No scheme, no path, no port. Strictly homepage-only — the bot fetches https://\u003cdomain\u003e/ with HTTP fallback (we do NOT crawl).",
                "title": "Domain",
                "type": "string"
              }
            },
            "required": [
              "domain"
            ],
            "title": "geo_auditArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "GeoAuditResponse": {
                "description": "Deterministic GEO / AI-visibility readiness audit of a domain's homepage (0-100).\n\nAnswers \"can AI assistants discover, crawl, and recommend this site?\"\nusing structural signals ONLY — NO LLM is queried. AI-native cousin\nof `seo_audit`. Same ethical floor: robots.txt honoured (Disallow `/`\nfor our UA → 403, no fetch).\n\nScore = 7 weighted rules: llms.txt present (15), AI-crawler robots\naccess (25), schema.org @type coverage (20), server-side rendering\n(15), discovery signals OG/canonical/sitemap (10), semantic headings\n(10), comparison content (5). `missing_signals` names each gap.",
                "properties": {
                  "ai_crawlers_allowed": {
                    "default": 0,
                    "description": "How many of those AI crawlers are permitted to fetch path '/'.",
                    "title": "Ai Crawlers Allowed",
                    "type": "integer"
                  },
                  "ai_crawlers_blocked": {
                    "description": "AI crawler tokens explicitly disallowed by robots.txt (e.g. 'GPTBot'). Blocking = invisible to that AI surface.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Ai Crawlers Blocked",
                    "type": "array"
                  },
                  "ai_crawlers_total": {
                    "default": 0,
                    "description": "Number of AI crawler user-agents checked against robots.txt.",
                    "title": "Ai Crawlers Total",
                    "type": "integer"
                  },
                  "cache_respected": {
                    "default": true,
                    "description": "True if we wrote the result to our cache. False when the target sent `Cache-Control: no-store`/`private`.",
                    "title": "Cache Respected",
                    "type": "boolean"
                  },
                  "client_side_rendered": {
                    "default": false,
                    "description": "True if the homepage appears to be a client-only SPA (framework marker + near-empty server HTML) — AI crawlers may see no content.",
                    "title": "Client Side Rendered",
                    "type": "boolean"
                  },
                  "comparison_content": {
                    "default": false,
                    "description": "True if the page shows competitor-comparison signals ('vs', 'versus', 'compare', 'alternative').",
                    "title": "Comparison Content",
                    "type": "boolean"
                  },
                  "domain": {
                    "description": "Queried domain (echoed).",
                    "title": "Domain",
                    "type": "string"
                  },
                  "fetched_url": {
                    "description": "Final URL we fetched (post-redirects).",
                    "title": "Fetched Url",
                    "type": "string"
                  },
                  "h1_count": {
                    "default": 0,
                    "description": "Total `\u003ch1\u003e` tags found.",
                    "title": "H1 Count",
                    "type": "integer"
                  },
                  "h2_count": {
                    "default": 0,
                    "description": "Total `\u003ch2\u003e` tags found.",
                    "title": "H2 Count",
                    "type": "integer"
                  },
                  "has_canonical": {
                    "default": false,
                    "description": "True if a `\u003clink rel='canonical'\u003e` is present.",
                    "title": "Has Canonical",
                    "type": "boolean"
                  },
                  "llms_txt_present": {
                    "default": false,
                    "description": "True if https://\u003cdomain\u003e/llms.txt returns 200 with a non-empty body (emerging AI-context standard).",
                    "title": "Llms Txt Present",
                    "type": "boolean"
                  },
                  "missing_signals": {
                    "description": "Rule-IDs that did NOT earn full points. Subset of: llms_txt_missing, ai_crawlers_blocked, schema_org_missing, schema_org_sparse, client_side_rendered, og_missing, canonical_missing, sitemap_missing, h1_not_single, no_h2_structure, comparison_content_missing.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Missing Signals",
                    "type": "array"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "og_tag_count": {
                    "default": 0,
                    "description": "Number of `\u003cmeta property='og:*'\u003e` tags (capped at 50).",
                    "title": "Og Tag Count",
                    "type": "integer"
                  },
                  "render_framework": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "SPA framework marker detected in the served HTML, if any (informational; one of a fixed known set).",
                    "title": "Render Framework"
                  },
                  "schema_types": {
                    "description": "Distinct valuable schema.org @types found in JSON-LD (Organization, Product, FAQPage, SoftwareApplication, WebSite, BreadcrumbList).",
                    "items": {
                      "type": "string"
                    },
                    "title": "Schema Types",
                    "type": "array"
                  },
                  "score": {
                    "description": "Composite 0-100 GEO-readiness score across 7 weighted rules.",
                    "title": "Score",
                    "type": "integer"
                  },
                  "sitemap_count": {
                    "default": 0,
                    "description": "Number of Sitemap: entries declared in robots.txt.",
                    "title": "Sitemap Count",
                    "type": "integer"
                  },
                  "status_code": {
                    "description": "HTTP status returned by the homepage fetch.",
                    "title": "Status Code",
                    "type": "integer"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line human-readable summary.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "domain",
                  "fetched_url",
                  "status_code",
                  "score"
                ],
                "title": "GeoAuditResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/GeoAuditResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "geo_auditOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "phone_lookup",
          "title": "Phone Lookup",
          "description": "Validate and analyze phone number: country, region, carrier, line type (mobile/landline/VoIP), timezone, formatted versions. Use to verify phone legitimacy and detect fraud risks. Requires E.164 format (+1234567890). Companion OSINT identity-investigation tools: username_lookup (social-platform handle correlation), email_disposable (throwaway-mail signal on associated email). Free: 30/hr, Pro: 500/hr. Returns {valid, country, region, carrier, carrier_status, line_type, timezone, formats}. carrier is omitted from the wire when libphonenumber has no mapping for the region (US/CA/GB and other MNP-restricted regions); always read carrier_status — 'known' means carrier is present, 'unsupported_region' means we cannot identify the carrier (do not infer the number lacks one).",
          "inputSchema": {
            "properties": {
              "number": {
                "description": "Phone number in E.164 format: + followed by country code and number, no spaces or dashes. Examples: '+14155552671' (US), '+905551234567' (TR), '+442071234567' (UK). Wrong: '0555-123-4567', '(415) 555-2671'",
                "title": "Number",
                "type": "string"
              }
            },
            "required": [
              "number"
            ],
            "title": "phone_lookupArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PhoneFormat": {
                "properties": {
                  "e164": {
                    "default": "",
                    "description": "E.164 canonical format, e.g. '+14155552671'. Empty when parse fails.",
                    "title": "E164",
                    "type": "string"
                  },
                  "international": {
                    "default": "",
                    "description": "Human-readable international format, e.g. '+1 415-555-2671'.",
                    "title": "International",
                    "type": "string"
                  },
                  "national": {
                    "default": "",
                    "description": "Domestic format for the number's country, e.g. '(415) 555-2671'.",
                    "title": "National",
                    "type": "string"
                  }
                },
                "title": "PhoneFormat",
                "type": "object"
              },
              "PhoneLookupResponse": {
                "properties": {
                  "carrier": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Carrier/network name from libphonenumber carrier DB. Excluded from the wire (response_model_exclude_none=True) when no carrier mapping exists for the region — inspect carrier_status to distinguish 'known' vs 'unsupported_region' (US/CA/GB and other MNP-restricted regions are commonly unsupported).",
                    "title": "Carrier"
                  },
                  "carrier_status": {
                    "anyOf": [
                      {
                        "enum": [
                          "known",
                          "unsupported_region"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "'known' when libphonenumber returned a carrier name; 'unsupported_region' when the carrier DB has no mapping for this region (do not treat the absent carrier field as evidence the number lacks a carrier — it just means we cannot identify it). Null on invalid/unparseable input.",
                    "title": "Carrier Status"
                  },
                  "country_code": {
                    "default": "",
                    "description": "ISO 3166-1 alpha-2 region code (e.g. 'US', 'TR'). Empty when region cannot be inferred.",
                    "title": "Country Code",
                    "type": "string"
                  },
                  "country_name": {
                    "default": "",
                    "description": "Full country name from libphonenumber geocoder. Empty when region cannot be inferred.",
                    "title": "Country Name",
                    "type": "string"
                  },
                  "error": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Parse/validation error message. Null on successful lookups.",
                    "title": "Error"
                  },
                  "format": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/PhoneFormat"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "E.164, international, and national representations. Null when the number could not be parsed at all."
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "number": {
                    "default": "",
                    "description": "Echoed input, normalized. Prefer format.e164 for downstream lookups.",
                    "title": "Number",
                    "type": "string"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line human summary, e.g. '+14155552671 United States mobile AT\u0026T'.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "timezone": {
                    "description": "IANA timezone identifiers associated with the number's geography (e.g. ['America/Los_Angeles']).",
                    "items": {
                      "type": "string"
                    },
                    "title": "Timezone",
                    "type": "array"
                  },
                  "type": {
                    "default": "unknown",
                    "description": "Phone number type: 'mobile', 'fixed_line', 'fixed_line_or_mobile', 'voip', 'toll_free', 'premium_rate', 'shared_cost', 'personal_number', 'pager', 'uan', or 'unknown'.",
                    "title": "Type",
                    "type": "string"
                  },
                  "valid": {
                    "default": false,
                    "description": "True only when phonenumbers.is_valid_number() passes (correct length, valid prefix for region).",
                    "title": "Valid",
                    "type": "boolean"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "title": "PhoneLookupResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/PhoneLookupResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "phone_lookupOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "ip_lookup",
          "title": "IP Lookup",
          "description": "Query comprehensive IP intelligence: reverse DNS, ASN + holder name + country inline (RIPE Stat, Phase 1), open ports, hostnames, vulnerabilities (Shodan InternetDB enriched with severity + cvss_v3 from local cve.db — Phase 2 v1.16.0 BREAKING; vulns is now list[VulnInfo] {cve_id, severity, cvss_v3} dicts, pre-1.16 it was list[str] of CVE IDs; unknown CVEs emit severity='UNKNOWN' / cvss_v3=null — do NOT infer benign), cloud provider, Tor exit status, and reputation. cloud_provider uses two-tier detection: published cloud CIDR ranges (AWS/GCP/Cloudflare) first, then an ASN-to-provider fallback map for anycast/public-service IPs outside published ranges (e.g. 8.8.8.8 → AS15169 → 'Google'). Reputation: FireHOL level1 blocklist on Free tier; +AbuseIPDB + Shodan on Pro (Phase 4). Use for IP investigation; for orchestrated IP+reputation use threat_report. Response is null-explicit: every field is always present (cloud_provider=null when neither tier matches; tor_exit=false when not listed or upstream fetch failed — check verdict.sources_unavailable to disambiguate fetch failure from genuine absence). Response carries next_calls (conditional) — asn_lookup when ASN is populated, ioc_lookup when reputation is FireHOL-listed or AbuseIPDB confidence\u003e50, threat_report on Pro tier for orchestrated profile. Free: 30/hr, Pro: 500/hr. Returns {ip, ptr, geo, asn, asn_name, country, ports, hostnames, vulns, cloud_provider, tor_exit, reputation, risk_score, verdict, next_calls}.",
          "inputSchema": {
            "properties": {
              "ip": {
                "description": "IPv4 or IPv6 address to investigate (e.g. '8.8.8.8', '2606:4700::1111')",
                "title": "Ip",
                "type": "string"
              }
            },
            "required": [
              "ip"
            ],
            "title": "ip_lookupArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "AbuseIpdbInfo": {
                "description": "AbuseIPDB reputation check (Pro tier only).",
                "properties": {
                  "abuse_score": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "AbuseIPDB confidence-of-abuse score (0-100). Only present when status='ok'.",
                    "title": "Abuse Score"
                  },
                  "country": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 3166-1 alpha-2 country code from AbuseIPDB geolocation (may differ from RIPE).",
                    "title": "Country"
                  },
                  "is_tor": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "AbuseIPDB's Tor exit flag (cross-reference with top-level tor_exit field).",
                    "title": "Is Tor"
                  },
                  "isp": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISP name as reported by AbuseIPDB.",
                    "title": "Isp"
                  },
                  "reason": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Human-readable reason string. Present when status is skipped/rate_limited/error/pro_only.",
                    "title": "Reason"
                  },
                  "status": {
                    "description": "'ok' = data fetched; 'skipped' = API key not configured; 'rate_limited' = AbuseIPDB quota exceeded; 'error' = transient HTTP/network failure; 'pro_only' = returned on Free tier as upsell hint (see upgrade_url).",
                    "enum": [
                      "ok",
                      "skipped",
                      "rate_limited",
                      "error",
                      "pro_only"
                    ],
                    "title": "Status",
                    "type": "string"
                  },
                  "total_reports": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Number of reports submitted against this IP in the last 90 days.",
                    "title": "Total Reports"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Upgrade link returned when status='pro_only'.",
                    "title": "Upgrade Url"
                  },
                  "usage_type": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "AbuseIPDB usage classification: 'Data Center/Web Hosting/Transit', 'ISP', 'Mobile ISP', etc.",
                    "title": "Usage Type"
                  }
                },
                "required": [
                  "status"
                ],
                "title": "AbuseIpdbInfo",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "FireholInfo": {
                "description": "FireHOL level1 blocklist check (Free tier and Pro).",
                "properties": {
                  "listed": {
                    "default": false,
                    "description": "True if the IP matches any range in firehol_level1 (known-bad aggregated blocklist).",
                    "title": "Listed",
                    "type": "boolean"
                  },
                  "lists_matched": {
                    "description": "List identifiers matched. Currently ['firehol_level1'] when listed, else empty.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Lists Matched",
                    "type": "array"
                  },
                  "status": {
                    "description": "'ok' = trie lookup succeeded; 'skipped' = private/reserved/loopback/link-local IP, not meaningful to check; 'unavailable' = FireHOL feed could not be fetched (be honest with agent).",
                    "enum": [
                      "ok",
                      "skipped",
                      "unavailable"
                    ],
                    "title": "Status",
                    "type": "string"
                  }
                },
                "required": [
                  "status"
                ],
                "title": "FireholInfo",
                "type": "object"
              },
              "IpLookupResponse": {
                "properties": {
                  "asn": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Autonomous System Number from RIPE Stat network-info (e.g. 13335 for Cloudflare).",
                    "title": "Asn"
                  },
                  "asn_name": {
                    "anyOf": [
                      {
                        "maxLength": 256,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Human-readable AS name from RIPE Stat as-overview (e.g. 'CLOUDFLARENET').",
                    "title": "Asn Name"
                  },
                  "cloud_provider": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Cloud provider name resolved via two-tier detection: (1) published cloud CIDR ranges (AWS/GCP/Cloudflare), (2) ASN-to-provider map fallback for anycast/public-service IPs outside published ranges (e.g. 8.8.8.8 → AS15169 → 'Google'). Null when neither matches. Always present in response (route emits null-explicit so agents can disambiguate 'not detected' from 'field absent').",
                    "title": "Cloud Provider"
                  },
                  "country": {
                    "anyOf": [
                      {
                        "maxLength": 8,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 3166-1 alpha-2 country code from RIPE Stat rir-stats-country (RIR-allocated).",
                    "title": "Country"
                  },
                  "cpes": {
                    "description": "CPE 2.3 strings for services detected on this IP per Shodan InternetDB.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Cpes",
                    "type": "array"
                  },
                  "hostnames": {
                    "description": "Hostnames observed pointing to this IP per Shodan InternetDB.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Hostnames",
                    "type": "array"
                  },
                  "ip": {
                    "description": "Queried IP address (IPv4 or IPv6, echoed back verbatim).",
                    "title": "Ip",
                    "type": "string"
                  },
                  "is_datacenter": {
                    "default": false,
                    "description": "True if IP is hosted on a known datacenter / cloud provider. Detection: (1) cloud_provider populated (CIDR or ASN map hit covering AWS/GCP/Cloudflare/DigitalOcean/Hetzner/OVH/Linode/Vultr/Microsoft Azure), (2) ASN in tier-1 datacenter set (adds Oracle/Alibaba/Tencent on top of the cloud_provider map). Use for Nuclei matchers + bug-bounty triage where datacenter targets warrant different scan policy than residential IPs. Always present — never null.",
                    "title": "Is Datacenter",
                    "type": "boolean"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "ports": {
                    "description": "Open ports observed by Shodan InternetDB (free, no API key; superseded by reputation.shodan.ports on Pro).",
                    "items": {
                      "type": "integer"
                    },
                    "title": "Ports",
                    "type": "array"
                  },
                  "ptr": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Reverse-DNS PTR record. Null when no PTR is published.",
                    "title": "Ptr"
                  },
                  "reputation": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/ReputationInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Multi-source reputation. Free tier: firehol populated, abuseipdb/shodan return status='pro_only' upsell stubs. Pro tier: all three live."
                  },
                  "risk_score": {
                    "default": 0,
                    "description": "Composite 0-100 risk score (v1.17.0 formula). Additive components: ports (10 * min(count, 5) = 0-50), tor_exit (+30), firehol.listed (+20), AbuseIPDB confidence (round(15 * score / 100) = 0-15), is_datacenter (+10), known vulns (5 * min(count, 4) = 0-20). Datacenter membership now adds risk (was a -10 trust bonus pre-1.17). Use severity_label for thresholding.",
                    "title": "Risk Score",
                    "type": "integer"
                  },
                  "severity_label": {
                    "default": "low",
                    "description": "Coarse risk band derived from risk_score (\u003e=75 critical, \u003e=50 high, \u003e=25 medium, else low). Use this for Nuclei matchers and MCP agent triage when you don't want to re-implement the threshold logic; risk_score is the canonical numeric source.",
                    "enum": [
                      "low",
                      "medium",
                      "high",
                      "critical"
                    ],
                    "title": "Severity Label",
                    "type": "string"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line human-readable summary built from IP, PTR, ASN, country, ports, vulns.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "tags": {
                    "description": "Shodan InternetDB classification tags (e.g. 'cdn', 'cloud', 'vpn', 'tor', 'self-signed').",
                    "items": {
                      "type": "string"
                    },
                    "title": "Tags",
                    "type": "array"
                  },
                  "tor_exit": {
                    "default": false,
                    "description": "True if IP appears in the Tor Project's exit node list. False when not listed or when the upstream list fetch failed (check verdict.sources_unavailable for 'tor' to distinguish). Always present in response — never null.",
                    "title": "Tor Exit",
                    "type": "boolean"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  },
                  "vulns": {
                    "description": "CVEs Shodan InternetDB has associated with banners on this IP, enriched with severity + cvss_v3 from local cve.db (Phase 2 IP enrichment, v1.16.0 BREAKING). Pre-1.16 this was a flat list[str] of CVE IDs. Order is preserved from Shodan (meaningful — Shodan ranks confidence). Unknown CVEs emit severity='UNKNOWN'; do NOT infer 'benign' from UNKNOWN.",
                    "items": {
                      "$ref": "#/$defs/VulnInfo"
                    },
                    "title": "Vulns",
                    "type": "array"
                  }
                },
                "required": [
                  "ip"
                ],
                "title": "IpLookupResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "ReputationInfo": {
                "description": "Multi-source IP reputation. Sources present depend on tier (Free: firehol only; Pro: all three).",
                "properties": {
                  "abuseipdb": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/AbuseIpdbInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "AbuseIPDB abuse confidence. Pro tier only — omitted from the response on Free."
                  },
                  "firehol": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/FireholInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "FireHOL level1 blocklist membership. Available on Free tier."
                  },
                  "shodan": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/ShodanRepInfo"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Shodan full API enrichment. Pro tier only — omitted from the response on Free."
                  },
                  "upgrade": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/ReputationUpgradeHint"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Free-tier-only pointer to the Pro-only sources that were skipped."
                  }
                },
                "title": "ReputationInfo",
                "type": "object"
              },
              "ReputationUpgradeHint": {
                "description": "Compact pointer that replaces the verbose pro_only sub-stubs for Free tier.\n\nBug I4: previously the abuseipdb/shodan slots carried full Pydantic models\nwith every field null + a status='pro_only' marker — ~150 tokens of pure\nnegative space per Free-tier ip_lookup response. The verdict block already\nlists those sources in sources_unavailable on Free; this hint just points\ncallers at the upgrade page in one line.",
                "properties": {
                  "pro_only_sources": {
                    "items": {
                      "type": "string"
                    },
                    "title": "Pro Only Sources",
                    "type": "array"
                  },
                  "reason": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Reason"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Upgrade Url"
                  }
                },
                "title": "ReputationUpgradeHint",
                "type": "object"
              },
              "ShodanRepInfo": {
                "description": "Shodan full API enrichment (Pro tier only). Richer than InternetDB fields at top level.",
                "properties": {
                  "asn": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ASN string per Shodan (e.g. 'AS13335'); may differ from top-level asn int.",
                    "title": "Asn"
                  },
                  "city": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "City name per Shodan geolocation.",
                    "title": "City"
                  },
                  "country_name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Country name per Shodan geolocation.",
                    "title": "Country Name"
                  },
                  "hostnames": {
                    "description": "Hostnames observed pointing to this IP per Shodan.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Hostnames",
                    "type": "array"
                  },
                  "isp": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISP per Shodan (may differ from AbuseIPDB/RIPE).",
                    "title": "Isp"
                  },
                  "last_update": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 timestamp of Shodan's most recent data point for this IP.",
                    "title": "Last Update"
                  },
                  "org": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Organization name owning the IP per Shodan.",
                    "title": "Org"
                  },
                  "os": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Shodan-detected operating system (fingerprint-based, best-effort).",
                    "title": "Os"
                  },
                  "ports": {
                    "description": "Open ports observed by Shodan full scan (superset of top-level InternetDB ports).",
                    "items": {
                      "type": "integer"
                    },
                    "title": "Ports",
                    "type": "array"
                  },
                  "reason": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Human-readable reason. Present when status is skipped/restricted/rate_limited/error/pro_only.",
                    "title": "Reason"
                  },
                  "status": {
                    "description": "'ok' = data fetched; 'skipped' = API key not configured; 'restricted' = 403 (IP not available on free Shodan tier); 'rate_limited' = 429 quota exceeded; 'error' = transient HTTP/network failure; 'pro_only' = returned on Free tier as upsell hint.",
                    "enum": [
                      "ok",
                      "skipped",
                      "restricted",
                      "rate_limited",
                      "error",
                      "pro_only"
                    ],
                    "title": "Status",
                    "type": "string"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Upgrade link returned when status='pro_only'.",
                    "title": "Upgrade Url"
                  },
                  "vulns": {
                    "description": "CVE IDs Shodan has associated with banners on this IP.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Vulns",
                    "type": "array"
                  }
                },
                "required": [
                  "status"
                ],
                "title": "ShodanRepInfo",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              },
              "VulnInfo": {
                "description": "Severity-enriched CVE entry attached to /v1/ip and /v1/threat_report.\n\nPhase 2 IP enrichment (v1.16.0 BREAKING): Shodan InternetDB returns a flat\nlist of CVE IDs with no severity context, forcing agents to fan out\ncve_lookup calls for triage. We resolve severity + cvss_v3 against the\nlocal cve.db in a single SQL batch so the agent can prioritise without\nextra round-trips. Unknown CVEs are emitted with severity='UNKNOWN' /\ncvss_v3=null so the ID is preserved (the agent must not infer 'benign'\nfrom the absence of a row).",
                "properties": {
                  "cve_id": {
                    "description": "CVE identifier (e.g. 'CVE-2021-44228').",
                    "title": "Cve Id",
                    "type": "string"
                  },
                  "cvss_v3": {
                    "anyOf": [
                      {
                        "maximum": 10,
                        "minimum": 0,
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CVSS v3 base score (0.0-10.0). Null when severity='UNKNOWN' or NVD has no v3 score.",
                    "title": "Cvss V3"
                  },
                  "severity": {
                    "description": "NVD CVSS v3 severity bucket from local cve.db. 'UNKNOWN' when the CVE is not in our database (NVD may not have classified it yet, or the ID is reserved). Treat UNKNOWN as 'do not assume benign — call cve_lookup for fresh upstream data.'",
                    "enum": [
                      "CRITICAL",
                      "HIGH",
                      "MEDIUM",
                      "LOW",
                      "UNKNOWN"
                    ],
                    "title": "Severity",
                    "type": "string"
                  }
                },
                "required": [
                  "cve_id",
                  "severity"
                ],
                "title": "VulnInfo",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/IpLookupResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "ip_lookupOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "asn_lookup",
          "title": "ASN Lookup",
          "description": "Look up Autonomous System Number (ASN) for a domain or IP: AS number, organization, IPv4/IPv6 prefixes. Use to identify network operator and IP range ownership. Default returns first 50 prefixes per family — set include_full_prefixes=True for full list. Free: 30/hr, Pro: 500/hr. Returns {asn, asn_name, ipv4_prefixes, ipv6_prefixes, ipv4_count, ipv6_count}.",
          "inputSchema": {
            "properties": {
              "include_full_prefixes": {
                "default": false,
                "description": "Return the full announced-prefixes list (default: False, returns first 50). ipv4_count and ipv6_count are always honest pre-truncation totals. Set True for network mapping or BGP route audits — Cloudflare AS13335 announces 2500+ prefixes.",
                "title": "Include Full Prefixes",
                "type": "boolean"
              },
              "target": {
                "description": "Domain or IP address to look up ASN for (e.g. 'cloudflare.com', '8.8.8.8')",
                "title": "Target",
                "type": "string"
              }
            },
            "required": [
              "target"
            ],
            "title": "asn_lookupArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "AsnResponse": {
                "properties": {
                  "asn": {
                    "title": "Asn",
                    "type": "integer"
                  },
                  "asn_name": {
                    "default": "",
                    "maxLength": 256,
                    "title": "Asn Name",
                    "type": "string"
                  },
                  "ipv4_count": {
                    "default": 0,
                    "title": "Ipv4 Count",
                    "type": "integer"
                  },
                  "ipv4_prefixes": {
                    "items": {
                      "type": "string"
                    },
                    "title": "Ipv4 Prefixes",
                    "type": "array"
                  },
                  "ipv6_count": {
                    "default": 0,
                    "title": "Ipv6 Count",
                    "type": "integer"
                  },
                  "ipv6_prefixes": {
                    "items": {
                      "type": "string"
                    },
                    "title": "Ipv6 Prefixes",
                    "type": "array"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "resolved_ip": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Resolved Ip"
                  },
                  "summary": {
                    "default": "",
                    "title": "Summary",
                    "type": "string"
                  },
                  "target": {
                    "title": "Target",
                    "type": "string"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  },
                  "warnings": {
                    "items": {
                      "type": "string"
                    },
                    "title": "Warnings",
                    "type": "array"
                  }
                },
                "required": [
                  "target",
                  "asn"
                ],
                "title": "AsnResponse",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/AsnResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "asn_lookupOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "cve_lookup",
          "title": "CVE Lookup",
          "description": "Retrieve detailed CVE data by ID: description, CVSS v3.1 + vector, CVSS v2 (always emitted), EPSS score + percentile, CISA KEV status (expanded: due_date, required_action, ransomware flag, vendor_project, product, vulnerability_name, short_description, notes, cwes, date_removed when in_kev=true), NVD vulnerability_status (Analyzed/Modified/Awaiting Analysis/Deferred/Rejected/Withdrawn), cve_tags ('disputed' triggers [DISPUTED] summary prefix), affected products (CPE), references, patch availability, related CVEs. By default affected_products is truncated to the first 20 entries (total_products reports the honest count) and references to the first 10 (total_references reports the honest count). Pass include_affected_products=true and/or include_full_references=true for the complete lists. Pass include_reference_tags=true to receive structured references_full=[{url, tags, source}] (NVD upstream tags + source provenance) — also activates tag-first patch detection. Pass include_severity_breakdown=true to receive severity_sources/consensus/disagreement (multi-source view of NVD/MITRE/GHSA/OSV severity assessments). Use for single-CVE details; use cve_search for queries by product/severity. Response carries next_calls — chain with kev_detail when kev.in_kev=true, with cwe_lookup on each CWE in cwes (up to 3 pivots), and with exploit_lookup for public PoC availability. Free: 30/hr, Pro: 500/hr. Returns {cve_id, summary, description, severity, cvss_v3, cvss_v2, cvss_v2_vector, cvss_breakdown, cwe_id, cwes, vulnerability_status, cve_tags, published, modified, sources, first_seen_source, first_seen_at, epss, kev (in_kev, date_added, due_date, required_action, known_ransomware_use, vendor_project, product, vulnerability_name, short_description, notes, cwes, date_removed), affected_products (first 20 by default), total_products, references (first 10 by default), total_references, total_references_unique, references_full (only when include_reference_tags=true), severity_sources/severity_consensus/severity_disagreement (only when include_severity_breakdown=true), patch_available, related_cves, verdict, next_calls}.",
          "inputSchema": {
            "properties": {
              "cve_id": {
                "description": "CVE identifier in format CVE-YYYY-NNNNN (e.g. 'CVE-2024-3094', 'CVE-2023-44487')",
                "title": "Cve Id",
                "type": "string"
              },
              "include_affected_products": {
                "default": false,
                "description": "Return the full affected_products list (default: False, returns first 20). Set True for bulk audits or dependency scanning of Log4j-class CVEs with 50+ products.",
                "title": "Include Affected Products",
                "type": "boolean"
              },
              "include_full_references": {
                "default": true,
                "description": "Return the full references list (default: True, returns all references). total_references is always emitted with the honest count; patch URL detection always runs against the full list, so patch_url/patch_available are unaffected. Set False to truncate to first 10 entries when bandwidth-bound.",
                "title": "Include Full References",
                "type": "boolean"
              },
              "include_reference_tags": {
                "default": true,
                "description": "Return structured references_full field with [{url, tags, source}] objects (NVD reference tags + source provenance) (default: True). Inspects which references are vendor patches (tags=['Patch']) vs exploit PoCs (tags=['Exploit']) vs mailing list discussions. Patch URL detection is tag-first when refs_with_tags is populated; legacy cached rows fall back to regex. Set False to skip the structured shape for legacy clients.",
                "title": "Include Reference Tags",
                "type": "boolean"
              },
              "include_severity_breakdown": {
                "default": true,
                "description": "Return severity_sources, severity_consensus, and severity_disagreement (multi-source severity breakdown) (default: True). Surfaces vendor disputes (e.g. CVE-2023-38545 NVD-CRITICAL vs GHSA-HIGH). cvss_v2 and cvss_v2_vector are always emitted (additive non-opt-in). Consensus uses majority-bucket vote with highest-severity tie-break (CRITICAL \u003e HIGH \u003e MEDIUM \u003e LOW \u003e NONE). Set False to skip if downstream cannot tolerate the extra fields.",
                "title": "Include Severity Breakdown",
                "type": "boolean"
              }
            },
            "required": [
              "cve_id"
            ],
            "title": "cve_lookupArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "CveResponse": {
                "properties": {
                  "affected_products": {
                    "description": "Affected products: vendor/product entries from NVD and MITRE, plus package entries from GitHub advisories and OSV (vendor = ecosystem such as 'python' or 'nodejs', product = package name). Entries may carry version_start (inclusive), version_end (exclusive) and version_end_including. Truncated to first 20 by default. For GET /v1/cve/{cve_id}, use ?include_affected_products=true; for POST /v1/cves/bulk, set body field \"include_affected_products\": true.",
                    "items": {
                      "additionalProperties": true,
                      "type": "object"
                    },
                    "title": "Affected Products",
                    "type": "array"
                  },
                  "cve_id": {
                    "description": "Canonical CVE identifier, e.g. 'CVE-2021-44228'.",
                    "title": "Cve Id",
                    "type": "string"
                  },
                  "cve_tags": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "NVD cveTags (e.g. 'disputed', 'unsupported-when-assigned', 'exclusively-hosted-service'). When 'disputed' is present, summary is prefixed with [DISPUTED].",
                    "title": "Cve Tags"
                  },
                  "cvss_breakdown": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Per-metric CVSS v3 breakdown (attack_vector, attack_complexity, privileges_required, user_interaction, scope, confidentiality, integrity, availability). Keys present only when parsed from vector string.",
                    "title": "Cvss Breakdown"
                  },
                  "cvss_v2": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CVSS v2.0 base score (0.0-10.0). Always present (additive, non-opt-in); null for CVEs with no v2 metric or for legacy cached rows synced before v1.29.x. Pre-2010 CVEs and select dual-scored entries have v2-only or v2+v3 metrics.",
                    "title": "Cvss V2"
                  },
                  "cvss_v2_vector": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CVSS v2.0 vector string, e.g. 'AV:N/AC:L/Au:N/C:C/I:C/A:C'. Null when cvss_v2 is None.",
                    "title": "Cvss V2 Vector"
                  },
                  "cvss_v3": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CVSS v3.x base score (0.0-10.0). Null if no CVSS data available.",
                    "title": "Cvss V3"
                  },
                  "cwe_id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Primary CWE identifier, e.g. 'CWE-502'. First CWE when multiple are assigned.",
                    "title": "Cwe Id"
                  },
                  "cwes": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "All CWE identifiers assigned to this CVE, Primary first then Secondary. Null on legacy cache rows; cwe_id is always populated when cwes is non-empty.",
                    "title": "Cwes"
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Full vulnerability description sourced from NVD/MITRE/GHSA.",
                    "title": "Description"
                  },
                  "epss": {
                    "$ref": "#/$defs/EpssInfo",
                    "description": "Exploit Prediction Scoring System: score (0.0-1.0 probability) and percentile (0.0-100.0)."
                  },
                  "first_seen_at": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 timestamp when this CVE was first ingested locally.",
                    "title": "First Seen At"
                  },
                  "first_seen_source": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "First source that introduced this CVE into the local DB (for provenance/auditing).",
                    "title": "First Seen Source"
                  },
                  "kev": {
                    "$ref": "#/$defs/KevInfo",
                    "description": "CISA Known Exploited Vulnerabilities catalog: in_kev flag, date_added, plus 10 fields populated when in_kev=true (due_date, required_action, known_ransomware_use, vendor_project, product, vulnerability_name, short_description, notes, cwes, date_removed)."
                  },
                  "modified": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 last-modified timestamp; advances on NVD/MITRE revisions.",
                    "title": "Modified"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "patch_available": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "True when a vendor patch URL was detected in references (allowlisted vendor patterns). Null when enrichment was not requested.",
                    "title": "Patch Available"
                  },
                  "patch_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "First matched vendor patch/advisory URL from an allowlist (GitHub, RedHat, Ubuntu, Debian, Microsoft MSRC, Apple, Fortinet, Linux kernel.org, Cisco). Open-redirect params are filtered. Verify the host before clicking. Null when no match.",
                    "title": "Patch Url"
                  },
                  "published": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 publication timestamp from NVD/MITRE.",
                    "title": "Published"
                  },
                  "references": {
                    "description": "Advisory URLs (vendor bulletins, patch commits, exploit PoCs, analysis writeups). Truncated to first 10 by default. For GET /v1/cve/{cve_id}, use ?include_full_references=true; for POST /v1/cves/bulk, set body field \"include_full_references\": true. Patch URL detection always runs against the full list — patch_url/patch_available are unaffected by the cap.",
                    "items": {
                      "type": "string"
                    },
                    "title": "References",
                    "type": "array"
                  },
                  "references_full": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/ReferenceItem"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Structured references with NVD reference tags + source provenance. Populated only when ?include_reference_tags=true (or body field include_reference_tags=true for bulk_cve_lookup). Default None for backward compat. Same truncation as `references` field — use include_full_references=true for the complete list.",
                    "title": "References Full"
                  },
                  "related_cves": {
                    "anyOf": [
                      {
                        "items": {
                          "additionalProperties": true,
                          "type": "object"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Up to 5 CVEs sharing affected products, ordered by severity DESC. Each item: {cve_id, severity, cvss_v3}. Null when enrichment was not requested.",
                    "title": "Related Cves"
                  },
                  "severity": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CVSS v3 severity label: 'critical', 'high', 'medium', 'low', or 'none'.",
                    "title": "Severity"
                  },
                  "severity_consensus": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Majority-bucket consensus severity computed from severity_sources. On a tie, the highest severity wins (CRITICAL \u003e HIGH \u003e MEDIUM \u003e LOW \u003e NONE). Null when severity_breakdown was not requested or when no source reported a severity.",
                    "title": "Severity Consensus"
                  },
                  "severity_disagreement": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "True when 2+ severity buckets appear across severity_sources entries — counts both across-source disagreement (NVD CRITICAL vs GHSA HIGH) and within-source v2-vs-v3 disagreement (v2 HIGH vs v3 MEDIUM on the same NVD entry). Null when severity_breakdown was not requested.",
                    "title": "Severity Disagreement"
                  },
                  "severity_sources": {
                    "anyOf": [
                      {
                        "items": {
                          "additionalProperties": true,
                          "type": "object"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Multi-source severity breakdown (one entry per source: nvd, mitre, ghsa, osv). Populated only when ?include_severity_breakdown=true (or body field include_severity_breakdown=true for bulk_cve_lookup). Each entry has {source, severity, cvss_v3, cvss_v2}. Use to inspect vendor disputes (e.g. CVE-2023-38545 NVD-CRITICAL vs GHSA-HIGH).",
                    "title": "Severity Sources"
                  },
                  "sources": {
                    "description": "Data sources that wrote the CVE record itself: 'nvd', 'mitre', 'ghsa', 'osv'. EPSS and KEV are tracked separately — see the top-level epss.* and kev.* fields, not this list.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources",
                    "type": "array"
                  },
                  "summary": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Human-readable one-line summary built from severity, CVSS, KEV status, and EPSS.",
                    "title": "Summary"
                  },
                  "total_products": {
                    "default": 0,
                    "description": "Honest count of all affected products in the CVE database. Always present (emitted even when 0); matches len(affected_products) when not truncated.",
                    "title": "Total Products",
                    "type": "integer"
                  },
                  "total_references": {
                    "default": 0,
                    "description": "Honest count of all references in the CVE database. Always present (emitted even when 0); matches len(references) when not truncated.",
                    "title": "Total References",
                    "type": "integer"
                  },
                  "total_references_unique": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Unique-URL upstream count from refs_with_tags (Batch 6A). None for legacy cached rows synced before v1.29.x; populated after the next sync run for all 4 sources (NVD/MITRE/GHSA/OSV).",
                    "title": "Total References Unique"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  },
                  "vulnerability_status": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "NVD lifecycle status: 'Analyzed', 'Modified', 'Awaiting Analysis', 'Deferred', 'Rejected', 'Withdrawn'. Drives verdict.completeness downgrade for Rejected/Withdrawn/Awaiting Analysis.",
                    "title": "Vulnerability Status"
                  }
                },
                "required": [
                  "cve_id"
                ],
                "title": "CveResponse",
                "type": "object"
              },
              "EpssInfo": {
                "properties": {
                  "percentile": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "EPSS percentile rank (0.0-100.0) relative to all scored CVEs; higher = more at-risk.",
                    "title": "Percentile"
                  },
                  "score": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "EPSS probability (0.0-1.0) that this CVE will be exploited in the next 30 days.",
                    "title": "Score"
                  }
                },
                "title": "EpssInfo",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "KevInfo": {
                "properties": {
                  "cwes": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CWE identifiers CISA reports for this CVE (Batch 4A view-ID filtered).",
                    "title": "Cwes"
                  },
                  "date_added": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 date this CVE was added to CISA's Known Exploited Vulnerabilities catalog.",
                    "title": "Date Added"
                  },
                  "date_removed": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 timestamp when CISA removed this CVE from the KEV catalog. Null when CVE is still active in KEV.",
                    "title": "Date Removed"
                  },
                  "due_date": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Federal patch deadline (ISO 8601). Null for entries from before BOD 22-01 (Nov 2021).",
                    "title": "Due Date"
                  },
                  "in_kev": {
                    "default": false,
                    "description": "True when CISA has confirmed this CVE is being actively exploited in the wild.",
                    "title": "In Kev",
                    "type": "boolean"
                  },
                  "known_ransomware_use": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "True when CISA links this CVE to a known ransomware campaign. Null when CVE is not in KEV.",
                    "title": "Known Ransomware Use"
                  },
                  "notes": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Reference URLs published by CISA, separated by '; '.",
                    "title": "Notes"
                  },
                  "product": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Affected product name as published by CISA (mirrors kev_detail.product).",
                    "title": "Product"
                  },
                  "required_action": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CISA-specified remediation action text (mirrors kev_detail.required_action).",
                    "title": "Required Action"
                  },
                  "short_description": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CISA's one-sentence summary (mirrors kev_detail.short_description).",
                    "title": "Short Description"
                  },
                  "vendor_project": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Vendor or project name as published by CISA (mirrors kev_detail.vendor_project).",
                    "title": "Vendor Project"
                  },
                  "vulnerability_name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Short common name when CISA assigns one, e.g. 'Log4Shell', 'ProxyShell'.",
                    "title": "Vulnerability Name"
                  }
                },
                "title": "KevInfo",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "ReferenceItem": {
                "description": "Structured reference object with NVD upstream tags + source provenance.\nEmitted in CveResponse.references_full when ?include_reference_tags=true.",
                "properties": {
                  "source": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Upstream source identifier. NVD: raw 'source' field (UUID/email of the CVE Numbering Authority); MITRE/GHSA/OSV: parser-name normalized to 'mitre'/'ghsa'/'osv'.",
                    "title": "Source"
                  },
                  "tags": {
                    "description": "NVD reference tags: Patch, Vendor Advisory, Mailing List, Exploit, Third Party Advisory, Issue Tracking, Release Notes, Technical Description, US Government Resource, VDB Entry. Empty list for MITRE/GHSA/OSV refs (those upstream feeds don't carry tags).",
                    "items": {
                      "type": "string"
                    },
                    "title": "Tags",
                    "type": "array"
                  },
                  "url": {
                    "description": "Reference URL (advisory, patch commit, exploit PoC, mailing list, etc.)",
                    "title": "Url",
                    "type": "string"
                  }
                },
                "required": [
                  "url"
                ],
                "title": "ReferenceItem",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/CveResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "cve_lookupOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "calculate_risk_score",
          "title": "Calculate Risk Score",
          "description": "Composite CVE risk score (0-100) — fuses CVSS, EPSS, KEV, and PoC into a single agent-ready triage signal. Formula: CVSS*0.20 + EPSS*0.35 + KEV*0.30 + PoC*0.15 (each component rescaled to 0-100 before weighting). Multiplicative boosters applied in order: KEV+PoC combo (*1.15), critical-severity-with-high-EPSS (CVSS\u003e=9 AND EPSS\u003e0.7, *1.10), recently published (within last 7 days, *1.05). Final score clamped to [0, 100]. Label bands: CRITICAL\u003e=90, HIGH\u003e=70, MEDIUM\u003e=40, LOW\u003c40. Urgency text encodes patch SLA (immediate when KEV; 24h/72h/30d by label). Use to triage a single CVE without orchestrating cve_lookup + exploit_lookup separately. PoC signal here is the local ExploitDB mirror only — for full multi-source exploit detail (GitHub Advisory + Shodan refs + ExploitDB), call exploit_lookup separately. Methodology adapted from mukul975/cve-mcp-server (Apache-2.0): https://github.com/mukul975/cve-mcp-server. Free: 30/hr, Pro: 500/hr. Returns {cve_id, score (0-100), label (CRITICAL/HIGH/MEDIUM/LOW), urgency, has_public_poc, components (cvss_v3, epss_score, in_kev, has_public_poc, weighted_breakdown), boosters_applied, recommendation, summary, verdict, next_calls}.",
          "inputSchema": {
            "properties": {
              "cve_id": {
                "description": "CVE identifier in format CVE-YYYY-NNNNN (e.g. 'CVE-2021-44228', 'CVE-2024-3094')",
                "title": "Cve Id",
                "type": "string"
              }
            },
            "required": [
              "cve_id"
            ],
            "title": "calculate_risk_scoreArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "RiskScoreResponse": {
                "description": "Composite CVE risk score (CVSS / EPSS / KEV / PoC fusion).",
                "properties": {
                  "boosters_applied": {
                    "description": "Multiplicative boosters applied: kev_with_public_poc (*1.15), critical_severity_high_epss (*1.10), published_within_7_days (*1.05).",
                    "items": {
                      "type": "string"
                    },
                    "title": "Boosters Applied",
                    "type": "array"
                  },
                  "components": {
                    "additionalProperties": true,
                    "description": "Inputs that fed the score: cvss_v3, epss_score, in_kev, has_public_poc, weighted_breakdown ({cvss, epss, kev, poc} each scaled 0-100 * weight).",
                    "title": "Components",
                    "type": "object"
                  },
                  "cve_id": {
                    "description": "Canonical CVE identifier, e.g. 'CVE-2021-44228'.",
                    "title": "Cve Id",
                    "type": "string"
                  },
                  "has_public_poc": {
                    "description": "True when a public PoC is available (ExploitDB local mirror).",
                    "title": "Has Public Poc",
                    "type": "boolean"
                  },
                  "label": {
                    "description": "Risk band derived from score (CRIT≥90, HIGH≥70, MED≥40, LOW\u003c40).",
                    "enum": [
                      "CRITICAL",
                      "HIGH",
                      "MEDIUM",
                      "LOW"
                    ],
                    "title": "Label",
                    "type": "string"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "recommendation": {
                    "description": "One-sentence remediation guidance.",
                    "title": "Recommendation",
                    "type": "string"
                  },
                  "score": {
                    "description": "Composite risk score in 0.0-100.0. Higher = more urgent.",
                    "title": "Score",
                    "type": "number"
                  },
                  "summary": {
                    "description": "One-line agent-friendly summary of the verdict.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "urgency": {
                    "description": "Human-readable patch urgency (e.g. 'Patch within 24 hours').",
                    "title": "Urgency",
                    "type": "string"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "cve_id",
                  "score",
                  "label",
                  "urgency",
                  "has_public_poc",
                  "components",
                  "recommendation",
                  "summary"
                ],
                "title": "RiskScoreResponse",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/RiskScoreResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "calculate_risk_scoreOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "get_cvss_details",
          "title": "Get CVSS Details",
          "description": "Parse a CVSS v3.x vector string into a per-metric breakdown plus a recomputed base score. Returns the canonicalized vector, version (3.0 or 3.1), base_score, base_severity (NONE/LOW/MEDIUM/HIGH/CRITICAL), and the eight base metrics: attack_vector (NETWORK/ADJACENT_NETWORK/LOCAL/PHYSICAL), attack_complexity (LOW/HIGH), privileges_required (NONE/LOW/HIGH), user_interaction (NONE/REQUIRED), scope (UNCHANGED/CHANGED), and the three impact metrics confidentiality_impact / integrity_impact / availability_impact (NONE/LOW/HIGH each). When temporal/environmental metrics are explicit in the vector, temporal_score and environmental_score are populated separately. Use to translate raw CVSS strings into agent-friendly attributes without re-parsing the vector grammar yourself, and to verify upstream NVD scoring against the recomputed value. v2 vectors (AV:N/AC:L/Au:N/...) are rejected with 400 — read cvss_v2_vector from cve_lookup if you need v2 detail. Free: 30/hr, Pro: 500/hr. Returns {version, vector, base_score, base_severity, metrics: {attack_vector, attack_complexity, privileges_required, user_interaction, scope, confidentiality_impact, integrity_impact, availability_impact}, temporal_score, environmental_score, summary, verdict}.",
          "inputSchema": {
            "properties": {
              "vector": {
                "description": "CVSS v3.0 or v3.1 vector string, e.g. 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H'. v2 vectors are rejected — use the cvss_v2_vector field on cve_lookup if you need v2.",
                "title": "Vector",
                "type": "string"
              }
            },
            "required": [
              "vector"
            ],
            "title": "get_cvss_detailsArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "CvssDetailsResponse": {
                "description": "Per-metric breakdown of a CVSS v3.x vector string.",
                "properties": {
                  "base_score": {
                    "description": "Recomputed base score (0.0-10.0).",
                    "title": "Base Score",
                    "type": "number"
                  },
                  "base_severity": {
                    "description": "Base severity label: NONE / LOW / MEDIUM / HIGH / CRITICAL.",
                    "title": "Base Severity",
                    "type": "string"
                  },
                  "environmental_score": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Environmental score when env metrics are explicit; null otherwise.",
                    "title": "Environmental Score"
                  },
                  "metrics": {
                    "$ref": "#/$defs/CvssMetrics",
                    "description": "Per-metric human-readable breakdown."
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "summary": {
                    "description": "One-line agent-friendly summary.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "temporal_score": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Temporal score when temporal metrics are explicit; null otherwise.",
                    "title": "Temporal Score"
                  },
                  "vector": {
                    "description": "Canonicalized CVSS vector string.",
                    "title": "Vector",
                    "type": "string"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  },
                  "version": {
                    "description": "CVSS specification version, e.g. '3.1' or '3.0'.",
                    "title": "Version",
                    "type": "string"
                  }
                },
                "required": [
                  "version",
                  "vector",
                  "base_score",
                  "base_severity",
                  "metrics",
                  "summary"
                ],
                "title": "CvssDetailsResponse",
                "type": "object"
              },
              "CvssMetrics": {
                "properties": {
                  "attack_complexity": {
                    "description": "AC — LOW / HIGH.",
                    "title": "Attack Complexity",
                    "type": "string"
                  },
                  "attack_vector": {
                    "description": "AV — NETWORK / ADJACENT_NETWORK / LOCAL / PHYSICAL.",
                    "title": "Attack Vector",
                    "type": "string"
                  },
                  "availability_impact": {
                    "description": "A — NONE / LOW / HIGH.",
                    "title": "Availability Impact",
                    "type": "string"
                  },
                  "confidentiality_impact": {
                    "description": "C — NONE / LOW / HIGH.",
                    "title": "Confidentiality Impact",
                    "type": "string"
                  },
                  "integrity_impact": {
                    "description": "I — NONE / LOW / HIGH.",
                    "title": "Integrity Impact",
                    "type": "string"
                  },
                  "privileges_required": {
                    "description": "PR — NONE / LOW / HIGH.",
                    "title": "Privileges Required",
                    "type": "string"
                  },
                  "scope": {
                    "description": "S — UNCHANGED / CHANGED.",
                    "title": "Scope",
                    "type": "string"
                  },
                  "user_interaction": {
                    "description": "UI — NONE / REQUIRED.",
                    "title": "User Interaction",
                    "type": "string"
                  }
                },
                "required": [
                  "attack_vector",
                  "attack_complexity",
                  "privileges_required",
                  "user_interaction",
                  "scope",
                  "confidentiality_impact",
                  "integrity_impact",
                  "availability_impact"
                ],
                "title": "CvssMetrics",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/CvssDetailsResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "get_cvss_detailsOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "cve_search",
          "title": "CVE Search",
          "description": "Search CVE database with filters: product/vendor, severity, published date range, EPSS score, CWE, CVSS range, CISA KEV status. Default response is SLIM per-result (cve_id, summary, severity, cvss_v3, cwe_id, epss, kev, total_products, published, modified, sources) — pass include='full' for description, cvss_breakdown, affected_products, references, first_seen_*. Verdict (sources_queried, falsifiable_fields, completeness, data_age) is at the response root — applies to the whole batch, not per-row. Product/vendor filters are EXACT NVD-canonical-token matches (not the common name — e.g. nginx is 'nginx_open_source'/'nginx_plus', vendor 'f5'); a low/zero count for a well-known product means the token differs, so for dependency/package lists use check_dependencies and for a domain's whole stack tech_stack_cve_audit (both auto-normalize tokens). Use for vulnerability discovery by criteria; pass cwe_id (e.g. CWE-79) to enumerate every CVE in our database mapped to a weakness — pair with cwe_lookup for the category description and mitigations. Use cve_lookup for single CVE by ID, kev_detail when kev=true filtering and the agent needs federal patch deadlines per result. Response carries a global hint pointing at cve_lookup — drill into any returned cve_id for full detail and chained pivots (exploit_lookup, kev_detail, cwe_lookup). Free: 30/hr, Pro: 500/hr. Returns {count, total, truncated, offset, summary, results, query_echo, next_offset, verdict, hint}.",
          "inputSchema": {
            "properties": {
              "cvss_max": {
                "default": 10,
                "description": "Maximum CVSS v3 base score (0.0-10.0). Default 10.0 = no filter (sentinel, not applied). Set \u003c 10.0 to filter — CVEs with null CVSS are excluded when active. Combine with cvss_min for a range.",
                "maximum": 10,
                "minimum": 0,
                "title": "Cvss Max",
                "type": "number"
              },
              "cvss_min": {
                "default": 0,
                "description": "Minimum CVSS v3 base score (0.0-10.0). Default 0.0 = no filter (sentinel, not applied). Set \u003e 0 to filter — CVEs with null CVSS are excluded when active. Use 7.0 for high+critical, 9.0 for critical only.",
                "maximum": 10,
                "minimum": 0,
                "title": "Cvss Min",
                "type": "number"
              },
              "cwe_id": {
                "default": "",
                "description": "Filter by CWE weakness ID. Exact match, case-insensitive. Common values: CWE-79 (XSS), CWE-89 (SQL injection), CWE-120 (buffer overflow), CWE-78 (command injection). Format: CWE-\u003cnumber\u003e. Omit to not filter by CWE.",
                "title": "Cwe Id",
                "type": "string"
              },
              "epss_min": {
                "default": 0,
                "description": "Minimum EPSS score filter (0.0-1.0). EPSS predicts exploitation probability. 0.5 = top ~5% most likely to be exploited. 0.0 = no filter.",
                "maximum": 1,
                "minimum": 0,
                "title": "Epss Min",
                "type": "number"
              },
              "include": {
                "default": "",
                "description": "Per-result detail level. Default (omit) returns slim list items (cve_id, summary, severity, cvss_v3, cwe_id, epss, kev, total_products, published, modified, sources). Pass 'full' to also return description, cvss_breakdown, affected_products, references, first_seen_source, first_seen_at — only do this when the user explicitly wants drill-down on every result. Even with 'full', per-result affected_products and references may be truncated (the per-result total_products/total_references report the honest counts); use cve_lookup for the guaranteed-complete per-CVE lists. For single-CVE detail prefer cve_lookup; slim default keeps token cost ~70% lower on Log4j-class queries. Note: verdict is at the response root, not per-row (was deduplicated to save ~40% payload).",
                "enum": [
                  "",
                  "full"
                ],
                "title": "Include",
                "type": "string"
              },
              "kev": {
                "default": false,
                "description": "If true, return only CVEs in the CISA Known Exploited Vulnerabilities (KEV) catalog — these are actively exploited in the wild.",
                "title": "Kev",
                "type": "boolean"
              },
              "limit": {
                "default": 50,
                "description": "Maximum results to return. Range: 1-200.",
                "maximum": 200,
                "minimum": 1,
                "title": "Limit",
                "type": "integer"
              },
              "offset": {
                "default": 0,
                "description": "Skip N results for pagination. Use with limit to page through results.",
                "maximum": 5000,
                "minimum": 0,
                "title": "Offset",
                "type": "integer"
              },
              "product": {
                "default": "",
                "description": "Product or vendor token to filter by. EXACT match (case-insensitive) against the NVD-canonical CPE product/vendor token — NOT substring/fuzzy, and NOT necessarily the common project name. Common names, vendor renames, and build-tool artifact ids often differ from the canonical token (e.g. modern nginx CVEs are under 'nginx_open_source'/'nginx_plus', vendor 'f5', not 'nginx'; Maven 'log4j-core' maps to 'log4j'). A low or zero count for a well-known product usually means the token differs — do NOT assume coverage is complete. For dependency/package lists prefer check_dependencies, and for a domain's whole tech stack tech_stack_cve_audit (both auto-normalize tokens). A product match means CVEs exist for that product, not that a specific running version is affected — verify the running version is within each CVE's affected range. Omit to search all products.",
                "title": "Product",
                "type": "string"
              },
              "published_after": {
                "default": "",
                "description": "Inclusive lower bound on publish date as YYYY-MM-DD (UTC). Pick this when the user names a starting point, e.g. 'since 2015' → '2015-01-01', 'after March 2024' → '2024-03-01'. Omit to not bound the lower edge. Combine with published_before for ranges.",
                "title": "Published After",
                "type": "string"
              },
              "published_before": {
                "default": "",
                "description": "Inclusive upper bound on publish date as YYYY-MM-DD (UTC). Pick this when the user names an ending point, e.g. 'before 2020' → '2019-12-31', 'up to 2023' → '2023-12-31'. Omit to not bound the upper edge. Combine with published_after for ranges.",
                "title": "Published Before",
                "type": "string"
              },
              "severity": {
                "default": "",
                "description": "CVSS severity level. Must be one of: CRITICAL, HIGH, MEDIUM, LOW. Omit for all severities.",
                "enum": [
                  "",
                  "CRITICAL",
                  "HIGH",
                  "MEDIUM",
                  "LOW"
                ],
                "title": "Severity",
                "type": "string"
              },
              "sort": {
                "default": "",
                "description": "Sort order for results. Must be one of: published_desc (newest first), epss_desc (most exploitable first), cvss_desc (most severe first). Omit for newest first (default=published_desc).",
                "enum": [
                  "",
                  "published_desc",
                  "epss_desc",
                  "cvss_desc"
                ],
                "title": "Sort",
                "type": "string"
              },
              "vendor": {
                "default": "",
                "description": "Filter by vendor name (case-insensitive). When combined with product, both must match the same CPE row — prevents cross-row false matches. Example: vendor=apache, product=struts.",
                "title": "Vendor",
                "type": "string"
              }
            },
            "title": "cve_searchArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "CveSearchItem": {
                "additionalProperties": true,
                "description": "Slim per-result shape for cve_search list items.\n\nDefault cve_search response uses this shape (description / cvss_breakdown /\naffected_products / references / first_seen_* are dropped). Pass cve_search\n?include=full to get the full CveResponse shape — extra=\"allow\" lets the\nfull-mode fields pass through without a schema fork.",
                "properties": {
                  "cve_id": {
                    "description": "Canonical CVE identifier, e.g. 'CVE-2021-44228'.",
                    "title": "Cve Id",
                    "type": "string"
                  },
                  "cvss_v3": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CVSS v3.x base score (0.0-10.0).",
                    "title": "Cvss V3"
                  },
                  "cwe_id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Primary CWE identifier (legacy single-value field). Equals cwes[0] when cwes is present. Kept for backward-compat; consumers should prefer cwes.",
                    "title": "Cwe Id"
                  },
                  "cwes": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Multi-CWE list as published by NVD. Mirrors cve_lookup.cwes (v1.28.0 multi-CWE adoption). Null/omitted when DB row has no multi-CWE list — legacy cwe_id still emitted.",
                    "title": "Cwes"
                  },
                  "epss": {
                    "$ref": "#/$defs/EpssInfo",
                    "description": "EPSS score + percentile."
                  },
                  "kev": {
                    "$ref": "#/$defs/KevInfo",
                    "description": "CISA KEV status."
                  },
                  "modified": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 last-modified timestamp.",
                    "title": "Modified"
                  },
                  "published": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 publication timestamp.",
                    "title": "Published"
                  },
                  "references_count": {
                    "default": 0,
                    "description": "Honest count of upstream references for this CVE. Use this to decide whether a cve_lookup pivot is worthwhile (e.g. \u003e0 refs → drill down; 0 → skip). The reference list itself is NOT included in slim search items — pass include=full or call cve_lookup to retrieve URLs.",
                    "title": "References Count",
                    "type": "integer"
                  },
                  "severity": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CVSS v3 severity label.",
                    "title": "Severity"
                  },
                  "sources": {
                    "description": "Source feeds for this CVE row.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources",
                    "type": "array"
                  },
                  "summary": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Human-readable one-line summary.",
                    "title": "Summary"
                  },
                  "total_products": {
                    "default": 0,
                    "description": "Honest count of affected products in DB.",
                    "title": "Total Products",
                    "type": "integer"
                  }
                },
                "required": [
                  "cve_id"
                ],
                "title": "CveSearchItem",
                "type": "object"
              },
              "CveSearchResponse": {
                "properties": {
                  "count": {
                    "default": 0,
                    "description": "Number of CVEs in this page (== len(results)). Capped by `limit`.",
                    "title": "Count",
                    "type": "integer"
                  },
                  "hint": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/SearchHint"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pivot/refine hint emitted when the query returned 0 results or is overly broad."
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "next_offset": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Offset to pass on the next page. Null when truncated=False (no more results).",
                    "title": "Next Offset"
                  },
                  "offset": {
                    "default": 0,
                    "description": "Offset of the first item in this page (echoed from input).",
                    "title": "Offset",
                    "type": "integer"
                  },
                  "query_echo": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Echoed search filters with empty values stripped. Keys: product, vendor, severity, cwe_id, published_after, published_before, kev, epss_min, cvss_min, cvss_max, sort, limit, offset, tagged. Useful for verifying the parsed query matched the intent.",
                    "title": "Query Echo"
                  },
                  "results": {
                    "description": "Per-CVE slim records — see CveSearchItem.",
                    "items": {
                      "$ref": "#/$defs/CveSearchItem"
                    },
                    "title": "Results",
                    "type": "array"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line summary like '50 CVEs returned, 1234 total (product=nginx, severity=HIGH)'.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "total": {
                    "default": 0,
                    "description": "Total CVE matches in the database for the query — the honest pre-pagination count.",
                    "title": "Total",
                    "type": "integer"
                  },
                  "truncated": {
                    "default": false,
                    "description": "True when total \u003e offset + count (more pages available — use next_offset).",
                    "title": "Truncated",
                    "type": "boolean"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "title": "CveSearchResponse",
                "type": "object"
              },
              "EpssInfo": {
                "properties": {
                  "percentile": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "EPSS percentile rank (0.0-100.0) relative to all scored CVEs; higher = more at-risk.",
                    "title": "Percentile"
                  },
                  "score": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "EPSS probability (0.0-1.0) that this CVE will be exploited in the next 30 days.",
                    "title": "Score"
                  }
                },
                "title": "EpssInfo",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "KevInfo": {
                "properties": {
                  "cwes": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CWE identifiers CISA reports for this CVE (Batch 4A view-ID filtered).",
                    "title": "Cwes"
                  },
                  "date_added": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 date this CVE was added to CISA's Known Exploited Vulnerabilities catalog.",
                    "title": "Date Added"
                  },
                  "date_removed": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 timestamp when CISA removed this CVE from the KEV catalog. Null when CVE is still active in KEV.",
                    "title": "Date Removed"
                  },
                  "due_date": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Federal patch deadline (ISO 8601). Null for entries from before BOD 22-01 (Nov 2021).",
                    "title": "Due Date"
                  },
                  "in_kev": {
                    "default": false,
                    "description": "True when CISA has confirmed this CVE is being actively exploited in the wild.",
                    "title": "In Kev",
                    "type": "boolean"
                  },
                  "known_ransomware_use": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "True when CISA links this CVE to a known ransomware campaign. Null when CVE is not in KEV.",
                    "title": "Known Ransomware Use"
                  },
                  "notes": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Reference URLs published by CISA, separated by '; '.",
                    "title": "Notes"
                  },
                  "product": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Affected product name as published by CISA (mirrors kev_detail.product).",
                    "title": "Product"
                  },
                  "required_action": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CISA-specified remediation action text (mirrors kev_detail.required_action).",
                    "title": "Required Action"
                  },
                  "short_description": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CISA's one-sentence summary (mirrors kev_detail.short_description).",
                    "title": "Short Description"
                  },
                  "vendor_project": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Vendor or project name as published by CISA (mirrors kev_detail.vendor_project).",
                    "title": "Vendor Project"
                  },
                  "vulnerability_name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Short common name when CISA assigns one, e.g. 'Log4Shell', 'ProxyShell'.",
                    "title": "Vulnerability Name"
                  }
                },
                "title": "KevInfo",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "SearchHint": {
                "additionalProperties": true,
                "description": "Footer hint emitted on list responses (cve_search, cve_leading) to point\nLLM agents at the natural drill-down tool. Distinct from PivotHint: there is\nno `input` field because the hint is global to the list — the agent picks a\nresult of interest and passes its ID to the named tool.",
                "properties": {
                  "reason": {
                    "description": "Short rationale explaining what the drill-down tool adds beyond the slim list items (e.g. full description, affected_products, references, exploit/KEV/CWE pivots).",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "const": "cve_lookup",
                    "description": "Drill-down tool to call with any result ID from the list. Constrained to cve_lookup today; expand the Literal as new list endpoints get list-level hints.",
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "reason"
                ],
                "title": "SearchHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/CveSearchResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "cve_searchOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "cve_leading",
          "title": "CVE Leading",
          "description": "List CVEs indexed from MITRE/GHSA BEFORE NVD publication (early-warning, freshest data). By default each result is slim (no description, no cvss_breakdown, no affected_products list, no references) — pass include='full' for the same payload shape as cve_lookup; for drill-down on a single CVE prefer cve_lookup. Use for threat intelligence on emerging CVEs; use cve_search for published NVD data. Verdict (sources_queried, falsifiable_fields, completeness, data_age) is at the response root — applies to the whole batch, not per-row. Response carries a global hint pointing at cve_lookup — drill into any returned cve_id for full detail and chained pivots (exploit_lookup, kev_detail, cwe_lookup). Free: 30/hr, Pro: 500/hr. Returns {count, total, truncated, offset, summary, results, next_offset, verdict, hint}.",
          "inputSchema": {
            "properties": {
              "include": {
                "default": "",
                "description": "Per-result detail level. Default ('') returns slim list items (cve_id, summary, severity, cvss_v3, cwe_id, epss, kev, total_products, published, modified, sources). Pass 'full' to also return description, cvss_breakdown, affected_products, references, first_seen_source, first_seen_at. Slim default avoids description/summary duplication that bloats 50-item leading lists. Verdict is at the response root, not per-row (deduplicated for ~40% payload savings). Allowed: '' or 'full'.",
                "enum": [
                  "",
                  "full"
                ],
                "title": "Include",
                "type": "string"
              },
              "limit": {
                "default": 50,
                "description": "Maximum results to return. Range: 1-200.",
                "maximum": 200,
                "minimum": 1,
                "title": "Limit",
                "type": "integer"
              },
              "offset": {
                "default": 0,
                "description": "Skip N results for pagination.",
                "maximum": 5000,
                "minimum": 0,
                "title": "Offset",
                "type": "integer"
              }
            },
            "title": "cve_leadingArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "CveSearchItem": {
                "additionalProperties": true,
                "description": "Slim per-result shape for cve_search list items.\n\nDefault cve_search response uses this shape (description / cvss_breakdown /\naffected_products / references / first_seen_* are dropped). Pass cve_search\n?include=full to get the full CveResponse shape — extra=\"allow\" lets the\nfull-mode fields pass through without a schema fork.",
                "properties": {
                  "cve_id": {
                    "description": "Canonical CVE identifier, e.g. 'CVE-2021-44228'.",
                    "title": "Cve Id",
                    "type": "string"
                  },
                  "cvss_v3": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CVSS v3.x base score (0.0-10.0).",
                    "title": "Cvss V3"
                  },
                  "cwe_id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Primary CWE identifier (legacy single-value field). Equals cwes[0] when cwes is present. Kept for backward-compat; consumers should prefer cwes.",
                    "title": "Cwe Id"
                  },
                  "cwes": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Multi-CWE list as published by NVD. Mirrors cve_lookup.cwes (v1.28.0 multi-CWE adoption). Null/omitted when DB row has no multi-CWE list — legacy cwe_id still emitted.",
                    "title": "Cwes"
                  },
                  "epss": {
                    "$ref": "#/$defs/EpssInfo",
                    "description": "EPSS score + percentile."
                  },
                  "kev": {
                    "$ref": "#/$defs/KevInfo",
                    "description": "CISA KEV status."
                  },
                  "modified": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 last-modified timestamp.",
                    "title": "Modified"
                  },
                  "published": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 publication timestamp.",
                    "title": "Published"
                  },
                  "references_count": {
                    "default": 0,
                    "description": "Honest count of upstream references for this CVE. Use this to decide whether a cve_lookup pivot is worthwhile (e.g. \u003e0 refs → drill down; 0 → skip). The reference list itself is NOT included in slim search items — pass include=full or call cve_lookup to retrieve URLs.",
                    "title": "References Count",
                    "type": "integer"
                  },
                  "severity": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CVSS v3 severity label.",
                    "title": "Severity"
                  },
                  "sources": {
                    "description": "Source feeds for this CVE row.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources",
                    "type": "array"
                  },
                  "summary": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Human-readable one-line summary.",
                    "title": "Summary"
                  },
                  "total_products": {
                    "default": 0,
                    "description": "Honest count of affected products in DB.",
                    "title": "Total Products",
                    "type": "integer"
                  }
                },
                "required": [
                  "cve_id"
                ],
                "title": "CveSearchItem",
                "type": "object"
              },
              "CveSearchResponse": {
                "properties": {
                  "count": {
                    "default": 0,
                    "description": "Number of CVEs in this page (== len(results)). Capped by `limit`.",
                    "title": "Count",
                    "type": "integer"
                  },
                  "hint": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/SearchHint"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pivot/refine hint emitted when the query returned 0 results or is overly broad."
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "next_offset": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Offset to pass on the next page. Null when truncated=False (no more results).",
                    "title": "Next Offset"
                  },
                  "offset": {
                    "default": 0,
                    "description": "Offset of the first item in this page (echoed from input).",
                    "title": "Offset",
                    "type": "integer"
                  },
                  "query_echo": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Echoed search filters with empty values stripped. Keys: product, vendor, severity, cwe_id, published_after, published_before, kev, epss_min, cvss_min, cvss_max, sort, limit, offset, tagged. Useful for verifying the parsed query matched the intent.",
                    "title": "Query Echo"
                  },
                  "results": {
                    "description": "Per-CVE slim records — see CveSearchItem.",
                    "items": {
                      "$ref": "#/$defs/CveSearchItem"
                    },
                    "title": "Results",
                    "type": "array"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line summary like '50 CVEs returned, 1234 total (product=nginx, severity=HIGH)'.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "total": {
                    "default": 0,
                    "description": "Total CVE matches in the database for the query — the honest pre-pagination count.",
                    "title": "Total",
                    "type": "integer"
                  },
                  "truncated": {
                    "default": false,
                    "description": "True when total \u003e offset + count (more pages available — use next_offset).",
                    "title": "Truncated",
                    "type": "boolean"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "title": "CveSearchResponse",
                "type": "object"
              },
              "EpssInfo": {
                "properties": {
                  "percentile": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "EPSS percentile rank (0.0-100.0) relative to all scored CVEs; higher = more at-risk.",
                    "title": "Percentile"
                  },
                  "score": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "EPSS probability (0.0-1.0) that this CVE will be exploited in the next 30 days.",
                    "title": "Score"
                  }
                },
                "title": "EpssInfo",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "KevInfo": {
                "properties": {
                  "cwes": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CWE identifiers CISA reports for this CVE (Batch 4A view-ID filtered).",
                    "title": "Cwes"
                  },
                  "date_added": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 date this CVE was added to CISA's Known Exploited Vulnerabilities catalog.",
                    "title": "Date Added"
                  },
                  "date_removed": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 timestamp when CISA removed this CVE from the KEV catalog. Null when CVE is still active in KEV.",
                    "title": "Date Removed"
                  },
                  "due_date": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Federal patch deadline (ISO 8601). Null for entries from before BOD 22-01 (Nov 2021).",
                    "title": "Due Date"
                  },
                  "in_kev": {
                    "default": false,
                    "description": "True when CISA has confirmed this CVE is being actively exploited in the wild.",
                    "title": "In Kev",
                    "type": "boolean"
                  },
                  "known_ransomware_use": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "True when CISA links this CVE to a known ransomware campaign. Null when CVE is not in KEV.",
                    "title": "Known Ransomware Use"
                  },
                  "notes": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Reference URLs published by CISA, separated by '; '.",
                    "title": "Notes"
                  },
                  "product": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Affected product name as published by CISA (mirrors kev_detail.product).",
                    "title": "Product"
                  },
                  "required_action": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CISA-specified remediation action text (mirrors kev_detail.required_action).",
                    "title": "Required Action"
                  },
                  "short_description": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CISA's one-sentence summary (mirrors kev_detail.short_description).",
                    "title": "Short Description"
                  },
                  "vendor_project": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Vendor or project name as published by CISA (mirrors kev_detail.vendor_project).",
                    "title": "Vendor Project"
                  },
                  "vulnerability_name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Short common name when CISA assigns one, e.g. 'Log4Shell', 'ProxyShell'.",
                    "title": "Vulnerability Name"
                  }
                },
                "title": "KevInfo",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "SearchHint": {
                "additionalProperties": true,
                "description": "Footer hint emitted on list responses (cve_search, cve_leading) to point\nLLM agents at the natural drill-down tool. Distinct from PivotHint: there is\nno `input` field because the hint is global to the list — the agent picks a\nresult of interest and passes its ID to the named tool.",
                "properties": {
                  "reason": {
                    "description": "Short rationale explaining what the drill-down tool adds beyond the slim list items (e.g. full description, affected_products, references, exploit/KEV/CWE pivots).",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "const": "cve_lookup",
                    "description": "Drill-down tool to call with any result ID from the list. Constrained to cve_lookup today; expand the Literal as new list endpoints get list-level hints.",
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "reason"
                ],
                "title": "SearchHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/CveSearchResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "cve_leadingOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "exploit_lookup",
          "title": "Exploit Lookup",
          "description": "Search public exploits/PoC for a specific CVE across three sources: (1) GitHub Advisory Database (sources.github.advisories[]), (2) Shodan CVEDB references (sources.shodan_refs.results[] — packetstorm/seclists/vendor URLs cited by Shodan; results capped at SHODAN_REFS_LIMIT default 200, truncated=true when capped, count is the honest upstream total), (3) ExploitDB CSV mirror (exploits[] array, with edb_id + author + verified flag — these are the actual ExploitDB entries). Use to assess if a vulnerability has weaponized exploits in the wild; run after cve_lookup to evaluate real-world risk. When the CVE is also in CISA KEV (kev.in_kev=true on cve_lookup), pair with kev_detail for federal patch deadline; pair with cwe_lookup on cwe_id for the underlying weakness category and mitigations. Response carries next_calls — single cve_lookup pivot for full context (KEV status, CWE chain, CVSS, EPSS); cve_lookup's own next_calls then surface kev_detail and cwe_lookup automatically (this endpoint has no in_kev/cwe_id schema, so blind emission of those pivots is intentionally avoided). Free: 30/hr, Pro: 500/hr. Returns {cve_id, exploits_found, has_public_exploit, sources: {github, shodan_refs: {found, count, truncated, results}}, exploits: [{edb_id, cve_id, date_published, author, type, platform, url, verified, description}], summary, verdict, next_calls}.",
          "inputSchema": {
            "properties": {
              "cve_id": {
                "description": "CVE identifier in format CVE-YYYY-NNNNN (e.g. 'CVE-2024-3094', 'CVE-2023-44487')",
                "title": "Cve Id",
                "type": "string"
              }
            },
            "required": [
              "cve_id"
            ],
            "title": "exploit_lookupArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "Exploit": {
                "properties": {
                  "author": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Author"
                  },
                  "cve_id": {
                    "title": "Cve Id",
                    "type": "string"
                  },
                  "date_published": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Date Published"
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Description"
                  },
                  "edb_id": {
                    "title": "Edb Id",
                    "type": "integer"
                  },
                  "platform": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Platform"
                  },
                  "type": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Type"
                  },
                  "url": {
                    "title": "Url",
                    "type": "string"
                  },
                  "verified": {
                    "default": false,
                    "title": "Verified",
                    "type": "boolean"
                  }
                },
                "required": [
                  "edb_id",
                  "cve_id",
                  "url"
                ],
                "title": "Exploit",
                "type": "object"
              },
              "ExploitResponse": {
                "properties": {
                  "cve_id": {
                    "title": "Cve Id",
                    "type": "string"
                  },
                  "exploits": {
                    "items": {
                      "$ref": "#/$defs/Exploit"
                    },
                    "title": "Exploits",
                    "type": "array"
                  },
                  "exploits_found": {
                    "default": 0,
                    "title": "Exploits Found",
                    "type": "integer"
                  },
                  "has_public_exploit": {
                    "default": false,
                    "title": "Has Public Exploit",
                    "type": "boolean"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "sources": {
                    "$ref": "#/$defs/ExploitSources"
                  },
                  "summary": {
                    "default": "",
                    "title": "Summary",
                    "type": "string"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "cve_id"
                ],
                "title": "ExploitResponse",
                "type": "object"
              },
              "ExploitSources": {
                "properties": {
                  "github": {
                    "$ref": "#/$defs/GithubExploitSource"
                  },
                  "shodan_refs": {
                    "$ref": "#/$defs/ShodanRefSource"
                  }
                },
                "title": "ExploitSources",
                "type": "object"
              },
              "GhsaAdvisory": {
                "properties": {
                  "ghsa_id": {
                    "default": "",
                    "title": "Ghsa Id",
                    "type": "string"
                  },
                  "published_at": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Published At"
                  },
                  "references": {
                    "items": {
                      "type": "string"
                    },
                    "title": "References",
                    "type": "array"
                  },
                  "severity": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Severity"
                  },
                  "summary": {
                    "default": "",
                    "title": "Summary",
                    "type": "string"
                  }
                },
                "title": "GhsaAdvisory",
                "type": "object"
              },
              "GithubExploitSource": {
                "properties": {
                  "advisories": {
                    "items": {
                      "$ref": "#/$defs/GhsaAdvisory"
                    },
                    "title": "Advisories",
                    "type": "array"
                  },
                  "count": {
                    "default": 0,
                    "title": "Count",
                    "type": "integer"
                  },
                  "error": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Error"
                  },
                  "found": {
                    "default": false,
                    "title": "Found",
                    "type": "boolean"
                  }
                },
                "title": "GithubExploitSource",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "ShodanRefItem": {
                "properties": {
                  "description": {
                    "default": "",
                    "title": "Description",
                    "type": "string"
                  },
                  "id": {
                    "default": "",
                    "title": "Id",
                    "type": "string"
                  },
                  "source": {
                    "default": "",
                    "title": "Source",
                    "type": "string"
                  }
                },
                "title": "ShodanRefItem",
                "type": "object"
              },
              "ShodanRefSource": {
                "properties": {
                  "count": {
                    "default": 0,
                    "title": "Count",
                    "type": "integer"
                  },
                  "error": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Error"
                  },
                  "found": {
                    "default": false,
                    "title": "Found",
                    "type": "boolean"
                  },
                  "results": {
                    "items": {
                      "$ref": "#/$defs/ShodanRefItem"
                    },
                    "title": "Results",
                    "type": "array"
                  },
                  "truncated": {
                    "default": false,
                    "title": "Truncated",
                    "type": "boolean"
                  }
                },
                "title": "ShodanRefSource",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/ExploitResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "exploit_lookupOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "bulk_cve_lookup",
          "title": "Bulk CVE Lookup",
          "description": "Batch query multiple CVEs (up to 50 per call, same for Free and Pro): retrieve full CVE details for all in 1 request instead of N. By default each CVE's affected_products is truncated to the first 20 entries (total_products reports honest count) and references to the first 10 (total_references reports honest count); pass include_affected_products=true / include_full_references=true to return full lists. Pass include_reference_tags=true to receive references_full=[{url, tags, source}] per CVE in the batch. Pass include_severity_breakdown=true to receive severity_sources/consensus/disagreement per CVE. Use for dependency audits or bulk vulnerability enrichment; use cve_lookup for single CVE. Each successful item carries next_calls — chain with kev_detail (when kev.in_kev=true), cwe_lookup (when cwe_id is present), or exploit_lookup. Free: 30/hr (1 per item), Pro: 500/hr. Returns {results, total, successful, failed, timed_out, partial, summary}.",
          "inputSchema": {
            "properties": {
              "cve_ids": {
                "description": "List of CVE identifiers in format CVE-YYYY-NNNNN (e.g. ['CVE-2024-3094', 'CVE-2021-44228', 'CVE-2023-44487']). Maximum 50 per request (same cap for Free and Pro).",
                "items": {
                  "type": "string"
                },
                "title": "Cve Ids",
                "type": "array"
              },
              "include_affected_products": {
                "default": false,
                "description": "Return the full affected_products list for each CVE in the batch (default: False, each CVE returns first 20). Set True for bulk dependency audits.",
                "title": "Include Affected Products",
                "type": "boolean"
              },
              "include_full_references": {
                "default": true,
                "description": "Return the full references list for each CVE in the batch (default: True). total_references is always emitted. Set False to truncate each item to first 10 entries when payload-bound.",
                "title": "Include Full References",
                "type": "boolean"
              },
              "include_reference_tags": {
                "default": true,
                "description": "Return structured references_full per CVE in the batch [{url, tags, source}]. Same shape as cve_lookup (default: True). Activates tag-first patch detection per item. Set False for legacy clients.",
                "title": "Include Reference Tags",
                "type": "boolean"
              },
              "include_severity_breakdown": {
                "default": true,
                "description": "Return severity_sources/consensus/disagreement per CVE in batch. Same shape as cve_lookup (default: True). cvss_v2 and cvss_v2_vector are always emitted (additive non-opt-in). Set False to skip if downstream cannot tolerate the extra fields.",
                "title": "Include Severity Breakdown",
                "type": "boolean"
              }
            },
            "required": [
              "cve_ids"
            ],
            "title": "bulk_cve_lookupArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "BulkCveItem": {
                "properties": {
                  "cve": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/CveResponse"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Full CVE record when status='ok'. Same shape as /v1/cve/{cve_id}."
                  },
                  "cve_id": {
                    "description": "Echoed input CVE identifier (upper-cased + de-duplicated).",
                    "title": "Cve Id",
                    "type": "string"
                  },
                  "error": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Human-readable error message when status is 'error' or 'not_found'.",
                    "title": "Error"
                  },
                  "status": {
                    "default": "ok",
                    "description": "Per-item outcome. 'ok' = cve populated; 'not_found' = CVE not in local cve.db (likely reserved or post-cutoff); 'invalid_format' = ID failed CVE-YYYY-NNNN+ regex; 'error' = lookup failed (transient).",
                    "enum": [
                      "ok",
                      "error",
                      "not_found",
                      "invalid_format"
                    ],
                    "title": "Status",
                    "type": "string"
                  }
                },
                "required": [
                  "cve_id"
                ],
                "title": "BulkCveItem",
                "type": "object"
              },
              "BulkCveResponse": {
                "properties": {
                  "failed": {
                    "default": 0,
                    "description": "Count of items with status='error' (transient lookup failure).",
                    "title": "Failed",
                    "type": "integer"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "partial": {
                    "default": false,
                    "description": "True when at least one item failed, timed out, was not_found, or skipped due to rate limit.",
                    "title": "Partial",
                    "type": "boolean"
                  },
                  "processed": {
                    "default": 0,
                    "description": "Count of items actually looked up (== len(results)). Equal to total unless dynamic-budget partial-fill kicked in.",
                    "title": "Processed",
                    "type": "integer"
                  },
                  "results": {
                    "description": "Per-CVE outcome list, preserving input order after upper-case de-duplication.",
                    "items": {
                      "$ref": "#/$defs/BulkCveItem"
                    },
                    "title": "Results",
                    "type": "array"
                  },
                  "skipped_due_to_rate_limit": {
                    "description": "CVE IDs that were not processed because the caller's remaining hourly quota was smaller than the input list. Empty when full budget was available.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Skipped Due To Rate Limit",
                    "type": "array"
                  },
                  "successful": {
                    "default": 0,
                    "description": "Count of items with status='ok'.",
                    "title": "Successful",
                    "type": "integer"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line aggregate summary (e.g. '45/50 CVEs found').",
                    "title": "Summary",
                    "type": "string"
                  },
                  "timed_out": {
                    "default": 0,
                    "description": "Count of items that hit the per-CVE or overall timeout.",
                    "title": "Timed Out",
                    "type": "integer"
                  },
                  "total": {
                    "default": 0,
                    "description": "Total number of unique CVE IDs submitted (== processed + len(skipped_due_to_rate_limit)).",
                    "title": "Total",
                    "type": "integer"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "title": "BulkCveResponse",
                "type": "object"
              },
              "CveResponse": {
                "properties": {
                  "affected_products": {
                    "description": "Affected products: vendor/product entries from NVD and MITRE, plus package entries from GitHub advisories and OSV (vendor = ecosystem such as 'python' or 'nodejs', product = package name). Entries may carry version_start (inclusive), version_end (exclusive) and version_end_including. Truncated to first 20 by default. For GET /v1/cve/{cve_id}, use ?include_affected_products=true; for POST /v1/cves/bulk, set body field \"include_affected_products\": true.",
                    "items": {
                      "additionalProperties": true,
                      "type": "object"
                    },
                    "title": "Affected Products",
                    "type": "array"
                  },
                  "cve_id": {
                    "description": "Canonical CVE identifier, e.g. 'CVE-2021-44228'.",
                    "title": "Cve Id",
                    "type": "string"
                  },
                  "cve_tags": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "NVD cveTags (e.g. 'disputed', 'unsupported-when-assigned', 'exclusively-hosted-service'). When 'disputed' is present, summary is prefixed with [DISPUTED].",
                    "title": "Cve Tags"
                  },
                  "cvss_breakdown": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Per-metric CVSS v3 breakdown (attack_vector, attack_complexity, privileges_required, user_interaction, scope, confidentiality, integrity, availability). Keys present only when parsed from vector string.",
                    "title": "Cvss Breakdown"
                  },
                  "cvss_v2": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CVSS v2.0 base score (0.0-10.0). Always present (additive, non-opt-in); null for CVEs with no v2 metric or for legacy cached rows synced before v1.29.x. Pre-2010 CVEs and select dual-scored entries have v2-only or v2+v3 metrics.",
                    "title": "Cvss V2"
                  },
                  "cvss_v2_vector": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CVSS v2.0 vector string, e.g. 'AV:N/AC:L/Au:N/C:C/I:C/A:C'. Null when cvss_v2 is None.",
                    "title": "Cvss V2 Vector"
                  },
                  "cvss_v3": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CVSS v3.x base score (0.0-10.0). Null if no CVSS data available.",
                    "title": "Cvss V3"
                  },
                  "cwe_id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Primary CWE identifier, e.g. 'CWE-502'. First CWE when multiple are assigned.",
                    "title": "Cwe Id"
                  },
                  "cwes": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "All CWE identifiers assigned to this CVE, Primary first then Secondary. Null on legacy cache rows; cwe_id is always populated when cwes is non-empty.",
                    "title": "Cwes"
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Full vulnerability description sourced from NVD/MITRE/GHSA.",
                    "title": "Description"
                  },
                  "epss": {
                    "$ref": "#/$defs/EpssInfo",
                    "description": "Exploit Prediction Scoring System: score (0.0-1.0 probability) and percentile (0.0-100.0)."
                  },
                  "first_seen_at": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 timestamp when this CVE was first ingested locally.",
                    "title": "First Seen At"
                  },
                  "first_seen_source": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "First source that introduced this CVE into the local DB (for provenance/auditing).",
                    "title": "First Seen Source"
                  },
                  "kev": {
                    "$ref": "#/$defs/KevInfo",
                    "description": "CISA Known Exploited Vulnerabilities catalog: in_kev flag, date_added, plus 10 fields populated when in_kev=true (due_date, required_action, known_ransomware_use, vendor_project, product, vulnerability_name, short_description, notes, cwes, date_removed)."
                  },
                  "modified": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 last-modified timestamp; advances on NVD/MITRE revisions.",
                    "title": "Modified"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "patch_available": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "True when a vendor patch URL was detected in references (allowlisted vendor patterns). Null when enrichment was not requested.",
                    "title": "Patch Available"
                  },
                  "patch_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "First matched vendor patch/advisory URL from an allowlist (GitHub, RedHat, Ubuntu, Debian, Microsoft MSRC, Apple, Fortinet, Linux kernel.org, Cisco). Open-redirect params are filtered. Verify the host before clicking. Null when no match.",
                    "title": "Patch Url"
                  },
                  "published": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 publication timestamp from NVD/MITRE.",
                    "title": "Published"
                  },
                  "references": {
                    "description": "Advisory URLs (vendor bulletins, patch commits, exploit PoCs, analysis writeups). Truncated to first 10 by default. For GET /v1/cve/{cve_id}, use ?include_full_references=true; for POST /v1/cves/bulk, set body field \"include_full_references\": true. Patch URL detection always runs against the full list — patch_url/patch_available are unaffected by the cap.",
                    "items": {
                      "type": "string"
                    },
                    "title": "References",
                    "type": "array"
                  },
                  "references_full": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/ReferenceItem"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Structured references with NVD reference tags + source provenance. Populated only when ?include_reference_tags=true (or body field include_reference_tags=true for bulk_cve_lookup). Default None for backward compat. Same truncation as `references` field — use include_full_references=true for the complete list.",
                    "title": "References Full"
                  },
                  "related_cves": {
                    "anyOf": [
                      {
                        "items": {
                          "additionalProperties": true,
                          "type": "object"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Up to 5 CVEs sharing affected products, ordered by severity DESC. Each item: {cve_id, severity, cvss_v3}. Null when enrichment was not requested.",
                    "title": "Related Cves"
                  },
                  "severity": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CVSS v3 severity label: 'critical', 'high', 'medium', 'low', or 'none'.",
                    "title": "Severity"
                  },
                  "severity_consensus": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Majority-bucket consensus severity computed from severity_sources. On a tie, the highest severity wins (CRITICAL \u003e HIGH \u003e MEDIUM \u003e LOW \u003e NONE). Null when severity_breakdown was not requested or when no source reported a severity.",
                    "title": "Severity Consensus"
                  },
                  "severity_disagreement": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "True when 2+ severity buckets appear across severity_sources entries — counts both across-source disagreement (NVD CRITICAL vs GHSA HIGH) and within-source v2-vs-v3 disagreement (v2 HIGH vs v3 MEDIUM on the same NVD entry). Null when severity_breakdown was not requested.",
                    "title": "Severity Disagreement"
                  },
                  "severity_sources": {
                    "anyOf": [
                      {
                        "items": {
                          "additionalProperties": true,
                          "type": "object"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Multi-source severity breakdown (one entry per source: nvd, mitre, ghsa, osv). Populated only when ?include_severity_breakdown=true (or body field include_severity_breakdown=true for bulk_cve_lookup). Each entry has {source, severity, cvss_v3, cvss_v2}. Use to inspect vendor disputes (e.g. CVE-2023-38545 NVD-CRITICAL vs GHSA-HIGH).",
                    "title": "Severity Sources"
                  },
                  "sources": {
                    "description": "Data sources that wrote the CVE record itself: 'nvd', 'mitre', 'ghsa', 'osv'. EPSS and KEV are tracked separately — see the top-level epss.* and kev.* fields, not this list.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources",
                    "type": "array"
                  },
                  "summary": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Human-readable one-line summary built from severity, CVSS, KEV status, and EPSS.",
                    "title": "Summary"
                  },
                  "total_products": {
                    "default": 0,
                    "description": "Honest count of all affected products in the CVE database. Always present (emitted even when 0); matches len(affected_products) when not truncated.",
                    "title": "Total Products",
                    "type": "integer"
                  },
                  "total_references": {
                    "default": 0,
                    "description": "Honest count of all references in the CVE database. Always present (emitted even when 0); matches len(references) when not truncated.",
                    "title": "Total References",
                    "type": "integer"
                  },
                  "total_references_unique": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Unique-URL upstream count from refs_with_tags (Batch 6A). None for legacy cached rows synced before v1.29.x; populated after the next sync run for all 4 sources (NVD/MITRE/GHSA/OSV).",
                    "title": "Total References Unique"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  },
                  "vulnerability_status": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "NVD lifecycle status: 'Analyzed', 'Modified', 'Awaiting Analysis', 'Deferred', 'Rejected', 'Withdrawn'. Drives verdict.completeness downgrade for Rejected/Withdrawn/Awaiting Analysis.",
                    "title": "Vulnerability Status"
                  }
                },
                "required": [
                  "cve_id"
                ],
                "title": "CveResponse",
                "type": "object"
              },
              "EpssInfo": {
                "properties": {
                  "percentile": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "EPSS percentile rank (0.0-100.0) relative to all scored CVEs; higher = more at-risk.",
                    "title": "Percentile"
                  },
                  "score": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "EPSS probability (0.0-1.0) that this CVE will be exploited in the next 30 days.",
                    "title": "Score"
                  }
                },
                "title": "EpssInfo",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "KevInfo": {
                "properties": {
                  "cwes": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CWE identifiers CISA reports for this CVE (Batch 4A view-ID filtered).",
                    "title": "Cwes"
                  },
                  "date_added": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 date this CVE was added to CISA's Known Exploited Vulnerabilities catalog.",
                    "title": "Date Added"
                  },
                  "date_removed": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 timestamp when CISA removed this CVE from the KEV catalog. Null when CVE is still active in KEV.",
                    "title": "Date Removed"
                  },
                  "due_date": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Federal patch deadline (ISO 8601). Null for entries from before BOD 22-01 (Nov 2021).",
                    "title": "Due Date"
                  },
                  "in_kev": {
                    "default": false,
                    "description": "True when CISA has confirmed this CVE is being actively exploited in the wild.",
                    "title": "In Kev",
                    "type": "boolean"
                  },
                  "known_ransomware_use": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "True when CISA links this CVE to a known ransomware campaign. Null when CVE is not in KEV.",
                    "title": "Known Ransomware Use"
                  },
                  "notes": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Reference URLs published by CISA, separated by '; '.",
                    "title": "Notes"
                  },
                  "product": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Affected product name as published by CISA (mirrors kev_detail.product).",
                    "title": "Product"
                  },
                  "required_action": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CISA-specified remediation action text (mirrors kev_detail.required_action).",
                    "title": "Required Action"
                  },
                  "short_description": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CISA's one-sentence summary (mirrors kev_detail.short_description).",
                    "title": "Short Description"
                  },
                  "vendor_project": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Vendor or project name as published by CISA (mirrors kev_detail.vendor_project).",
                    "title": "Vendor Project"
                  },
                  "vulnerability_name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Short common name when CISA assigns one, e.g. 'Log4Shell', 'ProxyShell'.",
                    "title": "Vulnerability Name"
                  }
                },
                "title": "KevInfo",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "ReferenceItem": {
                "description": "Structured reference object with NVD upstream tags + source provenance.\nEmitted in CveResponse.references_full when ?include_reference_tags=true.",
                "properties": {
                  "source": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Upstream source identifier. NVD: raw 'source' field (UUID/email of the CVE Numbering Authority); MITRE/GHSA/OSV: parser-name normalized to 'mitre'/'ghsa'/'osv'.",
                    "title": "Source"
                  },
                  "tags": {
                    "description": "NVD reference tags: Patch, Vendor Advisory, Mailing List, Exploit, Third Party Advisory, Issue Tracking, Release Notes, Technical Description, US Government Resource, VDB Entry. Empty list for MITRE/GHSA/OSV refs (those upstream feeds don't carry tags).",
                    "items": {
                      "type": "string"
                    },
                    "title": "Tags",
                    "type": "array"
                  },
                  "url": {
                    "description": "Reference URL (advisory, patch commit, exploit PoC, mailing list, etc.)",
                    "title": "Url",
                    "type": "string"
                  }
                },
                "required": [
                  "url"
                ],
                "title": "ReferenceItem",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/BulkCveResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "bulk_cve_lookupOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "kev_detail",
          "title": "KEV Detail",
          "description": "Look up CISA KEV (Known Exploited Vulnerabilities) full record for a CVE. Returns federal patch deadline (due_date), CISA-specified required_action remediation, known ransomware association, vendor/product, the CISA-given common name (e.g. 'Log4Shell'), CISA-reported CWE list, plus lifecycle metadata: date_updated (when CISA last revised the entry), date_removed (set when CISA removed the CVE from the catalog — null while still active), and updated_at (our DB sync freshness). Returns 404 when the CVE is not in the KEV catalog — use cve_lookup for non-KEV CVEs. Best follow-up after cve_lookup or cve_search(kev=true) when an in_kev=true CVE is identified; chain with cwe_lookup on each returned CWE to investigate the weakness category. Free: 30/hr, Pro: 500/hr. Returns {cve_id, vendor_project, product, vulnerability_name, date_added, due_date, required_action, known_ransomware_use, notes, cwes, date_updated, date_removed, updated_at, verdict, next_calls}.",
          "inputSchema": {
            "properties": {
              "cve_id": {
                "description": "CVE identifier in format CVE-YYYY-NNNNN (e.g. 'CVE-2021-44228', 'CVE-2024-3094')",
                "title": "Cve Id",
                "type": "string"
              }
            },
            "required": [
              "cve_id"
            ],
            "title": "kev_detailArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "KevDetailResponse": {
                "additionalProperties": true,
                "description": "Full CISA KEV catalog record for a single CVE.\n\nText fields (required_action, notes, vulnerability_name, short_description) are\nsourced verbatim from CISA's official feed and JSON-encoded — safe for\nJSON consumers, but downstream callers that render into HTML must apply their\nown escaping.\n\n`extra=\"allow\"` is set for forward-compat (Tier 2 audit pattern, Session 171).\nOnly PivotHint objects in `next_calls` and CISA-sourced DB columns appear in extras.",
                "properties": {
                  "cve_id": {
                    "description": "Canonical CVE identifier, e.g. 'CVE-2021-44228'.",
                    "title": "Cve Id",
                    "type": "string"
                  },
                  "cwes": {
                    "description": "CWE identifiers CISA reports for this CVE. May differ from the NVD-assigned CWE. Call cwe_lookup with each entry to fetch weakness category, mitigations, and parent/child chain.",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 100,
                    "title": "Cwes",
                    "type": "array"
                  },
                  "date_added": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 date CISA added this CVE to the Known Exploited Vulnerabilities catalog.",
                    "title": "Date Added"
                  },
                  "date_removed": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 timestamp when CISA removed this CVE from the KEV catalog. Null while still active.",
                    "title": "Date Removed"
                  },
                  "date_updated": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 timestamp from KEV catalog 'dateUpdated' field — when CISA last revised this entry's metadata.",
                    "title": "Date Updated"
                  },
                  "due_date": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Federal patch deadline (ISO 8601). Null for older entries from before CISA enforced remediation due dates (BOD 22-01, Nov 2021).",
                    "title": "Due Date"
                  },
                  "in_kev": {
                    "default": true,
                    "description": "Always True for this endpoint — 404 is returned when the CVE is not in the KEV catalog.",
                    "title": "In Kev",
                    "type": "boolean"
                  },
                  "known_ransomware_use": {
                    "default": false,
                    "description": "True when CISA has linked this CVE to a known ransomware campaign. Derived from CISA's 'knownRansomwareCampaignUse=Known' field.",
                    "title": "Known Ransomware Use",
                    "type": "boolean"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "notes": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Reference URLs published by CISA, separated by '; '.",
                    "title": "Notes"
                  },
                  "product": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Affected product name as published by CISA, e.g. 'Log4j2', 'Exchange Server'.",
                    "title": "Product"
                  },
                  "required_action": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CISA-specified remediation action text, e.g. 'Apply updates per vendor instructions'.",
                    "title": "Required Action"
                  },
                  "short_description": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "CISA's one-sentence summary of the vulnerability.",
                    "title": "Short Description"
                  },
                  "updated_at": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 timestamp of our last KEV sync that touched this row (DB-side freshness, distinct from date_updated).",
                    "title": "Updated At"
                  },
                  "vendor_project": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Vendor or project name as published by CISA, e.g. 'Apache', 'Microsoft', 'Atlassian'.",
                    "title": "Vendor Project"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  },
                  "vulnerability_name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Short common name of the vulnerability when one is assigned, e.g. 'Log4Shell', 'ProxyShell'.",
                    "title": "Vulnerability Name"
                  }
                },
                "required": [
                  "cve_id"
                ],
                "title": "KevDetailResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/KevDetailResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "kev_detailOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "cwe_lookup",
          "title": "CWE Lookup",
          "description": "Look up MITRE CWE (Common Weakness Enumeration) catalog record from research view 1000. Default response is SLIM (first 3 mitigations, first 3 examples; extended_description is null) — pass include='full' for the verbose record (full mitigations + examples lists, populated extended_description). Returns description, abstract type (Pillar/Class/Base/Variant/Compound), status (Stable/Draft/Incomplete/Deprecated), exploit likelihood, recommended mitigations, observed example CVEs, parent_cwe (walk up the hierarchy), child_cwes (drill down to more specific weaknesses), and cve_count (LOWER BOUND — counts only CVEs whose primary CWE matches; CVEs with multiple CWEs may not be counted). Use after cve_lookup or kev_detail to understand the underlying weakness category; chain with cve_search(cwe_id=...) to enumerate all matching CVEs. Returns 404 when the CWE is not in research view 1000. Free: 30/hr, Pro: 500/hr. Returns {cwe_id, name, description, extended_description (null on slim, populated on include='full'), abstract_type, status, likelihood, mitigations (first 3 by default), total_mitigations, examples (first 3 by default), total_examples, parent_cwe, child_cwes, cve_count, updated_at, verdict, next_calls}.",
          "inputSchema": {
            "properties": {
              "cwe_id": {
                "description": "CWE identifier — accepts 'CWE-79', 'cwe-79', or bare '79'. Common values: CWE-79 (XSS), CWE-89 (SQL injection), CWE-78 (command injection), CWE-502 (deserialization), CWE-22 (path traversal), CWE-120 (buffer overflow).",
                "title": "Cwe Id",
                "type": "string"
              },
              "include": {
                "default": "",
                "description": "Detail level. Default ('') returns slim record (first 3 mitigations, first 3 examples; extended_description is null). total_mitigations / total_examples are always honest pre-truncation counts. Pass 'full' to populate extended_description and return the full mitigations + examples lists.",
                "enum": [
                  "",
                  "full"
                ],
                "title": "Include",
                "type": "string"
              }
            },
            "required": [
              "cwe_id"
            ],
            "title": "cwe_lookupArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "CweLookupResponse": {
                "additionalProperties": true,
                "description": "MITRE CWE catalog record (research view 1000).\n\nText fields are sourced verbatim from MITRE's published CSV and JSON-encoded —\nsafe for JSON consumers, but downstream callers that render into HTML must apply\ntheir own escaping. `extra=\"allow\"` is set for forward-compat (Tier 2 audit pattern,\nSession 171).",
                "properties": {
                  "abstract_type": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "MITRE 'Weakness Abstraction' level: 'Pillar' (most abstract), 'Class', 'Base', 'Variant' (most specific), or 'Compound'.",
                    "title": "Abstract Type"
                  },
                  "child_cwes": {
                    "description": "Direct child CWEs in research view 1000 (ParentOf entries). Call cwe_lookup on any entry to traverse down to a more specific weakness.",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 50,
                    "title": "Child Cwes",
                    "type": "array"
                  },
                  "cve_count": {
                    "default": 0,
                    "description": "Number of CVEs in our database whose primary cwe_id equals this CWE. Lower bound — upstream CVEs may map to multiple CWEs but our schema stores only the primary. Use cve_search?cwe=\u003cid\u003e for the actual list.",
                    "title": "Cve Count",
                    "type": "integer"
                  },
                  "cwe_id": {
                    "description": "Canonical CWE identifier, e.g. 'CWE-79', 'CWE-502'.",
                    "title": "Cwe Id",
                    "type": "string"
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "MITRE one-paragraph summary of the weakness.",
                    "title": "Description"
                  },
                  "examples": {
                    "description": "Observed example CVEs as 'CVE-x: description' strings. These are MITRE-curated exemplars, not an exhaustive list — use cve_search?cwe= for the full list.",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 50,
                    "title": "Examples",
                    "type": "array"
                  },
                  "extended_description": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "MITRE's longer-form explanation including consequences and typical exploitation paths.",
                    "title": "Extended Description"
                  },
                  "likelihood": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "MITRE's 'Likelihood of Exploit' rating: 'High', 'Medium', 'Low', or null when unrated.",
                    "title": "Likelihood"
                  },
                  "mitigations": {
                    "description": "Recommended mitigations as 'Phase — Description' strings, parsed from MITRE's 'Potential Mitigations' field (Architecture and Design, Implementation, etc.).",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 30,
                    "title": "Mitigations",
                    "type": "array"
                  },
                  "name": {
                    "description": "Short human-readable weakness name, e.g. 'Improper Neutralization of Input During Web Page Generation'.",
                    "title": "Name",
                    "type": "string"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "parent_cwe": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Direct parent CWE in research view 1000 (Primary ChildOf), e.g. 'CWE-707'. Call cwe_lookup with this value to traverse up the weakness hierarchy.",
                    "title": "Parent Cwe"
                  },
                  "status": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Catalog lifecycle status: 'Stable', 'Draft', 'Incomplete', 'Deprecated', or 'Obsolete'. Prefer Stable when chaining to other tools.",
                    "title": "Status"
                  },
                  "total_examples": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Honest pre-truncation count of example CVEs from MITRE. When the slim default is used, examples is capped to the first 3 — compare to total_examples to decide whether to refetch with include=full.",
                    "title": "Total Examples"
                  },
                  "total_mitigations": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Honest pre-truncation count of mitigation entries from MITRE. When the slim default is used, mitigations is capped to the first 3 — compare to total_mitigations to decide whether to refetch with include=full.",
                    "title": "Total Mitigations"
                  },
                  "updated_at": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO 8601 timestamp of the last sync from MITRE's CSV catalog.",
                    "title": "Updated At"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "cwe_id",
                  "name"
                ],
                "title": "CweLookupResponse",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/CweLookupResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "cwe_lookupOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "atlas_technique_lookup",
          "title": "ATLAS Technique Lookup",
          "description": "Look up a MITRE ATLAS technique — the AI/ML adversarial attack catalog. ATLAS catalogues TTPs targeting machine learning systems: prompt injection, model evasion, training data poisoning, model theft, etc. Roughly 80% of ATLAS techniques are AI/ML-specific (no ATT\u0026CK bridge); 20% mirror an enterprise ATT\u0026CK technique via attack_reference_id — use that to pivot to D3FEND defenses (d3fend_defense_for_attack) and CVE search. Sub-techniques inherit `tactics` from the parent (inherited_tactics=true flag) when ATLAS upstream leaves them empty. Use this tool when the user asks about AI/ML threats, LLM red-teaming, or adversarial ML; for multiple techniques in one call (e.g. drilling into a case study's techniques_used), prefer bulk_atlas_technique_lookup. Returns 404 when the id is not in the synced ATLAS catalog. Free: 30/hr, Pro: 500/hr. Returns {technique_id, name, description, tactics, inherited_tactics, maturity (demonstrated|feasible|realized), attack_reference_id, attack_reference_url, subtechnique_of, created_date, modified_date, next_calls}.",
          "inputSchema": {
            "properties": {
              "technique_id": {
                "description": "MITRE ATLAS technique id, format 'AML.T####' or 'AML.T####.###' for sub-techniques (e.g. 'AML.T0000', 'AML.T0051' LLM Prompt Injection, 'AML.T0000.000').",
                "title": "Technique Id",
                "type": "string"
              }
            },
            "required": [
              "technique_id"
            ],
            "title": "atlas_technique_lookupArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "AtlasTechniqueResponse": {
                "additionalProperties": true,
                "description": "MITRE ATLAS technique record (AI/ML attack catalog).\n\nATLAS catalogues adversarial techniques targeting AI/ML systems (LLM prompt\ninjection, model poisoning, evasion). About 80% of techniques have no ATT\u0026CK\nbridge — ATLAS is the canonical reference for AI/ML-specific TTPs.",
                "properties": {
                  "attack_reference_id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Bridged ATT\u0026CK technique id when ATLAS cites a parallel enterprise TTP, e.g. 'T1596'. About 20% of ATLAS techniques carry an ATT\u0026CK reference; use this to pivot to D3FEND defenses.",
                    "title": "Attack Reference Id"
                  },
                  "attack_reference_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Canonical ATT\u0026CK URL for the bridged technique, e.g. 'https://attack.mitre.org/techniques/T1596/'.",
                    "title": "Attack Reference Url"
                  },
                  "created_date": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO-8601 date the technique was first published in ATLAS.",
                    "title": "Created Date"
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Full technique description as published by MITRE ATLAS. May be multi-paragraph.",
                    "title": "Description"
                  },
                  "inherited_tactics": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "True when `tactics` was inherited from the parent technique (this is a sub-technique). Omitted when tactics are native to the record.",
                    "title": "Inherited Tactics"
                  },
                  "maturity": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "MITRE ATLAS maturity classification: 'demonstrated' (observed in real attacks) or 'feasible' (theoretical).",
                    "title": "Maturity"
                  },
                  "modified_date": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO-8601 date of the most recent ATLAS update for this technique.",
                    "title": "Modified Date"
                  },
                  "name": {
                    "description": "Human-readable technique name, e.g. 'Search Open Technical Databases'.",
                    "title": "Name",
                    "type": "string"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "subtechnique_of": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Parent technique id when this is a sub-technique, e.g. 'AML.T0000' for 'AML.T0000.000'.",
                    "title": "Subtechnique Of"
                  },
                  "tactics": {
                    "description": "ATLAS tactic ids that this technique belongs to, e.g. ['AML.TA0002'] (Reconnaissance). Sub-techniques have empty tactics in upstream ATLAS; we backfill from the parent and set inherited_tactics=true when this happens.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Tactics",
                    "type": "array"
                  },
                  "technique_id": {
                    "description": "Canonical ATLAS technique id, e.g. 'AML.T0000', 'AML.T0000.000'.",
                    "title": "Technique Id",
                    "type": "string"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "technique_id",
                  "name"
                ],
                "title": "AtlasTechniqueResponse",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/AtlasTechniqueResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "atlas_technique_lookupOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "bulk_atlas_technique_lookup",
          "title": "Bulk ATLAS Technique Lookup",
          "description": "Bulk ATLAS technique lookup — retrieve full records for up to 50 techniques in a single request instead of N separate atlas_technique_lookup calls. Designed as the natural follow-up to atlas_case_study_lookup, whose techniques_used array can be passed directly. Each item is the same shape as atlas_technique_lookup, including parent-tactics inheritance for sub-techniques (inherited_tactics=true flag) and per-item next_calls (D3FEND bridge when attack_reference_id present, sibling-technique search by tactic, parent lookup for sub-techniques). Free: 30/hr (1 per item), Pro: 500/hr. Returns {results [{technique_id, status (ok|not_found|invalid_format), technique, error}], total, successful, failed, partial, summary}.",
          "inputSchema": {
            "properties": {
              "technique_ids": {
                "description": "List of MITRE ATLAS technique ids in format 'AML.T####' or 'AML.T####.###' (e.g. ['AML.T0051', 'AML.T0043', 'AML.T0000.000']). Up to 50 per call. Case-insensitive; normalized + de-duplicated server-side. Each id counts as 1 request toward the rate limit.",
                "items": {
                  "type": "string"
                },
                "maxItems": 50,
                "title": "Technique Ids",
                "type": "array"
              }
            },
            "required": [
              "technique_ids"
            ],
            "title": "bulk_atlas_technique_lookupArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "AtlasTechniqueResponse": {
                "additionalProperties": true,
                "description": "MITRE ATLAS technique record (AI/ML attack catalog).\n\nATLAS catalogues adversarial techniques targeting AI/ML systems (LLM prompt\ninjection, model poisoning, evasion). About 80% of techniques have no ATT\u0026CK\nbridge — ATLAS is the canonical reference for AI/ML-specific TTPs.",
                "properties": {
                  "attack_reference_id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Bridged ATT\u0026CK technique id when ATLAS cites a parallel enterprise TTP, e.g. 'T1596'. About 20% of ATLAS techniques carry an ATT\u0026CK reference; use this to pivot to D3FEND defenses.",
                    "title": "Attack Reference Id"
                  },
                  "attack_reference_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Canonical ATT\u0026CK URL for the bridged technique, e.g. 'https://attack.mitre.org/techniques/T1596/'.",
                    "title": "Attack Reference Url"
                  },
                  "created_date": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO-8601 date the technique was first published in ATLAS.",
                    "title": "Created Date"
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Full technique description as published by MITRE ATLAS. May be multi-paragraph.",
                    "title": "Description"
                  },
                  "inherited_tactics": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "True when `tactics` was inherited from the parent technique (this is a sub-technique). Omitted when tactics are native to the record.",
                    "title": "Inherited Tactics"
                  },
                  "maturity": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "MITRE ATLAS maturity classification: 'demonstrated' (observed in real attacks) or 'feasible' (theoretical).",
                    "title": "Maturity"
                  },
                  "modified_date": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO-8601 date of the most recent ATLAS update for this technique.",
                    "title": "Modified Date"
                  },
                  "name": {
                    "description": "Human-readable technique name, e.g. 'Search Open Technical Databases'.",
                    "title": "Name",
                    "type": "string"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "subtechnique_of": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Parent technique id when this is a sub-technique, e.g. 'AML.T0000' for 'AML.T0000.000'.",
                    "title": "Subtechnique Of"
                  },
                  "tactics": {
                    "description": "ATLAS tactic ids that this technique belongs to, e.g. ['AML.TA0002'] (Reconnaissance). Sub-techniques have empty tactics in upstream ATLAS; we backfill from the parent and set inherited_tactics=true when this happens.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Tactics",
                    "type": "array"
                  },
                  "technique_id": {
                    "description": "Canonical ATLAS technique id, e.g. 'AML.T0000', 'AML.T0000.000'.",
                    "title": "Technique Id",
                    "type": "string"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "technique_id",
                  "name"
                ],
                "title": "AtlasTechniqueResponse",
                "type": "object"
              },
              "BulkAtlasTechniqueItem": {
                "additionalProperties": true,
                "description": "One ATLAS technique outcome inside a bulk_atlas_technique_lookup response.",
                "properties": {
                  "error": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Human-readable error message when status is 'not_found' or 'invalid_format'.",
                    "title": "Error"
                  },
                  "status": {
                    "default": "ok",
                    "description": "Per-item outcome (v1.21.0+ unified across bulk_cve/bulk_ioc/bulk_atlas): 'ok' = technique populated; 'not_found' = id not in synced ATLAS catalog; 'invalid_format' = id failed AML.T#### / AML.T####.### regex; 'error' = transient lookup failure (DB I/O exception) — rare, server-side fallback only.",
                    "enum": [
                      "ok",
                      "error",
                      "not_found",
                      "invalid_format"
                    ],
                    "title": "Status",
                    "type": "string"
                  },
                  "technique": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/AtlasTechniqueResponse"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Full ATLAS technique record when status='ok'. Same shape as /v1/atlas/{technique_id}."
                  },
                  "technique_id": {
                    "description": "Echoed input ATLAS technique id (upper-cased + de-duplicated).",
                    "title": "Technique Id",
                    "type": "string"
                  }
                },
                "required": [
                  "technique_id"
                ],
                "title": "BulkAtlasTechniqueItem",
                "type": "object"
              },
              "BulkAtlasTechniqueResponse": {
                "additionalProperties": true,
                "properties": {
                  "failed": {
                    "default": 0,
                    "description": "Count of items with status='not_found' or 'invalid_format'.",
                    "title": "Failed",
                    "type": "integer"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "partial": {
                    "default": false,
                    "description": "True when at least one item was not_found, invalid_format, or skipped due to rate limit.",
                    "title": "Partial",
                    "type": "boolean"
                  },
                  "processed": {
                    "default": 0,
                    "description": "Count of items actually looked up (== len(results)). Equal to total unless dynamic-budget partial-fill kicked in.",
                    "title": "Processed",
                    "type": "integer"
                  },
                  "results": {
                    "description": "Per-technique outcome list, preserving input order after upper-case de-duplication.",
                    "items": {
                      "$ref": "#/$defs/BulkAtlasTechniqueItem"
                    },
                    "title": "Results",
                    "type": "array"
                  },
                  "skipped_due_to_rate_limit": {
                    "description": "Technique IDs that were not processed because the caller's remaining hourly quota was smaller than the input list. Empty when full budget was available.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Skipped Due To Rate Limit",
                    "type": "array"
                  },
                  "successful": {
                    "default": 0,
                    "description": "Count of items with status='ok'.",
                    "title": "Successful",
                    "type": "integer"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line aggregate summary (e.g. '4/5 techniques found').",
                    "title": "Summary",
                    "type": "string"
                  },
                  "total": {
                    "default": 0,
                    "description": "Total number of unique technique IDs submitted (== processed + len(skipped_due_to_rate_limit)).",
                    "title": "Total",
                    "type": "integer"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "title": "BulkAtlasTechniqueResponse",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/BulkAtlasTechniqueResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "bulk_atlas_technique_lookupOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "atlas_technique_search",
          "title": "ATLAS Technique Search",
          "description": "Search the MITRE ATLAS catalog of AI/ML attack techniques by keyword, tactic, or maturity. Default response is SLIM (description truncated to 240 chars per row); pass include='full' for the verbose record. Pass exclude_id when chaining from atlas_technique_lookup to skip self in sibling-tactic searches. Use this to discover techniques matching a threat-model question, e.g. 'what techniques target LLM serving infrastructure?'. Drill into atlas_technique_lookup with any returned technique_id for the full description, ATT\u0026CK bridge, and pivot hints. For broader cross-referencing: when a result has attack_reference_id, that bridges to D3FEND mitigations via d3fend_defense_for_attack. Free: 30/hr, Pro: 500/hr. Returns {query (echoed filters), total, results [{technique_id, name, description (truncated by default), tactics, inherited_tactics, maturity, attack_reference_id, subtechnique_of}], next_calls}.",
          "inputSchema": {
            "properties": {
              "exclude_id": {
                "default": "",
                "description": "Optional ATLAS technique id to exclude from results, format 'AML.T####' or 'AML.T####.###'. Useful when chaining from atlas_technique_lookup to fetch siblings without echoing self in the same-tactic search.",
                "title": "Exclude Id",
                "type": "string"
              },
              "include": {
                "default": "",
                "description": "Detail level. Default ('') returns slim records (description truncated to 240 chars; drill via atlas_technique_lookup for full text). Pass 'full' for full description on every row — large catalogs (167 techniques) can return ~100KB at full.",
                "enum": [
                  "",
                  "full"
                ],
                "title": "Include",
                "type": "string"
              },
              "keyword": {
                "default": "",
                "description": "Substring match against technique name + description (case-insensitive). Min 2 chars. Example: 'prompt injection', 'model evasion', 'poisoning'. Omit to list all.",
                "title": "Keyword",
                "type": "string"
              },
              "limit": {
                "default": 50,
                "description": "Max results to return. Range: 1-200.",
                "maximum": 200,
                "minimum": 1,
                "title": "Limit",
                "type": "integer"
              },
              "maturity": {
                "default": "",
                "description": "Filter by maturity: 'demonstrated' (observed in real attacks), 'feasible' (theoretical), or 'realized' (newer ATLAS classification, treat similar to demonstrated). Omit for all.",
                "enum": [
                  "",
                  "demonstrated",
                  "feasible",
                  "realized"
                ],
                "title": "Maturity",
                "type": "string"
              },
              "tactic": {
                "default": "",
                "description": "Filter by ATLAS tactic id, format 'AML.TA####'. Examples: 'AML.TA0002' (Reconnaissance), 'AML.TA0007' (ML Attack Staging). Omit for all tactics.",
                "title": "Tactic",
                "type": "string"
              }
            },
            "title": "atlas_technique_searchArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "AtlasTechniqueListItem": {
                "additionalProperties": true,
                "description": "Slim ATLAS technique row for search results.",
                "properties": {
                  "attack_reference_id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Bridged ATT\u0026CK id or null.",
                    "title": "Attack Reference Id"
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Full description; consider drilling into atlas_technique_lookup for context.",
                    "title": "Description"
                  },
                  "inherited_tactics": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "True when tactics were inherited from the parent technique. Omitted when native.",
                    "title": "Inherited Tactics"
                  },
                  "maturity": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "'demonstrated' or 'feasible'.",
                    "title": "Maturity"
                  },
                  "name": {
                    "description": "Human-readable technique name.",
                    "title": "Name",
                    "type": "string"
                  },
                  "subtechnique_of": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Parent technique id when applicable.",
                    "title": "Subtechnique Of"
                  },
                  "tactics": {
                    "description": "ATLAS tactic ids covering this technique. Sub-techniques inherit from parent; see inherited_tactics.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Tactics",
                    "type": "array"
                  },
                  "technique_id": {
                    "description": "Canonical ATLAS technique id.",
                    "title": "Technique Id",
                    "type": "string"
                  }
                },
                "required": [
                  "technique_id",
                  "name"
                ],
                "title": "AtlasTechniqueListItem",
                "type": "object"
              },
              "AtlasTechniqueSearchResponse": {
                "additionalProperties": true,
                "description": "List response for atlas_technique_search.",
                "properties": {
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "query": {
                    "additionalProperties": true,
                    "description": "Echo of the input filters (keyword/tactic/maturity).",
                    "title": "Query",
                    "type": "object"
                  },
                  "results": {
                    "description": "Matching ATLAS techniques.",
                    "items": {
                      "$ref": "#/$defs/AtlasTechniqueListItem"
                    },
                    "title": "Results",
                    "type": "array"
                  },
                  "total": {
                    "default": 0,
                    "description": "Number of techniques returned (capped at 200).",
                    "title": "Total",
                    "type": "integer"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "title": "AtlasTechniqueSearchResponse",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/AtlasTechniqueSearchResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "atlas_technique_searchOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "atlas_case_study_lookup",
          "title": "ATLAS Case Study Lookup",
          "description": "Look up a MITRE ATLAS case study — a documented real-world AI/ML attack incident. Each case study links a sequence of ATLAS techniques (techniques_used) to the incident. Default response is SLIM (description truncated to 240 chars); pass include='full' for the verbose narrative. Use this after atlas_technique_search to find which incidents have exercised a given technique. Drill into the full techniques_used array via bulk_atlas_technique_lookup in a single call (next_calls emits exactly that hint). Returns 404 when the id is not in the synced catalog. Free: 30/hr, Pro: 500/hr. Returns {case_study_id, name, description, techniques_used, next_calls}.",
          "inputSchema": {
            "properties": {
              "case_study_id": {
                "description": "MITRE ATLAS case study id, format 'AML.CS####' (e.g. 'AML.CS0000', 'AML.CS0014').",
                "title": "Case Study Id",
                "type": "string"
              },
              "include": {
                "default": "",
                "description": "Detail level. Default (omit/empty) returns slim (description truncated to 240 chars). Pass 'full' for the verbose narrative — case-study descriptions can run 1-3KB.",
                "enum": [
                  "",
                  "full"
                ],
                "title": "Include",
                "type": "string"
              }
            },
            "required": [
              "case_study_id"
            ],
            "title": "atlas_case_study_lookupArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "AtlasCaseStudyResponse": {
                "additionalProperties": true,
                "description": "MITRE ATLAS case study record — real-world AI/ML incidents.",
                "properties": {
                  "case_study_id": {
                    "description": "Canonical ATLAS case study id, e.g. 'AML.CS0000'.",
                    "title": "Case Study Id",
                    "type": "string"
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Narrative summary of the incident as published by MITRE ATLAS.",
                    "title": "Description"
                  },
                  "name": {
                    "description": "Short title of the incident, e.g. 'Evasion of Deep Learning Detector'.",
                    "title": "Name",
                    "type": "string"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "techniques_used": {
                    "description": "ATLAS technique ids used in this incident's procedure, in observed order.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Techniques Used",
                    "type": "array"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "case_study_id",
                  "name"
                ],
                "title": "AtlasCaseStudyResponse",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/AtlasCaseStudyResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "atlas_case_study_lookupOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "atlas_case_study_search",
          "title": "ATLAS Case Study Search",
          "description": "Search ATLAS case studies (real-world AI/ML attack incidents) by keyword or referenced technique. Default response is SLIM (description truncated to 240 chars per row); pass include='full' for the verbose summary. Useful when the user has a technique in hand and wants to see incidents that exercised it. Drill via atlas_case_study_lookup for the full procedure list. Free: 30/hr, Pro: 500/hr. Returns {query, total, results [{case_study_id, name, description (truncated by default), techniques_used}], next_calls}.",
          "inputSchema": {
            "properties": {
              "include": {
                "default": "",
                "description": "Detail level. Default ('') returns slim records (description truncated to 240 chars). Pass 'full' for full description on every row.",
                "enum": [
                  "",
                  "full"
                ],
                "title": "Include",
                "type": "string"
              },
              "keyword": {
                "default": "",
                "description": "Substring match against case study name + description (case-insensitive). Min 2 chars. Example: 'evasion', 'data poisoning'. Omit to list all.",
                "title": "Keyword",
                "type": "string"
              },
              "limit": {
                "default": 50,
                "description": "Max results to return. Range: 1-200.",
                "maximum": 200,
                "minimum": 1,
                "title": "Limit",
                "type": "integer"
              },
              "technique_id": {
                "default": "",
                "description": "Filter to case studies that include this ATLAS technique id, format 'AML.T####' or 'AML.T####.###' (e.g. 'AML.T0051'). Omit for any technique.",
                "title": "Technique Id",
                "type": "string"
              }
            },
            "title": "atlas_case_study_searchArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "AtlasCaseStudyResponse": {
                "additionalProperties": true,
                "description": "MITRE ATLAS case study record — real-world AI/ML incidents.",
                "properties": {
                  "case_study_id": {
                    "description": "Canonical ATLAS case study id, e.g. 'AML.CS0000'.",
                    "title": "Case Study Id",
                    "type": "string"
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Narrative summary of the incident as published by MITRE ATLAS.",
                    "title": "Description"
                  },
                  "name": {
                    "description": "Short title of the incident, e.g. 'Evasion of Deep Learning Detector'.",
                    "title": "Name",
                    "type": "string"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "techniques_used": {
                    "description": "ATLAS technique ids used in this incident's procedure, in observed order.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Techniques Used",
                    "type": "array"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "case_study_id",
                  "name"
                ],
                "title": "AtlasCaseStudyResponse",
                "type": "object"
              },
              "AtlasCaseStudySearchResponse": {
                "additionalProperties": true,
                "description": "List response for atlas_case_study_search.",
                "properties": {
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "query": {
                    "additionalProperties": true,
                    "description": "Echo of input filters (keyword/technique_id).",
                    "title": "Query",
                    "type": "object"
                  },
                  "results": {
                    "description": "Matching case studies.",
                    "items": {
                      "$ref": "#/$defs/AtlasCaseStudyResponse"
                    },
                    "title": "Results",
                    "type": "array"
                  },
                  "total": {
                    "default": 0,
                    "description": "Number of case studies returned (capped at 200).",
                    "title": "Total",
                    "type": "integer"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "title": "AtlasCaseStudySearchResponse",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/AtlasCaseStudySearchResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "atlas_case_study_searchOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "d3fend_defense_lookup",
          "title": "D3FEND Defense Lookup",
          "description": "Look up a MITRE D3FEND defense technique. D3FEND is the canonical defensive counterpart to ATT\u0026CK — each defense is classified into one of 7 tactics (Model/Harden/Detect/Isolate/Deceive/Evict/Restore) and may target a specific digital artifact (e.g. 'Access Token'). Response includes attack_techniques: the list of ATT\u0026CK T-codes this defense mitigates. Use after d3fend_defense_search for the full record + ATT\u0026CK chain. Returns 404 when the slug is not in the synced D3FEND catalog. Free: 30/hr, Pro: 500/hr. Returns {defense_id, label, uri, parent_label, description, tactic, artifact, attack_techniques, next_calls}.",
          "inputSchema": {
            "properties": {
              "defense_id": {
                "description": "D3FEND defense slug from the ontology URI fragment (CamelCase), e.g. 'TokenBinding', 'FileHashing', 'CertificatePinning'.",
                "title": "Defense Id",
                "type": "string"
              }
            },
            "required": [
              "defense_id"
            ],
            "title": "d3fend_defense_lookupArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "D3fendDefenseResponse": {
                "additionalProperties": true,
                "description": "MITRE D3FEND defense technique record.\n\nD3FEND catalogues defensive techniques against ATT\u0026CK TTPs. Each defense is\nclassified into one of 7 tactics (Model, Harden, Detect, Isolate, Deceive,\nEvict, Restore) and may target a specific digital artifact (e.g. 'Access\nToken', 'Process'). Use attack_techniques to see which ATT\u0026CK T-codes this\ndefense mitigates.",
                "properties": {
                  "artifact": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Digital artifact the defense targets, e.g. 'Access Token', 'File', 'Process'.",
                    "title": "Artifact"
                  },
                  "attack_techniques": {
                    "description": "ATT\u0026CK T-codes this defense mitigates, e.g. ['T1550.001', 'T1539']. Drill via cve_search or d3fend_defense_for_attack to bridge.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Attack Techniques",
                    "type": "array"
                  },
                  "defense_id": {
                    "description": "Slug derived from the D3FEND ontology URI fragment, e.g. 'TokenBinding', 'FileHashing'.",
                    "title": "Defense Id",
                    "type": "string"
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "D3FEND-published description of the defense (may be null in current sync).",
                    "title": "Description"
                  },
                  "label": {
                    "description": "Human-readable defense name, e.g. 'Token Binding', 'File Hashing'.",
                    "title": "Label",
                    "type": "string"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "parent_label": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Parent defense category, e.g. 'Credential Hardening' for 'Token Binding'.",
                    "title": "Parent Label"
                  },
                  "tactic": {
                    "description": "One of seven D3FEND tactics: Model, Harden, Detect, Isolate, Deceive, Evict, Restore.",
                    "title": "Tactic",
                    "type": "string"
                  },
                  "uri": {
                    "description": "Full D3FEND ontology URI, e.g. 'http://d3fend.mitre.org/ontologies/d3fend.owl#TokenBinding'.",
                    "title": "Uri",
                    "type": "string"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "defense_id",
                  "label",
                  "uri",
                  "tactic"
                ],
                "title": "D3fendDefenseResponse",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/D3fendDefenseResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "d3fend_defense_lookupOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "d3fend_defense_search",
          "title": "D3FEND Defense Search",
          "description": "Search the MITRE D3FEND catalog of defensive techniques by keyword, tactic, or targeted artifact. Default response is SLIM (drops `uri` from each row — saves ~60 chars/row, ~30% on popular drills); pass include='full' for the verbose record. Pass exclude_id when chaining from d3fend_defense_lookup to skip self in sibling-artifact searches. Use to discover defenses applicable to a given threat model — e.g. 'what defenses harden access tokens?' (tactic=Harden + artifact='Access Token'). Drill into d3fend_defense_lookup with any returned defense_id for the ATT\u0026CK technique mappings. Free: 30/hr, Pro: 500/hr. Returns {query, total, results [{defense_id, label, uri (only when include=full), parent_label, tactic, artifact}], next_calls}.",
          "inputSchema": {
            "properties": {
              "artifact": {
                "default": "",
                "description": "Filter by exact targeted digital artifact (case-insensitive), e.g. 'Access Token', 'File', 'Process'. Omit for any artifact.",
                "title": "Artifact",
                "type": "string"
              },
              "exclude_id": {
                "default": "",
                "description": "Optional D3FEND defense slug (CamelCase, e.g. 'TokenBinding') to omit from results. Useful when chaining from d3fend_defense_lookup so the originating defense is not echoed back in its own siblings list. Omit when not needed.",
                "title": "Exclude Id",
                "type": "string"
              },
              "include": {
                "default": "",
                "description": "Detail level. Default (omit/empty) returns slim rows (drops the deterministic ontology `uri` field, ~60 chars/row saved). Pass 'full' to get `uri` back on every row. The slug `defense_id` is always returned and uniquely identifies the defense.",
                "enum": [
                  "",
                  "full"
                ],
                "title": "Include",
                "type": "string"
              },
              "keyword": {
                "default": "",
                "description": "Substring match against defense label, description, or parent_label (case-insensitive). Min 2 chars. Example: 'token', 'hashing', 'sandbox'. Omit to list all.",
                "title": "Keyword",
                "type": "string"
              },
              "limit": {
                "default": 50,
                "description": "Max results to return. Range: 1-200.",
                "maximum": 200,
                "minimum": 1,
                "title": "Limit",
                "type": "integer"
              },
              "tactic": {
                "default": "",
                "description": "Filter by D3FEND tactic. One of: Model, Harden, Detect, Isolate, Deceive, Evict, Restore. Omit for all tactics.",
                "enum": [
                  "",
                  "Model",
                  "Harden",
                  "Detect",
                  "Isolate",
                  "Deceive",
                  "Evict",
                  "Restore"
                ],
                "title": "Tactic",
                "type": "string"
              }
            },
            "title": "d3fend_defense_searchArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "D3fendDefenseListItem": {
                "additionalProperties": true,
                "description": "Slim D3FEND defense row for search results (no attack_techniques list).",
                "properties": {
                  "artifact": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Targeted digital artifact.",
                    "title": "Artifact"
                  },
                  "defense_id": {
                    "description": "D3FEND defense slug.",
                    "title": "Defense Id",
                    "type": "string"
                  },
                  "label": {
                    "description": "Human-readable defense name.",
                    "title": "Label",
                    "type": "string"
                  },
                  "parent_label": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Parent defense category.",
                    "title": "Parent Label"
                  },
                  "tactic": {
                    "description": "D3FEND tactic.",
                    "title": "Tactic",
                    "type": "string"
                  },
                  "uri": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Full D3FEND ontology URI. Omitted in slim default; pass include=full to get it back.",
                    "title": "Uri"
                  }
                },
                "required": [
                  "defense_id",
                  "label",
                  "tactic"
                ],
                "title": "D3fendDefenseListItem",
                "type": "object"
              },
              "D3fendDefenseSearchResponse": {
                "additionalProperties": true,
                "description": "List response for d3fend_defense_search.",
                "properties": {
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "query": {
                    "additionalProperties": true,
                    "description": "Echo of input filters (keyword/tactic/artifact).",
                    "title": "Query",
                    "type": "object"
                  },
                  "results": {
                    "description": "Matching D3FEND defenses.",
                    "items": {
                      "$ref": "#/$defs/D3fendDefenseListItem"
                    },
                    "title": "Results",
                    "type": "array"
                  },
                  "total": {
                    "default": 0,
                    "description": "Number of defenses returned (capped at 200).",
                    "title": "Total",
                    "type": "integer"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "title": "D3fendDefenseSearchResponse",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/D3fendDefenseSearchResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "d3fend_defense_searchOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "d3fend_defense_for_attack",
          "title": "D3FEND Defense for Attack",
          "description": "Reverse lookup: given an ATT\u0026CK T-code, return D3FEND defenses that mitigate it. This is the bridge from offensive intelligence (ATT\u0026CK / ATLAS / CVE) to defensive playbook. Pair with cve_lookup or atlas_technique_lookup output — when those carry an ATT\u0026CK id, call this tool to surface the mitigations. `defenses` is capped at `limit` (default 30) for token efficiency; `total` is the honest pre-truncation count and `truncated=true` flags when the cap was hit. `coverage_by_tactic` always aggregates the FULL set, not the slice. Default response is SLIM (drops `uri` from each row); pass include='full' for the verbose record. Pass exclude_id when drilling from d3fend_defense_lookup to skip self in the 'see also' list. Returns 200 with empty defenses list when the T-code has no D3FEND mapping (the gap is itself a signal). Free: 30/hr, Pro: 500/hr. Returns {attack_technique_id, total, truncated, defenses [{defense_id, label, uri (only when include=full), parent_label, tactic, artifact, attack_label, attack_tactic}], coverage_by_tactic, next_calls}.",
          "inputSchema": {
            "properties": {
              "attack_technique_id": {
                "description": "ATT\u0026CK technique id matching 'T####' or 'T####.###' (e.g. 'T1059', 'T1550.001'). Use this to bridge from CVE/ATLAS findings to D3FEND mitigations.",
                "title": "Attack Technique Id",
                "type": "string"
              },
              "exclude_id": {
                "default": "",
                "description": "Optional D3FEND defense slug to omit from the defenses list. Used when chaining from d3fend_defense_lookup so the originating defense is not echoed back in its own 'see also' results.",
                "title": "Exclude Id",
                "type": "string"
              },
              "include": {
                "default": "",
                "description": "Detail level. Default (omit/empty) returns slim rows (drops the deterministic ontology `uri` — popular T-codes with 15+ defenses save ~900 chars). Pass 'full' to get `uri` back on every row.",
                "enum": [
                  "",
                  "full"
                ],
                "title": "Include",
                "type": "string"
              },
              "limit": {
                "default": 30,
                "description": "Cap on `defenses` array length. Default 30; popular T-codes (T1059, T1078) map to 30-50+ defenses. `total` and `coverage_by_tactic` always reflect the honest pre-truncation count.",
                "maximum": 200,
                "minimum": 1,
                "title": "Limit",
                "type": "integer"
              }
            },
            "required": [
              "attack_technique_id"
            ],
            "title": "d3fend_defense_for_attackArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "D3fendDefenseForAttackItem": {
                "additionalProperties": true,
                "description": "One defense entry in a reverse-lookup result.",
                "properties": {
                  "artifact": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Targeted digital artifact.",
                    "title": "Artifact"
                  },
                  "attack_label": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Original ATT\u0026CK technique label as published by MITRE.",
                    "title": "Attack Label"
                  },
                  "attack_tactic": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ATT\u0026CK tactic the technique sits under.",
                    "title": "Attack Tactic"
                  },
                  "defense_id": {
                    "description": "D3FEND defense slug.",
                    "title": "Defense Id",
                    "type": "string"
                  },
                  "label": {
                    "description": "Human-readable defense name.",
                    "title": "Label",
                    "type": "string"
                  },
                  "parent_label": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Parent defense category.",
                    "title": "Parent Label"
                  },
                  "tactic": {
                    "description": "D3FEND tactic — one of Model/Harden/Detect/Isolate/Deceive/Evict/Restore.",
                    "title": "Tactic",
                    "type": "string"
                  },
                  "uri": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Full D3FEND ontology URI. Omitted in slim default; pass include=full to get it back.",
                    "title": "Uri"
                  }
                },
                "required": [
                  "defense_id",
                  "label",
                  "tactic"
                ],
                "title": "D3fendDefenseForAttackItem",
                "type": "object"
              },
              "D3fendForAttackResponse": {
                "additionalProperties": true,
                "description": "Reverse lookup response: given an ATT\u0026CK T-code, list mitigating D3FEND defenses.",
                "properties": {
                  "attack_technique_id": {
                    "description": "The ATT\u0026CK T-code that was queried, e.g. 'T1059'.",
                    "title": "Attack Technique Id",
                    "type": "string"
                  },
                  "coverage_by_tactic": {
                    "additionalProperties": {
                      "type": "integer"
                    },
                    "description": "Defense count per D3FEND tactic for this single technique, e.g. {'Harden': 3, 'Detect': 5}.",
                    "title": "Coverage By Tactic",
                    "type": "object"
                  },
                  "defenses": {
                    "description": "D3FEND defenses mapped to this ATT\u0026CK technique (capped at request `limit`, default 30).",
                    "items": {
                      "$ref": "#/$defs/D3fendDefenseForAttackItem"
                    },
                    "title": "Defenses",
                    "type": "array"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "total": {
                    "default": 0,
                    "description": "Honest pre-truncation count of D3FEND defenses that mitigate this technique.",
                    "title": "Total",
                    "type": "integer"
                  },
                  "truncated": {
                    "default": false,
                    "description": "True when defenses[] was capped at `limit`. Inspect `total` for the full count and re-call with a higher `limit` if needed.",
                    "title": "Truncated",
                    "type": "boolean"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "attack_technique_id"
                ],
                "title": "D3fendForAttackResponse",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/D3fendForAttackResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "d3fend_defense_for_attackOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "d3fend_attack_coverage",
          "title": "D3FEND Attack Coverage",
          "description": "Batch coverage breakdown: given a list of ATT\u0026CK T-codes, return distinct defense counts per D3FEND tactic + identify which techniques have NO D3FEND mapping (undefended_techniques). Use to assess the defensive posture of an entire attack campaign or threat model in one call. defended_techniques is the subset with at least one D3FEND defense; undefended_techniques are gaps worth flagging. Pair with cve_search per gap to identify exploit availability. Free: 30/hr, Pro: 500/hr. Returns {queried_techniques, coverage_by_tactic, defended_techniques, undefended_techniques, next_calls}.",
          "inputSchema": {
            "properties": {
              "attack_technique_ids": {
                "description": "List of ATT\u0026CK technique ids (T#### or T####.###) to assess. Capped at 500 — extra entries are dropped server-side. Example: ['T1059', 'T1550.001', 'T1190', 'T9999'].",
                "items": {
                  "type": "string"
                },
                "maxItems": 500,
                "title": "Attack Technique Ids",
                "type": "array"
              }
            },
            "required": [
              "attack_technique_ids"
            ],
            "title": "d3fend_attack_coverageArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "D3fendCoverageResponse": {
                "additionalProperties": true,
                "description": "Batch coverage breakdown for a list of ATT\u0026CK T-codes.",
                "properties": {
                  "coverage_by_tactic": {
                    "additionalProperties": {
                      "type": "integer"
                    },
                    "description": "Distinct D3FEND defenses per tactic across all queried techniques. Keys are tactics (Harden/Detect/Isolate/...), values are counts.",
                    "title": "Coverage By Tactic",
                    "type": "object"
                  },
                  "defended_techniques": {
                    "description": "Subset of queried techniques that have at least one D3FEND defense.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Defended Techniques",
                    "type": "array"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "queried_techniques": {
                    "description": "The ATT\u0026CK T-codes the caller queried (truncated to 500 if larger).",
                    "items": {
                      "type": "string"
                    },
                    "title": "Queried Techniques",
                    "type": "array"
                  },
                  "undefended_techniques": {
                    "description": "Subset of queried techniques with NO D3FEND mapping — gap candidates.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Undefended Techniques",
                    "type": "array"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "title": "D3fendCoverageResponse",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/D3fendCoverageResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "d3fend_attack_coverageOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "sigma_rule_lookup",
          "title": "Sigma Rule Lookup",
          "description": "Look up a single Sigma detection rule by UUID from the SigmaHQ corpus (~3,200 rules, refreshed daily at 02:00 UTC). Returns the full rule with title, description, status (stable/test/experimental/deprecated/unsupported), level (informational/low/medium/high/critical), logsource (product/category/service), detection logic, tags (including attack.t#### ATT\u0026CK technique refs and cve.YYYY-#### CVE refs), author, references, and modification date. Use to fetch a known rule for context (e.g., a SIEM detection that fired) or to inspect a rule discovered via REST sigma_rule_search. When a rule tags an ATT\u0026CK technique or CVE, the response next_calls surfaces atlas_technique_lookup / cve_lookup as natural follow-ups. Free: 30/hr, Pro: 500/hr. Returns {rule, next_calls}.",
          "inputSchema": {
            "properties": {
              "rule_id": {
                "description": "Sigma rule UUID (RFC 4122, 36 chars, hyphenated). Example: '195e1b9d-bfc2-4ffa-ab4e-35aef69815f8'. Obtained from the REST sigma_rule_search endpoint or external SIEM correlation.",
                "maxLength": 50,
                "title": "Rule Id",
                "type": "string"
              }
            },
            "required": [
              "rule_id"
            ],
            "title": "sigma_rule_lookupArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "SigmaDetection": {
                "description": "Nested detection block — preserve raw YAML structure.",
                "properties": {
                  "condition": {
                    "default": "unknown",
                    "description": "Boolean condition syntax (e.g., 'all of selection_*', 'selection_a and selection_b')",
                    "title": "Condition",
                    "type": "string"
                  },
                  "selections": {
                    "additionalProperties": true,
                    "description": "Selection blocks keyed by name (e.g., {'selection_img': {...}, 'selection_cmd': {...}})",
                    "title": "Selections",
                    "type": "object"
                  }
                },
                "title": "SigmaDetection",
                "type": "object"
              },
              "SigmaRule": {
                "description": "Full Sigma detection rule parsed from YAML.",
                "properties": {
                  "author": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Rule author(s); defaults to 'Unknown' if missing",
                    "title": "Author"
                  },
                  "date": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO-8601 creation date",
                    "title": "Date"
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Multi-line rule description; may be None if omitted in YAML",
                    "title": "Description"
                  },
                  "detection": {
                    "$ref": "#/$defs/SigmaDetection",
                    "description": "Nested detection block with selections and condition"
                  },
                  "detection_summary": {
                    "default": "",
                    "description": "Human-readable summary (e.g., '2 selections, condition: all of selection_*')",
                    "title": "Detection Summary",
                    "type": "string"
                  },
                  "falsepositives": {
                    "description": "Known false-positive scenarios",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsepositives",
                    "type": "array"
                  },
                  "level": {
                    "default": "medium",
                    "description": "Detection alert severity",
                    "enum": [
                      "informational",
                      "low",
                      "medium",
                      "high",
                      "critical"
                    ],
                    "title": "Level",
                    "type": "string"
                  },
                  "license": {
                    "default": "DRL 1.1",
                    "description": "Detection Rule License version",
                    "title": "License",
                    "type": "string"
                  },
                  "logsource": {
                    "additionalProperties": true,
                    "description": "Logsource metadata: {product, service, category, definition}",
                    "title": "Logsource",
                    "type": "object"
                  },
                  "modified": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO-8601 last modification date",
                    "title": "Modified"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "references": {
                    "description": "List of reference URLs from the rule",
                    "items": {
                      "type": "string"
                    },
                    "title": "References",
                    "type": "array"
                  },
                  "rule_id": {
                    "description": "UUID of the rule (unique identifier)",
                    "title": "Rule Id",
                    "type": "string"
                  },
                  "source_url": {
                    "default": "",
                    "description": "GitHub URL to the rule in SigmaHQ repository (set by indexer)",
                    "title": "Source Url",
                    "type": "string"
                  },
                  "status": {
                    "default": "test",
                    "description": "Rule maturity level",
                    "enum": [
                      "test",
                      "stable",
                      "experimental",
                      "unsupported",
                      "deprecated"
                    ],
                    "title": "Status",
                    "type": "string"
                  },
                  "tags": {
                    "description": "Flattened tags list (attack.t1059, cve.2024-1234, detection.threat_hunting, etc.)",
                    "items": {
                      "type": "string"
                    },
                    "title": "Tags",
                    "type": "array"
                  },
                  "title": {
                    "description": "Human-readable rule title",
                    "title": "Title",
                    "type": "string"
                  },
                  "updated_at": {
                    "default": "",
                    "description": "ISO-8601 timestamp when ContrastAPI last synced this rule",
                    "title": "Updated At",
                    "type": "string"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "rule_id",
                  "title",
                  "detection"
                ],
                "title": "SigmaRule",
                "type": "object"
              },
              "SigmaRuleLookupResponse": {
                "additionalProperties": false,
                "description": "Single rule lookup response.",
                "properties": {
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "rule": {
                    "$ref": "#/$defs/SigmaRule",
                    "description": "Full Sigma rule record"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "rule"
                ],
                "title": "SigmaRuleLookupResponse",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/SigmaRuleLookupResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "sigma_rule_lookupOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "bulk_sigma_rule_lookup",
          "title": "Bulk Sigma Rule Lookup",
          "description": "Bulk Sigma rule lookup — retrieve full records for up to 50 rule UUIDs in a single request instead of N separate sigma_rule_lookup calls. Designed for triage workflows where multiple rule ids are known (e.g., from a SIEM alert batch or a tagged detection bundle). Each item is the same shape as sigma_rule_lookup with status ok/not_found/invalid_format and an error field when applicable. Up to 50 rule ids per call (same cap for Free and Pro). Each rule_id consumes 1 unit of the hourly quota; ids beyond the caller's remaining quota land in skipped_due_to_rate_limit instead of failing the whole batch (parity with bulk_cve/ioc). Free: 30/hr, Pro: 500/hr. Returns {results [{rule_id, status, rule, error}], total, processed, skipped_due_to_rate_limit, successful, failed, partial, summary, next_calls}.",
          "inputSchema": {
            "properties": {
              "rule_ids": {
                "description": "List of Sigma rule UUIDs in RFC 4122 format. Up to 50 per call (same cap for Free and Pro). Each rule_id counts as 1 request toward the hourly quota. Per-item validation: invalid-format ids return status='invalid_format', unknown UUIDs return status='not_found' — the whole call does not fail.",
                "items": {
                  "type": "string"
                },
                "maxItems": 50,
                "title": "Rule Ids",
                "type": "array"
              }
            },
            "required": [
              "rule_ids"
            ],
            "title": "bulk_sigma_rule_lookupArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "BulkSigmaRuleLookupItem": {
                "additionalProperties": false,
                "description": "Single item in bulk lookup response.",
                "properties": {
                  "error": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Error message when status != 'ok'",
                    "title": "Error"
                  },
                  "rule": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/SigmaRule"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Full rule when status='ok'"
                  },
                  "rule_id": {
                    "description": "Echoed input rule UUID",
                    "title": "Rule Id",
                    "type": "string"
                  },
                  "status": {
                    "description": "'ok' = rule found; 'not_found' = UUID not in index; 'invalid_format' = invalid UUID",
                    "enum": [
                      "ok",
                      "not_found",
                      "invalid_format"
                    ],
                    "title": "Status",
                    "type": "string"
                  }
                },
                "required": [
                  "rule_id",
                  "status"
                ],
                "title": "BulkSigmaRuleLookupItem",
                "type": "object"
              },
              "BulkSigmaRuleLookupResponse": {
                "additionalProperties": false,
                "description": "Bulk rule lookup response.",
                "properties": {
                  "failed": {
                    "default": 0,
                    "description": "Count of items with status != 'ok'",
                    "title": "Failed",
                    "type": "integer"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up tool calls (atlas_technique_lookup, cve_lookup, etc.)",
                    "title": "Next Calls"
                  },
                  "partial": {
                    "default": false,
                    "description": "True when at least one item was not_found, invalid_format, or skipped due to rate limit.",
                    "title": "Partial",
                    "type": "boolean"
                  },
                  "processed": {
                    "default": 0,
                    "description": "Count of items actually looked up (== len(results)). Equal to total unless dynamic-budget partial-fill kicked in.",
                    "title": "Processed",
                    "type": "integer"
                  },
                  "results": {
                    "description": "Per-rule outcome, preserving input order",
                    "items": {
                      "$ref": "#/$defs/BulkSigmaRuleLookupItem"
                    },
                    "title": "Results",
                    "type": "array"
                  },
                  "skipped_due_to_rate_limit": {
                    "description": "Rule UUIDs not processed because the caller's remaining hourly quota was smaller than the input list. Empty when full budget was available.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Skipped Due To Rate Limit",
                    "type": "array"
                  },
                  "successful": {
                    "default": 0,
                    "description": "Count of items with status='ok'",
                    "title": "Successful",
                    "type": "integer"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line aggregate (e.g., '3/5 rules found')",
                    "title": "Summary",
                    "type": "string"
                  },
                  "total": {
                    "default": 0,
                    "description": "Total unique rule IDs submitted (== processed + len(skipped_due_to_rate_limit)).",
                    "title": "Total",
                    "type": "integer"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "title": "BulkSigmaRuleLookupResponse",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "SigmaDetection": {
                "description": "Nested detection block — preserve raw YAML structure.",
                "properties": {
                  "condition": {
                    "default": "unknown",
                    "description": "Boolean condition syntax (e.g., 'all of selection_*', 'selection_a and selection_b')",
                    "title": "Condition",
                    "type": "string"
                  },
                  "selections": {
                    "additionalProperties": true,
                    "description": "Selection blocks keyed by name (e.g., {'selection_img': {...}, 'selection_cmd': {...}})",
                    "title": "Selections",
                    "type": "object"
                  }
                },
                "title": "SigmaDetection",
                "type": "object"
              },
              "SigmaRule": {
                "description": "Full Sigma detection rule parsed from YAML.",
                "properties": {
                  "author": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Rule author(s); defaults to 'Unknown' if missing",
                    "title": "Author"
                  },
                  "date": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO-8601 creation date",
                    "title": "Date"
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Multi-line rule description; may be None if omitted in YAML",
                    "title": "Description"
                  },
                  "detection": {
                    "$ref": "#/$defs/SigmaDetection",
                    "description": "Nested detection block with selections and condition"
                  },
                  "detection_summary": {
                    "default": "",
                    "description": "Human-readable summary (e.g., '2 selections, condition: all of selection_*')",
                    "title": "Detection Summary",
                    "type": "string"
                  },
                  "falsepositives": {
                    "description": "Known false-positive scenarios",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsepositives",
                    "type": "array"
                  },
                  "level": {
                    "default": "medium",
                    "description": "Detection alert severity",
                    "enum": [
                      "informational",
                      "low",
                      "medium",
                      "high",
                      "critical"
                    ],
                    "title": "Level",
                    "type": "string"
                  },
                  "license": {
                    "default": "DRL 1.1",
                    "description": "Detection Rule License version",
                    "title": "License",
                    "type": "string"
                  },
                  "logsource": {
                    "additionalProperties": true,
                    "description": "Logsource metadata: {product, service, category, definition}",
                    "title": "Logsource",
                    "type": "object"
                  },
                  "modified": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO-8601 last modification date",
                    "title": "Modified"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "references": {
                    "description": "List of reference URLs from the rule",
                    "items": {
                      "type": "string"
                    },
                    "title": "References",
                    "type": "array"
                  },
                  "rule_id": {
                    "description": "UUID of the rule (unique identifier)",
                    "title": "Rule Id",
                    "type": "string"
                  },
                  "source_url": {
                    "default": "",
                    "description": "GitHub URL to the rule in SigmaHQ repository (set by indexer)",
                    "title": "Source Url",
                    "type": "string"
                  },
                  "status": {
                    "default": "test",
                    "description": "Rule maturity level",
                    "enum": [
                      "test",
                      "stable",
                      "experimental",
                      "unsupported",
                      "deprecated"
                    ],
                    "title": "Status",
                    "type": "string"
                  },
                  "tags": {
                    "description": "Flattened tags list (attack.t1059, cve.2024-1234, detection.threat_hunting, etc.)",
                    "items": {
                      "type": "string"
                    },
                    "title": "Tags",
                    "type": "array"
                  },
                  "title": {
                    "description": "Human-readable rule title",
                    "title": "Title",
                    "type": "string"
                  },
                  "updated_at": {
                    "default": "",
                    "description": "ISO-8601 timestamp when ContrastAPI last synced this rule",
                    "title": "Updated At",
                    "type": "string"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "rule_id",
                  "title",
                  "detection"
                ],
                "title": "SigmaRule",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/BulkSigmaRuleLookupResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "bulk_sigma_rule_lookupOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "ioc_lookup",
          "title": "IOC Lookup",
          "description": "Enrich Indicator of Compromise (IP/domain/URL/hash) by auto-detecting type and querying abuse.ch feeds. Per-type source coverage: hash → ThreatFox only (Feodo and URLhaus do not index hashes); IP → ThreatFox + Feodo Tracker + URLhaus; domain / URL → ThreatFox + URLhaus. verdict.sources_queried lists what actually ran; verdict.sources_unavailable lists what failed (timeout / upstream error). Use as primary IOC triage tool when type unknown; use threat_intel for domain-only, hash_lookup for richer MalwareBazaar hash data. Free: 30/hr, Pro: 500/hr. Returns {indicator, type, threat_level, sources, summary, verdict}.",
          "inputSchema": {
            "properties": {
              "indicator": {
                "description": "Indicator of Compromise: IP address, domain, full URL, or file hash in MD5/SHA1/SHA256 format (e.g. '8.8.8.8', 'evil.com', 'https://evil.com/malware.exe', 'd41d8cd98f00b204e9800998ecf8427e')",
                "title": "Indicator",
                "type": "string"
              }
            },
            "required": [
              "indicator"
            ],
            "title": "ioc_lookupArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "FeodoSource": {
                "description": "Feodo Tracker C2 blocklist entry inside IocResponse.sources.feodo (IP only).",
                "properties": {
                  "first_seen": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO timestamp of first Feodo observation. Null when found=False.",
                    "title": "First Seen"
                  },
                  "found": {
                    "description": "True when the IP appears on the Feodo Tracker C2 blocklist.",
                    "title": "Found",
                    "type": "boolean"
                  },
                  "last_online": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO timestamp the C2 was last seen online. Null when found=False.",
                    "title": "Last Online"
                  },
                  "malware": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Malware family attributed by Feodo (e.g. 'Emotet'). Null when found=False.",
                    "title": "Malware"
                  },
                  "status": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "C2 lifecycle status per Feodo (e.g. 'online', 'offline'). Null when found=False.",
                    "title": "Status"
                  }
                },
                "required": [
                  "found"
                ],
                "title": "FeodoSource",
                "type": "object"
              },
              "IocResponse": {
                "properties": {
                  "indicator": {
                    "description": "Echoed input indicator (sanitized; control chars stripped).",
                    "title": "Indicator",
                    "type": "string"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "sources": {
                    "$ref": "#/$defs/IocSourcesInfo",
                    "description": "Per-source lookup results. See IocSourcesInfo for which sources apply per indicator type."
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line human summary aggregating threat indicators across sources.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "threat_level": {
                    "default": "none",
                    "description": "Heuristic threat tier from cross-source agreement. 'high' = \u003e=2 sources flagged; 'medium' = 1 source flagged; 'none' = no source flagged. 'low' is a soft cap applied when the only flag came from a ThreatFox test/demo honeypot tag.",
                    "enum": [
                      "none",
                      "low",
                      "medium",
                      "high"
                    ],
                    "title": "Threat Level",
                    "type": "string"
                  },
                  "type": {
                    "description": "Auto-detected indicator type. 'unknown' is rejected at route level (400).",
                    "enum": [
                      "ip",
                      "domain",
                      "url",
                      "hash",
                      "unknown"
                    ],
                    "title": "Type",
                    "type": "string"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "indicator",
                  "type"
                ],
                "title": "IocResponse",
                "type": "object"
              },
              "IocSourcesInfo": {
                "description": "Per-source lookup results inside IocResponse. Keys present depend on indicator type.\n\n- hash → only `threatfox` (Feodo and URLhaus do not index hashes).\n- ip → `threatfox` + `feodo` + `urlhaus` + `tor`.\n- domain / url → `threatfox` + `urlhaus`.",
                "properties": {
                  "feodo": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/FeodoSource"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Feodo Tracker C2 blocklist lookup. IP indicators only."
                  },
                  "threatfox": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/ThreatFoxSource"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ThreatFox lookup result. Always queried."
                  },
                  "tor": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/TorSource"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Tor exit list membership. IP indicators only."
                  },
                  "urlhaus": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/UrlhausSource"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "URLhaus URL/host match. IP/domain/URL indicators."
                  }
                },
                "title": "IocSourcesInfo",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "ThreatFoxSource": {
                "description": "ThreatFox abuse.ch source entry inside IocResponse.sources.threatfox.",
                "properties": {
                  "confidence": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ThreatFox confidence score (0-100). Null when found=False or not provided upstream.",
                    "title": "Confidence"
                  },
                  "error": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "'upstream timeout' or 'upstream error' when ThreatFox query failed; absent on success.",
                    "title": "Error"
                  },
                  "first_seen": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "ISO timestamp of first ThreatFox observation. Null when found=False.",
                    "title": "First Seen"
                  },
                  "found": {
                    "description": "True when ThreatFox returned at least one IOC entry for the indicator.",
                    "title": "Found",
                    "type": "boolean"
                  },
                  "ioc_count": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Total ThreatFox IOC entries matching this indicator. Null when found=False.",
                    "title": "Ioc Count"
                  },
                  "malware": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Malware family name (e.g. 'Cobalt Strike'). Null when found=False.",
                    "title": "Malware"
                  },
                  "tags": {
                    "description": "ThreatFox tags. May include 'test'/'demo' for honeypot entries.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Tags",
                    "type": "array"
                  },
                  "threat_type": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Threat classification (e.g. 'botnet_cc', 'payload_delivery'). Null when found=False.",
                    "title": "Threat Type"
                  }
                },
                "required": [
                  "found"
                ],
                "title": "ThreatFoxSource",
                "type": "object"
              },
              "TorSource": {
                "description": "Tor exit list entry inside IocResponse.sources.tor (IP only).",
                "properties": {
                  "fetch_status": {
                    "description": "Cache state of the Tor exit list snapshot used for the lookup. 'initial' = no refresh has run yet; 'ok' = fresh fetch; 'failed' = upstream fetch failed (treat listed=False as 'unknown', not 'safe'); 'capped' = upstream response exceeded the size cap and was rejected.",
                    "enum": [
                      "initial",
                      "ok",
                      "failed",
                      "capped"
                    ],
                    "title": "Fetch Status",
                    "type": "string"
                  },
                  "listed": {
                    "description": "True when the IP appears in the Tor Project's bulk exit list.",
                    "title": "Listed",
                    "type": "boolean"
                  }
                },
                "required": [
                  "listed",
                  "fetch_status"
                ],
                "title": "TorSource",
                "type": "object"
              },
              "UrlhausSource": {
                "description": "URLhaus abuse.ch source entry inside IocResponse.sources.urlhaus.",
                "properties": {
                  "found": {
                    "description": "True when URLhaus has at least one URL for the indicator.",
                    "title": "Found",
                    "type": "boolean"
                  },
                  "urls_online": {
                    "default": 0,
                    "description": "Subset of URLhaus URLs currently marked online.",
                    "title": "Urls Online",
                    "type": "integer"
                  }
                },
                "required": [
                  "found"
                ],
                "title": "UrlhausSource",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/IocResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "ioc_lookupOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "hash_lookup",
          "title": "Hash Lookup",
          "description": "Query MalwareBazaar for file hash (MD5/SHA1/SHA256): malware family, file type, size, tags, first/last seen, download count. Use to check if file hash is known malware; use ioc_lookup for auto-detection of all IOC types. Companion malware-investigation tools: ioc_lookup (multi-source: ThreatFox + Feodo Tracker + URLhaus), threat_intel (domain-level URLhaus check), exploit_lookup (link a known CVE to PoC code if the hash maps to an exploit binary). Free: 30/hr, Pro: 500/hr. Returns {found, malware_family, file_type, file_size, tags, first_seen, last_seen, signature}.",
          "inputSchema": {
            "properties": {
              "file_hash": {
                "description": "File hash to look up. Accepts MD5 (32 chars), SHA-1 (40 chars), or SHA-256 (64 chars). Lowercase hex only, no spaces. Example: 'd41d8cd98f00b204e9800998ecf8427e'",
                "title": "File Hash",
                "type": "string"
              }
            },
            "required": [
              "file_hash"
            ],
            "title": "hash_lookupArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "HashResponse": {
                "properties": {
                  "file_name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "File Name"
                  },
                  "file_size": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "File Size"
                  },
                  "file_type": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "File Type"
                  },
                  "first_seen": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "First Seen"
                  },
                  "found": {
                    "default": false,
                    "title": "Found",
                    "type": "boolean"
                  },
                  "hash": {
                    "title": "Hash",
                    "type": "string"
                  },
                  "hash_type": {
                    "title": "Hash Type",
                    "type": "string"
                  },
                  "malware_family": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Malware Family"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "summary": {
                    "default": "",
                    "title": "Summary",
                    "type": "string"
                  },
                  "tags": {
                    "items": {
                      "type": "string"
                    },
                    "title": "Tags",
                    "type": "array"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "hash",
                  "hash_type"
                ],
                "title": "HashResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/HashResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "hash_lookupOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "password_check",
          "title": "Password Check",
          "description": "Check if SHA-1 hash appears in Have I Been Pwned (HIBP) breach dataset using k-anonymity (5-char prefix only, full hash never leaves tool). Use for password breach audits; read-only, no data stored. Companion OSINT investigation tools: hash_lookup (file-hash malware family lookup, different namespace), email_disposable (throwaway-mail signal on associated accounts), username_lookup (social-platform exposure on associated handles). Free: 30/hr, Pro: 500/hr. Returns {found, count}.",
          "inputSchema": {
            "properties": {
              "sha1_hash": {
                "description": "Full SHA-1 hash of the password as 40 lowercase hexadecimal characters (e.g. '5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8' for 'password')",
                "title": "Sha1 Hash",
                "type": "string"
              }
            },
            "required": [
              "sha1_hash"
            ],
            "title": "password_checkArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PasswordResponse": {
                "properties": {
                  "breach_count": {
                    "default": 0,
                    "description": "Number of breach corpora that contained this password. 0 when found=False.",
                    "title": "Breach Count",
                    "type": "integer"
                  },
                  "found": {
                    "default": false,
                    "description": "True when the full SHA-1 was matched in HIBP's breach corpus.",
                    "title": "Found",
                    "type": "boolean"
                  },
                  "hash_prefix": {
                    "description": "First 5 chars of the SHA-1 hash (the only data sent upstream — k-anonymity). The full hash never leaves the server.",
                    "title": "Hash Prefix",
                    "type": "string"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line human-readable result (e.g. 'This password appeared in 12,345 data breaches').",
                    "title": "Summary",
                    "type": "string"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "hash_prefix"
                ],
                "title": "PasswordResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/PasswordResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "password_checkOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "phishing_check",
          "title": "Phishing Check",
          "description": "Query URLhaus for a specific URL and its host. is_malicious is True only when there is ACTIVE evidence — exact URL match with url_status='online' (or unknown) OR host has urls_online \u003e 0. URLhaus retains historical records forever, so a host can have url_count \u003e 0 with urls_online == 0; in that case is_malicious=False, is_stale=True, threat_level='low'. Use for URL-level threat assessment; use threat_intel for domain-level checks. Companion threat-investigation tools: ioc_lookup (multi-source IOC: ThreatFox + URLhaus + Feodo Tracker, auto-detect type), hash_lookup (file-hash malware family, MalwareBazaar), threat_intel (domain-level URLhaus only). Free: 30/hr, Pro: 500/hr. Returns {url, host, is_malicious, is_stale, urlhaus_host:{found,urls_online,url_count}, urlhaus_url:{found,threat,tags,status}, threat_level, summary}.",
          "inputSchema": {
            "properties": {
              "url": {
                "description": "Full URL to check, including protocol (e.g. 'https://suspicious-login.com/verify', 'http://evil.com/payload.exe')",
                "title": "Url",
                "type": "string"
              }
            },
            "required": [
              "url"
            ],
            "title": "phishing_checkArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PhishingResponse": {
                "properties": {
                  "host": {
                    "title": "Host",
                    "type": "string"
                  },
                  "is_malicious": {
                    "default": false,
                    "title": "Is Malicious",
                    "type": "boolean"
                  },
                  "is_stale": {
                    "default": false,
                    "description": "True when the only URLhaus evidence is historical (host has url_count \u003e 0 but urls_online == 0, OR exact URL match has status == 'offline'). The host or URL was once flagged but no live malware is currently being served — useful for distinguishing past compromise from active threat.",
                    "title": "Is Stale",
                    "type": "boolean"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "summary": {
                    "default": "",
                    "title": "Summary",
                    "type": "string"
                  },
                  "threat_level": {
                    "default": "none",
                    "description": "Aggregate severity. 'high' = exact URL active AND host has live malware URLs. 'medium' = exactly one of those active. 'low' = only stale historical evidence (is_stale=True). 'none' = no URLhaus listing for either.",
                    "enum": [
                      "none",
                      "low",
                      "medium",
                      "high"
                    ],
                    "title": "Threat Level",
                    "type": "string"
                  },
                  "url": {
                    "title": "Url",
                    "type": "string"
                  },
                  "urlhaus_host": {
                    "$ref": "#/$defs/UrlhausHostDetail"
                  },
                  "urlhaus_url": {
                    "$ref": "#/$defs/UrlhausUrlDetail"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "required": [
                  "url",
                  "host"
                ],
                "title": "PhishingResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "UrlhausHostDetail": {
                "properties": {
                  "found": {
                    "default": false,
                    "title": "Found",
                    "type": "boolean"
                  },
                  "url_count": {
                    "default": 0,
                    "title": "Url Count",
                    "type": "integer"
                  },
                  "urls_online": {
                    "default": 0,
                    "title": "Urls Online",
                    "type": "integer"
                  }
                },
                "title": "UrlhausHostDetail",
                "type": "object"
              },
              "UrlhausUrlDetail": {
                "properties": {
                  "found": {
                    "default": false,
                    "title": "Found",
                    "type": "boolean"
                  },
                  "status": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "URLhaus url_status for the exact URL match: 'online' (active threat), 'offline' (historical, threat may be cleaned up), or 'unknown'. Null when the URL was not found.",
                    "title": "Status"
                  },
                  "tags": {
                    "items": {
                      "type": "string"
                    },
                    "title": "Tags",
                    "type": "array"
                  },
                  "threat": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Threat"
                  }
                },
                "title": "UrlhausUrlDetail",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/PhishingResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "phishing_checkOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "bulk_ioc_lookup",
          "title": "Bulk IOC Lookup",
          "description": "Batch query multiple IOCs (IP/domain/URL/hash, up to 50 per call, same for Free and Pro) in 1 request: auto-detects type + queries abuse.ch feeds per-indicator. Per-type source coverage matches ioc_lookup: hash → ThreatFox only; IP → ThreatFox + Feodo + URLhaus; domain / URL → ThreatFox + URLhaus. Each result item carries its own verdict.sources_queried / sources_unavailable so partial failures are visible per indicator. Use for SOC alert triage or batch enrichment; use ioc_lookup for single indicator. Free: 30/hr (1 per item), Pro: 500/hr. Returns {results, total, successful, failed, timed_out, partial, summary}.",
          "inputSchema": {
            "properties": {
              "indicators": {
                "description": "List of indicators of compromise: IP addresses, domains, URLs, or file hashes (e.g. ['8.8.8.8', 'evil.com', 'd41d8cd98f00b204e9800998ecf8427e']). Maximum 50 per request (same cap for Free and Pro). Each indicator type is auto-detected.",
                "items": {
                  "type": "string"
                },
                "title": "Indicators",
                "type": "array"
              }
            },
            "required": [
              "indicators"
            ],
            "title": "bulk_ioc_lookupArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "BulkIocItem": {
                "additionalProperties": true,
                "properties": {
                  "error": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Human-readable error message when status='error' (timeout, invalid indicator, upstream error).",
                    "title": "Error"
                  },
                  "indicator": {
                    "description": "Echoed input indicator (sanitized; type auto-detected per-item).",
                    "title": "Indicator",
                    "type": "string"
                  },
                  "ioc": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Slim IOC enrichment when status='ok' — keys: type, threat_level, sources. Bulk endpoint omits indicator/summary/verdict (use /v1/ioc/{indicator} for the full IocResponse shape). Per-source dicts may carry richer fields than the single endpoint (raw urlhaus dict instead of {found, urls_online}).",
                    "title": "Ioc"
                  },
                  "status": {
                    "default": "ok",
                    "description": "Per-item outcome (v1.21.0+ unified across bulk_cve/bulk_ioc/bulk_atlas): 'ok' = ioc populated; 'invalid_format' = indicator failed validation (empty / unknown type / private IP); 'error' = transient lookup failure (timeout / upstream error); 'not_found' is reserved for parity with bulk_cve_lookup — IOC queries always reach upstream feeds, so this value is rarely emitted (treat as semantic equivalent of 'ok' with threat_level='none' and empty sources).",
                    "enum": [
                      "ok",
                      "error",
                      "not_found",
                      "invalid_format"
                    ],
                    "title": "Status",
                    "type": "string"
                  }
                },
                "required": [
                  "indicator"
                ],
                "title": "BulkIocItem",
                "type": "object"
              },
              "BulkIocResponse": {
                "properties": {
                  "failed": {
                    "default": 0,
                    "description": "Count of items with status='error' from non-timeout failures.",
                    "title": "Failed",
                    "type": "integer"
                  },
                  "invalid": {
                    "default": 0,
                    "description": "Count of items with status='invalid_format' (validation rejection: empty / unknown type / private IP). Distinct from `failed` which counts only transient errors. `successful + failed + timed_out + invalid == processed` always holds.",
                    "title": "Invalid",
                    "type": "integer"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "partial": {
                    "default": false,
                    "description": "True when at least one item failed, timed out, was invalid, or skipped due to rate limit.",
                    "title": "Partial",
                    "type": "boolean"
                  },
                  "processed": {
                    "default": 0,
                    "description": "Count of items actually enriched (== len(results)). Equal to total unless dynamic-budget partial-fill kicked in.",
                    "title": "Processed",
                    "type": "integer"
                  },
                  "results": {
                    "description": "Per-indicator outcome list, preserving input order.",
                    "items": {
                      "$ref": "#/$defs/BulkIocItem"
                    },
                    "title": "Results",
                    "type": "array"
                  },
                  "skipped_due_to_rate_limit": {
                    "description": "Indicators that were not processed because the caller's remaining hourly quota was smaller than the input list. Empty when full budget was available.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Skipped Due To Rate Limit",
                    "type": "array"
                  },
                  "successful": {
                    "default": 0,
                    "description": "Count of items with status='ok'.",
                    "title": "Successful",
                    "type": "integer"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line aggregate summary (e.g. '12/15 indicators enriched').",
                    "title": "Summary",
                    "type": "string"
                  },
                  "timed_out": {
                    "default": 0,
                    "description": "Count of items that hit the per-IOC or overall timeout.",
                    "title": "Timed Out",
                    "type": "integer"
                  },
                  "total": {
                    "default": 0,
                    "description": "Total number of input indicators submitted (== processed + len(skipped_due_to_rate_limit)).",
                    "title": "Total",
                    "type": "integer"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "title": "BulkIocResponse",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/BulkIocResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "bulk_ioc_lookupOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "check_secrets",
          "title": "Check Secrets",
          "description": "Scan source code (or snippet) for hardcoded secrets — cloud provider keys, API tokens, connection strings, private keys, passwords. Supports Python, JavaScript, TypeScript, Java, Go, Ruby, Shell, Bash. Use to detect leaked credentials before commit; for injection detection use check_injection. Free: 30/hr, Pro: 500/hr. Returns {total, by_severity, findings}. No data stored. The generic password-assignment rule is suppressed when a more-specific credential rule fires on the same line — one targeted finding per leaked secret, not two.",
          "inputSchema": {
            "properties": {
              "code": {
                "description": "Source code string to scan for secrets (can be a single file or code snippet)",
                "title": "Code",
                "type": "string"
              },
              "language": {
                "default": "generic",
                "description": "Programming language of the code. Must be one of: python, javascript, typescript, java, go, ruby, shell, bash, generic. Use 'generic' if unsure.",
                "enum": [
                  "python",
                  "javascript",
                  "typescript",
                  "java",
                  "go",
                  "ruby",
                  "shell",
                  "bash",
                  "generic"
                ],
                "title": "Language",
                "type": "string"
              }
            },
            "required": [
              "code"
            ],
            "title": "check_secretsArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "CodeCheckResponse": {
                "properties": {
                  "by_severity": {
                    "additionalProperties": {
                      "type": "integer"
                    },
                    "description": "Finding counts bucketed by severity, e.g. {'critical': 1, 'high': 2, 'medium': 0, 'low': 1}.",
                    "title": "By Severity",
                    "type": "object"
                  },
                  "findings": {
                    "description": "Per-rule findings emitted by the scanner. Empty when the code is clean.",
                    "items": {
                      "$ref": "#/$defs/CodeFinding"
                    },
                    "title": "Findings",
                    "type": "array"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line summary aggregating finding counts by severity.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "total": {
                    "default": 0,
                    "description": "Total number of findings (== len(findings)).",
                    "title": "Total",
                    "type": "integer"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "title": "CodeCheckResponse",
                "type": "object"
              },
              "CodeFinding": {
                "properties": {
                  "description": {
                    "default": "",
                    "description": "Human-readable explanation of what the rule detects.",
                    "title": "Description",
                    "type": "string"
                  },
                  "line": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "1-indexed line number in the submitted code where the rule matched. Null if line cannot be determined.",
                    "title": "Line"
                  },
                  "match": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Snippet of the matching text (truncated for ReDoS safety). Null when the rule does not capture text.",
                    "title": "Match"
                  },
                  "remediation": {
                    "default": "",
                    "description": "Actionable fix or mitigation guidance.",
                    "title": "Remediation",
                    "type": "string"
                  },
                  "severity": {
                    "default": "medium",
                    "description": "Impact bucket assigned by the rule. 'critical'/'high' are typically actionable; 'low' is advisory.",
                    "enum": [
                      "critical",
                      "high",
                      "medium",
                      "low"
                    ],
                    "title": "Severity",
                    "type": "string"
                  },
                  "type": {
                    "default": "",
                    "description": "Rule identifier that fired (e.g. 'aws_secret_key', 'sql_injection'). Stable across releases.",
                    "title": "Type",
                    "type": "string"
                  }
                },
                "title": "CodeFinding",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/CodeCheckResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "check_secretsOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "check_injection",
          "title": "Check Injection",
          "description": "Scan source code for injection vulnerabilities: SQL injection, command injection, path traversal via unsafe string concatenation/unsanitized input. Supports Python, JavaScript, TypeScript, Java, Go, Ruby, Shell, Bash. Use to detect input-handling bugs; for secrets use check_secrets. Companion code-security tools: check_secrets (hard-coded credential detection), check_dependencies (known-CVE vulnerability audit), check_headers (live HTTP security-header validation), scan_headers (live HTTP scan via domain). Free: 30/hr, Pro: 500/hr. Returns {total, by_severity, findings}. No data stored.",
          "inputSchema": {
            "properties": {
              "code": {
                "description": "Source code string to scan for injection vulnerabilities (can be a single file or code snippet)",
                "title": "Code",
                "type": "string"
              },
              "language": {
                "default": "generic",
                "description": "Programming language of the code. Must be one of: python, javascript, typescript, java, go, ruby, shell, bash, generic. Use 'generic' if unsure.",
                "enum": [
                  "python",
                  "javascript",
                  "typescript",
                  "java",
                  "go",
                  "ruby",
                  "shell",
                  "bash",
                  "generic"
                ],
                "title": "Language",
                "type": "string"
              }
            },
            "required": [
              "code"
            ],
            "title": "check_injectionArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "CodeCheckResponse": {
                "properties": {
                  "by_severity": {
                    "additionalProperties": {
                      "type": "integer"
                    },
                    "description": "Finding counts bucketed by severity, e.g. {'critical': 1, 'high': 2, 'medium': 0, 'low': 1}.",
                    "title": "By Severity",
                    "type": "object"
                  },
                  "findings": {
                    "description": "Per-rule findings emitted by the scanner. Empty when the code is clean.",
                    "items": {
                      "$ref": "#/$defs/CodeFinding"
                    },
                    "title": "Findings",
                    "type": "array"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line summary aggregating finding counts by severity.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "total": {
                    "default": 0,
                    "description": "Total number of findings (== len(findings)).",
                    "title": "Total",
                    "type": "integer"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "title": "CodeCheckResponse",
                "type": "object"
              },
              "CodeFinding": {
                "properties": {
                  "description": {
                    "default": "",
                    "description": "Human-readable explanation of what the rule detects.",
                    "title": "Description",
                    "type": "string"
                  },
                  "line": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "1-indexed line number in the submitted code where the rule matched. Null if line cannot be determined.",
                    "title": "Line"
                  },
                  "match": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Snippet of the matching text (truncated for ReDoS safety). Null when the rule does not capture text.",
                    "title": "Match"
                  },
                  "remediation": {
                    "default": "",
                    "description": "Actionable fix or mitigation guidance.",
                    "title": "Remediation",
                    "type": "string"
                  },
                  "severity": {
                    "default": "medium",
                    "description": "Impact bucket assigned by the rule. 'critical'/'high' are typically actionable; 'low' is advisory.",
                    "enum": [
                      "critical",
                      "high",
                      "medium",
                      "low"
                    ],
                    "title": "Severity",
                    "type": "string"
                  },
                  "type": {
                    "default": "",
                    "description": "Rule identifier that fired (e.g. 'aws_secret_key', 'sql_injection'). Stable across releases.",
                    "title": "Type",
                    "type": "string"
                  }
                },
                "title": "CodeFinding",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/CodeCheckResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "check_injectionOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "check_dependencies",
          "title": "Check Dependencies",
          "description": "Audit project dependencies (npm/PyPI/Maven/RubyGems/etc.) against CVE database: find known vulnerabilities in your package list. Bulk query up to 50 packages per call (same for Free and Pro). Use for dependency security scanning; use cve_lookup for single CVE. Free: 30/hr (1 per package), Pro: 500/hr. Returns {findings, total, by_severity, summary}. Each finding includes fixed_in (first release outside the matched vulnerable range: its exclusive upper bound from NVD, MITRE, GitHub advisory or OSV data, usually the first patched version) when a version range matched — omitted from wire when the range has no exclusive upper bound or no input version was supplied; remediation copy then says 'Check if ... is affected ... and upgrade if so' instead of 'Upgrade to X.Y.Z or later'.",
          "inputSchema": {
            "properties": {
              "packages": {
                "description": "List of dependency packages to audit. Each item is an object with 'name' (required, max 200 chars, e.g. 'lodash', 'django', 'log4j-core') and optional 'version' (max 100 chars, e.g. '4.17.0', '2.14.1'). Only 'name' and 'version' fields are used; extra fields are ignored. Example: [{\"name\": \"lodash\", \"version\": \"4.17.0\"}, {\"name\": \"django\"}]. Maximum 50 per request (same cap for Free and Pro).",
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "title": "Packages",
                "type": "array"
              }
            },
            "required": [
              "packages"
            ],
            "title": "check_dependenciesArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "DepFinding": {
                "properties": {
                  "cve_id": {
                    "title": "Cve Id",
                    "type": "string"
                  },
                  "cvss_v3": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Cvss V3"
                  },
                  "description": {
                    "default": "",
                    "title": "Description",
                    "type": "string"
                  },
                  "epss_score": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Epss Score"
                  },
                  "fixed_in": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "First release outside the matched vulnerable range: the range's exclusive upper bound (CVE affected_products[].version_end from NVD, MITRE, GitHub advisory or OSV data; usually the first patched release). Excluded from the wire (response_model_exclude_none=True) when the matched range has no exclusive upper bound (open-ended, or bounded only by an inclusive last-affected version) or no input version was supplied — in those cases inspect remediation copy.",
                    "title": "Fixed In"
                  },
                  "in_kev": {
                    "default": false,
                    "title": "In Kev",
                    "type": "boolean"
                  },
                  "package": {
                    "title": "Package",
                    "type": "string"
                  },
                  "remediation": {
                    "default": "",
                    "title": "Remediation",
                    "type": "string"
                  },
                  "severity": {
                    "default": "unknown",
                    "title": "Severity",
                    "type": "string"
                  },
                  "version": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "title": "Version"
                  }
                },
                "required": [
                  "package",
                  "cve_id"
                ],
                "title": "DepFinding",
                "type": "object"
              },
              "DependenciesResponse": {
                "properties": {
                  "by_severity": {
                    "additionalProperties": {
                      "type": "integer"
                    },
                    "title": "By Severity",
                    "type": "object"
                  },
                  "findings": {
                    "items": {
                      "$ref": "#/$defs/DepFinding"
                    },
                    "title": "Findings",
                    "type": "array"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "processed": {
                    "default": 0,
                    "description": "Count of packages actually scanned. Equal to input count unless dynamic-budget partial-fill kicked in. Field name aligns with the other 4 bulk endpoints (atlas/cve/ioc/domain).",
                    "title": "Processed",
                    "type": "integer"
                  },
                  "skipped_due_to_rate_limit": {
                    "description": "Package names that were not scanned because the caller's remaining hourly quota was smaller than the input list. Empty when full budget was available.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Skipped Due To Rate Limit",
                    "type": "array"
                  },
                  "summary": {
                    "default": "",
                    "title": "Summary",
                    "type": "string"
                  },
                  "total": {
                    "default": 0,
                    "description": "Total CVE findings across processed packages (not the input package count).",
                    "title": "Total",
                    "type": "integer"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "title": "DependenciesResponse",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/DependenciesResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "check_dependenciesOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        },
        {
          "name": "username_lookup",
          "title": "Username Lookup",
          "description": "Search for username across 15+ social/dev platforms (GitHub, Reddit, X/Twitter, LinkedIn, Instagram, TikTok, Discord, YouTube, Keybase, HackerOne, etc.). Use for OSINT investigations and identity verification. Free: 30/hr, Pro: 500/hr. Returns {username, total_found, platforms: [{name, exists, url, status_code}]}.",
          "inputSchema": {
            "properties": {
              "username": {
                "description": "Username string to search across platforms, without @ prefix (e.g. 'torvalds', 'johndoe', 'elonmusk')",
                "title": "Username",
                "type": "string"
              }
            },
            "required": [
              "username"
            ],
            "title": "username_lookupArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "UsernameLookupResponse": {
                "properties": {
                  "checked_count": {
                    "default": 0,
                    "description": "Number of platforms actually checked (may be less than total platforms if early-exit).",
                    "title": "Checked Count",
                    "type": "integer"
                  },
                  "error": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Input validation error (empty username, invalid chars, too long). Null on successful lookups.",
                    "title": "Error"
                  },
                  "found_count": {
                    "default": 0,
                    "description": "Number of platforms where status=='found'.",
                    "title": "Found Count",
                    "type": "integer"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "results": {
                    "description": "Per-platform results, sorted: found first, then alphabetical by platform.",
                    "items": {
                      "$ref": "#/$defs/UsernameMatch"
                    },
                    "title": "Results",
                    "type": "array"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line human-readable summary, e.g. 'username \"x\" found on 6/20 platforms (3 unavailable)'.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "username": {
                    "default": "",
                    "description": "Echoed normalized username (lowercased, validated against [a-z0-9._-]).",
                    "title": "Username",
                    "type": "string"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "title": "UsernameLookupResponse",
                "type": "object"
              },
              "UsernameMatch": {
                "properties": {
                  "platform": {
                    "default": "",
                    "description": "Platform identifier, e.g. 'github', 'twitter', 'reddit'.",
                    "title": "Platform",
                    "type": "string"
                  },
                  "status": {
                    "default": "error",
                    "description": "Per-platform outcome. 'found'/'not_found' are terminal factual answers. 'rate_limited' (429), 'blocked' (403 — often Cloudflare/bot detection), 'timeout' (network), and 'error' (5xx/other) are unavailability states — the platform's answer is unknown, NOT 'user does not exist'. Agents should treat these four as sources_unavailable, not negative evidence.",
                    "enum": [
                      "found",
                      "not_found",
                      "rate_limited",
                      "blocked",
                      "timeout",
                      "error"
                    ],
                    "title": "Status",
                    "type": "string"
                  },
                  "url": {
                    "default": "",
                    "description": "Canonical profile URL for this platform+username (may 200/redirect even when not_found).",
                    "title": "Url",
                    "type": "string"
                  }
                },
                "title": "UsernameMatch",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/UsernameLookupResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "username_lookupOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true,
            "readOnlyHint": true
          }
        },
        {
          "name": "check_headers",
          "title": "Check Headers",
          "description": "Validate HTTP security headers you provide (JSON): CSP, HSTS, X-Frame-Options, X-Content-Type-Options, Permissions-Policy, Referrer-Policy against best practices. Use to test header config before deployment or validate non-public servers; use scan_headers to fetch live. Free: 30/hr, Pro: 500/hr. By default header values are truncated to 500 chars; pass include='full' for the full raw value. Returns {total, by_severity, findings}. No external requests.",
          "inputSchema": {
            "properties": {
              "headers": {
                "description": "JSON string of HTTP header name-value pairs to validate. Example: '{\"Strict-Transport-Security\": \"max-age=31536000\", \"X-Frame-Options\": \"DENY\"}'. Include only security-relevant headers you want to analyze.",
                "title": "Headers",
                "type": "string"
              },
              "include": {
                "default": "",
                "description": "Detail level. Default ('') returns slim findings — raw header values capped at 500 chars with total_value_length carrying the honest pre-truncation length. Pass 'full' to restore the full raw value. Allowed: '' or 'full'.",
                "enum": [
                  "",
                  "full"
                ],
                "title": "Include",
                "type": "string"
              }
            },
            "required": [
              "headers"
            ],
            "title": "check_headersArguments",
            "type": "object"
          },
          "outputSchema": {
            "$defs": {
              "CheckHeadersResponse": {
                "properties": {
                  "by_severity": {
                    "additionalProperties": {
                      "type": "integer"
                    },
                    "description": "Finding counts bucketed by severity, e.g. {'high': 2, 'medium': 1, 'low': 0}.",
                    "title": "By Severity",
                    "type": "object"
                  },
                  "findings": {
                    "description": "Per-header validation findings — one entry per header you submitted that the validator recognized.",
                    "items": {
                      "$ref": "#/$defs/HeaderFinding"
                    },
                    "title": "Findings",
                    "type": "array"
                  },
                  "grade": {
                    "default": "F",
                    "description": "Letter grade derived from score: A=90+, B=75+, C=60+, D=40+, else F.",
                    "enum": [
                      "A",
                      "B",
                      "C",
                      "D",
                      "F"
                    ],
                    "title": "Grade",
                    "type": "string"
                  },
                  "headers_missing": {
                    "description": "Header names the ruleset expects but were not present in the submitted set.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Headers Missing",
                    "type": "array"
                  },
                  "headers_present": {
                    "description": "Header names from the submitted set that the validator recognized as present.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Headers Present",
                    "type": "array"
                  },
                  "next_calls": {
                    "anyOf": [
                      {
                        "items": {
                          "$ref": "#/$defs/PivotHint"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Suggested follow-up MCP tool calls. Ordered by relevance; agents should chain these without re-prompting the user.",
                    "title": "Next Calls"
                  },
                  "score": {
                    "default": 0,
                    "description": "Aggregate header-posture score (0-100) computed from per-finding severity weights.",
                    "title": "Score",
                    "type": "integer"
                  },
                  "summary": {
                    "default": "",
                    "description": "One-line human-readable summary of grade + key issues.",
                    "title": "Summary",
                    "type": "string"
                  },
                  "total": {
                    "default": 0,
                    "description": "Total number of findings emitted (== len(findings)).",
                    "title": "Total",
                    "type": "integer"
                  },
                  "verdict": {
                    "anyOf": [
                      {
                        "$ref": "#/$defs/Verdict"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Falsifiability metadata: sources_queried, sources_unavailable, completeness, deterministic flag. Lets agents distinguish 'no data' from 'source failed' without re-running the call."
                  }
                },
                "title": "CheckHeadersResponse",
                "type": "object"
              },
              "ErrorDetail": {
                "description": "Structured failure body. Codes mirror app/exceptions.AppException\nsubclasses; agent retry / upgrade decisions key off `code`, not `message`.",
                "properties": {
                  "code": {
                    "description": "Stable machine-readable failure category. Agents key retry/upgrade decisions off this.",
                    "enum": [
                      "invalid_argument",
                      "not_found",
                      "rate_limit_exceeded",
                      "auth_required",
                      "tier_limit",
                      "upstream_timeout",
                      "upstream_error",
                      "internal_error"
                    ],
                    "title": "Code",
                    "type": "string"
                  },
                  "docs_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Documentation pointer (e.g. tool input contract) when code='invalid_argument'.",
                    "title": "Docs Url"
                  },
                  "message": {
                    "description": "Human-readable detail. Free text — never parse. Capped at 500 chars to prevent oversized upstream errors from bloating responses.",
                    "maxLength": 500,
                    "title": "Message",
                    "type": "string"
                  },
                  "retry_after_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "When code='rate_limit_exceeded', the minimum seconds to wait before retrying.",
                    "title": "Retry After Seconds"
                  },
                  "upgrade_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Pricing/upgrade URL when code='tier_limit' or 'rate_limit_exceeded' on the Free tier.",
                    "title": "Upgrade Url"
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "title": "ErrorDetail",
                "type": "object"
              },
              "ErrorResponse": {
                "description": "MCP error envelope. Tool return type is always\n`SpecificResponse | ErrorResponse` — Union flag tells the agent which arm\narrived without parsing the inner body.",
                "properties": {
                  "error": {
                    "$ref": "#/$defs/ErrorDetail"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "ErrorResponse",
                "type": "object"
              },
              "HeaderFinding": {
                "properties": {
                  "description": {
                    "default": "",
                    "description": "Human-readable explanation of what this header protects against.",
                    "title": "Description",
                    "type": "string"
                  },
                  "header": {
                    "description": "Canonical header name as defined by the ruleset (e.g. 'Strict-Transport-Security', 'Content-Security-Policy').",
                    "title": "Header",
                    "type": "string"
                  },
                  "issues": {
                    "description": "Machine-readable issue codes emitted by the validator for present-but-invalid headers (e.g. 'hsts_max_age_too_short', 'csp_wildcard_script_src', 'xfo_allowall'). Empty when the header is absent, valid, or has no validator.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Issues",
                    "type": "array"
                  },
                  "present": {
                    "description": "True when the response sent this header at all (regardless of whether the value is valid).",
                    "title": "Present",
                    "type": "boolean"
                  },
                  "reference": {
                    "default": "",
                    "description": "URL to authoritative spec/documentation (MDN, OWASP, RFC).",
                    "title": "Reference",
                    "type": "string"
                  },
                  "remediation": {
                    "default": "",
                    "description": "Concrete recommended header value or configuration snippet.",
                    "title": "Remediation",
                    "type": "string"
                  },
                  "severity": {
                    "description": "Impact weight assigned by the ruleset: 'high' (25 pts), 'medium' (15 pts), 'low' (10 pts). Drives the overall score/grade — missing a 'high' header costs more than missing a 'low' one.",
                    "enum": [
                      "high",
                      "medium",
                      "low"
                    ],
                    "title": "Severity",
                    "type": "string"
                  },
                  "total_value_length": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Honest pre-truncation char length of the raw header value. Only emitted when the value was actually truncated (raw length \u003e 500). Null when no truncation occurred, when no validator applies, or when the header is absent.",
                    "title": "Total Value Length"
                  },
                  "valid": {
                    "default": false,
                    "description": "Value-level validation result. True when the header is present AND its value passes the header-specific validator (e.g. HSTS max-age \u003e= 1 year + includeSubDomains; CSP has no wildcard source in script-src). True also when the header is present but no validator exists for it. False when the header is absent, or present-but-invalid. Inspect `issues` for the specific reasons a present-but-invalid header failed.",
                    "title": "Valid",
                    "type": "boolean"
                  },
                  "value": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Raw header value as sent by the origin, when the header is present AND a validator exists for it. Null when the header is absent, or when it's present but no validator applies to it. By default the value is capped at the first 500 chars (CSP headers can exceed 4 KB); inspect total_value_length to see if truncation occurred and refetch with include=full to restore the full value.",
                    "title": "Value"
                  }
                },
                "required": [
                  "header",
                  "severity",
                  "present"
                ],
                "title": "HeaderFinding",
                "type": "object"
              },
              "PivotHint": {
                "additionalProperties": true,
                "description": "A suggested follow-up MCP tool call. Surfaced inside response.next_calls so\nLLM agents can chain related lookups without manual prompting. Each hint names\nthe tool, the input value to pass, and a short reason explaining why this\npivot adds value in the current context.",
                "properties": {
                  "input": {
                    "description": "Suggested input value to pass to the tool — typically a CVE ID, CWE ID, domain, or IP. Pre-populated from the current response so the agent can call the next tool without re-deriving the argument.",
                    "title": "Input",
                    "type": "string"
                  },
                  "params": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Optional extra kwargs to pass alongside `input`. Used by pivot generators when the next call benefits from a secondary parameter, e.g. {'exclude_id': 'AML.T0051'} to skip the originating technique from a sibling-tactic search. Omitted when no extra args are needed.",
                    "title": "Params"
                  },
                  "reason": {
                    "description": "Short rationale (one sentence) for why this follow-up call adds value, e.g. 'Federal patch deadline + ransomware association', 'Public exploits / PoC availability'.",
                    "title": "Reason",
                    "type": "string"
                  },
                  "tool": {
                    "description": "Canonical MCP tool name to call next. Constrained to known operation_ids in tools/list — adding a new tool here requires expanding the Literal.",
                    "enum": [
                      "cve_lookup",
                      "cve_search",
                      "cve_leading",
                      "bulk_cve_lookup",
                      "calculate_risk_score",
                      "get_cvss_details",
                      "exploit_lookup",
                      "kev_detail",
                      "cwe_lookup",
                      "subdomain_enum",
                      "ssl_check",
                      "tech_fingerprint",
                      "asn_lookup",
                      "ip_lookup",
                      "ioc_lookup",
                      "bulk_ioc_lookup",
                      "hash_lookup",
                      "threat_intel",
                      "threat_report",
                      "audit_domain",
                      "domain_report",
                      "dns_lookup",
                      "whois_lookup",
                      "wayback_lookup",
                      "scan_headers",
                      "check_headers",
                      "check_secrets",
                      "check_injection",
                      "check_dependencies",
                      "email_mx",
                      "email_security_posture",
                      "email_disposable",
                      "email_verify",
                      "robots_txt",
                      "redirect_chain",
                      "brand_assets",
                      "seo_audit",
                      "geo_audit",
                      "phone_lookup",
                      "username_lookup",
                      "password_check",
                      "phishing_check",
                      "atlas_technique_lookup",
                      "atlas_technique_search",
                      "bulk_atlas_technique_lookup",
                      "atlas_case_study_lookup",
                      "atlas_case_study_search",
                      "d3fend_defense_lookup",
                      "d3fend_defense_search",
                      "d3fend_defense_for_attack",
                      "d3fend_attack_coverage",
                      "sigma_rule_lookup",
                      "bulk_sigma_rule_lookup",
                      "tech_stack_cve_audit",
                      "contrast_scan"
                    ],
                    "title": "Tool",
                    "type": "string"
                  }
                },
                "required": [
                  "tool",
                  "input",
                  "reason"
                ],
                "title": "PivotHint",
                "type": "object"
              },
              "Verdict": {
                "properties": {
                  "completeness": {
                    "default": "complete",
                    "description": "'complete' = every planned source returned data; 'partial' = at least one source in sources_unavailable failed or was skipped; 'minimal' = only the primary/required source returned, optional enrichment missing.",
                    "enum": [
                      "complete",
                      "partial",
                      "minimal"
                    ],
                    "title": "Completeness",
                    "type": "string"
                  },
                  "data_age_seconds": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": null,
                    "description": "Seconds elapsed since the oldest cached source was fetched, or null when every source was queried live for this request. Use to judge freshness.",
                    "title": "Data Age Seconds"
                  },
                  "deterministic": {
                    "description": "True when the response is fully reproducible from the listed sources for the same input at the same moment (no randomness, no model inference). False for endpoints that include probabilistic scoring or LLM output.",
                    "title": "Deterministic",
                    "type": "boolean"
                  },
                  "falsifiable_fields": {
                    "description": "Top-level response fields whose values a caller can independently re-derive from the named upstream sources (e.g. 'dns', 'ssl', 'whois'). Fields not in this list are derived/computed and cannot be directly re-verified.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Falsifiable Fields",
                    "type": "array"
                  },
                  "sources_queried": {
                    "description": "Canonical source identifiers successfully consulted for this response (e.g. 'ripe_stat', 'shodan_internetdb', 'firehol'). Agent-readable list, order not significant.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Queried",
                    "type": "array"
                  },
                  "sources_unavailable": {
                    "description": "Sources that were expected but not returned — either intentionally skipped (lite mode, tier gating) or failed (quota, timeout, upstream down). Empty list means every planned source produced data.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Sources Unavailable",
                    "type": "array"
                  }
                },
                "required": [
                  "deterministic"
                ],
                "title": "Verdict",
                "type": "object"
              }
            },
            "properties": {
              "result": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/CheckHeadersResponse"
                  },
                  {
                    "$ref": "#/$defs/ErrorResponse"
                  }
                ],
                "title": "Result"
              }
            },
            "required": [
              "result"
            ],
            "title": "check_headersOutput",
            "type": "object"
          },
          "annotations": {
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false,
            "readOnlyHint": true
          }
        }
      ]
    },
    "name": "ContrastAPI",
    "note": "Indexed from the official MCP registry: facts and our own checks, not reviewed, so no score, grade or rank.",
    "packages": null,
    "pageJsonUrl": "https://www.anchorterminal.com/tools/contrastcyber-api.json",
    "popularity": {
      "githubStars": 33
    },
    "registryName": "com.contrastcyber/api",
    "remotes": [
      {
        "type": "streamable-http",
        "url": "https://api.contrastcyber.com/mcp/"
      }
    ],
    "repository": "https://github.com/UPinar/contrastapi",
    "reviewed": false,
    "slug": "contrastcyber-api",
    "source": "the official MCP registry",
    "sourceUrl": "https://registry.modelcontextprotocol.io/v0.1/servers?search=com.contrastcyber/api",
    "summary": "55 tools, 7 Resources, Sigma rules, email SPF/DMARC, MITRE, CVE/KEV, risk_score. No key.",
    "updatedAt": "2026-08-24T22:31:56Z",
    "url": "https://www.anchorterminal.com/tools/contrastcyber-api",
    "vendor": "contrastcyber.com",
    "vendorUrl": "https://api.contrastcyber.com",
    "version": "1.36.2",
    "websiteUrl": "https://api.contrastcyber.com",
    "where": "hosted",
    "why": [
      "vendor"
    ]
  }
}
