answerbeacon
# answerbeacon-check
**See what AI search tools can read on a page, and get a copy-paste fix for every miss.**
ChatGPT, Perplexity, Claude and Gemini answer questions that used to go to a list of links. They can only quote what they can read. `answerbeacon-check` fetches one page, scores it against 20 on-page elements those tools and search engines rely on (titles, descriptions, headings, JSON-LD, FAQ, breadcrumbs, calls to action and more), shows the evidence for every result, and generates the markup to fix each miss.
It is a CLI and a local [MCP](https://modelcontextprotocol.io) server. Pure Python standard library, no API keys, no account.
```console
$ answerbeacon-check eliteagenticsolutions.com
https://eliteagenticsolutions.com score 16/20
PASS 1. SEO Page Titles — 'Elite Agentic Solutions — Governable AI Agents' (52 chars)
PASS 2. Meta Descriptions — 'A five-agent engine with a hash-chained audit trail and rule engine on every a
PASS 3. Keyword Rich H1s — 1 <h1> found: ['Ship AI Agents Any Business CanAudit, Govern, and Trust.']
MISS 5. Image Alt Text — 1 imgs, 0 with alt (0%)
MISS 10. Location Pages — no location page link
MISS 16. Customer Reviews — JSON-LD types present: ['Answer', 'Brand', 'BreadcrumbList', 'ContactPoint', 'FA
MISS 20. Helpful Blog Content — no blog link; JSON-LD types: ['Answer', 'Brand', 'BreadcrumbList', 'ContactP
... (PASS lines for the other elements trimmed)
```
That is a real run against our own site on 2026-11-04, misses included.
## Install
```bash
pipx install git+https://github.com/iskra-astudillo/answerbeacon-check
# or, from a clone:
python -m answerbeacon_check example.com
```
Python 3.8 or newer. No dependencies.
## Use
```bash
answerbeacon-check example.com # human report
answerbeacon-check example.com --json # full report with evidence and fixes
answerbeacon-check example.com --fixes-out fixes/ # one file per fix (JSON-LD, meta tags, robots.txt, sitemap.xml)
answerbeacon-check example.com --min-score 18 # exit 1 below 18: a CI gate for your marketing site
answerbeacon-check example.com --no-robots # skip the robots.txt check (only for sites you own)
```
Exit codes: `0` scanned, `1` below `--min-score`, `2` the page could not be read.
## MCP server
`answerbeacon-check mcp` starts a stdio MCP server with two tools:
| Tool | What it does |
|---|---|
| `audit_page(url)` | Runs the audit and returns the JSON report: score, evidence per element, fixes. |
| `explain_check(check)` | Explains what one element (`e01_title` … `e20_blog`) looks for. |
**Claude Code**
```bash
claude mcp add answerbeacon -- answerbeacon-check mcp
```
**Claude Desktop / Cursor** (`claude_desktop_config.json` or `.cursor/mcp.json`)
```json
{
"mcpServers": {
"answerbeacon": { "command": "answerbeacon-check", "args": ["mcp"] }
}
}
```
Then ask your agent: *"Audit example.com for AI-search readiness and apply the fixes to our templates."* The repo also ships a [`SKILL.md`](SKILL.md) that tells an agent how to apply fixes without inventing facts.
## The 20 elements
| # | Element | Passes when |
|---|---|---|
| 1 | Page title | `<title>` present, 15–70 characters |
| 2 | Meta description | `meta name="description"`, 50–180 characters |
| 3 | H1 | exactly one `<h1>`, at least 10 characters |
| 4 | Internal links | at least 5 distinct internal links |
| 5 | Image alt text | at least 80% of `<img>` carry alt text |
| 6 | FAQ section | a visible FAQ heading |
| 7 | FAQ schema | JSON-LD `FAQPage` |
| 8 | Local keywords | locality phrases in body copy ("serving", "based in", …) |
| 9 | Service pages | a link to `/services`, `/solutions`, `/products` or `/pricing` |
| 10 | Location pages | a link to `/locations`, `/areas-we-serve` or `/service-area` |
| 11 | Breadcrumbs | `BreadcrumbList` JSON-LD or a breadcrumb nav |
| 12 | Organization schema | `Organization`, `Corporation`, `SoftwareApplication` or `WebSite` |
| 13 | Local business schema | `LocalBusiness` or a subtype |
| 14 | Service schema | `Service`, `Product` or `Offer` |
| 15 | Author bios | `Person` schema or an author or team byline |
| 16 | Reviews | `Review` / `AggregateRating` schema or a testimonials block |
| 17 | Case studies | case-study or success-story content |
| 18 | Related content | a related-reading block |
| 19 | Call to action | an explicit CTA phrase in visible text |
| 20 | Blog | a link to `/blog`, `/articles`, `/resources`, `/insights`, `/guides` or `Article` schema |
Every element in the JSON report carries `what` (what was searched for) and `found` (what was actually seen), so you can check any verdict yourself.
A second, **non-scored** block (`hygiene_checks`) covers single-page technical hygiene: title and description length, multiple H1s, skipped heading levels, thin content, noindex, canonical pointing elsewhere, redirect chains and slow responses. Its taxonomy is adapted from [every-app/open-seo](https://github.com/every-app/open-seo) (MIT); see [NOTICE](NOTICE).
## Fixes that refuse to lie
Fixes are generated per miss: title and meta templates, `Organization`, `Service` and `BreadcrumbList` JSON-LD, Open Graph tags, `robots.txt`, `sitemap.xml` and a canonical link. Two guardrails are built in:
- **No FAQPage schema without a visible FAQ.** Google treats it as structured-data spam, so the fix says to write the visible FAQ first.
- **No LocalBusiness schema without a real address on the page.** Emitting it would assert premises that do not exist.
## Safety
- **One bounded fetch** of the page, plus `robots.txt` and `sitemap.xml`. Hard timeout (8 s), 2 MB byte cap, at most 3 redirects.
- **SSRF guard.** Every hop is resolved and refused if it points at private, loopback, link-local, reserved or multicast space, so the MCP tool cannot be used to probe your network or a cloud metadata endpoint.
- **Respects robots.txt.** A `Disallow: /` for `*` or for this tool stops the scan.
- **Fails closed.** An unreachable, blocked or non-HTML page returns `ok: false` with an error class and `score: null`. It never returns a number it did not measure.
## What it does not do
It does not query ChatGPT, Perplexity or any other assistant, and it does not promise that a page will be cited. It checks whether the page gives those tools something clear to read. Treat the score as a work list, not a ranking.
## Design notes
- **Evidence over booleans.** An early internal version required quoted attributes and missed `<meta name=description content=...>` on minified pages. Attribute parsing now accepts unquoted values, and every result carries the string it matched, so a false negative is visible in the report.
- **Fix next to the failure.** Each check that can fail has a generated fix, so the output is a task list rather than a grade.
- **Score stability.** Hygiene checks were added as a separate block so that "20/20" keeps meaning the same thing across versions.
## Hosted version
[AnswerBeacon](https://brandrank.eliteaiempire.com) runs the same audit in the browser, re-audits on a schedule and attributes AI-crawler visits to the company behind each bot.
## License
MIT. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
TDQS
Scored across 2 tools
audit_page performs the scoring action on a URL, while explain_check only describes a single element's criteria; there is no plausible way to confuse the two. Each tool also has a distinct return shape (score plus evidence vs. explanatory text).
Both names use the same snake_case verb_noun pattern (audit_page, explain_check), with clear, concrete verbs. No mixed conventions or vague catch-all names.
Two tools is on the thin side, though they map cleanly to the only two actions implied by the domain (score a page, explain a criterion). The surface feels borderline minimal rather than over- or under-built for a single-purpose auditor.
The core lifecycle—run an audit and look up what each of the 20 checks means—is covered, and audit_page returns evidence plus fixes for every element, so there are few dead ends. A minor gap: there is no tool to enumerate e01...e20, so an agent must obtain IDs from audit output or guess them.