Website Auditor MCP
This server lets an AI agent audit any website's AI-visibility (GEO) and site health through the Website Auditor API, returning scores, competitor comparisons, fixes and monitoring.
Check AI visibility (
get_ai_visibility): 0–100 GEO score, per-engine breakdown (ChatGPT, Perplexity, Claude, Gemini), whether the site appears, top competitor taking its place, cited sources, and 7/30-day trend.Run a full audit (
run_audit): category scores (AI visibility, SEO/crawlability, security, performance), top issues, and a shareable report URL.Track changes (
get_changes): like-for-like score movement across snapshots that asked the same question.Compare competitors (
compare_competitors): head-to-head ranking, per-engine gaps where rivals appear and you don't, quota-aware.Monitor sites (
track_site,untrack_site,list_tracked_sites,get_monitoring_status): weekly re-audits, slots, dashboards, latest scores and changes.Get fixes (
get_recommendations,generate_schema): prioritized, evidence-backed actions and draft JSON-LD structured data.Benchmark (
get_benchmark): percentile versus industry/geo peers.Share results (
get_report): report URL plus embeddable badge snippet.Build a plan (
get_gtm_plan): written 30/60/90-day GTM plan grounded in citation evidence.Check account (
check_upgrade_status): tier, trial/renewal status, upgrade URL — no quota used.Try it free (
get_sample_audit): full sample report for example.com, no API key or network needed.
Provides AI-visibility checks for the Perplexity engine, reporting whether a website is recommended by Perplexity and including a Perplexity-specific score in the per-engine breakdown.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Website Auditor MCPcheck my AI visibility score for example.com"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Website Auditor MCP
An MCP server for website-auditor.io — AI-visibility (GEO) and site-audit tools you can call from any MCP client (Claude Desktop, Claude Code, Cursor, Codex, and other agents).
Ask an agent "does ChatGPT recommend my business?", "what's my AI-visibility score?", "audit example.com", or "how do I stack up against my competitors?" and it answers with real data — an overall AI-visibility score (0–100), a per-engine breakdown across ChatGPT, Perplexity, Claude, Gemini, Microsoft Copilot and Google AI Overviews, a full site audit (security, performance, crawlability and markup), competitor comparisons, and ongoing monitoring.
The server is a thin, authenticated wrapper over the Website Auditor API — the audit engine, AI-visibility scoring and monitoring live in that service; this server just makes them available to agents.
Tools
Tool | Tier | What it does |
| Free — no key | A complete sample report for |
| Pro | Current AI-visibility score (0–100) + per-engine breakdown (ChatGPT, Perplexity, Claude, Gemini, Microsoft Copilot, Google AI Overviews) + the top competitor appearing in your place. Pro subscribers also get |
| Pro, rate-limited | Full one-time audit → category scores (AI visibility, crawlability and markup as |
| Pro | What changed in the AI-visibility score — the change in the overall score and the per-engine score changes, for engines measured both times, the overall only when the same engines answered both snapshots (else it is null with an |
| Pro | Head-to-head AI-visibility ranking against named competitor domains + where each appears that you don't. Quota-aware: caps the audit fan-out to your remaining daily quota, reuses recent cached audits, and reports any competitors it had to skip rather than dropping them silently. Also |
| Pro | Start (or stop) weekly monitoring of a site's AI visibility. Its weekly re-audits join the history |
| Pro | Stop monitoring a site and free up a monitoring slot. Deletes the site's monitoring enrollment; past audits are kept. |
| Pro | List the sites you're monitoring, with cadence, active state, and slots used/remaining. |
| Pro | A glanceable dashboard across all tracked sites — latest score of each site's series (the series |
| Pro | A tracked site's ready-made fixes ("Get this fix"), top first: whether each is needed and why, whether the site's platform can take it, and its newest request and status (live / missing). Records nothing. |
| Pro | The business facts the fixes are written from, to show the owner: what the site says, what they confirmed, the business name the audits found, and |
| Pro | "Get this fix": the fix served finished (structured data plus About/FAQ text, an llms.txt, or robots.txt lines that let blocked AI assistants in), the first two written only from the owner's confirmed facts, each block ready to copy, with paste steps for the site's platform and |
| Pro | Confirms the facts the owner confirmed or corrected, sending back exactly the |
| Pro | "I've added it": reads the live site for a fix request and says it's live or names what's missing. Once a minute per request ( |
| Any valid key | Your own subscription standing — tier, status, period end, and what upgrading unlocks (starting Pro requires a payment method and accepting the Terms). Consumes no audit quota. |
Related MCP server: seo-audit-mcp
Prompts
Clients that support MCP prompts (Claude Desktop, claude.ai) render these as something you can pick from a menu, so you don't have to phrase the request yourself or know which tool to ask for. In clients that don't surface prompts (Codex, currently), nothing is lost but the menu — ask in words and the same tools run.
Prompt | Needs a key? | What it does |
See a sample report | No | Walks through a complete report for |
Check my AI visibility | Pro | Runs |
Run a full site audit | Pro | Runs |
Compare me to a competitor | Pro | Runs |
Each Pro prompt falls back to get_sample_audit when no API key is configured,
so you always get output rather than an error.
Naming the business (optional)
get_ai_visibility and run_audit both accept two optional arguments that
decide what question the AI-visibility check actually asks.
compare_competitors accepts business_location only — see below for why it
takes no name:
Argument | Omitted | Supplied |
| Detected from the site, and flagged with | Taken as fact and recorded as caller-supplied — which suppresses the warning |
| Detected from the site; if nothing is found the questions widen to the country, or drop the place entirely | Scopes the questions to that place |
Supply a name only when you actually know it. A supplied name overrides detection and is treated as confirmed, so a guess is scored exactly as if a human had verified it — and silences the warning that would have told you otherwise. Leaving it out is the safer default: detection is transparent about its own uncertainty.
The same applies to location, in the other direction. Omitting it is correct for a national or global business and wrong for a local one, since a local business measured without a place is measured against the wrong queries.
On compare_competitors: it takes business_location and applies it to
your site and every competitor, because a comparison asks about one market —
scoring you locally while scoring your rivals globally would rank the answers
to two different questions. It deliberately takes no business_name: a name
identifies one business, and forwarding yours to your competitors would score
every one of them as you. The result names the market it used, so a scoped
comparison is never mistaken for a global one.
"Check AI visibility for hawaiibackroad.com,
the business is Big Island Backroad Adventures in Hilo, HI"Install & configure
The server runs directly via npx — no clone or build required.
Try it before you buy it. Install with no API key at all and ask your agent
for a sample audit — get_sample_audit returns a full report for example.com
in the exact format a real run produces, so you can check the shape fits your
needs first.
Pricing. Auditing real domains needs a Website Auditor subscription at
$49/month — eligible new customers get a 7-day free trial (payment
method required to start; no charge until the trial ends; customers who used
a trial in the last 12 months are billed immediately). Sign up and create an
API key at
api.website-auditor.io/admin_portal,
then set it as WA_API_KEY below. There is no free API tier — a key only
functions with an active subscription.
Claude Desktop (claude_desktop_config.json), Cursor
(~/.cursor/mcp.json), and most other clients use the same mcpServers shape:
{
"mcpServers": {
"website-auditor": {
"command": "npx",
"args": ["-y", "website-auditor-mcp"],
"env": {
"WA_API_KEY": "wa_your_key_here"
}
}
}
}Claude Code — add it from the CLI:
claude mcp add website-auditor -e WA_API_KEY=wa_your_key_here -- npx -y website-auditor-mcpCodex — the CLI, IDE extension and ChatGPT desktop app all read the same
~/.codex/config.toml, so one of these covers all three:
codex mcp add website-auditor --env WA_API_KEY=wa_your_key_here -- npx -y website-auditor-mcp[mcp_servers.website-auditor]
command = "npx"
args = ["-y", "website-auditor-mcp"]
[mcp_servers.website-auditor.env]
WA_API_KEY = "wa_your_key_here"Codex doesn't render MCP prompts, so the Prompts above won't appear as menu entries there — ask in words instead ("show me a sample audit").
Or install the packaged Codex plugin, which bundles the same server and restores the prompts as skills (which Codex does render):
codex plugin marketplace add SpikeyCoder/website-auditor-mcp
codex plugin add website-auditor@spikeycoderCursor — one-click install, or put the same mcpServers JSON as above in
~/.cursor/mcp.json:
The one-click config arrives with an empty WA_API_KEY — the sample report
works as-is; fill the key in under Settings → MCP to audit real domains.
There is also a packaged Cursor plugin (this server plus the prompts as
skills) in cursor-plugin/; its Cursor Marketplace listing
is pending — status in docs/CURSOR-PLUGIN.md.
Restart the client and the tools appear.
Getting an API key
WA_API_KEY is a per-user key (it starts with wa_) minted from a Website
Auditor account at
api.website-auditor.io/admin_portal
— the admin portal, where you subscribe and manage keys.
Minting a key requires an active subscription ($49/month; eligible new
customers get a 7-day free trial — payment method required, no charge until
the trial ends): there is no free API tier, so every tool except
get_sample_audit, check_upgrade_status and get_recommendations needs one.
get_sample_audit needs no key at all. get_recommendations answers any valid
key with the next steps from an audit already on record; with Pro it also says
where to get listed, what AI assistants get wrong about the business, and which
fix file fixes each finding.
Treat the key like a password — set it only in your MCP client's env and never
commit it.
Restart after setting or changing the key. WA_API_KEY is read once, when
the server starts, so a key added while the client is running is invisible to
it — in Claude Desktop, quit and reopen the app. Without the restart the tools
keep returning the same AUTH_REQUIRED you just acted on, which looks
identical to the key not working.
Configuration (environment variables)
Var | Default | Purpose |
| (required) | Per-user API key (starts with |
|
| The Website Auditor API this server wraps. |
|
| Used to build shareable report links. |
|
| Where auth and subscription errors point you. |
|
|
|
|
|
|
|
| Which surface this server is: |
| (unset) |
|
|
| Hosted with Mixed Auth only. |
|
| Timeout for API calls. |
|
| Reuse a domain's audit within this window instead of spending quota (used by |
|
| How long a resolved Pro/free tier is cached per key before re-checking the subscription. |
| (unset → metrics on) | Set to |
Only WA_API_KEY is normally needed; the rest have sensible defaults. See
.env.example for the full list.
Auth & tiers
Your key is validated on every call. The Pro/free tier is resolved live from the API and cached briefly, so upgrades and downgrades take effect within about a minute:
No key →
get_sample_auditstill works (that's the point of it); every other tool returnsAUTH_REQUIREDwith the price and a sign-up link.Revoked or unrecognized key →
INVALID_KEY, carrying the API's own remediation ("generate a new key"). Distinct fromPRO_REQUIRED: the fix is a new key, not a purchase.No active subscription (valid key, lapsed/canceled/never subscribed) →
PRO_REQUIREDwith the price and an upgrade link — there is no free API tier;check_upgrade_statusstill answers so the caller can learn why, andget_recommendationsstill answers with the free list ("tier": "free").Subscribed (status
activeor a trial in progress) → all tools.
Errors are normalized to stable codes agents can branch on — e.g.
AUTH_REQUIRED, INVALID_KEY, PRO_REQUIRED, OVER_QUOTA,
UNREACHABLE_DOMAIN, INVALID_INPUT, TIMEOUT. A domain that resolves but
whose pages never load (down, refusing, timing out, or answering 404/5xx on
every page) returns UNREACHABLE_DOMAIN; one that does not resolve is refused
before any audit runs, as INVALID_INPUT. Neither gets a fabricated score.
Develop
npm install
npm run build # compile TypeScript → dist/
npm start # serve over stdio
npm run dev # run from source without building
npm test # vitest
npm run typecheckThe suite is hermetic — the API client, subscription provider and meter are
injected, and HTTP is mocked at the fetch boundary, so no network is touched.
Privacy Policy
Anonymous install id. When telemetry is enabled, the server generates a
random UUID on first run and stores it at
~/.config/website-auditor-mcp/install-id (or $XDG_CONFIG_HOME), sending it
with each event. It exists solely to tell one install restarting many times
apart from many separate installs — without it, install counts are just restart
counts. It is randomly generated, never derived from your machine, username or
network, and is not a fingerprint. Setting WA_METRICS_DISABLED stops
telemetry entirely: no id is generated and nothing is written to disk.
This connector talks to a single external service: the Website Auditor API at website-auditor.io. When you invoke a tool it sends only two things to that API:
the target domain you asked to audit or monitor, and
your API key (
WA_API_KEY), used to authenticate the request and resolve your plan tier.
At startup, and at most hourly while tools are in use, the server also asks
the same API for Pro's current price (GET /pricing.json), so the price it
states is never out of date. That request carries no key, no install id and no
data about you or your sites.
That's the full extent of what leaves your machine. The connector does not collect, store, or transmit your files, prompts, conversation content, or any other personal data, and it does not send data to any third party beyond the Website Auditor API. Your API key is held only in your MCP client's configuration (in Claude Desktop it is stored in the OS keychain and injected as an environment variable); it is never written to the bundle or logged.
Anonymous, aggregate usage telemetry (which tool ran, success/failure, latency —
no domains, no keys, no personal data) may be emitted to improve the service, and
can be disabled entirely by setting WA_METRICS_DISABLED=1. Installed as a
desktop extension, the same opt-out is a "Disable anonymous usage telemetry"
checkbox in the extension's settings.
Full privacy policy: https://website-auditor.io/privacy
License
MIT — © 2026 Kevin Armstrong / SpikeyCoder.
This covers the MCP server in this repo: the client that talks to the Website Auditor API. The audit engine and the API behind it are separate products, not covered here, and running real audits still needs a Website Auditor account.
Learn more at website-auditor.io.
Available Tools
20 toolscheck_fixCheck a fix is liveA
"I've added it": check whether a fix is live on the site. Use this when the owner says they have added, pasted or published a fix, or asks "is it live" or "did it work." Reads the live site for the fix request id (from get_fix, or a fix's newest request in list_fixes) and records what it found: live, or what is missing, each named. For the business-facts fix the home page's structured data has to state every fact the fix stated; for llms.txt, /llms.txt has to answer with a valid file; for the robots.txt lines, /robots.txt has to let in every assistant the fix named. A site that did not answer is not called missing the fix (reached false). One check a minute per request: asked again sooner it answers CHECKED_RECENTLY with retry_after. It does not predict any change in AI visibility; the weekly check observes that. Requires a Website Auditor subscription ($49/month; eligible new customers get a 7-day free trial — payment method required, no charge until the trial ends) — if the user doesn't have one, call get_sample_audit first to show them the exact output format, free and with no API key.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The fix request's id: `request.id` from the fix as served, or a fix's newest `request.id` in the site's fix list. | |
| domain | Yes | The website domain, e.g. "example.com". |
Output Schema
| Name | Required | Description |
|---|---|---|
| live | Yes | |
| check | Yes | |
| domain | Yes | |
| message | Yes | |
| request | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well past the annotations: it describes exactly what is verified per fix type (structured data on the home page, /llms.txt, /robots.txt), how an unreachable site is treated (`reached` false rather than 'missing'), the one-per-minute throttle with CHECKED_RECENTLY and retry_after, and the subscription/trial requirement. The recording behavior is consistent with readOnlyHint=false, so no contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Despite its length, it is front-loaded with the core action and trigger, then verification criteria, then failure/throttle semantics, then the subscription caveat. Every sentence carries operational information; the pricing parenthetical is verbose but serves a routing purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a live-site verification tool with an output schema and non-obvious per-fix-type acceptance criteria, the description covers what an agent needs to call it correctly and interpret results. Nothing material about prerequisites, throttling, or failure modes is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both `domain` and `id`; the description's note that the id comes from get_fix or list_fixes largely restates the schema's own wording. It adds no format or validation detail beyond what the schema supplies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and object ('check whether a fix is live on the site') and frames it around the owner's claim ('I've added it'), which separates it cleanly from get_fix, list_fixes, and confirm_facts.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit trigger phrases ('added, pasted or published', 'is it live', 'did it work') and names where the required `id` comes from (get_fix or a fix's newest request in list_fixes). It also draws a clear boundary against the weekly AI-visibility check and prescribes a fallback (get_sample_audit) when the subscription is absent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_upgrade_statusCheck upgrade statusARead-only
Check the caller's own Website Auditor subscription standing. Use this when someone asks "am I on Pro," "is my trial still active," "when does my subscription renew/end," "why is this tool locked," or before suggesting an upgrade. Works with any valid API key and consumes no audit quota. Returns the tier (none/free/pro), raw subscription status, period end, whether the subscription is set to cancel, the upgrade URL, and a plain-language summary — including what starting Pro requires (a payment method and accepting the Terms).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| tier | Yes | "none" | "free" | "pro". |
| status | Yes | Raw subscription status: active, trialing, canceled, none, … |
| message | Yes | |
| upgrade_url | Yes | |
| current_period_end | Yes | |
| cancel_at_period_end | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description still adds real value beyond them: no audit quota is consumed and any valid API key works, which the agent cannot infer from annotations. Most of the remaining text enumerates return fields that the output schema already carries, so this is strong but not maximal.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose then triggers, and every clause is actionable. The lengthy enumeration of return fields (tier, raw status, period end, cancel flag, upgrade URL, summary) partly duplicates the output schema, which is the one place the text does not fully earn its length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only status tool with an output schema, the description covers everything an agent needs: when to call it, auth requirements, quota cost, and what starting Pro requires. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so schema coverage is moot and the baseline of 4 applies. The description usefully implies there is no subject argument — it only reports the caller's own subscription — which prevents an agent from hunting for a user ID to pass.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — 'Check the caller's own Website Auditor subscription standing' — and the 'caller's own' scope cleanly separates it from every sibling, none of which touch subscription state. An agent can identify the tool from the first sentence alone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit trigger conditions with quoted user phrasing ('am I on Pro', 'is my trial still active', 'why is this tool locked') plus a proactive case ('before suggesting an upgrade'). It also names the precondition for use (any valid API key) and confirms no cost, so an agent knows both when and how freely to call it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
compare_competitorsCompare against competitorsA
Compare a website's AI visibility head-to-head against named competitors. Use this when someone asks "how do I stack up against X and Y," "who does ChatGPT recommend instead of me," or wants a competitive AI-visibility view. Returns each competitor's score and where they appear that the site does not. Each competitor not already cached costs one audit against your daily quota; if the quota can't cover every competitor, it ranks the ones it could audit and returns a quota summary plus a skipped list naming the rest — it never drops competitors silently or invents scores. If the quota is already exhausted it returns an over-quota error with the reset time. Requires a Website Auditor subscription ($49/month; eligible new customers get a 7-day free trial — payment method required, no charge until the trial ends) — if the user doesn't have one, call get_sample_audit first to show them the exact output format, free and with no API key.
| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | The website domain, e.g. "example.com". | |
| competitors | Yes | Competitor domains to compare against. | |
| business_location | No | Optional. The market to compare within, e.g. "Chiang Mai, Thailand". Applied to the site AND every competitor, because a comparison asks about one market — scoring one locally and the others globally would rank answers to two different questions. Leave it out and each audit detects its own location, which is right for national or global businesses and wrong for local ones. |
Output Schema
| Name | Required | Description |
|---|---|---|
| gaps | Yes | Engines where a competitor appears in AI answers and this site does not. |
| quota | Yes | |
| market | Yes | The market every audit in this comparison was scored in, or null when each domain's own location was detected. |
| ranking | Yes | |
| skipped | Yes | |
| summary | Yes | |
| dashboard | No | |
| recommendation_gap | No | How far behind the competitor you trail most the site is, each side as a share of its own answers, compared on the assistants that answered for both. Present only when both audits recorded stances; its sentence reads the result back in one line. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say readOnly=false, destructive=false, openWorld=true; the description adds the material facts an agent needs: each uncached competitor costs one audit against a daily quota, partial results are ranked with a `skipped` list rather than silently dropped, and exhausted quota yields an over-quota error with reset time. It also discloses the paid subscription prerequisite and trial terms, which no annotation conveys.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and trigger phrases, then behavior, then prerequisites — a sensible ordering with no filler sentences. It is on the long side, and the parenthetical pricing/trial detail ($49/month, 7-day trial, payment method) is verbose, though it is information the agent may need to relay to the user.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 frames the result shape at a high level (per-competitor score plus where they appear) and documents the quota and skipped fields that explain partial results. Combined with the subscription gate and the get_sample_audit fallback, nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema itself already explains business_location's market-scoping rationale thoroughly, so the description adds little parameter-level meaning. It does imply that competitors are audited individually (each is a domain subject to quota), but not beyond what the schema conveys. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Compare a website's AI visibility head-to-head against named competitors") and makes clear it is a multi-domain comparison, which separates it from single-site siblings like get_ai_visibility and get_benchmark. An agent can pick it without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete user-intent triggers ("how do I stack up against X and Y", "who does ChatGPT recommend instead of me") and names an explicit alternative path: call get_sample_audit first for users without a Website Auditor subscription. It also tells the agent what happens when quota is insufficient versus exhausted, so the routing decision is fully specified.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
confirm_factsConfirm business factsA
Confirm the business facts a site's fixes are written from, as the site's owner confirms them. Use this only after showing the owner the facts get_fix_facts or get_fix returned (the confirm block, with the business name) and getting their own confirmation or corrections: never confirm facts on the owner's behalf, and never without asking them. facts is the owner's answers, keyed by each fact's fact in the confirm block (the business name under "name"); seen is sent back exactly as it was handed out, unchanged, and the confirmation is refused without it. Returns status "confirmed" with the confirmed block and its new seen. When the site's facts changed since they were shown, nothing is confirmed (status "facts_changed", with the facts as they are now): read them again with get_fix_facts and show the owner before confirming. With status "facts_not_read" the site has not been read yet and there is nothing to confirm. Confirmations are capped over any 24 hours (TOO_MANY_CONFIRMATIONS, with retry_after). Requires a Website Auditor subscription ($49/month; eligible new customers get a 7-day free trial — payment method required, no charge until the trial ends) — if the user doesn't have one, call get_sample_audit first to show them the exact output format, free and with no API key.
| Name | Required | Description | Default |
|---|---|---|---|
| seen | Yes | Exactly the `seen` that came with the facts shown to the owner, unchanged. Without it, or with it changed, nothing is confirmed. | |
| facts | Yes | The owner's answers, keyed by each fact's `fact` in the confirm block (the business name under "name"). A fact left out or empty is not confirmed. | |
| domain | Yes | The website domain, e.g. "example.com". |
Output Schema
| Name | Required | Description |
|---|---|---|
| seen | No | Present when confirmed: what the block shows now, for a later correction; null when the facts cannot be confirmed again now. |
| domain | Yes | |
| status | Yes | "confirmed"; "facts_changed": nothing confirmed, the site's facts changed since they were shown (`confirm` is the block as it is now); "facts_not_read": nothing confirmed, the site has not been read yet. |
| confirm | No | The confirm block: each fact with what the site says and what the owner confirmed. |
| message | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: discloses the concurrency/staleness guard (status 'facts_changed' with guidance to re-read and re-show), the 'facts_not_read' precondition, the hard failure without a matching 'seen', a 24-hour confirmation cap with TOO_MANY_CONFIRMATIONS and retry_after, and the subscription gating. None of this appears in the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and the show-then-confirm rule, and the status enumeration carries genuine information. It is a single dense paragraph with heavy parenthetical nesting, and the closing subscription/trial pricing sentence is verbose relative to its decision value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a gated, owner-consent-dependent mutation with nested parameters, the description covers preconditions, failure modes, follow-up actions, and rate limits. An output schema exists, yet the status semantics are still surfaced because they drive the next agent action.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds real meaning the schema lacks: 'facts' is keyed by each fact's `fact` field from the confirm block (business name under 'name'), and omitted/empty facts are simply not confirmed. The 'seen' explanation largely restates the schema's own wording, which keeps it from a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Confirm the business facts a site's fixes are written from') plus the authority framing ('as the site's owner confirms them'). It is clearly distinct from the read-only siblings get_fix_facts and get_fix, which are named as prerequisites.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit trigger condition ('only after showing the owner the facts get_fix_facts or get_fix returned'), explicit prohibitions ('never confirm facts on the owner's behalf, and never without asking them'), and an explicit alternative path ('call get_sample_audit first') when the subscription gate blocks use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
generate_schemaGenerate JSON-LD schemaARead-only
Generate structured data (JSON-LD schema) tailored to a website, to improve how AI assistants and search engines understand it. Use this when someone asks for "schema," "structured data," "JSON-LD," or wants the actual markup to implement a recommendation. Returns a DRAFT, not finished markup: every name field arrives as a placeholder — "Your Business Name" on the business types, and on a Product the product's own name and brand as "Your Product Name" and "Brand Name" — that the owner must replace with real names confirmed with them, never guessed from the domain or copied from an audit. placement_notes says what to replace first, then where to embed the finished snippet, so relay the whole ask and do not tell the user to paste the draft as returned. For a finished fix written from the owner's confirmed facts, with paste steps for their site's platform, use get_fix ("Get this fix") instead: its requests are recorded. Requires a Website Auditor subscription ($49/month; eligible new customers get a 7-day free trial — payment method required, no charge until the trial ends) — if the user doesn't have one, call get_sample_audit first to show them the exact output format, free and with no API key.
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | Schema type; "auto" (also the default when omitted) does not detect anything — it returns an Organization draft. | |
| domain | Yes | The website domain, e.g. "example.com". |
Output Schema
| Name | Required | Description |
|---|---|---|
| jsonld | No | The JSON-LD draft (object or array). NOT ready to paste: every name field arrives as a placeholder — "Your Business Name" on the business types, and on a Product the product's own name and brand as "Your Product Name" and "Brand Name" — that the owner must replace with real names confirmed with them, never guessed from the domain or copied from an audit. |
| placement_notes | Yes | What to replace in the draft first — each name placeholder, confirmed with the owner — then where to embed the finished snippet, e.g. "in the <head> of every page". Relay the whole string, in that order: the replacement ask comes before the placement. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/openWorld=false/non-destructive, but the description adds materially different context: the output is a DRAFT with placeholder name fields that must never be guessed or copied from an audit, `placement_notes` drives the follow-up steps, and the draft must not be relayed as paste-ready. It also discloses the commercial gate ($49/month, 7-day trial, payment method required) and the free no-key fallback. Generating a draft does not contradict readOnlyHint, since nothing is persisted.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and the DRAFT caveat are front-loaded and nearly every sentence carries operational weight (placeholders, placement_notes, alternative tool, paywall, fallback). It is still one dense unbroken paragraph mixing the draft warning with billing details, which makes the critical placeholder instruction harder to scan than it should be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return shape needn't be explained, and the description still covers the things the schema cannot: the draft nature of the output, what must be replaced, how placement_notes is used, the paid access gate, and the free alternative when access is missing. Nothing an agent needs in order to call this correctly is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters are already documented, including the important warning that "auto" detects nothing and falls back to an Organization draft. The description adds no further meaning about `domain` or `type` beyond what the schema states, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Generate structured data (JSON-LD schema)") plus the scope ("tailored to a website") and the goal ("improve how AI assistants and search engines understand it"). It also distinguishes itself from the nearest sibling by naming get_fix and the different artifact it returns, so an agent can route without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit trigger list ("when someone asks for 'schema,' 'structured data,' 'JSON-LD,' or wants the actual markup"), an explicit alternative ("For a finished fix ... use get_fix"), and an explicit prerequisite path (subscription required; if absent, call get_sample_audit first). When-to-use, when-not-to-use, and the fallback are all spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_ai_visibilityCheck AI visibilityA
Check how visible a website is to AI assistants right now. Use this whenever someone asks "does ChatGPT/Perplexity/Claude/Gemini/Copilot recommend this business," "is my site showing up in AI answers," "what's my AI visibility / GEO score," or wants a quick read on whether an AI assistant would surface a given domain. Returns an overall AI-visibility score (0–100), a per-engine breakdown (ChatGPT, Perplexity, Claude, Gemini, Microsoft Copilot, Google AI Overviews), and the top competitor appearing in place of the site. When the audit recorded citations, sources lists the documents the assistants actually read, ranked by cross-engine agreement, each marked yours, competitor or third_party — treat competitor rows as context, not as placement targets; sources: null means the recorded answers cited nothing attributable, and an absent key means citations were not recorded for this audit. The result also includes trend data: 7- and 30-day score movement computed from the domain's stored snapshot history, for the question this audit asked, ending at the snapshot this audit stored; when it stored no measured snapshot, trend is null and trend_note says why. If name_warning is present, the business name behind the score could not be verified — relay that caveat rather than presenting the score as settled fact, and offer to re-run with an explicit business name. Requires a Website Auditor subscription ($49/month; eligible new customers get a 7-day free trial — payment method required, no charge until the trial ends) — if the user doesn't have one, call get_sample_audit first to show them the exact output format, free and with no API key.
| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | The website domain, e.g. "example.com". | |
| business_name | No | Optional. The business's real name, if you know it. Leave it out and the audit detects the name from the site and flags it when unverified — a guessed name is scored as if confirmed, so supply one only when it is actually known. | |
| business_location | No | Optional. The city the business trades in, e.g. "Hilo, HI". Leave it out and the audit detects it; when nothing is detectable the questions widen to the country or drop the place entirely, which is right for a national or global business and wrong for a local one. |
Output Schema
| Name | Required | Description |
|---|---|---|
| score | Yes | Overall AI-visibility score, 0–100. |
| trend | Yes | Pro only; null when unavailable — trend_note says why. |
| sources | No | |
| summary | Yes | |
| by_engine | Yes | Per-engine AI-visibility score, 0–100. NULL means the engine was not scored — see engine_status for which of the two reasons. A null is NOT a zero: zero means the engine answered and never named the business. |
| dashboard | No | |
| next_steps | No | Free audits only: what this result found that another tool can act on, as plain facts with the tool's name. |
| trend_note | No | Present exactly when trend is null: the reason. |
| name_source | No | "detected" | "user_supplied" | "domain_fallback". |
| name_warning | No | Set ONLY when the business name behind the score could not be verified. The score is computed from queries built around that name, so relay this caveat rather than presenting the score as settled. |
| coverage_note | No | Present exactly when an engine was asked and did not answer. Relay it: the score covers fewer engines than the run asked (four on a free audit, six on a paid one). |
| engine_status | Yes | Why each engine's score is what it is. 'scored' — the engine answered and the number is a measurement. 'unanswered' — it was asked and returned nothing, so there is no score; do not report it as 0. 'not_asked' — it was not part of this run at all — Google AI Overviews and Microsoft Copilot are asked on paid plans only. |
| name_verified | No | |
| stance_counts | No | How many answers recommended, mentioned or cautioned against the site. Present when recorded. |
| top_competitor | Yes | The competitor appearing in place of the site, if any. |
| questions_asked | No | The questions put to the assistants for this score, when the report recorded them. |
| appears_by_engine | Yes | Whether the site appeared at all on each engine. Distinct from the scores: an engine can have appearances yet a low score, or the reverse. NULL when the engine was not scored — false would assert it did not name the business, which is a claim an unmeasured engine cannot support. |
| recommendation_gap | No | How far behind the top beatable rival the site is, in the answers that recommend it. Present only when measured; its sentence is also in summary. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are sparse (readOnlyHint=false, openWorldHint=true, destructiveHint=false) and the description supplies substantial context beyond them: the paid subscription requirement, the $49/month price and trial terms without a charge, and the free get_sample_audit fallback. It also explains null semantics for `sources` (null vs. absent key) and the `name_warning` caveat that should be relayed rather than treated as settled. Minor gap: it does not say that launching this consumes an audit/snapshot, which is the likely reason readOnlyHint is false.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is front-loaded well, opening with the action and use triggers, but the single dense paragraph runs long and spends most of its words describing return values (per-engine breakdown, sources ranking, trend computation) despite an output schema existing. That detail is useful but duplicative, and one paragraph makes the routing and caveat rules harder to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a paid, open-world audit tool with a required domain, the definition covers prerequisites, cost, fallback path, output shape, null/degraded cases, and the name_warning interpretation guidance. Nothing an agent needs in order to call it and relay its result correctly appears to be missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, including the warning that a guessed business_name is scored as if confirmed and that a missing business_location widens questions to country level. The description adds no parameter-level meaning beyond that beyond linking business_name to the `name_warning` output, so it sits at the baseline when the schema carries the burden.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("check how visible a website is to AI assistants") and names the exact engines and score type, so it is unmistakable against siblings like get_report or run_audit. The follow-on clause also gives concrete user phrasings ("does ChatGPT recommend this business", "is my site showing up in AI answers") that map intent to this tool directly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit triggers for when to use it and an explicit fallback: call get_sample_audit first if the user lacks the Website Auditor subscription. It does not clarify when to prefer this over run_audit or get_report for an existing audit, so the sibling routing is not fully closed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_benchmarkBenchmark vs industry/geoARead-only
Benchmark a website's AI visibility against its industry and location. Use this when someone asks "how do I compare to others in my space," "is this a good score for my industry," or wants percentile/peer context rather than an absolute number. Backed by aggregated audit data. Requires a Website Auditor subscription ($49/month; eligible new customers get a 7-day free trial — payment method required, no charge until the trial ends) — if the user doesn't have one, call get_sample_audit first to show them the exact output format, free and with no API key.
| Name | Required | Description | Default |
|---|---|---|---|
| geo | No | Optional location override. | |
| domain | Yes | The website domain, e.g. "example.com". | |
| industry | No | Optional industry override. |
Output Schema
| Name | Required | Description |
|---|---|---|
| percentile | Yes | The domain's percentile within its industry/geo peer set, 0–100. |
| peer_median | Yes | |
| sample_size | Yes | How many peers the percentile and median are computed over. |
| position_summary | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds essential behavioral context beyond annotations, specifically detailing the subscription model, the cost structure, and the necessary preliminary call (get_sample_audit) for free users. This manages user expectations and guides agent pre-checks effectively.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
While highly informative, the description is lengthy due to its comprehensive nature regarding business logic. However, every sentence serves a distinct purpose (definition, use case, access requirements), preventing excessive bloat.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the required payment barrier and the need to guide the agent through the user's subscription status, this definition is maximally complete. It leaves no ambiguity regarding when this tool is usable versus the related sample tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Since the schema description coverage is 100%, the description provides no new semantic information about the `domain`, `geo`, or `industry` parameters beyond what the structured schema already provides. It aligns with the baseline score for high coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly defines the purpose: benchmarking a website's AI visibility against its industry and location. It distinguishes this specialized, relative comparison from general audit retrieval by framing the goal around peer context.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The definition provides explicit use cases by listing exact user queries (e.g., 'is this a good score for my industry'). Crucially, it outlines the prerequisite logic: use this only if the user has a subscription, otherwise use get_sample_audit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_changesWhat changed in AI visibilityARead-only
Report what changed in a website's AI-visibility score, only between two snapshots that asked the same question. Use this when someone asks "did anything change," "what's different this week/month," or "did my AI visibility drop." The domain need not be tracked: history accrues from any audit of it, tracked or not — track_site adds the weekly re-audits to the series, it is not a precondition, so do not track a site just to answer a change question. Returns the change in the overall score and the per-engine score changes, for engines measured both times — the overall only when the same engines answered both snapshots, otherwise it is null with an overall_note naming which answered each, and the per-engine changes stand alone; a summary says the change in plain sentences; competitor_changes, new_issues and resolved_issues are always empty, since snapshots record neither competitors nor audit issues. A change is only ever measured between two snapshots that asked the same question (the same business name, market and queries); when there is no such pair it says why instead of giving a number, with the date the series re-baselined when it did. The series is the measured weekly re-audits and any audit that asked the same question as the newest recorded one, while it has no gap longer than four weeks and a day from the newest weekly re-audit that recorded its question, through each later snapshot of the series (weekly re-audits included, recorded or not), to the newest measured snapshot; otherwise every measured snapshot. Requires a Website Auditor subscription ($49/month; eligible new customers get a 7-day free trial — payment method required, no charge until the trial ends) — if the user doesn't have one, call get_sample_audit first to show them the exact output format, free and with no API key.
| Name | Required | Description | Default |
|---|---|---|---|
| since | No | Optional ISO date or "last_check". | |
| domain | Yes | The website domain, e.g. "example.com". |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | Present when skipped_snapshots is above 0, when the two snapshots compared were answered by different engines, when newer measured snapshots were left out of the series, or when newer weekly re-audits measured nothing of the business: which, and why, in words. Relay it. |
| summary | No | The change in plain sentences, built from this result's two snapshots and any newer run the comparison leaves out: the overall scores and move, each assistant that moved, those newer runs, and what Pro checks each week; note beside it carries any snapshot passed over in between. |
| new_issues | Yes | Always empty: AI-visibility snapshots record no audit issues. Kept for clients that read it. |
| score_delta | Yes | Only ever between two snapshots that asked the same question AND were answered by the same engines. When there is no such pair, including a re-baseline after the business name, market or queries changed, the tool returns NOT_YET_AVAILABLE saying so, never a number; when the pair exists but different engines answered the two snapshots, the overall is not subtracted and is null with overall_note, and engine_changes still compares every engine that answered both. |
| overall_note | No | Present exactly when score_delta is null: the two snapshots were answered by different engines, and which answered each. Relay it — a null delta for this reason must not read like a null for want of history. |
| engine_changes | Yes | |
| to_captured_at | No | When the later one was. |
| resolved_issues | Yes | Always empty: AI-visibility snapshots record no audit issues. Kept for clients that read it. |
| from_captured_at | No | When the earlier snapshot compared was captured. |
| skipped_snapshots | No | Snapshots passed over because they asked a different question (another business name, market or queries) or do not record what they asked. |
| competitor_changes | Yes | Always empty: AI-visibility snapshots record no competitors. Kept for clients that read it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well past the readOnly/destructive annotations: it discloses that overall becomes null with an overall_note when engine sets differ, that competitor_changes/new_issues/resolved_issues are always empty, and how re-baselining is reported. The paywall prerequisite ($49/month, 7-day trial, payment method required) is disclosed up front — a material behavioral fact not captured anywhere in structured fields. The definition of the 'series' window is present but phrased in dense nested clauses that are hard to operationalize.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose, triggers, output behavior and the fallback path are front-loaded, which is good, but the single sentence defining the series ('while it has no gap longer than four weeks and a day from the newest weekly re-audit that recorded its question, through each later snapshot...') is close to unparseable. Pricing and trial mechanics are also embedded mid-paragraph, inflating length without helping the agent decide or call correctly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter read tool with full schema coverage, annotations and an output schema, this is more than sufficient. Edge cases an agent would otherwise mishandle — no comparable snapshot pair, changed engine set, always-empty fields, and the subscription gate — are all addressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents both parameters, and the baseline is 3. The description elaborates on time-window semantics through the series definition, which hints at what `since` selects from, but it never explicitly explains what `since` does or how "last_check" versus an ISO date changes behavior — the one parameter ambiguity is left unresolved.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: report what changed in a website's AI-visibility score, restricted to comparable snapshots. This distinguishes it from get_ai_visibility (current score) and get_report (full report) without requiring the agent to open any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names concrete trigger questions ("did anything change," "what's different this week/month," "did my AI visibility drop"). It also pre-empts the obvious wrong move by stating the domain need not be tracked and that track_site is not a precondition, and routes users without a subscription to get_sample_audit instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_fixGet this fixA
"Get this fix": a site fix served finished, with paste steps for the platform the site runs on: the business-facts structured data and the llms.txt are written from the facts its owner confirmed; the robots.txt lines from what the newest audit found blocked. Use this when someone asks to "get this fix," "do it for me," "give me the structured data / llms.txt / robots.txt lines to paste," or wants a fix done rather than described. Returns status "served" with the request (its id is what check_fix checks) and the fix: each block ready to copy, the steps for the site's platform (or the platform given), and copy_all, the prompt and every block in one paste, where the steps carry a prompt for the agent that edits the site. Each call is recorded as a request for the fix. When the newest audit found nothing for the fix to change (for robots_txt, no AI assistant blocked), it returns status "nothing_to_fix" and records nothing. Nothing that states the owner's facts is served before the owner has confirmed them: then it returns status "confirm_first" with the reason, the confirm block and seen — show the owner those facts, and once they confirm or correct them, call confirm_facts with seen unchanged and ask again. With reason "facts_not_read" the site has not been read yet, so there is nothing to confirm until its next weekly check. It answers only for a site the account tracks. Requires a Website Auditor subscription ($49/month; eligible new customers get a 7-day free trial — payment method required, no charge until the trial ends) — if the user doesn't have one, call get_sample_audit first to show them the exact output format, free and with no API key.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Which fix: "business_facts" (structured data plus About and FAQ text, from the owner's confirmed facts), "llms_txt" (an llms.txt titled with the confirmed name), or "robots_txt" (Allow lines for the AI assistants the newest audit found blocked by robots.txt; it states no facts, so nothing is confirmed first). Left out, the site's top fix. | |
| domain | Yes | The website domain, e.g. "example.com". | |
| platform | No | The platform to write the steps for, one of the `platforms` keys in the site's fix list (e.g. "wordpress", "shopify", "developer_host"). Left out, the platform detected for the site. |
Output Schema
| Name | Required | Description |
|---|---|---|
| fix | No | Present when served. |
| seen | No | Present on confirm_first when the owner can answer it. |
| domain | Yes | |
| reason | No | Present on confirm_first: "unconfirmed", "stale" (the site changed a confirmed fact), "no_name", or "facts_not_read" (the site has not been read, so nothing can be confirmed yet). |
| status | Yes | "served": the fix, finished. "confirm_first": nothing served; the facts it states are not confirmed by the owner yet. "nothing_to_fix": nothing served; the site's newest audit found nothing for this fix to change. |
| confirm | No | The confirm block: each fact with what the site says and what the owner confirmed. |
| message | Yes | |
| request | No | Present when served: the request this call was recorded as. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false and destructiveHint=false, and the description supplies the missing context: each call is recorded as a request for the fix (the side effect that justifies the non-read-only hint), nothing is recorded when the status is nothing_to_fix, and no owner-stated fact is served before the owner confirms it. It further discloses a hard prerequisite (Website Auditor subscription, $49/month, trial terms) and the fact that the tool answers only for tracked sites.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core 'what' and the trigger condition before branching into statuses, so an agent can stop reading early if the happy path is enough. The downside is a single ~300-word paragraph of run-on sentences with mid-clause parentheticals, which makes the status branches harder to scan than a short list would be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers everything an agent needs for a non-read-only tool that can refuse: the success shape, each failure status with its follow-up action, the recording side effect, the precondition, and the billing gate. Return values are additionally backed by an output schema, so the description is complete without duplicating field-level detail.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and every parameter already carries a description, including defaults (kind left out = top fix; platform left out = detected platform). The description reinforces the impact of these choices but adds little syntactic or format meaning beyond what the schema states, so the baseline of 3 for full schema coverage applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — it serves a finished site fix with paste steps, plus the platform-specific instructions and copy_all bundle. It also distinguishes itself from siblings by naming check_fix (which checks the returned request id), confirm_facts (which handles the confirm_first branch) and get_sample_audit (the no-subscription fallback).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit trigger phrases ('get this fix', 'do it for me', 'give me the structured data / llms.txt / robots.txt lines to paste') and an explicit contrast with wanting a fix 'described' rather than done. It also routes each non-happy path: nothing_to_fix, confirm_first (call confirm_facts with `seen` unchanged), facts_not_read (wait for the next weekly check), and no-subscription (call get_sample_audit first).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_fix_factsFacts to confirmARead-only
Read the business facts a site's fixes are written from, as they stand to be confirmed. Use this before confirming facts, to correct facts already confirmed, or after a confirmation answered facts_changed. Returns confirm (each fact with what the site says and what the owner confirmed, confirmed_at, and any facts gone stale), name (the business name the audits found, for the name fact where the site states none), and seen, exactly what the block shows, which confirm_facts sends back unchanged. seen is absent when the facts cannot be confirmed yet (can_confirm false: the site has not been read). The facts are the owner's to confirm: show them to the owner. Reads only. Requires a Website Auditor subscription ($49/month; eligible new customers get a 7-day free trial — payment method required, no charge until the trial ends) — if the user doesn't have one, call get_sample_audit first to show them the exact output format, free and with no API key.
| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | The website domain, e.g. "example.com". |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | Yes | The business name the audits found, for the name fact where the site states none; empty when none. |
| seen | No | Absent when the facts cannot be confirmed yet. |
| domain | Yes | |
| confirm | Yes | The confirm block: each fact with what the site says and what the owner confirmed. |
| message | Yes | |
| can_confirm | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, and the description reinforces this with 'Reads only'. It adds genuinely new behavior beyond annotations: the returned fields (confirm, name, seen), the 'seen' absence when can_confirm is false, and the paid Website Auditor prerequisite with trial terms. The pricing parenthetical is long, but the operational disclosures are strong.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose and when-to-use guidance are front-loaded, and the return-shape and prerequisite details follow logically. The subscription sentence is dense and overstuffed with pricing/trial detail, which blunts an otherwise well-structured description.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Complete for a single-parameter read tool: prerequisites, the can_confirm edge case, the meaning of 'seen' being echoed back through confirm_facts, and the owner-facing framing are all covered. The output schema exists, so the description's return-field summary is bonus clarity rather than a gap-filler.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is only one parameter (domain) and schema description coverage is 100%, so the schema already carries the semantics. The description adds nothing about domain format or validation, making the 3 baseline correct rather than higher.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb and resource ('Read the business facts a site's fixes are written from') and frames the state ('as they stand to be confirmed'), which separates it from confirm_facts and get_fix. An agent can tell it apart from sibling tools without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit trigger conditions: before confirming facts, to correct already-confirmed facts, or after a confirmation returned facts_changed. It also routes the agent to get_sample_audit when the user lacks a subscription, and gives the free/no-API-key alternative, so no usage decision is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_gtm_planBuild a GTM plan from the auditA
Build a written go-to-market plan from a website's latest audit, grounded in its citation evidence. Use this when someone asks "what should I do about my AI visibility," "turn this audit into a plan," or wants a GTM or marketing plan for their site. The plan is built from the sources the assistants actually read — each marked yours, competitor or third_party; competitor sources shape the analysis but are never placement targets. When the audit recorded no citation evidence the plan grounds itself in the report's issues and stats instead. Pass focus or constraints to steer it, and prior_plan (the markdown from an earlier call) to refine rather than start over. Requires a Website Auditor subscription ($49/month; eligible new customers get a 7-day free trial — payment method required, no charge until the trial ends) — if the user doesn't have one, call get_sample_audit first to show them the exact output format, free and with no API key.
| Name | Required | Description | Default |
|---|---|---|---|
| focus | No | What to emphasize — e.g. "local directories", "content", "a launch next month". | |
| domain | Yes | The website domain, e.g. "example.com". | |
| prior_plan | No | The markdown of a plan from an earlier call, to refine instead of starting over. | |
| constraints | No | Budget, team, or time constraints — e.g. "solo founder, $200/mo". |
Output Schema
| Name | Required | Description |
|---|---|---|
| plan | Yes | |
| model | Yes | |
| domain | Yes | |
| summary | Yes | |
| dashboard | No | |
| sources_used | Yes | |
| evidence_note | No | Additive, never an error: set when the plan had no citation evidence. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (which only say readOnly=false, destructive=false, openWorld=false), it discloses the paid subscription requirement with pricing and trial terms, the no-evidence fallback grounded in report issues and stats, and the rule that competitor sources shape analysis but are never placement targets. That is context an agent cannot get from structured fields and materially affects how it should set expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is front-loaded: purpose, then when-to-use, then how the plan is grounded, then parameters, then billing prerequisites. The paragraph is dense but every clause carries operational information; the nested parenthetical pricing detail is the only slightly heavy patch.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a paid generative tool with four params and an existing output schema, nothing essential is missing: inputs, grounding source, fallback behavior, refinement path and access prerequisites are all covered. Return values need not be described because the output schema handles them.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description adds value by framing focus and constraints as steering inputs and prior_plan as "the markdown from an earlier call" used to refine rather than start over. The domain parameter is left implicit (presumably the site whose audit is used), which is the only small gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: "Build a written go-to-market plan from a website's latest audit, grounded in its citation evidence." That distinguishes it immediately from siblings like get_report, get_recommendations and get_ai_visibility, which surface data rather than producing a plan artifact.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit trigger phrasings ("what should I do about my AI visibility," "turn this audit into a plan") and names an alternative path: call get_sample_audit first when the user lacks a subscription. It also explains refine-vs-restart via prior_plan, though it doesn't state when to prefer get_recommendations or get_report instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_monitoring_statusMonitoring status summaryARead-only
Get a glanceable summary of monitoring status across all tracked websites. Use this when someone asks "how are my tracked sites doing," "what's my current AI visibility across everything I monitor," "when were my sites last checked or when do they run next," or wants a dashboard of their monitored domains. Returns, per domain, the latest AI-visibility score of its series (the measured weekly re-audits and any audit that asked the same question as the newest recorded one, while it has no gap longer than four weeks and a day from the newest weekly re-audit that recorded its question, through each later snapshot of the series (weekly re-audits included, recorded or not), to the newest measured snapshot; otherwise every measured snapshot; a newer measured snapshot outside the series is not shown, and get_changes names it), the date of its last scheduled run and when the next one runs, and the most recent change against the last snapshot that asked the same question, or a note or the summary saying why there is none — when different engines answered the two snapshots, the change shows the per-engine changes only, with a note naming which answered each, and its score_delta is null; like get_changes, a change carries competitor_changes, new_issues and resolved_issues, always empty. Requires a Website Auditor subscription ($49/month; eligible new customers get a 7-day free trial — payment method required, no charge until the trial ends) — if the user doesn't have one, call get_sample_audit first to show them the exact output format, free and with no API key.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| used | Yes | |
| limit | Yes | |
| sites | Yes | |
| summary | Yes | |
| dashboard | No | |
| remaining | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare a safe read-only, closed-world call, and the description adds material context beyond them: the paid Website Auditor requirement, trial/payment terms, and a concrete fallback. The deduction is for the return-semantics passage, whose nested series/gap logic is so tangled that an agent could easily misreport which snapshot is shown.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose and trigger examples are well front-loaded, but the middle passage is a single roughly hundred-word run-on with recursively nested parentheticals about series membership, gaps, and per-engine deltas. That is information the output schema already carries, and its density actively impedes comprehension.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter tool with a full output schema and read-only annotations, coverage is nearly complete: purpose, triggers, gating, and fallback are all present. What is missing is a plain-language statement of the return shape (per-domain score, last run, next run, latest change) unobscured by the series-selection caveat.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes no parameters, so there is no parameter meaning to add; baseline 4 applies. The description correctly implies no input is needed to call it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb and resource: a glanceable summary of monitoring status across all tracked websites. It is clearly distinct from siblings like get_changes and list_tracked_sites, and the fallback to get_sample_audit further pins down its role.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives concrete trigger phrasings ("how are my tracked sites doing," "when were my sites last checked or when do they run next") and explicitly names the alternative path when the user lacks a subscription. Both the when-to-use and the when-not-to-use cases are covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recommendationsPrioritized fixesARead-only
Get specific, prioritized fixes to raise a website's AI visibility and audit scores. Use this when someone asks "how do I fix this," "what should I change," "how do I improve my AI visibility," or after an audit surfaces issues. Returns ranked actions with expected impact, each built from the domain's latest audit and citing its evidence (blocked AI crawlers, missing structured data, the competitor sites the assistants cited). Works with any Website Auditor API key and needs an audit on record for the domain; with Pro it also says where to get listed, what the assistants get wrong about the business, and which file in the fix package fixes each finding — without Pro the listing places are only counted.
| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | The website domain, e.g. "example.com". |
Output Schema
| Name | Required | Description |
|---|---|---|
| tier | No | Which list the API served. "free" omits where to get listed, what the assistants get wrong and each finding's fix file; its step marked `locked` only counts what Pro shows. |
| run_id | No | The audit the steps come from. |
| dashboard | No | |
| recommendations | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/destructive annotations, it discloses that results are derived from the domain's latest audit, that each action cites evidence (blocked crawlers, missing structured data, cited competitors), the API-key portability, the audit-on-record prerequisite, and the Pro vs non-Pro behavioral split. That tier gating materially changes what the agent will see and is not recoverable from any structured field.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is front-loaded: purpose, then trigger phrases, then return shape, then prerequisites and tiering. The quoted user utterances and the long Pro clause are slightly verbose, but each sentence carries operational information rather than restating the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the return-value explanation is bonus rather than required, and prerequisites and tier effects are well covered. The remaining gap is relational: among 21 siblings that include list_fixes, get_fix, and get_gtm_plan, the description never says when those are the better call.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is a single required parameter with 100% schema description coverage ('The website domain, e.g. \"example.com\"'), so the schema already carries the semantics. The description only implies the domain must have a prior audit, adding a constraint rather than new meaning for the parameter itself.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Get specific, prioritized fixes') and scopes the outcome ('raise a website's AI visibility and audit scores'), plus it characterizes the return as 'ranked actions with expected impact'. It does not name which sibling it replaces (list_fixes, get_fix, get_gtm_plan all sit nearby), so an agent still has to infer the boundary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives concrete triggering phrasing ('how do I fix this,' 'what should I change') and a timing condition ('after an audit surfaces issues'), and it states the prerequisite that an audit must be on record. It stops short of explicit when-not guidance or naming the alternative tool for a bare fix listing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_reportShareable report + badgeARead-only
Get a shareable report URL and the embeddable "Audited by Website Auditor" badge snippet for a website. Use this when someone wants to "share," "export," "send a client," or "embed" the audit result. Returns a link and an HTML badge snippet. Requires a Website Auditor subscription ($49/month; eligible new customers get a 7-day free trial — payment method required, no charge until the trial ends) — if the user doesn't have one, call get_sample_audit first to show them the exact output format, free and with no API key.
| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | The website domain, e.g. "example.com". |
Output Schema
| Name | Required | Description |
|---|---|---|
| badge_html | Yes | |
| report_url | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, non-destructive, closed-world), and the description goes further by disclosing the paid-subscription gate, the $49/month price, trial terms, and a fallback tool. It stops short of describing failure behavior (e.g., invalid or unauthorized domain), which would be the remaining useful detail.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core purpose and usage triggers are front-loaded in the first two sentences, with the prerequisite and fallback trailing logically. The pricing/trial parenthetical is the longest stretch and is arguably more commerce detail than an agent needs to select the tool, though it does support setting user expectations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description needn't explain return values, and it correctly defers to it while still noting the two artifacts returned. Annotations plus schema plus this text cover selection, prerequisites, and fallback; only error/edge-case behavior is unaddressed, which is minor for a read-only lookup.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is a single parameter with 100% schema description coverage, so the schema fully documents the domain field and its example format; the description adds no parameter detail but needs none. This is the baseline case for a one-parameter tool with complete schema documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: returning a shareable report URL plus an embeddable badge snippet for a website. It also implicitly distinguishes itself from sibling audit tools by naming the concrete artifacts (link, HTML badge) that only this tool produces.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It enumerates the user intents that select this tool ("share," "export," "send a client," "embed") and gives an explicit alternative path: if the user has no subscription, call get_sample_audit first. That is both a when-to-use and a when-not-to-use rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_sample_auditSee a sample audit (no key needed)ARead-only
Show a complete sample Website Auditor report — no API key required, nothing to set up. Use this whenever someone wants to "try it," "see a demo," "show me what this does," "what does the output look like," or is deciding whether Website Auditor is worth subscribing to — and use it INSTEAD of refusing when no API key is configured. Returns fixed sample data for example.com in the exact shape a real audit returns: scored summary, per-test results, and the AI-visibility breakdown by engine. It is clearly marked as a sample and always describes example.com, never the user's own site — auditing a real domain needs a subscription.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| note | Yes | |
| audit | Yes | A real GET /api/audit payload, populated with sample data. |
| price | No | |
| domain | Yes | The fixed sample domain. Never the caller's own. |
| is_sample | Yes | Always true. Never present this as a live result. |
| upgrade_url | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, non-destructive, closed-world), and the description adds meaningful context beyond them: fixed sample data for example.com, clearly marked as a sample, never the caller's own site, and returned in the exact shape of a real audit. That is exactly the behavior an agent needs to avoid misrepresenting results to a user.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and constraint, then the usage triggers, then return shape. The list of quoted trigger phrases is longer than strictly necessary but each maps to a real user intent and the total remains tight for the guidance it delivers.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be detailed, yet the description still summarizes the returned structure (scored summary, per-test results, AI-visibility breakdown). Combined with the no-key fallback rule and the example.com limitation, nothing an agent needs is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4; the description correctly signals there is nothing to configure ("nothing to set up") and explains why no domain argument exists — it always targets example.com. No further parameter meaning is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Show a complete sample Website Auditor report") plus a distinguishing constraint ("no API key required") that separates it from get_report and run_audit. An agent can immediately tell this returns demo data rather than a real audit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly enumerates when to use it ("try it," "see a demo," "what does the output look like," subscription evaluation) and gives a decisive fallback rule: use it INSTEAD of refusing when no API key is configured. It also states the exclusion — real-domain auditing needs a subscription.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_fixesList ready-made fixesARead-only
List the ready-made fixes Website Auditor can serve finished for a tracked site, top first: whether each is needed and why, whether the platform the site runs on can take it, and its newest request with that request's status (live, missing, or not checked yet). Use this when someone asks which fixes their site needs, which to do first, or whether a fix they added has gone live. Also returns the site's detected platform, the platforms a fix's steps can be written for, and each newest request's id, which check_fix takes, without recording a new request. Reads only: nothing is recorded and the site is not fetched. It answers only for a site the account tracks. Requires a Website Auditor subscription ($49/month; eligible new customers get a 7-day free trial — payment method required, no charge until the trial ends) — if the user doesn't have one, call get_sample_audit first to show them the exact output format, free and with no API key.
| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | The website domain, e.g. "example.com". |
Output Schema
| Name | Required | Description |
|---|---|---|
| top | Yes | The top fix's kind, or null when none is needed that the site's platform can take. |
| fixes | Yes | |
| domain | Yes | |
| summary | Yes | |
| platform | No | The platform detected for the site ("unknown" when none was). |
| platforms | No | The platforms a fix's steps can be written for. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well past the annotations by stating that nothing is recorded, the site is not fetched, and that it answers only for sites the account tracks — clarifying what would otherwise be ambiguous versus check_fix, which creates a request. It also discloses the subscription prerequisite and trial/payment terms that gate a successful call.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and payload before the usage and prerequisite details, which is the right ordering. It loses a little to redundancy ('without recording a new request' restated as 'nothing is recorded') and to the dense pricing/trial parenthetical.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description needn't detail return shapes, yet it still flags the key fields an agent will act on (platform, platforms, newest request id). Prerequisites, read-only semantics, and the free alternative are all covered.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter at 100% schema coverage, so the schema already defines it. The description adds the meaningful constraint that the domain must be a site the account tracks, which the schema does not say.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List the ready-made fixes'), the scope ('for a tracked site'), the ordering ('top first'), and the per-item payload (needed/why, platform compatibility, newest request + status). It is clearly separable from siblings like get_fix, get_fix_facts, and check_fix.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names three concrete triggering questions ('which fixes their site needs, which to do first, or whether a fix they added has gone live') and an explicit fallback path when the user lacks a subscription: call get_sample_audit first. It also signals the handoff to check_fix via the returned request id.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_tracked_sitesList monitored sitesARead-only
List the websites currently being monitored for AI visibility on a schedule. Use this when someone asks "what am I tracking," "which sites am I monitoring," "how many monitoring slots am I using," or wants to see their tracked domains. Returns each tracked domain with its cadence and active state, plus slots used and remaining out of the account's limit (3 sites, or 5 for a subscription started before 18 October 2026). Requires a Website Auditor subscription ($49/month; eligible new customers get a 7-day free trial — payment method required, no charge until the trial ends) — if the user doesn't have one, call get_sample_audit first to show them the exact output format, free and with no API key.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| used | Yes | |
| limit | Yes | |
| summary | Yes | |
| tracked | Yes | |
| remaining | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, non-destructive, closed-world), and the description adds what those annotations cannot: the return fields (domain, cadence, active state), slot accounting, the 3-site limit versus the 5-site grandfathered limit, and a subscription precondition with pricing. The only miss is not mentioning pagination or ordering, which is minor for a bounded slot-limited list.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and usage triggers are properly front-loaded and the routing sentence about get_sample_audit earns its place. The parenthetical subscription block, however, packs pricing, trial length, and payment-method terms into a single em-dash aside that is heavier than needed for tool selection and slows the read.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
All decision-critical facts are present: what is returned, the slot cap, the subscription gate, and the fallback tool. Since an output schema already exists, the sentence describing return fields is somewhat redundant, and the description stops short of noting ordering or empty-state behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate; baseline applies. No misleading parameter language is present.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — 'List the websites currently being monitored for AI visibility on a schedule' — which cleanly separates it from track_site, untrack_site, and get_monitoring_status. The scheduled-monitoring qualifier tells an agent exactly what population is returned.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit trigger phrasings ('what am I tracking', 'which sites am I monitoring', 'how many monitoring slots am I using') and an explicit alternative with its own condition: if the user lacks a subscription, call get_sample_audit first. That is a when-to-use plus when-to-switch instruction, not inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_auditRun a full auditA
Run a full one-time audit of a website — AI visibility, plus security headers, broken links, performance, and a crawlability-and-markup score (scores.seo: robots.txt, AI crawler access, sitemap, structured data, meta description and Open Graph tags). Use this when someone asks to "audit," "scan," "check," or "review" a website's health, or wants a complete report rather than just the AI-visibility number. Returns a scored summary across categories and a link to the full report. The ranked cited-sources evidence behind the AI-visibility number is returned by get_ai_visibility, not by this tool. If name_warning is present, the business name the AI-visibility score was measured against could not be verified — relay that caveat rather than presenting the score as settled fact. Requires a Website Auditor subscription ($49/month; eligible new customers get a 7-day free trial — payment method required, no charge until the trial ends) — if the user doesn't have one, call get_sample_audit first to show them the exact output format, free and with no API key.
| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | The website domain, e.g. "example.com". | |
| business_name | No | Optional. The business's real name, if you know it. Leave it out and the audit detects the name from the site and flags it when unverified — a guessed name is scored as if confirmed, so supply one only when it is actually known. | |
| business_location | No | Optional. The city the business trades in, e.g. "Hilo, HI". Leave it out and the audit detects it; when nothing is detectable the questions widen to the country or drop the place entirely, which is right for a national or global business and wrong for a local one. |
Output Schema
| Name | Required | Description |
|---|---|---|
| scores | Yes | |
| summary | No | Free audits only: next_steps in one sentence. |
| dashboard | No | |
| next_steps | No | Free audits only: what this result found that another tool can act on, as plain facts with the tool's name. |
| report_url | Yes | |
| top_issues | Yes | |
| name_warning | No | Set ONLY when the business name could not be verified, which puts the AI-visibility score in question. |
| stance_counts | No | |
| recommendation_gap | No | How far behind the top beatable rival the site is, in the answers that recommend it. Present only when measured; its sentence reads the result back in one line. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint=false, openWorldHint=true, destructiveHint=false; the description goes well beyond by disclosing the paid subscription requirement, trial terms and payment-method precondition, and the `name_warning` caveat that must be relayed rather than suppressed. It also tells the agent what it gets back (scored summary plus report link), which matters for a non-read-only, consumption-metered call.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and trigger words are front-loaded, and each sentence carries distinct information (scope, triggers, exclusions, return shape, caveat, cost). It is a single dense paragraph with nested parentheticals, which costs some scannability, but there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-parameter, paid, non-read-only tool with an output schema, everything an agent needs before calling is present: cost and entitlement gate, fallback tool, return summary, and the caveat to propagate. Return-value detail is appropriately brief since the output schema exists.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description adds real meaning by explaining why omitting `business_name` is safer (a guessed name is scored as confirmed) and linking that omission to the `name_warning` output. It does not discuss `domain` formats or `business_location` edge cases beyond what the schema already says.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Run a full one-time audit of a website") and enumerates the categories covered, including what `scores.seo` actually measures. It explicitly carves itself away from two siblings: the cited `sources` come from get_ai_visibility, and get_sample_audit is the preview path.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete trigger vocabulary ("audit," "scan," "check," "review") and the disambiguating condition — a complete report versus just the AI-visibility number. It also names the fallback path (get_sample_audit) for users without a subscription.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
track_siteStart/stop monitoringADestructive
Start (or stop) ongoing monitoring of a website's AI visibility on a schedule. Use this when someone wants to "monitor," "track," "watch," or "get alerted about" a site's AI visibility over time, rather than a one-off check. Adds weekly re-audits to the history that get_changes reads from — a history every audit already accrues, tracked or not — so use this to be watched on a schedule, not to make get_changes work. Passing enabled: false stops monitoring by deleting the enrollment, as untrack_site does. Requires a Website Auditor subscription ($49/month; eligible new customers get a 7-day free trial — payment method required, no charge until the trial ends) — if the user doesn't have one, call get_sample_audit first to show them the exact output format, free and with no API key.
| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | The website domain, e.g. "example.com". | |
| cadence | No | Monitoring cadence (weekly). | weekly |
| enabled | No | Set false to stop monitoring. |
Output Schema
| Name | Required | Description |
|---|---|---|
| domain | Yes | |
| cadence | No | |
| created | No | Present when starting: whether this call created a new tracking. |
| message | Yes | |
| removed | No | Present when stopping. |
| tracking | Yes | True after a start/confirm; false after a stop. |
| dashboard | No | |
| already_tracked | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the destructiveHint=true annotation, the description discloses what is actually destroyed — passing enabled:false deletes the enrollment — and that weekly re-audits accumulate into history. It also surfaces the hard prerequisite (Website Auditor subscription, $49/month, payment method required, 7-day trial) that gates a successful call.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The primary action, the trigger conditions, and the subscription prerequisite are front-loaded and easy to scan. The get_changes clause is noticeably convoluted ('a history every audit already accrues, tracked or not'), but it prevents a plausible misuse, so it earns its space even if it could be tightened.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description needn't explain return values, and it covers everything else an agent needs: the trigger, the stop semantics, the destructive consequence, the sibling equivalent, and the paywall fallback. Nothing material for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds real consequence-level meaning the schema lacks: enabled:false deletes the enrollment rather than merely pausing it, and that outcome matches untrack_site. Cadence is only weakly enriched (weekly re-audits), leaving the sole enum value mostly to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence gives a specific verb pair (start/stop), the resource (ongoing monitoring of a website's AI visibility), and the scope (on a schedule). It distinguishes itself from the one-off path by naming the contrast with 'a one-off check,' which separates it from run_audit without requiring the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit trigger vocabulary ('monitor,' 'track,' 'watch,' 'get alerted about') and an explicit exclusion ('not to make get_changes work') tell the agent both when and when-not to call it. It also names untrack_site as the equivalent stop path and prescribes a fallback (get_sample_audit) when the user lacks a subscription.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
untrack_siteStop monitoringADestructive
Stop ongoing monitoring of a website's AI visibility. Use this when someone wants to "stop tracking," "unmonitor," "stop watching," or "remove" a site from scheduled monitoring, or to free up a monitoring slot. Removing a tracked site deletes its monitoring enrollment (its past audits are kept); calling it for a site that isn't tracked changes nothing. Returns how many monitoring slots are now free. Requires a Website Auditor subscription ($49/month; eligible new customers get a 7-day free trial — payment method required, no charge until the trial ends) — if the user doesn't have one, call get_sample_audit first to show them the exact output format, free and with no API key.
| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | The website domain, e.g. "example.com". |
Output Schema
| Name | Required | Description |
|---|---|---|
| used | No | |
| limit | No | |
| domain | Yes | |
| message | Yes | |
| removed | Yes | |
| tracking | Yes | |
| remaining | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the destructiveHint=true annotation, the description specifies exactly what is destroyed (the monitoring enrollment) and what survives (past audits), plus idempotent no-op behavior for untracked sites. The subscription prerequisite and its cost/trial terms are behavioral context that appears nowhere in the annotations or schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Core purpose and destructiveness are front-loaded, then triggers, then the prerequisites/upsell path. It is dense and slightly overpacked with pricing detail, but each sentence carries operational value rather than filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Destination data is covered by the output schema and safety profile by annotations, so the description only needed to cover effects, idempotency, and preconditions — all of which it does. Nothing an agent needs before calling this destructive tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the single `domain` parameter, so the schema already carries its meaning. The description adds nothing about domain format, normalization, or what happens with a subdomain — baseline 3 is correct here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
"Stop ongoing monitoring of a website's AI visibility" gives a specific verb (stop) plus resource (monitoring of a site), and the sibling set makes the pairing with track_site obvious from the phrasing alone. An agent can distinguish this from track_site or list_tracked_sites without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit trigger vocabulary is supplied ("stop tracking," "unmonitor," "stop watching," "remove") along with a second condition — freeing up a monitoring slot. It also names a fallback path (call get_sample_audit when the user lacks a subscription) rather than leaving the agent to guess.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
14 tool updates
v1.0.29- Added
check_fix - Changed
compare_competitors3 fields changed- added
Output schema / properties / dashboardAdded value: +{ + "additionalProperties": false, + "properties": { + "note": { + "description": "One line naming what the page shows; the same text is in summary where a reply has one.", + "type": "string" + }, + "url": { + "description": "The member's own dashboard page.", + "type": "string" + } + }, + "required": [ + "url", + "note" + ], + "type": "object" +} - added
Output schema / properties / recommendation_gapAdded value: +{ + "additionalProperties": true, + "description": "How far behind the competitor you trail most the site is, each side as a share of its own answers, compared on the assistants that answered for both. Present only when both audits recorded stances; its sentence reads the result back in one line.", + "properties": { + "assistants": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The assistants the figures are over: those that answered for both sites. Null when that could not be checked." + }, + "by_competitor": { + "items": { + "additionalProperties": true, + "properties": { + "answers": { + "type": "number" + }, + "assistants": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "domain": { + "type": "string" + }, + "gap_points": { + "type": "number" + }, + "recommended": { + "type": "number" + }, + "same_questions": { + "type": [ + "boolean", + "null" + ] + }, + "state": { + "enum": [ + "behind", + "level", + "ahead" + ], + "type": "string" + }, + "unverified": { + "description": "True when this competitor's business name could not be verified.", + "type": "boolean" + }, + "you_answers": { + "description": "Your answers on the same basis as this competitor's figures.", + "type": "number" + }, + "you_recommended": { + "description": "Your recommended answers on the same basis as this competitor's figures.", + "type": "number" + } + }, + "required": [ + "domain", + "same_questions", + "assistants", + "state", + "gap_points", + "recommended", + "answers", + "you_recommended", + "you_answers", + "unverified" + ], + "type": "object" + }, + "type": "array" + }, + "gap_points": { + "description": "Positive when the top competitor is recommended more often.", + "type": "number" + }, + "not_compared": { + "description": "Competitors left out because their audit recorded no stances.", + "items": { + "type": "string" + }, + "type": "array" + }, + "rival": { + "description": "The competitor you trail most (when you lead every competitor, the one you lead least), compared on the assistants that answered for both sites.", + "type": "string" + }, + "rival_answers": { + "type": "number" + }, + "rival_recommended": { + "type": "number" + }, + "same_questions": { + "description": "Whether both audits asked the same set of questions; null when either did not record them.", + "type": [ + "boolean", + "null" + ] + }, + "sentence": { + "type": "string" + }, + "state": { + "enum": [ + "behind", + "level", + "ahead" + ], + "type": "string" + }, + "tied_with": { + "description": "Other competitors with identical counts over the identical basis: one gap, all named.", + "items": { + "type": "string" + }, + "type": "array" + }, + "you_answers": { + "type": "number" + }, + "you_recommended": { + "type": "number" + } + }, + "required": [ + "state", + "gap_points", + "rival", + "tied_with", + "same_questions", + "assistants", + "rival_recommended", + "rival_answers", + "you_recommended", + "you_answers", + "not_compared", + "sentence", + "by_competitor" + ], + "type": "object" +} - changed
Output schema / properties / skipped / items / properties / reason / descriptionPrevious value: -"\"quota\" | \"unreachable\" | \"error\"."New value: +"\"quota\" | \"unreachable\" | \"time_limit\" | \"error\"."
- Added
confirm_facts - Changed
get_ai_visibility16 fields changed- added
Output schema / properties / appears_by_engine / properties / copilotAdded value: +{ + "type": [ + "boolean", + "null" + ] +} - added
Output schema / properties / appears_by_engine / properties / google_ai_overviewsAdded value: +{ + "type": [ + "boolean", + "null" + ] +} - changed
Output schema / properties / appears_by_engine / requiredPrevious value: -[ - "chatgpt", - "perplexity", - "claude", - "gemini" -]New value: +[ + "chatgpt", + "perplexity", + "claude", + "gemini", + "google_ai_overviews", + "copilot" +] - added
Output schema / properties / by_engine / properties / copilotAdded value: +{ + "type": [ + "number", + "null" + ] +} - added
Output schema / properties / by_engine / properties / google_ai_overviewsAdded value: +{ + "type": [ + "number", + "null" + ] +} - changed
Output schema / properties / by_engine / requiredPrevious value: -[ - "chatgpt", - "perplexity", - "claude", - "gemini" -]New value: +[ + "chatgpt", + "perplexity", + "claude", + "gemini", + "google_ai_overviews", + "copilot" +] - changed
Output schema / properties / coverage_note / descriptionPrevious value: -"Present exactly when an engine was asked and did not answer. Relay it: the score covers fewer engines than the four this tool can query."New value: +"Present exactly when an engine was asked and did not answer. Relay it: the score covers fewer engines than the run asked (four on a free audit, six on a paid one)." - added
Output schema / properties / dashboardAdded value: +{ + "additionalProperties": false, + "properties": { + "note": { + "description": "One line naming what the page shows; the same text is in summary where a reply has one.", + "type": "string" + }, + "url": { + "description": "The member's own dashboard page.", + "type": "string" + } + }, + "required": [ + "url", + "note" + ], + "type": "object" +} - changed
Output schema / properties / engine_status / descriptionPrevious value: -"Why each engine's score is what it is. 'scored' — the engine answered and the number is a measurement. 'unanswered' — it was asked and returned nothing, so there is no score; do not report it as 0. 'not_asked' — it was not part of this run at all."New value: +"Why each engine's score is what it is. 'scored' — the engine answered and the number is a measurement. 'unanswered' — it was asked and returned nothing, so there is no score; do not report it as 0. 'not_asked' — it was not part of this run at all — Google AI Overviews and Microsoft Copilot are asked on paid plans only." - added
Output schema / properties / engine_status / properties / copilotAdded value: +{ + "enum": [ + "scored", + "unanswered", + "not_asked" + ], + "type": "string" +} - added
Output schema / properties / engine_status / properties / google_ai_overviewsAdded value: +{ + "enum": [ + "scored", + "unanswered", + "not_asked" + ], + "type": "string" +} - changed
Output schema / properties / engine_status / requiredPrevious value: -[ - "chatgpt", - "perplexity", - "claude", - "gemini" -]New value: +[ + "chatgpt", + "perplexity", + "claude", + "gemini", + "google_ai_overviews", + "copilot" +] - added
Output schema / properties / next_stepsAdded value: +{ + "description": "Free audits only: what this result found that another tool can act on, as plain facts with the tool's name.", + "items": { + "additionalProperties": false, + "properties": { + "tool": { + "description": "The tool that does it.", + "type": "string" + }, + "what": { + "description": "A plain fact about this result.", + "type": "string" + } + }, + "required": [ + "tool", + "what" + ], + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / questions_askedAdded value: +{ + "description": "The questions put to the assistants for this score, when the report recorded them.", + "items": { + "type": "string" + }, + "type": "array" +} - added
Output schema / properties / recommendation_gapAdded value: +{ + "additionalProperties": true, + "description": "How far behind the top beatable rival the site is, in the answers that recommend it. Present only when measured; its sentence is also in summary.", + "properties": { + "answers": { + "description": "The answers this is a share of: one per question, per assistant.", + "type": [ + "number", + "null" + ] + }, + "gap_points": { + "description": "Points behind the top rival in the answers that RECOMMEND the site (negative when ahead). Null, never 0, when there is no rival or too few answers.", + "type": [ + "number", + "null" + ] + }, + "per_engine": { + "items": { + "additionalProperties": true, + "properties": { + "answers": { + "type": [ + "number", + "null" + ] + }, + "engine": { + "type": "string" + }, + "gap_points": { + "type": [ + "number", + "null" + ] + }, + "rival_recommended": { + "type": [ + "number", + "null" + ] + }, + "state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "behind", + "level", + "ahead", + "no_rival", + "no_local_rival", + "not_enough_answers" + ], + "type": "string" + }, + { + "const": "not_measured", + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "you_recommended": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "engine", + "state", + "gap_points", + "you_recommended", + "rival_recommended", + "answers" + ], + "type": "object" + }, + "type": "array" + }, + "rival": { + "description": "The top BEATABLE rival: marketplaces, delivery and booking apps, directories and national chains are left out. Null when none is recommended.", + "type": [ + "string", + "null" + ] + }, + "rival_recommended": { + "type": [ + "number", + "null" + ] + }, + "sentence": { + "description": "One plain sentence to read back to the owner; also folded into summary.", + "type": "string" + }, + "state": { + "description": "Which kind of gap this is, or why there is none.", + "enum": [ + "behind", + "level", + "ahead", + "no_rival", + "no_local_rival", + "not_enough_answers" + ], + "type": "string" + }, + "tied_with": { + "description": "Other rivals tied for the top: one gap, all named.", + "items": { + "type": "string" + }, + "type": "array" + }, + "you_recommended": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "state", + "gap_points", + "rival", + "rival_recommended", + "tied_with", + "you_recommended", + "answers", + "per_engine", + "sentence" + ], + "type": "object" +} - added
Output schema / properties / stance_countsAdded value: +{ + "additionalProperties": true, + "description": "How many answers recommended, mentioned or cautioned against the site. Present when recorded.", + "properties": { + "answers": { + "type": "number" + }, + "cautioned": { + "type": "number" + }, + "mentioned": { + "type": "number" + }, + "not_named": { + "type": "number" + }, + "recommended": { + "type": "number" + }, + "unclear": { + "description": "The rules could not say how the answer treated the site. Not negative.", + "type": "number" + } + }, + "required": [ + "recommended", + "mentioned", + "cautioned", + "unclear", + "not_named", + "answers" + ], + "type": "object" +}
- Changed
get_changes1 field changed- added
Output schema / properties / summaryAdded value: +{ + "description": "The change in plain sentences, built from this result's two snapshots and any newer run the comparison leaves out: the overall scores and move, each assistant that moved, those newer runs, and what Pro checks each week; note beside it carries any snapshot passed over in between.", + "type": "string" +}
- Added
get_fix - Added
get_fix_facts - Changed
get_gtm_plan1 field changed- added
Output schema / properties / dashboardAdded value: +{ + "additionalProperties": false, + "properties": { + "note": { + "description": "One line naming what the page shows; the same text is in summary where a reply has one.", + "type": "string" + }, + "url": { + "description": "The member's own dashboard page.", + "type": "string" + } + }, + "required": [ + "url", + "note" + ], + "type": "object" +}
- Changed
get_monitoring_status1 field changed- added
Output schema / properties / dashboardAdded value: +{ + "additionalProperties": false, + "properties": { + "note": { + "description": "One line naming what the page shows; the same text is in summary where a reply has one.", + "type": "string" + }, + "url": { + "description": "The member's own dashboard page.", + "type": "string" + } + }, + "required": [ + "url", + "note" + ], + "type": "object" +}
- Changed
get_recommendations1 field changed- added
Output schema / properties / dashboardAdded value: +{ + "additionalProperties": false, + "properties": { + "note": { + "description": "One line naming what the page shows; the same text is in summary where a reply has one.", + "type": "string" + }, + "url": { + "description": "The member's own dashboard page.", + "type": "string" + } + }, + "required": [ + "url", + "note" + ], + "type": "object" +}
- Changed
get_sample_audit1 field changed- changed
Output schema / requiredPrevious value: -[ - "is_sample", - "domain", - "note", - "audit", - "price", - "upgrade_url" -]New value: +[ + "is_sample", + "domain", + "note", + "audit", + "upgrade_url" +]
- Added
list_fixes - Changed
run_audit5 fields changed- added
Output schema / properties / dashboardAdded value: +{ + "additionalProperties": false, + "properties": { + "note": { + "description": "One line naming what the page shows; the same text is in summary where a reply has one.", + "type": "string" + }, + "url": { + "description": "The member's own dashboard page.", + "type": "string" + } + }, + "required": [ + "url", + "note" + ], + "type": "object" +} - added
Output schema / properties / next_stepsAdded value: +{ + "description": "Free audits only: what this result found that another tool can act on, as plain facts with the tool's name.", + "items": { + "additionalProperties": false, + "properties": { + "tool": { + "description": "The tool that does it.", + "type": "string" + }, + "what": { + "description": "A plain fact about this result.", + "type": "string" + } + }, + "required": [ + "tool", + "what" + ], + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / recommendation_gapAdded value: +{ + "additionalProperties": true, + "description": "How far behind the top beatable rival the site is, in the answers that recommend it. Present only when measured; its sentence reads the result back in one line.", + "properties": { + "answers": { + "description": "The answers this is a share of: one per question, per assistant.", + "type": [ + "number", + "null" + ] + }, + "gap_points": { + "description": "Points behind the top rival in the answers that RECOMMEND the site (negative when ahead). Null, never 0, when there is no rival or too few answers.", + "type": [ + "number", + "null" + ] + }, + "per_engine": { + "items": { + "additionalProperties": true, + "properties": { + "answers": { + "type": [ + "number", + "null" + ] + }, + "engine": { + "type": "string" + }, + "gap_points": { + "type": [ + "number", + "null" + ] + }, + "rival_recommended": { + "type": [ + "number", + "null" + ] + }, + "state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "behind", + "level", + "ahead", + "no_rival", + "no_local_rival", + "not_enough_answers" + ], + "type": "string" + }, + { + "const": "not_measured", + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "you_recommended": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "engine", + "state", + "gap_points", + "you_recommended", + "rival_recommended", + "answers" + ], + "type": "object" + }, + "type": "array" + }, + "rival": { + "description": "The top BEATABLE rival: marketplaces, delivery and booking apps, directories and national chains are left out. Null when none is recommended.", + "type": [ + "string", + "null" + ] + }, + "rival_recommended": { + "type": [ + "number", + "null" + ] + }, + "sentence": { + "description": "One plain sentence to read back to the owner; also folded into summary.", + "type": "string" + }, + "state": { + "description": "Which kind of gap this is, or why there is none.", + "enum": [ + "behind", + "level", + "ahead", + "no_rival", + "no_local_rival", + "not_enough_answers" + ], + "type": "string" + }, + "tied_with": { + "description": "Other rivals tied for the top: one gap, all named.", + "items": { + "type": "string" + }, + "type": "array" + }, + "you_recommended": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "state", + "gap_points", + "rival", + "rival_recommended", + "tied_with", + "you_recommended", + "answers", + "per_engine", + "sentence" + ], + "type": "object" +} - added
Output schema / properties / stance_countsAdded value: +{ + "additionalProperties": true, + "properties": { + "answers": { + "type": "number" + }, + "cautioned": { + "type": "number" + }, + "mentioned": { + "type": "number" + }, + "not_named": { + "type": "number" + }, + "recommended": { + "type": "number" + }, + "unclear": { + "description": "The rules could not say how the answer treated the site. Not negative.", + "type": "number" + } + }, + "required": [ + "recommended", + "mentioned", + "cautioned", + "unclear", + "not_named", + "answers" + ], + "type": "object" +} - added
Output schema / properties / summaryAdded value: +{ + "description": "Free audits only: next_steps in one sentence.", + "type": "string" +}
- Changed
track_site1 field changed- added
Output schema / properties / dashboardAdded value: +{ + "additionalProperties": false, + "properties": { + "note": { + "description": "One line naming what the page shows; the same text is in summary where a reply has one.", + "type": "string" + }, + "url": { + "description": "The member's own dashboard page.", + "type": "string" + } + }, + "required": [ + "url", + "note" + ], + "type": "object" +}
1 tool update
v1.0.26- Changed
get_recommendations8 fields changed- added
Output schema / properties / recommendations / items / properties / evidenceAdded value: +{ + "additionalProperties": {}, + "type": "object" +} - added
Output schema / properties / recommendations / items / properties / fix_idAdded value: +{ + "type": "string" +} - added
Output schema / properties / recommendations / items / properties / idAdded value: +{ + "type": "string" +} - added
Output schema / properties / recommendations / items / properties / lockedAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / recommendations / items / properties / rankAdded value: +{ + "type": "number" +} - added
Output schema / properties / recommendations / items / properties / sourceAdded value: +{ + "type": "string" +} - added
Output schema / properties / run_idAdded value: +{ + "description": "The audit the steps come from.", + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / tierAdded value: +{ + "description": "Which list the API served. \"free\" omits where to get listed, what the assistants get wrong and each finding's fix file; its step marked `locked` only counts what Pro shows.", + "enum": [ + "free", + "pro" + ], + "type": "string" +}
4 tool updates
v1.0.25- Changed
generate_schema3 fields changed- changed
Input schema / properties / type / descriptionPrevious value: -"Schema type, or auto-detect."New value: +"Schema type; \"auto\" (also the default when omitted) does not detect anything — it returns an Organization draft." - changed
Output schema / properties / jsonld / descriptionPrevious value: -"The JSON-LD document, ready to paste into the site."New value: +"The JSON-LD draft (object or array). NOT ready to paste: every name field arrives as a placeholder — \"Your Business Name\" on the business types, and on a Product the product's own name and brand as \"Your Product Name\" and \"Brand Name\" — that the owner must replace with real names confirmed with them, never guessed from the domain or copied from an audit." - changed
Output schema / properties / placement_notes / descriptionPrevious value: -"Where to put the snippet, e.g. \"in the <head> of every page\"."New value: +"What to replace in the draft first — each name placeholder, confirmed with the owner — then where to embed the finished snippet, e.g. \"in the <head> of every page\". Relay the whole string, in that order: the replacement ask comes before the placement."
- Changed
get_ai_visibility1 field changed- changed
Output schema / properties / trend / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": { - "change_30d": { - "anyOf": [ - { - "$ref": "#/properties/trend/anyOf/0/properties/change_7d/anyOf/0" - }, - { - "type": "null" - } - ] - }, - "change_7d": { - "anyOf": [ - { - "additionalProperties": true, - "properties": { - "engine_changes": { - "items": { - "additionalProperties": true, - "properties": { - "delta": { - "type": "number" - }, - "engine": { - "type": "string" - }, - "from": { - "type": "number" - }, - "to": { - "type": "number" - } - }, - "required": [ - "engine", - "from", - "to", - "delta" - ], - "type": "object" - }, - "type": "array" - }, - "from_captured_at": { - "description": "When the snapshot this window compares against was captured.", - "type": "string" - }, - "from_score": { - "type": "number" - }, - "score_delta": { - "type": "number" - }, - "skipped_snapshots": { - "description": "Snapshots in the window that were not compared: they asked a different question (another business name, market or queries), or do not record what they asked.", - "type": "number" - }, - "snapshots": { - "description": "Snapshots that fell inside this window.", - "type": "number" - }, - "to_score": { - "type": "number" - }, - "window_days": { - "type": "number" - } - }, - "required": [ - "window_days", - "from_score", - "to_score", - "score_delta", - "engine_changes", - "snapshots" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "Null when the window holds no earlier snapshot that asked the same question as the latest." - }, - "includes_simulated": { - "description": "Always false: simulated snapshots are left out of the trend. Kept for clients that read it.", - "type": "boolean" - }, - "latest_captured_at": { - "type": "string" - }, - "question_note": { - "description": "Present when what the snapshots asked shaped the trend: no earlier snapshot asked the latest one's question, snapshots from the last 30 days were not compared, or the latest snapshot does not record what it asked. Relay it — a difference between scores that answered different questions is not a change in visibility.", - "type": "string" - }, - "snapshots_analyzed": { - "type": "number" - } - }, - "required": [ - "change_7d", - "change_30d", - "snapshots_analyzed", - "latest_captured_at", - "includes_simulated" - ], - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": true, + "properties": { + "change_30d": { + "anyOf": [ + { + "$ref": "#/properties/trend/anyOf/0/properties/change_7d/anyOf/0" + }, + { + "type": "null" + } + ] + }, + "change_7d": { + "anyOf": [ + { + "additionalProperties": true, + "properties": { + "engine_changes": { + "items": { + "additionalProperties": true, + "properties": { + "delta": { + "type": "number" + }, + "engine": { + "type": "string" + }, + "from": { + "type": "number" + }, + "to": { + "type": "number" + } + }, + "required": [ + "engine", + "from", + "to", + "delta" + ], + "type": "object" + }, + "type": "array" + }, + "from_captured_at": { + "description": "When the snapshot this window compares against was captured.", + "type": "string" + }, + "from_score": { + "type": "number" + }, + "overall_note": { + "description": "Present exactly when score_delta is null: which engines answered each endpoint. Relay it — a null delta for this reason reads like one for want of history otherwise.", + "type": "string" + }, + "score_delta": { + "description": "The overall move across the window, or null when its two endpoints were answered by different engines — an overall over a different set of engines is a different quantity. `overall_note` says which engines answered each; engine_changes still compares every engine that answered both.", + "type": [ + "number", + "null" + ] + }, + "skipped_snapshots": { + "description": "Snapshots in the window that were not compared: they asked a different question (another business name, market or queries), or do not record what they asked.", + "type": "number" + }, + "snapshots": { + "description": "Snapshots that fell inside this window.", + "type": "number" + }, + "to_score": { + "type": "number" + }, + "window_days": { + "type": "number" + } + }, + "required": [ + "window_days", + "from_score", + "to_score", + "score_delta", + "engine_changes", + "snapshots" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Null when the window holds no earlier snapshot that asked the same question as the latest." + }, + "includes_simulated": { + "description": "Always false: simulated snapshots are left out of the trend. Kept for clients that read it.", + "type": "boolean" + }, + "latest_captured_at": { + "type": "string" + }, + "question_note": { + "description": "Present when what the snapshots asked shaped the trend: no earlier snapshot asked the latest one's question, snapshots from the last 30 days were not compared, or the latest snapshot does not record what it asked. Relay it — a difference between scores that answered different questions is not a change in visibility.", + "type": "string" + }, + "snapshots_analyzed": { + "type": "number" + } + }, + "required": [ + "change_7d", + "change_30d", + "snapshots_analyzed", + "latest_captured_at", + "includes_simulated" + ], + "type": "object" + }, + { + "type": "null" + } +]
- Changed
get_changes4 fields changed- changed
Output schema / properties / note / descriptionPrevious value: -"Present when skipped_snapshots is above 0, when newer measured snapshots were left out of the series, or when newer weekly re-audits measured nothing of the business: which, and why, in words. Relay it."New value: +"Present when skipped_snapshots is above 0, when the two snapshots compared were answered by different engines, when newer measured snapshots were left out of the series, or when newer weekly re-audits measured nothing of the business: which, and why, in words. Relay it." - added
Output schema / properties / overall_noteAdded value: +{ + "description": "Present exactly when score_delta is null: the two snapshots were answered by different engines, and which answered each. Relay it — a null delta for this reason must not read like a null for want of history.", + "type": "string" +} - changed
Output schema / properties / score_delta / descriptionPrevious value: -"Only ever between two snapshots that asked the same question. When there is no such pair, including a re-baseline after the business name, market or queries changed, the tool returns NOT_YET_AVAILABLE saying so, never a number."New value: +"Only ever between two snapshots that asked the same question AND were answered by the same engines. When there is no such pair, including a re-baseline after the business name, market or queries changed, the tool returns NOT_YET_AVAILABLE saying so, never a number; when the pair exists but different engines answered the two snapshots, the overall is not subtracted and is null with overall_note, and engine_changes still compares every engine that answered both." - changed
Output schema / properties / score_delta / typePrevious value: -"number"New value: +[ + "number", + "null" +]
- Changed
get_monitoring_status2 fields changed- changed
Output schema / properties / sites / items / properties / change / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": { - "competitor_changes": { - "description": "Always empty: AI-visibility snapshots record no competitors. Kept for clients that read it.", - "items": {}, - "type": "array" - }, - "engine_changes": { - "items": { - "additionalProperties": true, - "properties": { - "delta": { - "type": "number" - }, - "engine": { - "type": "string" - }, - "from": { - "type": "number" - }, - "to": { - "type": "number" - } - }, - "required": [ - "engine", - "from", - "to", - "delta" - ], - "type": "object" - }, - "type": "array" - }, - "from_captured_at": { - "description": "When the earlier snapshot compared was captured.", - "type": "string" - }, - "new_issues": { - "description": "Always empty: AI-visibility snapshots record no audit issues. Kept for clients that read it.", - "items": {}, - "type": "array" - }, - "resolved_issues": { - "description": "Always empty: AI-visibility snapshots record no audit issues. Kept for clients that read it.", - "items": {}, - "type": "array" - }, - "score_delta": { - "type": "number" - }, - "skipped_snapshots": { - "description": "Snapshots passed over because they asked a different question (another business name, market or queries) or do not record what they asked.", - "type": "number" - }, - "to_captured_at": { - "description": "When the later one was.", - "type": "string" - } - }, - "required": [ - "score_delta", - "engine_changes", - "competitor_changes", - "new_issues", - "resolved_issues" - ], - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": true, + "properties": { + "competitor_changes": { + "description": "Always empty: AI-visibility snapshots record no competitors. Kept for clients that read it.", + "items": {}, + "type": "array" + }, + "engine_changes": { + "items": { + "additionalProperties": true, + "properties": { + "delta": { + "type": "number" + }, + "engine": { + "type": "string" + }, + "from": { + "type": "number" + }, + "to": { + "type": "number" + } + }, + "required": [ + "engine", + "from", + "to", + "delta" + ], + "type": "object" + }, + "type": "array" + }, + "from_captured_at": { + "description": "When the earlier snapshot compared was captured.", + "type": "string" + }, + "new_issues": { + "description": "Always empty: AI-visibility snapshots record no audit issues. Kept for clients that read it.", + "items": {}, + "type": "array" + }, + "overall_note": { + "description": "Present exactly when score_delta is null: which engines answered each snapshot. Relay it.", + "type": "string" + }, + "resolved_issues": { + "description": "Always empty: AI-visibility snapshots record no audit issues. Kept for clients that read it.", + "items": {}, + "type": "array" + }, + "score_delta": { + "description": "The overall move, or null when the two snapshots were answered by different engines: the overall is computed over the engines that answered, so an overall over a different set of engines is a different quantity and is not subtracted. `overall_note` says which engines answered each; engine_changes still compares every engine that answered both.", + "type": [ + "number", + "null" + ] + }, + "skipped_snapshots": { + "description": "Snapshots passed over because they asked a different question (another business name, market or queries) or do not record what they asked.", + "type": "number" + }, + "to_captured_at": { + "description": "When the later one was.", + "type": "string" + } + }, + "required": [ + "score_delta", + "engine_changes", + "competitor_changes", + "new_issues", + "resolved_issues" + ], + "type": "object" + }, + { + "type": "null" + } +] - changed
Output schema / properties / sites / items / properties / note / descriptionPrevious value: -"Present when there is no like-for-like change because of a re-baseline or snapshots that do not record what they asked, or when snapshots were passed over: why, in words. Relay it."New value: +"Present when there is no like-for-like change because of a re-baseline or snapshots that do not record what they asked, when snapshots were passed over, or when the change shown has no overall because different engines answered the two snapshots: why, in words. Relay it."
4 tool updates
v1.0.24- Changed
get_ai_visibility1 field changed- changed
Output schema / properties / trend / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": { - "change_30d": { - "anyOf": [ - { - "$ref": "#/properties/trend/anyOf/0/properties/change_7d/anyOf/0" - }, - { - "type": "null" - } - ] - }, - "change_7d": { - "anyOf": [ - { - "additionalProperties": true, - "properties": { - "engine_changes": { - "items": { - "additionalProperties": true, - "properties": { - "delta": { - "type": "number" - }, - "engine": { - "type": "string" - }, - "from": { - "type": "number" - }, - "to": { - "type": "number" - } - }, - "required": [ - "engine", - "from", - "to", - "delta" - ], - "type": "object" - }, - "type": "array" - }, - "from_score": { - "type": "number" - }, - "score_delta": { - "type": "number" - }, - "snapshots": { - "description": "Snapshots that fell inside this window.", - "type": "number" - }, - "to_score": { - "type": "number" - }, - "window_days": { - "type": "number" - } - }, - "required": [ - "window_days", - "from_score", - "to_score", - "score_delta", - "engine_changes", - "snapshots" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "Null when fewer than two snapshots fall in the window." - }, - "includes_simulated": { - "description": "True if any analyzed snapshot was estimated rather than measured.", - "type": "boolean" - }, - "latest_captured_at": { - "type": "string" - }, - "snapshots_analyzed": { - "type": "number" - } - }, - "required": [ - "change_7d", - "change_30d", - "snapshots_analyzed", - "latest_captured_at", - "includes_simulated" - ], - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": true, + "properties": { + "change_30d": { + "anyOf": [ + { + "$ref": "#/properties/trend/anyOf/0/properties/change_7d/anyOf/0" + }, + { + "type": "null" + } + ] + }, + "change_7d": { + "anyOf": [ + { + "additionalProperties": true, + "properties": { + "engine_changes": { + "items": { + "additionalProperties": true, + "properties": { + "delta": { + "type": "number" + }, + "engine": { + "type": "string" + }, + "from": { + "type": "number" + }, + "to": { + "type": "number" + } + }, + "required": [ + "engine", + "from", + "to", + "delta" + ], + "type": "object" + }, + "type": "array" + }, + "from_captured_at": { + "description": "When the snapshot this window compares against was captured.", + "type": "string" + }, + "from_score": { + "type": "number" + }, + "score_delta": { + "type": "number" + }, + "skipped_snapshots": { + "description": "Snapshots in the window that were not compared: they asked a different question (another business name, market or queries), or do not record what they asked.", + "type": "number" + }, + "snapshots": { + "description": "Snapshots that fell inside this window.", + "type": "number" + }, + "to_score": { + "type": "number" + }, + "window_days": { + "type": "number" + } + }, + "required": [ + "window_days", + "from_score", + "to_score", + "score_delta", + "engine_changes", + "snapshots" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Null when the window holds no earlier snapshot that asked the same question as the latest." + }, + "includes_simulated": { + "description": "Always false: simulated snapshots are left out of the trend. Kept for clients that read it.", + "type": "boolean" + }, + "latest_captured_at": { + "type": "string" + }, + "question_note": { + "description": "Present when what the snapshots asked shaped the trend: no earlier snapshot asked the latest one's question, snapshots from the last 30 days were not compared, or the latest snapshot does not record what it asked. Relay it — a difference between scores that answered different questions is not a change in visibility.", + "type": "string" + }, + "snapshots_analyzed": { + "type": "number" + } + }, + "required": [ + "change_7d", + "change_30d", + "snapshots_analyzed", + "latest_captured_at", + "includes_simulated" + ], + "type": "object" + }, + { + "type": "null" + } +]
- Changed
get_changes8 fields changed- added
Output schema / properties / competitor_changes / descriptionAdded value: +"Always empty: AI-visibility snapshots record no competitors. Kept for clients that read it." - added
Output schema / properties / from_captured_atAdded value: +{ + "description": "When the earlier snapshot compared was captured.", + "type": "string" +} - added
Output schema / properties / new_issues / descriptionAdded value: +"Always empty: AI-visibility snapshots record no audit issues. Kept for clients that read it." - added
Output schema / properties / noteAdded value: +{ + "description": "Present when skipped_snapshots is above 0, when newer measured snapshots were left out of the series, or when newer weekly re-audits measured nothing of the business: which, and why, in words. Relay it.", + "type": "string" +} - added
Output schema / properties / resolved_issues / descriptionAdded value: +"Always empty: AI-visibility snapshots record no audit issues. Kept for clients that read it." - added
Output schema / properties / score_delta / descriptionAdded value: +"Only ever between two snapshots that asked the same question. When there is no such pair, including a re-baseline after the business name, market or queries changed, the tool returns NOT_YET_AVAILABLE saying so, never a number." - added
Output schema / properties / skipped_snapshotsAdded value: +{ + "description": "Snapshots passed over because they asked a different question (another business name, market or queries) or do not record what they asked.", + "type": "number" +} - added
Output schema / properties / to_captured_atAdded value: +{ + "description": "When the later one was.", + "type": "string" +}
- Changed
get_monitoring_status4 fields changed- changed
Output schema / properties / sites / items / properties / change / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": { - "competitor_changes": { - "items": {}, - "type": "array" - }, - "engine_changes": { - "items": { - "additionalProperties": true, - "properties": { - "delta": { - "type": "number" - }, - "engine": { - "type": "string" - }, - "from": { - "type": "number" - }, - "to": { - "type": "number" - } - }, - "required": [ - "engine", - "from", - "to", - "delta" - ], - "type": "object" - }, - "type": "array" - }, - "new_issues": { - "items": {}, - "type": "array" - }, - "resolved_issues": { - "items": {}, - "type": "array" - }, - "score_delta": { - "type": "number" - } - }, - "required": [ - "score_delta", - "engine_changes", - "competitor_changes", - "new_issues", - "resolved_issues" - ], - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": true, + "properties": { + "competitor_changes": { + "description": "Always empty: AI-visibility snapshots record no competitors. Kept for clients that read it.", + "items": {}, + "type": "array" + }, + "engine_changes": { + "items": { + "additionalProperties": true, + "properties": { + "delta": { + "type": "number" + }, + "engine": { + "type": "string" + }, + "from": { + "type": "number" + }, + "to": { + "type": "number" + } + }, + "required": [ + "engine", + "from", + "to", + "delta" + ], + "type": "object" + }, + "type": "array" + }, + "from_captured_at": { + "description": "When the earlier snapshot compared was captured.", + "type": "string" + }, + "new_issues": { + "description": "Always empty: AI-visibility snapshots record no audit issues. Kept for clients that read it.", + "items": {}, + "type": "array" + }, + "resolved_issues": { + "description": "Always empty: AI-visibility snapshots record no audit issues. Kept for clients that read it.", + "items": {}, + "type": "array" + }, + "score_delta": { + "type": "number" + }, + "skipped_snapshots": { + "description": "Snapshots passed over because they asked a different question (another business name, market or queries) or do not record what they asked.", + "type": "number" + }, + "to_captured_at": { + "description": "When the later one was.", + "type": "string" + } + }, + "required": [ + "score_delta", + "engine_changes", + "competitor_changes", + "new_issues", + "resolved_issues" + ], + "type": "object" + }, + { + "type": "null" + } +] - changed
Output schema / properties / sites / items / properties / change / descriptionPrevious value: -"Latest vs previous snapshot; null if fewer than two."New value: +"The latest change against the most recent earlier snapshot that asked the same question; null when there is none — no scored latest snapshot (the summary says why), a first snapshot, a re-baseline, or snapshots that do not record what they asked." - added
Output schema / properties / sites / items / properties / last_audited_at / descriptionAdded value: +"The date of the last scheduled run, stamped when the scheduler claims it and before the audit runs. It does not say how that run ended: it may still be going, or may have failed, been skipped or measured nothing of the business." - added
Output schema / properties / sites / items / properties / noteAdded value: +{ + "description": "Present when there is no like-for-like change because of a re-baseline or snapshots that do not record what they asked, or when snapshots were passed over: why, in words. Relay it.", + "type": "string" +}
- Changed
list_tracked_sites1 field changed- added
Output schema / properties / tracked / items / properties / last_audited_at / descriptionAdded value: +"The date of the last scheduled run, stamped when the scheduler claims it and before the audit runs. It does not say how that run ended: it may still be going, or may have failed, been skipped or measured nothing of the business."
15 tool updates
v1.0.23- Changed
check_upgrade_status1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "cancel_at_period_end": { + "type": "boolean" + }, + "current_period_end": { + "type": [ + "string", + "null" + ] + }, + "message": { + "type": "string" + }, + "status": { + "description": "Raw subscription status: active, trialing, canceled, none, …", + "type": "string" + }, + "tier": { + "description": "\"none\" | \"free\" | \"pro\".", + "type": "string" + }, + "upgrade_url": { + "type": "string" + } + }, + "required": [ + "tier", + "status", + "current_period_end", + "cancel_at_period_end", + "upgrade_url", + "message" + ], + "type": "object" +}
- Changed
compare_competitors2 fields changed- added
Input schema / properties / business_locationAdded value: +{ + "description": "Optional. The market to compare within, e.g. \"Chiang Mai, Thailand\". Applied to the site AND every competitor, because a comparison asks about one market — scoring one locally and the others globally would rank answers to two different questions. Leave it out and each audit detects its own location, which is right for national or global businesses and wrong for local ones.", + "type": "string" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "gaps": { + "description": "Engines where a competitor appears in AI answers and this site does not.", + "items": { + "additionalProperties": true, + "properties": { + "competitor": { + "type": "string" + }, + "engine": { + "type": "string" + } + }, + "required": [ + "engine", + "competitor" + ], + "type": "object" + }, + "type": "array" + }, + "market": { + "description": "The market every audit in this comparison was scored in, or null when each domain's own location was detected.", + "type": [ + "string", + "null" + ] + }, + "quota": { + "additionalProperties": true, + "properties": { + "audits_skipped": { + "description": "Competitors skipped because the daily quota ran out.", + "type": "number" + }, + "audits_used": { + "description": "Fresh audits actually spent by this call.", + "type": "number" + }, + "cached_reused": { + "description": "Domains served from a recent cached audit; cost no quota.", + "type": "number" + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "remaining": { + "type": [ + "number", + "null" + ] + }, + "reset": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "limit", + "remaining", + "audits_used", + "audits_skipped", + "cached_reused", + "reset" + ], + "type": "object" + }, + "ranking": { + "items": { + "additionalProperties": true, + "properties": { + "domain": { + "type": "string" + }, + "note": { + "type": "string" + }, + "score": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "domain", + "score" + ], + "type": "object" + }, + "type": "array" + }, + "skipped": { + "items": { + "additionalProperties": true, + "properties": { + "detail": { + "type": "string" + }, + "domain": { + "type": "string" + }, + "reason": { + "description": "\"quota\" | \"unreachable\" | \"error\".", + "type": "string" + } + }, + "required": [ + "domain", + "reason" + ], + "type": "object" + }, + "type": "array" + }, + "summary": { + "type": "string" + } + }, + "required": [ + "ranking", + "gaps", + "quota", + "skipped", + "summary", + "market" + ], + "type": "object" +}
- Changed
generate_schema1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "jsonld": { + "description": "The JSON-LD document, ready to paste into the site." + }, + "placement_notes": { + "description": "Where to put the snippet, e.g. \"in the <head> of every page\".", + "type": "string" + } + }, + "required": [ + "placement_notes" + ], + "type": "object" +}
- Changed
get_ai_visibility1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "appears_by_engine": { + "additionalProperties": true, + "description": "Whether the site appeared at all on each engine. Distinct from the scores: an engine can have appearances yet a low score, or the reverse. NULL when the engine was not scored — false would assert it did not name the business, which is a claim an unmeasured engine cannot support.", + "properties": { + "chatgpt": { + "type": [ + "boolean", + "null" + ] + }, + "claude": { + "type": [ + "boolean", + "null" + ] + }, + "gemini": { + "type": [ + "boolean", + "null" + ] + }, + "perplexity": { + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "chatgpt", + "perplexity", + "claude", + "gemini" + ], + "type": "object" + }, + "by_engine": { + "additionalProperties": true, + "description": "Per-engine AI-visibility score, 0–100. NULL means the engine was not scored — see engine_status for which of the two reasons. A null is NOT a zero: zero means the engine answered and never named the business.", + "properties": { + "chatgpt": { + "type": [ + "number", + "null" + ] + }, + "claude": { + "type": [ + "number", + "null" + ] + }, + "gemini": { + "type": [ + "number", + "null" + ] + }, + "perplexity": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "chatgpt", + "perplexity", + "claude", + "gemini" + ], + "type": "object" + }, + "coverage_note": { + "description": "Present exactly when an engine was asked and did not answer. Relay it: the score covers fewer engines than the four this tool can query.", + "type": "string" + }, + "engine_status": { + "additionalProperties": true, + "description": "Why each engine's score is what it is. 'scored' — the engine answered and the number is a measurement. 'unanswered' — it was asked and returned nothing, so there is no score; do not report it as 0. 'not_asked' — it was not part of this run at all.", + "properties": { + "chatgpt": { + "enum": [ + "scored", + "unanswered", + "not_asked" + ], + "type": "string" + }, + "claude": { + "enum": [ + "scored", + "unanswered", + "not_asked" + ], + "type": "string" + }, + "gemini": { + "enum": [ + "scored", + "unanswered", + "not_asked" + ], + "type": "string" + }, + "perplexity": { + "enum": [ + "scored", + "unanswered", + "not_asked" + ], + "type": "string" + } + }, + "required": [ + "chatgpt", + "perplexity", + "claude", + "gemini" + ], + "type": "object" + }, + "name_source": { + "description": "\"detected\" | \"user_supplied\" | \"domain_fallback\".", + "type": "string" + }, + "name_verified": { + "type": "boolean" + }, + "name_warning": { + "description": "Set ONLY when the business name behind the score could not be verified. The score is computed from queries built around that name, so relay this caveat rather than presenting the score as settled.", + "type": "string" + }, + "score": { + "description": "Overall AI-visibility score, 0–100.", + "type": "number" + }, + "sources": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "properties": { + "answers": { + "description": "Answers citing this domain — not citation entries.", + "type": "number" + }, + "domain": { + "type": "string" + }, + "ownership": { + "description": "\"yours\" | \"competitor\" | \"third_party\". Competitor rows are context, not targets.", + "type": "string" + }, + "platforms": { + "items": { + "type": "string" + }, + "type": "array" + }, + "title": { + "type": "string" + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "domain", + "answers", + "platforms", + "ownership", + "url", + "title" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "summary": { + "type": "string" + }, + "top_competitor": { + "description": "The competitor appearing in place of the site, if any.", + "type": [ + "string", + "null" + ] + }, + "trend": { + "anyOf": [ + { + "additionalProperties": true, + "properties": { + "change_30d": { + "anyOf": [ + { + "$ref": "#/properties/trend/anyOf/0/properties/change_7d/anyOf/0" + }, + { + "type": "null" + } + ] + }, + "change_7d": { + "anyOf": [ + { + "additionalProperties": true, + "properties": { + "engine_changes": { + "items": { + "additionalProperties": true, + "properties": { + "delta": { + "type": "number" + }, + "engine": { + "type": "string" + }, + "from": { + "type": "number" + }, + "to": { + "type": "number" + } + }, + "required": [ + "engine", + "from", + "to", + "delta" + ], + "type": "object" + }, + "type": "array" + }, + "from_score": { + "type": "number" + }, + "score_delta": { + "type": "number" + }, + "snapshots": { + "description": "Snapshots that fell inside this window.", + "type": "number" + }, + "to_score": { + "type": "number" + }, + "window_days": { + "type": "number" + } + }, + "required": [ + "window_days", + "from_score", + "to_score", + "score_delta", + "engine_changes", + "snapshots" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Null when fewer than two snapshots fall in the window." + }, + "includes_simulated": { + "description": "True if any analyzed snapshot was estimated rather than measured.", + "type": "boolean" + }, + "latest_captured_at": { + "type": "string" + }, + "snapshots_analyzed": { + "type": "number" + } + }, + "required": [ + "change_7d", + "change_30d", + "snapshots_analyzed", + "latest_captured_at", + "includes_simulated" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Pro only; null when unavailable — trend_note says why." + }, + "trend_note": { + "description": "Present exactly when trend is null: the reason.", + "type": "string" + } + }, + "required": [ + "score", + "by_engine", + "engine_status", + "appears_by_engine", + "top_competitor", + "summary", + "trend" + ], + "type": "object" +}
- Changed
get_benchmark1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "peer_median": { + "type": "number" + }, + "percentile": { + "description": "The domain's percentile within its industry/geo peer set, 0–100.", + "type": "number" + }, + "position_summary": { + "type": "string" + }, + "sample_size": { + "description": "How many peers the percentile and median are computed over.", + "type": "number" + } + }, + "required": [ + "percentile", + "peer_median", + "sample_size", + "position_summary" + ], + "type": "object" +}
- Changed
get_changes1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "competitor_changes": { + "items": {}, + "type": "array" + }, + "engine_changes": { + "items": { + "additionalProperties": true, + "properties": { + "delta": { + "type": "number" + }, + "engine": { + "type": "string" + }, + "from": { + "type": "number" + }, + "to": { + "type": "number" + } + }, + "required": [ + "engine", + "from", + "to", + "delta" + ], + "type": "object" + }, + "type": "array" + }, + "new_issues": { + "items": {}, + "type": "array" + }, + "resolved_issues": { + "items": {}, + "type": "array" + }, + "score_delta": { + "type": "number" + } + }, + "required": [ + "score_delta", + "engine_changes", + "competitor_changes", + "new_issues", + "resolved_issues" + ], + "type": "object" +}
- Changed
get_gtm_plan1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "domain": { + "type": "string" + }, + "evidence_note": { + "description": "Additive, never an error: set when the plan had no citation evidence.", + "type": "string" + }, + "model": { + "type": "string" + }, + "plan": { + "additionalProperties": true, + "properties": { + "markdown": { + "type": "string" + }, + "phases": { + "description": "The same plan as `markdown`, cut into 30/60/90-day cards — a rendering, never extra content. An empty array means this plan was not written in card form: render `markdown` instead, and do not report it as a plan without actions. The key being absent means the plan came from a build that predates the cards, which is also not a claim about the plan.", + "items": { + "additionalProperties": true, + "properties": { + "actions": { + "description": "Empty for a phase the plan wrote as prose. That is a real plan with nothing cut into cards for this band, not a plan with nothing in it.", + "items": { + "additionalProperties": true, + "properties": { + "effort": { + "description": "The plan's own effort estimate, or null when it did not give one. Null means unknown — never render a substitute.", + "type": [ + "string", + "null" + ] + }, + "goal": { + "type": [ + "string", + "null" + ] + }, + "priority": { + "description": "Typically \"High\" or \"Medium\"; null when the plan gave none or gave one outside the two the engine keeps. Upstream text, so not an enum here.", + "type": [ + "string", + "null" + ] + }, + "steps": { + "description": "How to apply it, in order. May be empty.", + "items": { + "type": "string" + }, + "type": "array" + }, + "title": { + "type": "string" + }, + "why": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "focus": { + "type": [ + "string", + "null" + ] + }, + "headline": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": "string" + }, + "phase": { + "description": "30, 60 or 90 — the day the band closes.", + "type": "number" + }, + "range": { + "description": "The band as the engine names it, e.g. \"Days 1–30\".", + "type": "string" + }, + "short": { + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "sections": { + "items": { + "additionalProperties": true, + "properties": { + "body_lines": { + "items": { + "type": "string" + }, + "type": "array" + }, + "title": { + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "markdown", + "sections" + ], + "type": "object" + }, + "sources_used": { + "items": { + "type": "string" + }, + "type": "array" + }, + "summary": { + "type": "string" + } + }, + "required": [ + "domain", + "plan", + "sources_used", + "model", + "summary" + ], + "type": "object" +}
- Changed
get_monitoring_status1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "limit": { + "type": "number" + }, + "remaining": { + "type": "number" + }, + "sites": { + "items": { + "additionalProperties": true, + "properties": { + "active": { + "type": "boolean" + }, + "cadence": { + "type": "string" + }, + "change": { + "anyOf": [ + { + "additionalProperties": true, + "properties": { + "competitor_changes": { + "items": {}, + "type": "array" + }, + "engine_changes": { + "items": { + "additionalProperties": true, + "properties": { + "delta": { + "type": "number" + }, + "engine": { + "type": "string" + }, + "from": { + "type": "number" + }, + "to": { + "type": "number" + } + }, + "required": [ + "engine", + "from", + "to", + "delta" + ], + "type": "object" + }, + "type": "array" + }, + "new_issues": { + "items": {}, + "type": "array" + }, + "resolved_issues": { + "items": {}, + "type": "array" + }, + "score_delta": { + "type": "number" + } + }, + "required": [ + "score_delta", + "engine_changes", + "competitor_changes", + "new_issues", + "resolved_issues" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Latest vs previous snapshot; null if fewer than two." + }, + "domain": { + "type": "string" + }, + "last_audited_at": { + "type": [ + "string", + "null" + ] + }, + "latest_score": { + "type": [ + "number", + "null" + ] + }, + "next_run_at": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": "string" + } + }, + "required": [ + "domain", + "latest_score", + "change", + "summary" + ], + "type": "object" + }, + "type": "array" + }, + "summary": { + "type": "string" + }, + "used": { + "type": "number" + } + }, + "required": [ + "limit", + "used", + "remaining", + "sites", + "summary" + ], + "type": "object" +}
- Changed
get_recommendations1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "recommendations": { + "items": { + "additionalProperties": true, + "properties": { + "action": { + "type": "string" + }, + "effort": { + "type": "string" + }, + "expected_impact": { + "type": "string" + }, + "why": { + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "recommendations" + ], + "type": "object" +}
- Changed
get_report1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "badge_html": { + "type": "string" + }, + "report_url": { + "type": "string" + } + }, + "required": [ + "report_url", + "badge_html" + ], + "type": "object" +}
- Changed
get_sample_audit1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "audit": { + "additionalProperties": true, + "description": "A real GET /api/audit payload, populated with sample data.", + "properties": { + "ai_visibility": {}, + "base_url": { + "type": "string" + }, + "results": { + "items": {}, + "type": "array" + }, + "run_id": { + "type": "string" + }, + "status": { + "type": "string" + }, + "summary": {} + }, + "type": "object" + }, + "domain": { + "description": "The fixed sample domain. Never the caller's own.", + "type": "string" + }, + "is_sample": { + "const": true, + "description": "Always true. Never present this as a live result.", + "type": "boolean" + }, + "note": { + "type": "string" + }, + "price": { + "type": "string" + }, + "upgrade_url": { + "type": "string" + } + }, + "required": [ + "is_sample", + "domain", + "note", + "audit", + "price", + "upgrade_url" + ], + "type": "object" +}
- Changed
list_tracked_sites1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "limit": { + "type": "number" + }, + "remaining": { + "type": "number" + }, + "summary": { + "type": "string" + }, + "tracked": { + "items": { + "additionalProperties": true, + "properties": { + "active": { + "type": "boolean" + }, + "cadence": { + "type": "string" + }, + "created_at": { + "type": [ + "string", + "null" + ] + }, + "digest_enabled": { + "type": "boolean" + }, + "domain": { + "type": "string" + }, + "last_audited_at": { + "type": [ + "string", + "null" + ] + }, + "next_run_at": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "domain" + ], + "type": "object" + }, + "type": "array" + }, + "used": { + "type": "number" + } + }, + "required": [ + "limit", + "used", + "remaining", + "tracked", + "summary" + ], + "type": "object" +}
- Changed
run_audit1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "name_warning": { + "description": "Set ONLY when the business name could not be verified, which puts the AI-visibility score in question.", + "type": "string" + }, + "report_url": { + "type": "string" + }, + "scores": { + "additionalProperties": true, + "properties": { + "ai_visibility": { + "type": [ + "number", + "null" + ] + }, + "performance": { + "type": [ + "number", + "null" + ] + }, + "security": { + "type": [ + "number", + "null" + ] + }, + "seo": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "ai_visibility", + "seo", + "security", + "performance" + ], + "type": "object" + }, + "top_issues": { + "items": { + "additionalProperties": true, + "properties": { + "details": { + "type": "string" + }, + "module": { + "type": "string" + }, + "name": { + "type": "string" + }, + "recommendation": { + "type": "string" + }, + "severity": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "required": [ + "severity" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "scores", + "top_issues", + "report_url" + ], + "type": "object" +}
- Changed
track_site1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "already_tracked": { + "type": "boolean" + }, + "cadence": { + "type": "string" + }, + "created": { + "description": "Present when starting: whether this call created a new tracking.", + "type": "boolean" + }, + "domain": { + "type": "string" + }, + "message": { + "type": "string" + }, + "removed": { + "description": "Present when stopping.", + "type": "boolean" + }, + "tracking": { + "description": "True after a start/confirm; false after a stop.", + "type": "boolean" + } + }, + "required": [ + "domain", + "tracking", + "message" + ], + "type": "object" +}
- Changed
untrack_site1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "domain": { + "type": "string" + }, + "limit": { + "type": "number" + }, + "message": { + "type": "string" + }, + "remaining": { + "type": "number" + }, + "removed": { + "type": "boolean" + }, + "tracking": { + "type": "boolean" + }, + "used": { + "type": "number" + } + }, + "required": [ + "domain", + "tracking", + "removed", + "message" + ], + "type": "object" +}
1 tool update
v1.0.20- Added
get_gtm_plan
3 tool updates
v1.0.15- Changed
get_ai_visibility2 fields changed- added
Input schema / properties / business_locationAdded value: +{ + "description": "Optional. The city the business trades in, e.g. \"Hilo, HI\". Leave it out and the audit detects it; when nothing is detectable the questions widen to the country or drop the place entirely, which is right for a national or global business and wrong for a local one.", + "type": "string" +} - added
Input schema / properties / business_nameAdded value: +{ + "description": "Optional. The business's real name, if you know it. Leave it out and the audit detects the name from the site and flags it when unverified — a guessed name is scored as if confirmed, so supply one only when it is actually known.", + "type": "string" +}
- Added
get_sample_audit - Changed
run_audit2 fields changed- added
Input schema / properties / business_locationAdded value: +{ + "description": "Optional. The city the business trades in, e.g. \"Hilo, HI\". Leave it out and the audit detects it; when nothing is detectable the questions widen to the country or drop the place entirely, which is right for a national or global business and wrong for a local one.", + "type": "string" +} - added
Input schema / properties / business_nameAdded value: +{ + "description": "Optional. The business's real name, if you know it. Leave it out and the audit detects the name from the site and flags it when unverified — a guessed name is scored as if confirmed, so supply one only when it is actually known.", + "type": "string" +}
13 tool updates
v1.0.6- First observed
check_upgrade_status - First observed
compare_competitors - First observed
generate_schema - First observed
get_ai_visibility - First observed
get_benchmark - First observed
get_changes - First observed
get_monitoring_status - First observed
get_recommendations - First observed
get_report - First observed
list_tracked_sites - First observed
run_audit - First observed
track_site - First observed
untrack_site
TDQS
Scored across 20 tools
Most tools target a clearly distinct resource+action (run_audit vs get_changes vs compare_competitors vs get_benchmark vs track_site), and descriptions explicitly cross-reference each other to steer selection. However, several boundaries blur: get_ai_visibility vs run_audit (which also returns an AI-visibility score), get_changes vs get_monitoring_status (which embeds the same change logic), and generate_schema vs get_fix (both emit structured data, one draft, one served). The extreme verbosity of each description mitigates but does not fully eliminate the risk of misselection.
All 20 tools are snake_case with a predictable verb_noun structure (get_report, run_audit, compare_competitors, list_tracked_sites, check_fix, confirm_facts). Even the paired lifecycle tools follow the pattern (track_site/untrack_site, get_fix_facts/confirm_facts). There is no mixing of conventions or vague un-prefixed names.
Twenty tools is heavy for a single auditing product; the surface spans audits, monitoring, fixes, facts confirmation and billing. Each has a plausible role, but the fixes cluster (list_fixes, get_fix, check_fix, get_fix_facts, confirm_facts) plus monitoring pair (list_tracked_sites, get_monitoring_status) pushes beyond what most agents need in one call path. It is defensible but on the crowded side rather than tightly scoped.
Coverage is broad and coherent: one-off audit, AI visibility breakdown, change tracking, competitor and industry benchmarks, recommendations, a full fix request/confirm/verify loop, monitoring lifecycle (track/untrack/list/status), report sharing, sample, and subscription status. Minor gaps remain — no way to browse stored audit history beyond get_changes, and no tool to manage the queries/business-name context an audit is measured against beyond re-running. Agents can work around both.
Maintenance
Related MCP Connectors
Audit any site's AI visibility from your assistant: crawler access, rendering, and schema.
Live SEO intelligence, rank tracking, site audits, and backlink analysis for AI agents.
Website health, SEO, security-header, SSL and broken-link audits for AI agents.
Run full technical SEO audits of any website from your AI agent and get structured findings back.
Related MCP Servers
AlicenseAqualityCmaintenanceLets any AI agent audit any website for SEO, GEO/AEO, and speed problems, reporting issues and recommendations without modifying the site.4MIT- AlicenseNot gradedqualityDmaintenanceEnables AI agents to perform instant SEO audits, check robots.txt, sitemaps, and AI crawler access for any URL without API keys.MIT
- AlicenseAqualityDmaintenanceProvides tools for AI agents to audit websites, including stack detection, DNS snapshots, and security checks.87 npmMIT
- AlicenseAqualityDmaintenanceEnables users to scan any website for AI search visibility, producing AEO, GEO, agent readiness, and mention-readiness scores along with AI identity and business profile insights. Paid tools extend this to competitive comparisons, detailed audits, and generated fixes.41MIT