Skip to main content
Glama

Site SEO & AI Crawler Audit

Check the exposed surface of a site you own

exposure_check
Read-onlyIdempotent

Checks what a site or app the user owns leaks publicly. Use it when the user asks what an attacker could find on their own domain, host or app, for example "does my app leak a .env file?". Pass the domain, host or app page address, not a bare IP. The first call returns ownership_not_proven with a DNS TXT record or file: publish it, then call again with the same target. Then it gives exposed or clean, the top three risks with fixes, and evidence: dangling subdomains, leaked files (never their contents), masked API keys, source maps, admin paths, dev servers and default pages. It adds six legal signals with law and source (COPPA, Google Fonts, session replay, renewals, DMCA, CAN-SPAM) and shipNaked: 7 pre-launch pages (privacy, refund and more) with text to paste; not legal advice. GET only, at most 32 fixed paths; no crawl, sign-in or port scan. Do not use it on a target the user does not own, to look up a person, user name or email, or for private or local addresses.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "target": "<target>"
    },
    "name": "exposure_check"
  }
}

Input Schema

NameRequiredDescriptionDefault
emailNoOptional: the text or HTML of one marketing email the app sends, checked for an unsubscribe link and a postal address (CAN-SPAM). It is read in memory and never returned; like every input it may sit in the 30-day input log, cleaned and cut to 2 KB.
targetYesA domain, host or page address you own, such as example.com or https://app.example.com/dashboard. Not a bare IP: pass a host name that points at the server. The host is checked; a page address also names the page whose scripts are read for keys (the home page otherwise).

Output Schema

NameRequiredDescriptionDefault
asOfNoWhen the check ran, ISO 8601 UTC.
legalNo
triedNo
answerYesOne-paragraph answer to lead with.
phasesNo
targetYesHost checked.
publishNo
sourcesNo
surfaceNo
verdictYesownership_not_proven: publicFindings holds what any visitor can see; publish the record or file in publish, then call exposure_check again with the same target for the rest.
evidenceNo
rejectedNo
topRisksNo
keysFoundNo
ownershipNo
shipNakedNoThe 7 pre-launch pages an app usually ships without, each pass, fail, warn or not_checked; a fail or warn carries snippet, the text to paste.
adminPathsNo
notCheckedNo
scriptsReadNo
requestsMadeNo
ownershipNoteYesReminder that the check is only for a target the caller owns.
publicFindingsNoBefore the proof: what any visitor can see. Headers, plain http, robots.txt paths and admin paths by status only.
needsVerificationNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / email / description
      Previous value: -"Optional: the text or HTML of one marketing email the app sends, checked for an unsubscribe link and a postal address (CAN-SPAM). It is read in memory only and never returned or kept."New value: +"Optional: the text or HTML of one marketing email the app sends, checked for an unsubscribe link and a postal address (CAN-SPAM). It is read in memory and never returned; like every input it may sit in the 30-day input log, cleaned and cut to 2 KB."
  2. Changed2 schema fields changed
    • addedOutput schema / properties / publicFindings
      Added value: +{
      +  "description": "Before the proof: what any visitor can see. Headers, plain http, robots.txt paths and admin paths by status only.",
      +  "properties": {
      +    "adminNote": {
      +      "type": "string"
      +    },
      +    "adminPaths": {
      +      "items": {
      +        "properties": {
      +          "path": {
      +            "type": "string"
      +          },
      +          "status": {
      +            "type": [
      +              "integer",
      +              "null"
      +            ]
      +          }
      +        },
      +        "required": [
      +          "path",
      +          "status"
      +        ],
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "findings": {
      +      "items": {
      +        "properties": {
      +          "evidence": {
      +            "type": "string"
      +          },
      +          "fix": {
      +            "type": "string"
      +          },
      +          "risk": {
      +            "type": "string"
      +          },
      +          "severity": {
      +            "enum": [
      +              "high",
      +              "medium",
      +              "low"
      +            ],
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "severity",
      +          "risk",
      +          "fix",
      +          "evidence"
      +        ],
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "headerFix": {
      +      "properties": {
      +        "hosting": {
      +          "type": "string"
      +        },
      +        "snippet": {
      +          "type": "string"
      +        },
      +        "where": {
      +          "type": "string"
      +        }
      +      },
      +      "type": [
      +        "object",
      +        "null"
      +      ]
      +    },
      +    "hosting": {
      +      "type": "string"
      +    },
      +    "notChecked": {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    "page": {
      +      "type": "string"
      +    },
      +    "robots": {
      +      "properties": {
      +        "paths": {
      +          "items": {
      +            "type": "string"
      +          },
      +          "type": "array"
      +        },
      +        "sitemaps": {
      +          "items": {
      +            "type": "string"
      +          },
      +          "type": "array"
      +        },
      +        "status": {
      +          "enum": [
      +            "found",
      +            "missing",
      +            "unreachable"
      +          ],
      +          "type": "string"
      +        },
      +        "url": {
      +          "type": "string"
      +        }
      +      },
      +      "type": "object"
      +    }
      +  },
      +  "type": "object"
      +}
    • changedOutput schema / properties / verdict / description
      Previous value: -"ownership_not_proven: publish the record or file in publish, then call exposure_check again with the same target."New value: +"ownership_not_proven: publicFindings holds what any visitor can see; publish the record or file in publish, then call exposure_check again with the same target for the rest."
  3. Changed2 schema fields changed
    • removedOutput schema / properties / publicFindings
      Removed value: -{
      -  "description": "Before the proof: what any visitor can see. Headers, plain http, robots.txt paths and admin paths by status only.",
      -  "properties": {
      -    "adminNote": {
      -      "type": "string"
      -    },
      -    "adminPaths": {
      -      "items": {
      -        "properties": {
      -          "path": {
      -            "type": "string"
      -          },
      -          "status": {
      -            "type": [
      -              "integer",
      -              "null"
      -            ]
      -          }
      -        },
      -        "required": [
      -          "path",
      -          "status"
      -        ],
      -        "type": "object"
      -      },
      -      "type": "array"
      -    },
      -    "findings": {
      -      "items": {
      -        "properties": {
      -          "evidence": {
      -            "type": "string"
      -          },
      -          "fix": {
      -            "type": "string"
      -          },
      -          "risk": {
      -            "type": "string"
      -          },
      -          "severity": {
      -            "enum": [
      -              "high",
      -              "medium",
      -              "low"
      -            ],
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "severity",
      -          "risk",
      -          "fix",
      -          "evidence"
      -        ],
      -        "type": "object"
      -      },
      -      "type": "array"
      -    },
      -    "headerFix": {
      -      "properties": {
      -        "hosting": {
      -          "type": "string"
      -        },
      -        "snippet": {
      -          "type": "string"
      -        },
      -        "where": {
      -          "type": "string"
      -        }
      -      },
      -      "type": [
      -        "object",
      -        "null"
      -      ]
      -    },
      -    "hosting": {
      -      "type": "string"
      -    },
      -    "notChecked": {
      -      "items": {
      -        "type": "string"
      -      },
      -      "type": "array"
      -    },
      -    "page": {
      -      "type": "string"
      -    },
      -    "robots": {
      -      "properties": {
      -        "paths": {
      -          "items": {
      -            "type": "string"
      -          },
      -          "type": "array"
      -        },
      -        "sitemaps": {
      -          "items": {
      -            "type": "string"
      -          },
      -          "type": "array"
      -        },
      -        "status": {
      -          "enum": [
      -            "found",
      -            "missing",
      -            "unreachable"
      -          ],
      -          "type": "string"
      -        },
      -        "url": {
      -          "type": "string"
      -        }
      -      },
      -      "type": "object"
      -    }
      -  },
      -  "type": "object"
      -}
    • changedOutput schema / properties / verdict / description
      Previous value: -"ownership_not_proven: publicFindings holds what any visitor can see; publish the record or file in publish, then call exposure_check again with the same target for the rest."New value: +"ownership_not_proven: publish the record or file in publish, then call exposure_check again with the same target."
  4. Changed2 schema fields changed
    • addedOutput schema / properties / publicFindings
      Added value: +{
      +  "description": "Before the proof: what any visitor can see. Headers, plain http, robots.txt paths and admin paths by status only.",
      +  "properties": {
      +    "adminNote": {
      +      "type": "string"
      +    },
      +    "adminPaths": {
      +      "items": {
      +        "properties": {
      +          "path": {
      +            "type": "string"
      +          },
      +          "status": {
      +            "type": [
      +              "integer",
      +              "null"
      +            ]
      +          }
      +        },
      +        "required": [
      +          "path",
      +          "status"
      +        ],
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "findings": {
      +      "items": {
      +        "properties": {
      +          "evidence": {
      +            "type": "string"
      +          },
      +          "fix": {
      +            "type": "string"
      +          },
      +          "risk": {
      +            "type": "string"
      +          },
      +          "severity": {
      +            "enum": [
      +              "high",
      +              "medium",
      +              "low"
      +            ],
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "severity",
      +          "risk",
      +          "fix",
      +          "evidence"
      +        ],
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "headerFix": {
      +      "properties": {
      +        "hosting": {
      +          "type": "string"
      +        },
      +        "snippet": {
      +          "type": "string"
      +        },
      +        "where": {
      +          "type": "string"
      +        }
      +      },
      +      "type": [
      +        "object",
      +        "null"
      +      ]
      +    },
      +    "hosting": {
      +      "type": "string"
      +    },
      +    "notChecked": {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    "page": {
      +      "type": "string"
      +    },
      +    "robots": {
      +      "properties": {
      +        "paths": {
      +          "items": {
      +            "type": "string"
      +          },
      +          "type": "array"
      +        },
      +        "sitemaps": {
      +          "items": {
      +            "type": "string"
      +          },
      +          "type": "array"
      +        },
      +        "status": {
      +          "enum": [
      +            "found",
      +            "missing",
      +            "unreachable"
      +          ],
      +          "type": "string"
      +        },
      +        "url": {
      +          "type": "string"
      +        }
      +      },
      +      "type": "object"
      +    }
      +  },
      +  "type": "object"
      +}
    • changedOutput schema / properties / verdict / description
      Previous value: -"ownership_not_proven: publish the record or file in publish, then call exposure_check again with the same target."New value: +"ownership_not_proven: publicFindings holds what any visitor can see; publish the record or file in publish, then call exposure_check again with the same target for the rest."
  5. Changed1 schema field changed
    • addedOutput schema / properties / shipNaked
      Added value: +{
      +  "description": "The 7 pre-launch pages an app usually ships without, each pass, fail, warn or not_checked; a fail or warn carries snippet, the text to paste.",
      +  "properties": {
      +    "checks": {
      +      "items": {
      +        "properties": {
      +          "finding": {
      +            "type": "string"
      +          },
      +          "fix": {
      +            "type": "string"
      +          },
      +          "id": {
      +            "type": "string"
      +          },
      +          "item": {
      +            "type": "string"
      +          },
      +          "n": {
      +            "type": "integer"
      +          },
      +          "snippet": {
      +            "type": "string"
      +          },
      +          "sources": {
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "status": {
      +            "enum": [
      +              "pass",
      +              "fail",
      +              "warn",
      +              "not_checked"
      +            ],
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "n",
      +          "id",
      +          "item",
      +          "status",
      +          "finding",
      +          "sources"
      +        ],
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "counts": {
      +      "properties": {
      +        "fail": {
      +          "type": "integer"
      +        },
      +        "not_checked": {
      +          "type": "integer"
      +        },
      +        "pass": {
      +          "type": "integer"
      +        },
      +        "warn": {
      +          "type": "integer"
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "note": {
      +      "type": "string"
      +    },
      +    "pagesRead": {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    "source": {
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "source",
      +    "counts",
      +    "checks"
      +  ],
      +  "type": "object"
      +}
  6. Changed12 schema fields changed
    • changedInput schema / properties / target / description
      Previous value: -"A domain, host or page address you own, such as example.com or https://app.example.com/dashboard. The host is checked; a page address also names the page whose scripts are read for keys (the home page otherwise). A bare IP address is refused: pass a host name that points at the server."New value: +"A domain, host or page address you own, such as example.com or https://app.example.com/dashboard. Not a bare IP: pass a host name that points at the server. The host is checked; a page address also names the page whose scripts are read for keys (the home page otherwise)."
    • addedOutput schema / properties / answer / description
      Added value: +"One-paragraph answer to lead with."
    • addedOutput schema / properties / asOf / description
      Added value: +"When the check ran, ISO 8601 UTC."
    • addedOutput schema / properties / evidence / items / properties / severity / description
      Added value: +"Confirmed findings only: high, medium or low."
    • addedOutput schema / properties / evidence / items / properties / severity / enum
      Added value: +[
      +  "high",
      +  "medium",
      +  "low"
      +]
    • addedOutput schema / properties / keysFound / items / properties / severity / description
      Added value: +"Confirmed findings only: high, medium or low."
    • addedOutput schema / properties / keysFound / items / properties / severity / enum
      Added value: +[
      +  "high",
      +  "medium",
      +  "low"
      +]
    • addedOutput schema / properties / ownershipNote / description
      Added value: +"Reminder that the check is only for a target the caller owns."
    • addedOutput schema / properties / target / description
      Added value: +"Host checked."
    • addedOutput schema / properties / topRisks / items / properties / severity / description
      Added value: +"Confirmed findings only: high, medium or low."
    • addedOutput schema / properties / topRisks / items / properties / severity / enum
      Added value: +[
      +  "high",
      +  "medium",
      +  "low"
      +]
    • addedOutput schema / properties / verdict / description
      Added value: +"ownership_not_proven: publish the record or file in publish, then call exposure_check again with the same target."
  7. Changed5 schema fields changed
    • addedInput schema / properties / email
      Added value: +{
      +  "description": "Optional: the text or HTML of one marketing email the app sends, checked for an unsubscribe link and a postal address (CAN-SPAM). It is read in memory only and never returned or kept.",
      +  "maxLength": 100000,
      +  "type": "string"
      +}
    • addedOutput schema / properties / legal
      Added value: +{
      +  "properties": {
      +    "checks": {
      +      "items": {
      +        "properties": {
      +          "finding": {
      +            "type": "string"
      +          },
      +          "fix": {
      +            "type": "string"
      +          },
      +          "id": {
      +            "type": "string"
      +          },
      +          "law": {
      +            "type": "string"
      +          },
      +          "sources": {
      +            "items": {
      +              "properties": {
      +                "title": {
      +                  "type": "string"
      +                },
      +                "url": {
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "title",
      +                "url"
      +              ],
      +              "type": "object"
      +            },
      +            "type": "array"
      +          },
      +          "status": {
      +            "enum": [
      +              "needs_verification",
      +              "pass",
      +              "not_checked"
      +            ],
      +            "type": "string"
      +          },
      +          "topic": {
      +            "type": "string"
      +          },
      +          "unresolved": {
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "id",
      +          "topic",
      +          "law",
      +          "status",
      +          "finding",
      +          "sources"
      +        ],
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "note": {
      +      "type": "string"
      +    }
      +  },
      +  "type": "object"
      +}
    • addedOutput schema / properties / needsVerification
      Added value: +{
      +  "items": {
      +    "properties": {
      +      "check": {
      +        "type": "string"
      +      },
      +      "item": {
      +        "type": "string"
      +      },
      +      "risk": {
      +        "type": "string"
      +      },
      +      "source": {
      +        "type": "string"
      +      },
      +      "unresolved": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "risk",
      +      "unresolved",
      +      "check",
      +      "source",
      +      "item"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / phases
      Added value: +{
      +  "items": {
      +    "properties": {
      +      "did": {
      +        "type": "string"
      +      },
      +      "phase": {
      +        "enum": [
      +          "map",
      +          "hunt",
      +          "verify",
      +          "report"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "phase",
      +      "did"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / rejected
      Added value: +{
      +  "items": {
      +    "properties": {
      +      "claim": {
      +        "type": "string"
      +      },
      +      "item": {
      +        "type": "string"
      +      },
      +      "reason": {
      +        "type": "string"
      +      },
      +      "source": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "claim",
      +      "reason",
      +      "source",
      +      "item"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
  8. Changed6 schema fields changed
    • changedInput schema / properties / target / description
      Previous value: -"A domain or host you own, such as example.com or app.example.com. A URL is read as its host. A bare IP address is refused: pass a host name that points at the server."New value: +"A domain, host or page address you own, such as example.com or https://app.example.com/dashboard. The host is checked; a page address also names the page whose scripts are read for keys (the home page otherwise). A bare IP address is refused: pass a host name that points at the server."
    • addedOutput schema / properties / adminPaths
      Added value: +{
      +  "items": {
      +    "properties": {
      +      "path": {
      +        "type": "string"
      +      },
      +      "status": {
      +        "type": [
      +          "integer",
      +          "null"
      +        ]
      +      }
      +    },
      +    "required": [
      +      "path",
      +      "status"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / keysFound
      Added value: +{
      +  "items": {
      +    "properties": {
      +      "prefix": {
      +        "type": "string"
      +      },
      +      "severity": {
      +        "type": "string"
      +      },
      +      "type": {
      +        "type": "string"
      +      },
      +      "where": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "where",
      +      "prefix"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / ownershipNote
      Added value: +{
      +  "type": "string"
      +}
    • addedOutput schema / properties / scriptsRead
      Added value: +{
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "target",
      -  "verdict",
      -  "answer"
      -]New value: +[
      +  "target",
      +  "verdict",
      +  "answer",
      +  "ownershipNote"
      +]
  9. Changed1 schema field changed
    • removedOutput schema / properties / note_from_openkrill
      Removed value: -{
      -  "description": "Shown at most once a day per caller: what this server offers, and a paid service for the person you work for.",
      -  "type": "string"
      -}
  10. Changed1 schema field changed
    • changedInput schema / properties / target / description
      Previous value: -"A domain or host you own, such as example.com or app.example.com, or a public IPv4 address such as 203.0.113.7. A URL is read as its host."New value: +"A domain or host you own, such as example.com or app.example.com. A URL is read as its host. A bare IP address is refused: pass a host name that points at the server."
  11. Added

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive and open-world, and the description adds substantial behavior the agent could not infer: a mandatory ownership-proof handshake via DNS TXT record or file, GET-only access to at most 32 fixed paths, no crawl/sign-in/port scan, and file contents never returned. It also discloses output categories and the 'not legal advice' caveat, which matters for how results should be relayed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads purpose, then usage, then the ownership handshake, then outputs, then exclusions — a sensible ordering with no filler. It is a long, tightly packed block with several clauses per sentence, which makes it slightly harder to scan than it needs to be for the amount of content it carries.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, yet the description still names the result states (ownership_not_proven, exposed, clean), the top-three risks with fixes, and the shipNaked/legal-signal extras, so an agent knows what to expect and what to tell the user. Nothing needed to invoke it correctly — target form, ownership prerequisite, scope limits, ethical restrictions — is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so both parameters are already well documented in the schema. The description reinforces the target rule ('a domain, host or app page address, not a bare IP') but adds no syntax or behavior beyond what the schema states, and it never mentions the optional email input or the 30-day input log for that field. Baseline 3 is appropriate when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Checks what a site or app the user owns leaks publicly') and then enumerates the concrete surface it inspects: dangling subdomains, leaked files, masked API keys, source maps, admin paths, dev servers, default pages. That enumerated scope separates it from the other checks in the catalog (AI readiness, page tags, landing page SEO) without needing to name them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit trigger ('when the user asks what an attacker could find on their own domain, host or app') with a sample query, plus explicit exclusions: not on targets the user does not own, not for person/user name/email lookups, not for private or local addresses. It also sets the two-call ownership flow so the agent knows a first 'ownership_not_proven' result is expected rather than a failure.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.