Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

squirrelscan

REMOTE · MCP.SQUIRRELSCAN.COM · SCANNED SEP 20

Website QA for your coding agent: audit SEO, performance, security, accessibility over MCP.

+6 this week 92 Trust /100
Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score → Why this is hard to score →

Endpoint Security97
Transport & Reachability100
Schema Quality & AI Usability64
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 9520 tokens (~380/item across 25 items; 25 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management100
  • No destabilizing schema changes in the last 30 days.Pass
Tool Coverage100
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 100% of tool parameters carry a description.Pass
Tool Safety100
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • All 3 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
  • An AI judge read all 26 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
  • Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
Install

How do I install the squirrelscan MCP server?

squirrelscan is a hosted endpoint at https://mcp.squirrelscan.com/mcp, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

remote · mcp.squirrelscan.com

# add to Claude Code
claude mcp add --transport http com-squirrelscan-squirrelscan 'https://mcp.squirrelscan.com/mcp'
// .cursor/mcp.json
{
  "mcpServers": {
    "com-squirrelscan-squirrelscan": {
      "url": "https://mcp.squirrelscan.com/mcp"
    }
  }
}
// .vscode/mcp.json
{
  "servers": {
    "com-squirrelscan-squirrelscan": {
      "type": "http",
      "url": "https://mcp.squirrelscan.com/mcp"
    }
  }
}
# ~/.codex/config.toml
[mcp_servers.com-squirrelscan-squirrelscan]
url = "https://mcp.squirrelscan.com/mcp"
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "com-squirrelscan-squirrelscan": {
      "type": "remote",
      "url": "https://mcp.squirrelscan.com/mcp",
      "enabled": true
    }
  }
}
# add to OpenClaw
openclaw mcp add com-squirrelscan-squirrelscan --url 'https://mcp.squirrelscan.com/mcp' --transport streamable-http
# ~/.hermes/config.yaml
mcp_servers:
  com-squirrelscan-squirrelscan:
    url: "https://mcp.squirrelscan.com/mcp"
// ~/.netclaw/config/netclaw.json
{
  "McpServers": {
    "com-squirrelscan-squirrelscan": {
      "Transport": "http",
      "Url": "https://mcp.squirrelscan.com/mcp"
    }
  }
}
# add to Vellum
assistant mcp add com-squirrelscan-squirrelscan -t streamable-http -u 'https://mcp.squirrelscan.com/mcp'
// mcp.json
{
  "mcpServers": {
    "com-squirrelscan-squirrelscan": {
      "type": "http",
      "url": "https://mcp.squirrelscan.com/mcp"
    }
  }
}

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 17 Sept 26 −1
    • The server rewrote its instructions, which are the text every model session reads security
    • Tool “get_audit_status” rewrote its description, which is the text the model reads security
    • Tool “run_audit” rewrote its description, which is the text the model reads security
    • Schema quality: 301 → 380 functional
    • New tool “compare_entities” functional
    • New tool “get_entity” functional
    • New tool “get_entity_findings” functional
    • New tool “get_entity_graph” functional
    • New tool “list_entities” functional
  • 15 Sept 26 +7
    • HTTPS: unverified → pass security
    • HSTS header: fail → pass security
  • 14 Sept 26 0
    • “run_audit” added an optional parameter “scope” cosmetic

    1 cosmetic change on this day. Switch on “Show cosmetic changes” to see it.

  • 8 Sept 26 0
    • Tool “get_report” rewrote its description, which is the text the model reads security
  • 6 Sept 26 0
    • Tool “get_audit_status” rewrote its description, which is the text the model reads security
    • Tool “get_report” rewrote its description, which is the text the model reads security
  • 3 Sept 26 0
    • Tool “add_website” rewrote its description, which is the text the model reads security
    • Tool “get_credit_balance” rewrote its description, which is the text the model reads security
    • Tool “list_notifications” rewrote its description, which is the text the model reads security
  • 2 Sept 26 0
    • Tool “get_audit_status” rewrote its description, which is the text the model reads security
    • Tool “get_report” rewrote its description, which is the text the model reads security
    • Tool “list_audits” rewrote its description, which is the text the model reads security
    • Tool “list_issues” rewrote its description, which is the text the model reads security
  • 1 Sept 26 −1
    • The server rewrote its instructions, which are the text every model session reads security
    • Tool “get_report” rewrote its description, which is the text the model reads security
    • New tool “compare_audits” functional
Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 20 Sept 2026 · Probed https://mcp.squirrelscan.com/mcp

TLS valid

Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .

Subject Issuer Valid from Valid until Key Signature Serial
CN=squirrelscan.com CN=WE1,O=Google Trust Services,C=US 1 Aug 2026 30 Oct 2026 ECDSA 256 ECDSA-SHA256 baab9f782db334270e5b08cc1bb103d4
SANs: squirrelscan.com, *.squirrelscan.com
CN=WE1,O=Google Trust Services,C=US (CA) CN=GTS Root R4,O=Google Trust Services LLC,C=US 13 Dec 2023 20 Feb 2029 ECDSA 256 ECDSA-SHA384 7ff31977972c224a76155d13b6d685e3
CN=GTS Root R4,O=Google Trust Services LLC,C=US (CA) CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE 15 Nov 2023 28 Jan 2028 ECDSA 384 SHA256-RSA 7fe530bf331343bedd821610493d8a1b

Background: What to check on a remote MCP endpoint →

DNSSEC insecure

Validation of mcp.squirrelscan.com. Not signed

Zone DS Keys Algorithms Outcome
. trust_anchor 20326, 38696 8, 8 Verified
com. present 19718 13 Verified
squirrelscan.com. absent Unsigned (proven) parent-signed NSEC/NSEC3 proves an unsigned delegation
Authentication Enforced and verified

The endpoint asked for a token and published valid RFC 9728 metadata describing how to get one.

Result Enforced and verified
Enforced On tool calls
HTTP status 200

WWW-Authenticate challenge Bearer error="invalid_token", error_description="Authentication required. Pass a squirrelscan API key as a Bearer token.", resource_metadata="https://mcp.squirrelscan.com/.well-known/oauth-protected-resource"

Bearer error="invalid_token", error_description="Authentication required. Pass a squirrelscan API key as a Bearer token.", resource_metadata="https://mcp.squirrelscan.com/.well-known/oauth-protected-resource"
Header Value
strict-transport-security max-age=31536000; includeSubDomains
x-content-type-options nosniff

Protected resource metadata

Document https://mcp.squirrelscan.com/.well-known/oauth-protected-resource
Retrieved Yes
Resource https://mcp.squirrelscan.com/mcp
Authorisation server https://mcp.squirrelscan.com

Background: How OAuth 2.1 works in the 2026 MCP spec →

Transports 2 probes
Transport URL Outcome Status Location
streamable-http https://mcp.squirrelscan.com/mcp Verified 200
http (plaintext) http://mcp.squirrelscan.com/mcp HTTPS enforced 301 https://mcp.squirrelscan.com/mcp
MCP tools · 25 exposed · ~8,208 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

Tool Tokens
add_website ~232

Register a website with the organization without running an audit (run_audit registers automatically, so this is only needed to set a site up ahead of time). Returns the website_id; idempotent per domain, so calling it again returns the existing website. Pass kind to classify it as owned or prospect up front. On a plan with scheduled audits, a NEW site is registered with recurring weekly audits already on, and each of those runs costs credits: tell the user before calling this, and point them at the site's schedule settings to turn it off. The result's scheduled_audits field reports what was actually set.

NameTypeReqDescription
kindstringClassify the site: 'owned' for something the user runs and monitors, 'prospect' for a lead or competitor. Filterable in list_websites. Unclassified sites read as 'owned', so only an explicit 'prospec…
urlstringyesWebsite URL to register, e.g. https://example.com (scheme optional).

No output schema declared.

No examples provided.

comment_on_issue ~87

Post a comment on a website issue — use it to record analysis, a proposed fix, or what you changed, so the team sees it in the dashboard issue thread. Markdown is supported.

NameTypeReqDescription
bodystringyesComment body (markdown supported).
issue_numberintegeryesIssue number from list_issues.
website_idstringyesWebsite id the issue belongs to.

No output schema declared.

No examples provided.

compare_audits ~314

Compare two completed audits of one website and get what changed. Defaults to the website's latest completed audit against the one before it; pass base/head run ids to compare any two. Each finding gets one of seven kinds: new, resolved, worsened, improved, unchanged (both audits published it), still_open (the evidence store says it is still there but the newer audit did not republish it), or not_crawled (the page was not visited, so the issue is neither fixed nor still broken). resolutionEvidence says what backed the resolved verdicts; when it is "none" nothing is reported as fixed. Score movement is broken down by category. A website with only one audit returns first_run with an empty finding list; an audit where nothing moved returns changed: false. Unchanged, still-open and not-crawled rows are omitted unless requested.

NameTypeReqDescription
basestringOlder run id. Default: the completed run before head.
headstringNewer run id. Default: the website's latest completed run.
include_not_crawledbooleanInclude not-crawled findings.
include_still_openbooleanInclude still-open findings (present per the evidence store, not republished).
include_unchangedbooleanInclude unchanged findings.
limitintegerMax findings returned (default 100). Totals are never capped.
website_idstringyesWebsite id from list_websites or run_audit.

No output schema declared.

No examples provided.

compare_entities ~577

Compare two audits of a site and get the change set: entities added and removed, entities that gained or lost an @id, occurrence changes, new and resolved conflicts and dangling references, summary deltas, and the pages each audit saw that the other did not. Defaults to the previous audit versus the latest. An entity is only reported as removed when every page that declared it was crawled again; anything unproven is reported separately as not crawled, so a smaller crawl never reads as a site that deleted its structured data. Each gainedId and lostId entry carries a coverage field saying whether the newer audit visited every page that declared the old version and found the replacement there. Absence of a gainedId entry is not proof a fix failed: the match needs the type and the name to be unchanged, so changing the @id and the name in one edit appears as a removal plus an addition instead. Fix-and-verify loop: call list_entities with problem="no-id" to find entities declared on several pages with nothing to tie them together, give each one an absolute @id, re-run the audit with run_audit, then call compare_entities and check that gainedId contains the keys you fixed. gainedId is the only confirmation that the fix landed: an entity that gained an @id changes key, so it would otherwise look like one removal plus one addition. Check each entry's coverage field before calling it done: "proven" means the newer audit visited every page that declared the broken version AND found the replacement on all of them, "partial" means one of those could not be established.

NameTypeReqDescription
from_run_idstringThe older audit. Defaults to the one before the newer audit, for the same site. When both runs are named they are ordered chronologically whichever field named them, so a diff always reads forward in…
occurrence_thresholdintegerSmallest occurrence change worth reporting. Default 1, meaning every change. Raise it on a site that publishes constantly, where a site-wide entity moves by one on every audit and would otherwise fil…
to_run_idstringThe newer audit. Defaults to the latest audit that stored at least one entity. When both runs are named they are ordered chronologically whichever field named them.
website_idstringThe registered website to read, on the hosted server. Ignored by the local server, which reads the project store. When both this and run_id are given, run_id wins and this is ignored; naming a run of…

No output schema declared.

No examples provided.

create_api_key ~183

Mint a new squirrelscan API key for this organization (requires credentials carrying the keys:write scope, which OAuth sign-in grants). The key is returned EXACTLY ONCE: show it to the user immediately and suggest saving it as the SQUIRRELSCAN_API_KEY environment variable for the CLI, CI, and MCP. Minted keys cannot themselves mint keys.

NameTypeReqDescription
expires_in_daysintegerExpire the key after this many days (default: never expires).
namestringyesHuman-readable label shown in the dashboard, e.g. "ci" or "claude-code".
scopesarrayScopes to grant (default: audits:write, audits:read, credits:read, org:read). Grantable: audits:write, audits:read, credits:read, org:read, org:write.

No output schema declared.

No examples provided.

delete_website ~149

Delete a website from the organization (soft delete: past audits, reports, and issues are preserved, and published report links keep working). Frees a slot under the plan's website limit. Re-adding the same domain later registers a fresh website with a new website_id. Call once without confirm to see what will happen; call again with confirm: true to delete. To remove many sites at once, use delete_websites.

NameTypeReqDescription
confirmbooleanApprove the deletion. Omit on the first call to see the effect; set true to delete after the user approves.
website_idstringyesWebsite id from list_websites, run_audit, or add_website.

No output schema declared.

No examples provided.

delete_websites ~271

Delete up to 50 websites in one call, for cleaning up a dashboard that has filled with one-off or prospect audits. Same soft delete as delete_website (past audits, reports, and issues are preserved, published report links keep working, slots are freed) and the same two-step confirm: call once without confirm to see the domain behind every id, then again with confirm: true. EVERY result echoes the domain, so read them back to the user before and after: an id is not a name, and this is the tool most likely to be pointed at the wrong list. The preview also shows each site's kind and an owned_count: unclassified sites read as owned, so an 'owned' entry in a list you built from prospects is the clearest sign the wrong ids were assembled. Ids that do not resolve are reported per-id, never as a whole-call failure. To pick the ids, list_websites with kind: "prospect" returns only sites explicitly marked disposable.

NameTypeReqDescription
confirmbooleanApprove the deletions. Omit on the first call to see which domain each id resolves to; set true to delete after the user approves.
website_idsarrayyesWebsite ids from list_websites (1 to 50). Duplicates are collapsed.

No output schema declared.

No examples provided.

get_audit_status ~338

Poll a running audit by run_id (from run_audit or list_audits). Status pending/running means keep polling (every 15-30 seconds): the response includes a progress field (phase, message, page/link counts) when available. Status completed means the report is ready: call get_report with the same run_id. Status failed/cancelled includes the error and completion reason. A failed run also carries failure_reason_code (one of dns, tls, connection, timeout, http_4xx, http_5xx, redirect, robots, unknown) and failure_next_step, so you can act on the cause rather than parsing the error sentence; a cancelled run has neither, because it was stopped rather than defeated by the site. Once the run has a report, health_score and issues_found are read from that published report, so they equal get_report's summary.healthScore and its failed+warnings (#1700). health_score is null for a blocked or unreachable site: that audit has no meaningful grade. A completed run also carries a schedule field describing the website's recurring audits: state is off, active, capped, unschedulable or paused, cadence_label reads as a sentence, settings_url is where the user changes the cadence or turns it off, and cap says how many scheduled sites the plan funds and how many are spent. Recurring audits turn on by themselves after a site's first successful audit and each run costs credits, so pass that on rather than leaving the user to discover the charge.

NameTypeReqDescription
run_idstringyesRun id returned by run_audit or listed by list_audits.

No output schema declared.

No examples provided.

get_credit_balance ~149

Get the organization's credit balance: monthly credits (reset each billing period) and pack credits (purchased, never expire). Audits spend credits pay-as-you-go while they run; run_audit shows an upper-bound estimate before starting. Every audit starts at 50 credits plus 2 per rendered page, so a balance under 50 cannot start one. Pro is $19 a month (or $190 a year) and includes 3,000 credits a month, daily scheduled audits on every site (free schedules one site weekly), faster crawls, and up to 2,000 pages per audit. Upgrade or top up at https://squirrelscan.com/upgrade?src=mcp.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

get_entity ~519

Get one entity as the map recorded it: the properties the map keeps (name, url, logo, image, sameAs, telephone, email, address, description), the pages that declare it, the properties whose values disagree between those pages, and the references in and out of it. The map keeps those nine and @type and nothing else, so a property missing here may still be in the page's JSON-LD, and a disagreement in a property outside that set is not detected. Accepts the entity key, its @id, or its name. Use this after list_entities to see why an entity was flagged, before deciding what to change. Edges and declaring pages are capped; the counts tell you when. Fix-and-verify loop: call list_entities with problem="no-id" to find entities declared on several pages with nothing to tie them together, give each one an absolute @id, re-run the audit with run_audit, then call compare_entities and check that gainedId contains the keys you fixed. gainedId is the only confirmation that the fix landed: an entity that gained an @id changes key, so it would otherwise look like one removal plus one addition. Check each entry's coverage field before calling it done: "proven" means the newer audit visited every page that declared the broken version AND found the replacement on all of them, "partial" means one of those could not be established.

NameTypeReqDescription
keystringyesThe entity key, its @id, or its name. Resolved in that order of certainty: an exact @id match, then an exact key match, then the key formed by prefixing the value with "id:", then an exact case-insen…
run_idstringA specific audit run to read. Defaults to the latest audit that stored at least one entity, which is NOT always the latest audit: an audit that stored none is passed over, because the store cannot te…
website_idstringThe registered website to read, on the hosted server. Ignored by the local server, which reads the project store. When both this and run_id are given, run_id wins and this is ignored; naming a run of…

No output schema declared.

No examples provided.

get_entity_findings ~469

Get the schema/entity-* rule verdicts for an audit: what is wrong with the site's entity graph, which entity keys and pages each finding affects, and the fix text for each. Use this instead of re-deriving the problems from the graph yourself. Each finding names one problem across the whole site rather than one per entity, so a count of 1 can still mean hundreds of pages. The keys and pages on a finding are a SAMPLE: the rule that produced it clipped its own lists before this tool saw them, so the pages listed are never the complete affected set and no field reports how many were left out. Use list_entities with the matching problem filter for the full set. analyzed says whether the rules ran at all: false means this audit was never analyzed, so empty findings are an absence of evidence rather than a clean result. Fix-and-verify loop: call list_entities with problem="no-id" to find entities declared on several pages with nothing to tie them together, give each one an absolute @id, re-run the audit with run_audit, then call compare_entities and check that gainedId contains the keys you fixed. gainedId is the only confirmation that the fix landed: an entity that gained an @id changes key, so it would otherwise look like one removal plus one addition. Check each entry's coverage field before calling it done: "proven" means the newer audit visited every page that declared the broken version AND found the replacement on all of them, "partial" means one of those could not be established.

NameTypeReqDescription
run_idstringA specific audit run to read. Defaults to the latest audit that stored at least one entity, which is NOT always the latest audit: an audit that stored none is passed over, because the store cannot te…
website_idstringThe registered website to read, on the hosted server. Ignored by the local server, which reads the project store. When both this and run_id are given, run_id wins and this is ignored; naming a run of…

No output schema declared.

No examples provided.

get_entity_graph ~736

Get the whole entity graph, or a filtered part of it, in a chosen format: json for the canonical document, jsonld for a validator, mermaid or markdown to read in a conversation, dot or graphml for a graph tool. Defaults to json. Takes the same filters as list_entities. mermaid caps declared entities at 150 and markdown caps rows at 50, and both say so in truncation; json, jsonld, dot and graphml apply no node cap. No cap is not the same as complete: every format renders the stored map, and on the local server that map carries no per-edge page list and no per-page reference list, so those arrays are empty because they were never stored rather than because nothing matched. mermaid's cap bounds declared entities only, so one entity referencing thousands of undeclared ids still renders thousands of placeholder nodes. Not every server implements every format: one that does not will say so rather than return an empty or partial graph, so read the error rather than treating a refusal as a site with nothing to draw. Fix-and-verify loop: call list_entities with problem="no-id" to find entities declared on several pages with nothing to tie them together, give each one an absolute @id, re-run the audit with run_audit, then call compare_entities and check that gainedId contains the keys you fixed. gainedId is the only confirmation that the fix landed: an entity that gained an @id changes key, so it would otherwise look like one removal plus one addition. Check each entry's coverage field before calling it done: "proven" means the newer audit visited every page that declared the broken version AND found the replacement on all of them, "partial" means one of those could not be established.

NameTypeReqDescription
formatstringHow to render the graph: json, jsonld, mermaid, dot, graphml, markdown. Defaults to json.
include_page_localbooleanInclude entities that describe one page rather than the site's subject matter, such as a page's own WebPage or BreadcrumbList. False by default because they usually outnumber everything else.
pageOnly entities declared on a page whose URL CONTAINS one of these strings. Not a prefix test and not a glob, so "/blog" matches https://example.com/blog/post and https://example.com/tag/blog alike. Se…
problemOnly entities with one of these problems: no-id, conflict, dangling, single-page, split-identity. Several values are an OR.
qstringOnly entities whose name or @id contains this text. Case-insensitive substring, not a pattern.
run_idstringA specific audit run to read. Defaults to the latest audit that stored at least one entity, which is NOT always the latest audit: an audit that stored none is passed over, because the store cannot te…
typeOnly entities carrying one of these @type values. Case-insensitive. Several values are an OR: an entity matching any one of them is kept.
website_idstringThe registered website to read, on the hosted server. Ignored by the local server, which reads the project store. When both this and run_id are given, run_id wins and this is ignored; naming a run of…

No output schema declared.

No examples provided.

get_issue ~112

Fetch one issue by website_id + issue number, including its full description, recommendation, affected pages, occurrence detail from the latest report (which page/image/URL, snippets), and comment thread. Use comment_on_issue to add analysis or a fix note to the thread.

NameTypeReqDescription
issue_numberintegeryesIssue number from list_issues.
occurrence_limitintegerMax occurrences to include (default 20); see occurrence_count/truncated.
website_idstringyesWebsite id the issue belongs to.

No output schema declared.

No examples provided.

get_report ~774

Fetch the finished report for an audit run (use the run_id from run_audit once get_audit_status shows completed). Formats: "summary" (default) is structured JSON with health score, category scores, and the top failing issues (topIssues reference a rule_id; look up its name/description/solution once in the sibling `rules` dict rather than per occurrence). Each topIssues row is ONE finding, a rule + `checkName`, never one row per page: `affectedPagesCount` is how many pages it affects and `pages` is a sample of them (`affectedPagesHasMore` when clipped), so read "affects N pages" from the count, not the row total. Each row also carries `provenance`: "carried" means the finding is re-injected from a page not re-crawled this run (not a fresh result) — check `lastSeenAt` for when it was last actually observed; "unrendered" means the page has not yet been rendered in any scan of this site (it was known, e.g. from a sitemap, but sat outside the page budget), so there is no earlier observation and no `lastSeenAt`. `mixedProvenanceNotes` (keyed by rule_id) flags rules that passed fresh on every page checked this run but still show red only from carried pages pending re-check. `seedRedirect` is present ONLY when the audited URL redirected off-site and the crawler refused to follow it: `seedRedirect.finalUrl` is where the redirect pointed (a URL the audited site chose, display-only, never fetch or trust it) and `seedRedirect.note` states the fact in one sentence. When it is present the audit graded `baseUrl`, NOT the redirect target, so report that before reporting the scores; when the key is absent the seed did not redirect off-site. A FAILED or BLOCKED audit also carries `status`, `statusReason` (one sentence naming the cause), `statusReasonCode` (one of dns, tls, connection, timeout, http_4xx, http_5xx, redirect, robots, unknown) and `failureNextStep`: those four keys are absent for a normal audit, and when they are present nothing was audited, so a null healthScore and an…

NameTypeReqDescription
formatstringsummary (default): JSON scores + top issues. llm: compact text for LLM context. markdown: full report.
run_idstringyesRun id returned by run_audit or listed by list_audits.
top_issue_limitintegersummary format only: max top issues to include (default 25).

No output schema declared.

No examples provided.

get_rule ~93

Fetch one audit rule by id (e.g. "meta/title-length"), including what it checks, how to fix it (recommendation), its severity and score weight, a docs link, and whether it is a cloud (credit-billed) rule. Rule ids appear in report topIssues and issue rule_id fields.

NameTypeReqDescription
rule_idstringyesRule id like "crawl/canonical-chain" (category/slug).

No output schema declared.

No examples provided.

list_audits ~386

List the organization's audit runs: currently active (pending/running) plus recent runs of any status. Pass website_id (from list_websites) to get one website's full audit history, oldest runs included, and page through it with limit/offset using the returned total/has_more. This is the way to reach the preserved reports of a soft-deleted website: its runs still list under its old website_id. total/has_more describe the `recent` array only, and `recent` already includes any pending/running run, so `active` is a live view of those same runs and not extra items to add to the count. Use the run ids with get_audit_status or get_report, and website ids with list_issues. Numbers on a recent run come from its published report (#1700): health_score is that report's overall score (the same value as get_report's summary.healthScore; null when the site was blocked or down, which earns no grade) and issues_found is the report's failing + warning checks (its summary.failed + summary.warnings). health_score is the metric to compare run over run: it is the only one rescored consistently across the whole site. Do NOT compare issues_found with the `open` count from list_issues: the issue tracker folds a rule failing on many pages into one open issue and carries issues forward until they are re-checked, so its count is legitimately much smaller and moves independently.

NameTypeReqDescription
limitintegerMax recent runs to return (default 20, max 100).
offsetintegerPagination offset into the recent runs (default 0). Use with total/has_more.
website_idstringOnly return runs of this website (id from list_websites, run_audit, or add_website). Works for soft-deleted websites too.

No output schema declared.

No examples provided.

list_credit_transactions ~153

Audit the organization's credit accounting log: grants (signup/monthly/pack/promo), debits (audit_base 50cr + render 2cr/page + folded 0-cost services), refunds, and adjustments — newest first, paginated. Each debit/refund carries `run_id` so you can group a single audit's spend. Use this to explain why an audit cost what it cost or to reconcile a balance. For one audit's per-feature breakdown, use get_report (its `cost` field). Read-only.

NameTypeReqDescription
cursorstringOpaque pagination cursor from a previous page's `next_cursor`.
limitintegerMax transactions to return (default 25, max 100).

No output schema declared.

No examples provided.

list_entities ~764

List the entities a site declares in its JSON-LD, collapsed across every crawled page into one graph, so an Organization declared identically on 60 pages is one row rather than 60. Declarations collapse by resolved @id, or by type and name when there is no @id, so the SAME real-world thing can still occupy several rows when its declared identity differs between pages: a relative @id such as "#organization" resolves against each page and yields one row per page. That is the split-identity problem, not a quirk of this tool. Filter by @type, by declaring page, by problem class, or by a text match on the name. Page-local entities (a page's own WebPage, BreadcrumbList and unnamed images) usually outnumber the site's actual subject matter and are hidden unless include_page_local is true. Returns a filtered summary, a page of nodes, total, and hasMore; keep requesting pages while hasMore is true rather than describing a site from one page. Fix-and-verify loop: call list_entities with problem="no-id" to find entities declared on several pages with nothing to tie them together, give each one an absolute @id, re-run the audit with run_audit, then call compare_entities and check that gainedId contains the keys you fixed. gainedId is the only confirmation that the fix landed: an entity that gained an @id changes key, so it would otherwise look like one removal plus one addition. Check each entry's coverage field before calling it done: "proven" means the newer audit visited every page that declared the broken version AND found the replacement on all of them, "partial" means one of those could not be established.

NameTypeReqDescription
include_page_localbooleanInclude entities that describe one page rather than the site's subject matter, such as a page's own WebPage or BreadcrumbList. False by default because they usually outnumber everything else.
limitintegerEntities to return. Default 25, maximum 100.
offsetintegerEntities to skip, for paging through a result larger than limit. Default 0. Ordering is by page count descending, then by key, and is stable across calls on one audit, so paging does not repeat or sk…
pageOnly entities declared on a page whose URL CONTAINS one of these strings. Not a prefix test and not a glob, so "/blog" matches https://example.com/blog/post and https://example.com/tag/blog alike. Se…
problemOnly entities with one of these problems: no-id, conflict, dangling, single-page, split-identity. Several values are an OR.
qstringOnly entities whose name or @id contains this text. Case-insensitive substring, not a pattern.
run_idstringA specific audit run to read. Defaults to the latest audit that stored at least one entity, which is NOT always the latest audit: an audit that stored none is passed over, because the store cannot te…
typeOnly entities carrying one of these @type values. Case-insensitive. Several values are an OR: an entity matching any one of them is kept.
website_idstringThe registered website to read, on the hosted server. Ignored by the local server, which reads the project store. When both this and run_id are given, run_id wins and this is ignored; naming a run of…

No output schema declared.

No examples provided.

list_issues ~263

List a website's open audit issues (like a bug tracker: each issue is one failing rule with occurrences across pages, numbered per website). Returns issues sorted by severity, plus severity and status summaries. Use the issue number with get_issue for full detail and comments. Filter by status/severity/category to narrow down. This is a per-website tracker spanning audits, not a per-run count: one rule failing on 600 pages is ONE issue here, and an issue stays open until an audit re-checks it. So the open count is expected to be far smaller than a run's issues_found (list_audits) or a report's failed+warnings, and the two are not comparable (#1700). To compare runs, use health_score from list_audits.

NameTypeReqDescription
categorystringFilter by rule category code (e.g. seo, performance, security).
limitintegerPage size (default 50).
offsetintegerPagination offset (default 0).
severitystringFilter by severity.
statusstringFilter by issue status (omit for all statuses).
website_idstringyesWebsite id from list_websites, run_audit, or list_audits.

No output schema declared.

No examples provided.

list_notifications ~227

Read the organization's notification feed, newest first: what finished, what broke, and what changed since you last looked. Categories include audit_complete, issues_detected, audit_failed, schedule_paused. Use this to catch up at the start of a session ("did last night's scheduled audit run?", "what failed?") instead of polling every website. Each entry carries the category, the human-readable title and body, a data payload with the ids involved (website_id, run_id, report_id), and whether a human has read it in the dashboard. Filter with category, or unread_only to see just what nobody has looked at yet. Paginated with limit/offset. Read-only: this never marks anything read.

NameTypeReqDescription
categoryarrayRestrict to these categories, e.g. ["audit_failed"]. Omit for every category.
limitintegerMax notifications to return (default 20, max 100).
offsetintegerRows to skip (default 0).
unread_onlybooleanOnly notifications no one has read in the dashboard yet.

No output schema declared.

No examples provided.

list_rules ~110

Browse the catalog of 260+ audit rules that run during an audit, grouped into categories (crawlability, meta tags, performance, security, accessibility, content, and more). Filter by category code or search by keyword to find what a specific rule checks. Use get_rule for one rule's full detail.

NameTypeReqDescription
categorystringFilter to one category code (see the categories list in the response).
searchstringCase-insensitive keyword match on rule id, name, and description.

No output schema declared.

No examples provided.

list_websites ~257

List websites the organization has audited, with their latest run status, health score, and owned/prospect kind. Each row carries last_run_id (the latest run, any status) and last_report_run_id / last_report_id (the latest completed run whose report has not been deleted) — pass last_report_run_id to get_report to read a website's newest report without knowing a run id in advance, or list_audits with website_id for its full history. Use the website_id with list_issues/get_issue. Websites registered but never audited do not appear; run_audit or add_website registers a new one. Ephemeral one-shot audits never appear. Returns total/has_more for pagination. Filter by kind to separate sites the user runs from one-off prospect audits: kind: "prospect" returns ONLY sites explicitly marked as such, so it is the safe way to build a bulk-delete list.

NameTypeReqDescription
kindstringFilter by classification. Unclassified sites count as 'owned', so 'prospect' never returns a site nobody explicitly marked disposable. Omit for all websites.
limitintegerPage size (default 50).
offsetintegerPagination offset (default 0).

No output schema declared.

No examples provided.

run_audit ~750

Run a cloud audit of a website (crawl + 260+ rule analysis + report). Credits are spent as the audit runs (pay-as-you-go). The dry run is optional: pass confirm: true on the first call to start straight away. Without confirm, an audit whose estimate is over the org's auto-run threshold comes back as status "confirmation_required" with the estimate to show the user; one at or under the threshold just starts. That response carries "sufficient": true means the organization can pay, so show the estimate and call again with confirm: true; false means it cannot, and the response then carries the cost, the balance, the credit reset date and an upgrade_url for that organization. Relay those, and do NOT retry with confirm: true, which is refused. Use max_pages to size the crawl (max_pages: 1 audits just the entry URL, the cheapest run). Audits are asynchronous and take minutes: poll get_audit_status with the returned run_id, then fetch results with get_report. The website is registered automatically on first audit. A started run carries a schedule field describing the site's recurring audits: when state is active say so, since each of those runs costs credits, and settings_url is where the user turns them off.

NameTypeReqDescription
confirmbooleanApprove the credit spend. Set true to start immediately. Omitting it returns an estimate first for anything over the auto-run threshold, and starts the audit anyway for anything at or under it.
coveragestringCrawl coverage profile (default fast, 10 pages). Deeper coverage crawls more pages and costs more credits.
ephemeralbooleanOne-shot check: run the audit and return the report without adding the site to the organization's website list, and without consuming a slot against the plan's website limit. Use for any 'just check…
kindstringClassify the site: 'owned' for something the user runs and monitors, 'prospect' for a lead or competitor audited once. Filterable in list_websites so a prospect cleanup can never sweep up a live site…
max_creditsintegerSpend guard: refuse to start if the upper-bound estimate exceeds this many credits.
max_pagesintegerCap the crawl at this many pages for this run. Overrides the coverage profile's page count, so max_pages: 1 audits just the entry URL for the cheapest possible run. A value above the plan's per-audit…
renderbooleanRender pages in a headless browser (default true). Catches JavaScript-dependent issues; costs extra credits per page.
scopestringWhich URLs to audit. 'discover' (the default) follows links from the pages it finds. 'sitemap' audits only the URLs the site's sitemap publishes, which is what you want when the sitemap is the list t…
urlstringyesWebsite URL to audit, e.g. https://example.com (scheme optional).

No output schema declared.

No examples provided.

send_feedback ~249

Report your experience using squirrelscan mid-session: a bug, a missing feature, what worked, what confused you, missing report data, or tool ergonomics. Reviewed by the team to improve the product — use it any time something surprises you, not just at the end of a session. Works with any authenticated credentials, including read-only API keys.

NameTypeReqDescription
categorystringyesbug_report (a defect in squirrelscan itself — wrong or missing rule result, crash, broken tool), feature_request (something squirrelscan should do but doesn't), what_worked (something worked well), c…
messagestringyesFree-text feedback (truncated at 2000 chars).
run_idstringAudit run id this feedback relates to, if any (from run_audit/get_report). Verified against your credentials' runs before being attached.
website_idstringWebsite id this feedback relates to, if any (from list_websites). Verified against your org's websites before being attached.

No output schema declared.

No examples provided.

whoami ~46

Identify the current credentials: how you are authenticated, which organization you act for, the plan, and the current credit balance. Call this first in a session to orient yourself before running audits.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

Common questions

What is the squirrelscan MCP server?

squirrelscan is an MCP server listed in the public MCP registry as com.squirrelscan/squirrelscan. Website QA for your coding agent: audit SEO, performance, security, accessibility over MCP. This page covers its hosted endpoint (https://mcp.squirrelscan.com/mcp).

Is the squirrelscan MCP server safe to use?

squirrelscan scores 92 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

What tools does the squirrelscan MCP server expose?

squirrelscan exposes 25 tools: run_audit, get_audit_status, list_audits, list_websites, add_website, and 20 more. Their descriptions and schemas cost roughly 8,208 tokens of context every time the server is loaded.

Does the squirrelscan MCP server require authentication?

Yes. squirrelscan asked us for credentials when we connected, so you will need to authorise it in your MCP client before it can do anything.

Is the squirrelscan MCP server still maintained?

squirrelscan is still listed as active in the MCP registry. We last reached this channel on 20 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.