Web Validator by DigestSEO
This MCP server validates web pages and assets and produces SEO/accessibility, JSON-LD, link, report, and screenshot outputs.
Validate local HTML/XHTML files with the W3C Nu HTML Checker.
Validate HTML fetched from a public URL with the W3C Nu HTML Checker.
Validate local CSS files with the W3C Jigsaw CSS Validator.
Run offline SEO and accessibility metadata audits on supplied HTML, including titles, descriptions, canonical tags, robots directives, headings, viewport metadata, image alt text, and Open Graph tags.
Check up to 25 public HTTP(S) links found in supplied HTML, reporting broken/blocked/failed links without following redirects.
Parse JSON-LD blocks and report empty blocks or JSON syntax errors, without validating vocabulary semantics.
Generate a combined Markdown and structured validation report covering HTML/XHTML, optional CSS, SEO/accessibility, JSON-LD syntax, and bounded public-link checks.
Capture responsive PNG screenshots of local HTML files or public URLs at desktop, tablet, mobile, or custom viewports, writing files to a chosen output directory.
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., "@Web Validator by DigestSEOValidate the HTML in about.html"
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.
Web Validator by DigestSEO
An MCP server for HTML and CSS validation, technical SEO and accessibility checks, JSON-LD syntax validation, broken-link checks, and responsive screenshots. It is part of the DigestSEO suite of open-source SEO tools.
Product: digestseo.com/validator-mcp
Engineering case study: DigestSEO MCP Suite — AI visibility, Search Console, web validation, and trend intelligence
Documentation: this README
Support: digestseo.com/support
Privacy: digestseo.com/privacy
Choose the right surface
This repository contains two deliberately separate MCP surfaces:
Surface | Transport | Best for | Access and side effects |
Local npm server | stdio | Claude Desktop, Cursor, and other local MCP clients | Can read user-selected workspace files, contact validation and link targets, and write screenshot files. |
Hosted app | Streamable HTTP | ChatGPT and remote MCP clients | Can fetch one authorized public HTML page, run a bounded sitemap-first site audit, or process supplied markup. It cannot access local files, authenticate, recursively crawl links, execute page JavaScript, or create screenshots. |
Local installation:
npx -y mcp-web-validatorHosted endpoint:
https://web-validator-mcp.digestseo.com/mcpRelated MCP server: GEO MCP by DigestSEO
Requirements
Node.js 22.12.0 or newer
An MCP client that supports stdio, or a client that supports Streamable HTTP for the hosted endpoint
The validation, SEO, schema, link, and report tools do not download a browser during installation. The local screenshot.capture tool installs its pinned headless browser into Puppeteer's cache on first use, then reuses that browser for later screenshots. Set PUPPETEER_CACHE_DIR if you need a custom cache location.
Tools
The npm package exposes these exact runtime tool names:
Tool | Purpose | Network or filesystem behavior |
| Validate a local HTML or XHTML file. | Reads the selected file and submits its markup to the external W3C Nu HTML Checker at |
| Validate the markup returned by a public URL. | Fetches the URL, then submits the returned markup to the external Nu checker. |
| Validate a local CSS file. | Reads the selected file and submits its CSS to the external W3C Jigsaw CSS Validator. |
| Audit titles, descriptions, canonical tags, robots noindex directives, headings, viewport metadata, image alt attributes, and Open Graph metadata. | Processes supplied HTML locally. |
| Check links extracted from supplied HTML. | Sends bounded HTTP requests to eligible public links. |
| Parse JSON-LD blocks and report JSON syntax errors. | Processes supplied HTML locally. |
| Combine HTML/XHTML, optional CSS, SEO, JSON-LD, and bounded link checks in a Markdown report. | Reads selected files, contacts the validators, and checks eligible public links found in the markup; |
| Capture desktop, tablet, mobile, or custom viewport screenshots. | Opens a selected local file or eligible public URL and writes PNG files to the selected output directory; existing matching files may be replaced. |
For direct Node.js integrations, auditSeoMetadata(html, xRobotsTag) and
auditSeoMetadataDetailed(html, xRobotsTag) from dist/seo-auditor.js accept
an optional caller-observed X-Robots-Tag HTTP response-header value. Separate
multiple header fields with newlines. This inspection is offline and never
fetches headers; the MCP seo.metadata tool still analyzes supplied HTML only.
Hosted app tools
The hosted app exposes eight tools:
Tool | Purpose |
| Fetch one authorized public HTML page and run the combined HTML, SEO/accessibility-signal, and JSON-LD syntax audit. Link checks are optional. |
| Run a bounded sitemap-first audit of up to eight authorized, same-origin public pages. It respects |
| Validate raw HTML markup already supplied in the conversation. |
| Parse supplied CSS for syntax errors inside the Worker. |
| Audit supplied HTML for covered on-page SEO, robots noindex, and accessibility signals. |
| Check JSON-LD blocks in supplied HTML for JSON syntax errors. |
| Check up to 20 authorized public links extracted from supplied HTML. |
| Combine the checks for supplied markup; |
audit_public_webpage follows at most three validated redirects, accepts a bounded text/html response, and records the final URL. It does not crawl additional pages, execute JavaScript, authenticate, or fetch linked stylesheets and assets. audit_public_site first locks the final public origin, then reads bounded robots.txt plus same-origin XML Sitemap, RSS 2.0, Atom 1.0, and plain-text sitemap representations before auditing at most eight eligible sitemap pages in one call. Robots discovery may follow up to five validated public redirects across authorities, as defined by the robots protocol; the resulting rules and relative Sitemap directives are still interpreted for the originally audited authority. Sitemap entries and audited pages remain same-origin, and private/reserved destinations, credentials, custom ports, service self-fetches, and HTTPS-to-HTTP redirect downgrades are rejected. The tool never follows HTML links or external sitemap entries; use page_offset when the response says more eligible pages remain. The fetched HTML is sent to https://html5.validator.nu/, the same external Nu HTML Checker used by validate_html and the report tool. CSS parsing, SEO analysis, and JSON-LD parsing run inside the DigestSEO Worker. Optional link checks make capped HEAD requests, with a bounded GET fallback where necessary, to eligible public HTTP(S) URLs; link redirects are reported but not followed. The site tool intentionally does not perform site-wide link checking. The hosted app does not retain tool inputs, fetched HTML, or results.
Privacy Policy
Only validate files, markup, and public webpages that you own or are authorized to inspect. Public page URLs can contain sensitive query values, so remove tokens and private identifiers before submitting them. Do not submit passwords, API keys, access tokens, payment data, health data, private source code, or other sensitive personal data.
The local server runs with the same operating-system permissions as its MCP client. Review tool inputs before approving file access, outbound validation, link checking, or screenshot creation. The hosted app has no access to your local filesystem.
See the published privacy policy for data-handling details and SECURITY.md for private vulnerability reporting.
Configure a local client
Claude Desktop
Add the server to claude_desktop_config.json:
Windows:
%APPDATA%\Claude\claude_desktop_config.jsonmacOS:
~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"mcp-web-validator": {
"command": "npx",
"args": ["-y", "mcp-web-validator"]
}
}
}Restart Claude Desktop after saving the configuration.
Cursor and compatible clients
Create a command/stdio MCP server with:
npx -y mcp-web-validatorThis repository also includes a Cursor Marketplace plugin manifest. After the plugin is published, install Web Validator by DigestSEO from Cursor's Marketplace or add the repository from Cursor's plugin UI. The plugin bundles the same local stdio server and does not require API keys or environment variables.
Visual Studio Code with GitHub Copilot
In VS Code, run MCP: Add Server from the Command Palette and choose Command
(stdio) with npx -y mcp-web-validator. Or add the following to your own
workspace's .vscode/mcp.json (VS Code format):
{
"servers": {
"mcp-web-validator": {
"type": "stdio",
"command": "npx",
"args": ["-y", "mcp-web-validator"]
}
}
}For a remote-only connection, use this server entry instead (no local Node.js required, but local-file and screenshot tools are unavailable):
{
"servers": {
"mcp-web-validator-hosted": {
"type": "http",
"url": "https://web-validator-mcp.digestseo.com/mcp"
}
}
}Open MCP: List Servers to start/check the connection. In Copilot Agent
chat, ask it to run seo.metadata on an HTML snippet you provide (input field
htmlContent) and report its metadata issues. This is an offline, no-network
smoke test of the local stdio server; it should return structured issues and
totalIssues without contacting W3C or fetching a webpage. Use the local
server for this check, since the hosted surface has different tool names.
The repository also contains a portable root .mcp.json for compatible
Copilot harness clients. Its top-level key is mcpServers, not servers;
do not copy that object unchanged into .vscode/mcp.json. VS Code's
MCP configuration reference
explains the file formats and supported scopes. Review tool permissions before
allowing outbound validation or filesystem-writing screenshot calls.
OpenAI Codex
Codex CLI can add the published local stdio package directly:
codex mcp add mcp-web-validator -- npx -y mcp-web-validatorOr add the existing hosted Streamable HTTP surface instead:
codex mcp add mcp-web-validator-hosted --url https://web-validator-mcp.digestseo.com/mcpVerify either configuration with:
codex mcp listThe local package includes workspace-file validation and responsive screenshot capture. The hosted surface is remote-only and cannot access local files or create screenshots.
Gemini CLI
Gemini CLI supports local stdio MCP servers. Add the published package with:
gemini mcp add mcp-web-validator npx -y mcp-web-validatorThis writes the server definition to Gemini CLI's MCP configuration. No API keys or environment variables are required by Web Validator.
GitHub Copilot CLI
Add the published local stdio server with:
copilot mcp add mcp-web-validator -- npx -y mcp-web-validatorWhen Copilot CLI is started inside a clone of this repository, it can also
discover the checked-in root .mcp.json, which already points
mcp-web-validator at npx -y mcp-web-validator.
Kiro
This installs the local stdio package, preserving its workspace-file and screenshot capabilities. Node.js 22.12.0+ is required.
Development
Clone the repository and install the locked dependencies:
git clone https://github.com/AKzar1el/mcp-web-validator.git
cd mcp-web-validator
npm ciRun the local quality gates:
npm run check
npm test
npm run build
npm pack --dry-runRun the local stdio server:
npm startValidate the hosted Worker separately:
cd chatgpt-plugin
npm ci
npm run check
npm test
npm run deploy:dry-runSee CONTRIBUTING.md for contribution expectations. Deployment and marketplace-review notes live in chatgpt-plugin/SUBMISSION.md. For agent-assisted installation, see llms-install.md. For a copy-ready, zero-paid-provider GitHub Actions metadata gate, see examples/github-actions.
Ecosystem
License
Licensed under the MIT License.
Available Tools
8 toolscss.localValidate local CSSARead-onlyIdempotentInspect
Reads a bounded local CSS file and sends it to the W3C Jigsaw CSS Validator. Use only files the user is authorized to share.
| Name | Required | Description | Default |
|---|---|---|---|
| filePath | Yes | Absolute or workspace-relative path to a CSS file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | |
| errors | Yes | |
| warnings | No | |
| truncated | Yes | |
| totalMessages | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, non-destructive, idempotent behavior, so the description adds meaningful context by revealing the external W3C Jigsaw validation step and the authorization requirement. This goes beyond what annotations alone would convey.
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?
Two concise sentences with no filler. The core action is front-loaded, and the important authorization caveat is placed second without redundancy.
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?
The tool is simple with one parameter, full schema coverage, rich annotations, and an output schema. The description covers the critical behavioral and authorization context, leaving no essential gap for an agent to call it correctly.
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 schema covers the single parameter fully at 100%, describing filePath as a CSS file path. The description adds no extra semantics beyond the schema, which matches the baseline for fully documented schema 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 states a specific verb ('Reads') and resource ('a bounded local CSS file') and clarifies the tool's purpose: sending the file to the W3C Jigsaw CSS Validator. This distinguishes it from sibling tools like html.url or links.broken.
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 phrase 'Use only files the user is authorized to share' provides clear usage context and a constraint on acceptable inputs. It does not explicitly name alternatives or when-not-to-use conditions, but the local CSS scope and sibling tool names imply the boundary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
html.localValidate local HTMLARead-onlyIdempotentInspect
Reads a bounded local HTML or .xhtml file and sends its markup to the W3C Nu HTML Checker. .xhtml files use application/xhtml+xml parsing semantics. Use only files the user is authorized to share.
| Name | Required | Description | Default |
|---|---|---|---|
| filePath | Yes | Absolute or workspace-relative path to an HTML or .xhtml file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | |
| errors | Yes | |
| truncated | Yes | |
| totalMessages | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, open-world, idempotent, and non-destructive. The description adds that the file's markup is sent to an external service (W3C), that .xhtml uses application/xhtml+xml parsing, and that content must be shareable, disclosing external data transmission and parsing semantics beyond 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?
Three sentences with no filler. The first states the core operation, the second adds a specific parsing detail, and the third adds a critical usage constraint. All earn their place.
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 one-parameter tool with a rich output schema and annotations, the description covers the input, the external validation behavior, parsing semantics, and an authorization constraint. There are no significant gaps for correct invocation.
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 schema already documents filePath as an absolute or workspace-relative path; the description adds that it must be bounded, local, and only for authorized files, and clarifies .xhtml parsing behavior, enriching the parameter's meaning beyond 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 description states a specific action (reads a local HTML or .xhtml file and sends it to the W3C Nu HTML Checker), names the resource, and the title reinforces validation. The 'local' qualifier distinguishes it from html.url and other siblings.
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 description gives clear context: use with local HTML/.xhtml files, and only files the user is authorized to share. It does not explicitly name alternatives like html.url, but the 'local' scope and authorization constraint effectively guide selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
html.urlValidate a public URLARead-onlyIdempotentInspect
Fetches a bounded public HTTP(S) page, then sends its markup to the W3C Nu HTML Checker. Private, reserved, credentialed, and nonstandard-port destinations are rejected.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Public HTTP(S) URL on port 80 or 443. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | |
| errors | Yes | |
| truncated | Yes | |
| fetchedUrl | No | |
| totalMessages | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=false. The description adds meaningful context beyond those hints: the fetch is bounded, it delegates to the W3C Nu HTML Checker, and specific destination classes are rejected. No contradiction with annotations is present.
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?
Two tightly scoped sentences that front-load the core mechanism and then state rejection constraints. Every sentence earns its place with no filler or repetition.
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 single-parameter tool with a full output schema, the description covers the operation, the external checker dependency, and the boundary conditions. Nothing an agent needs in order to correctly select and invoke this tool for a public URL 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 input schema already documents the url parameter as a public HTTP(S) URL on port 80 or 443. The description reinforces this constraint but adds no substantial new parameter-level semantics beyond what the schema states, so the baseline score of 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?
Description opens with a concrete action—fetching a bounded public HTTP(S) page and sending its markup to the W3C Nu HTML Checker—and the title 'Validate a public URL' reinforces the operation. The explicit focus on remote public pages distinguishes it from local and CSS-specific sibling validators like html.local and css.local.
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 description clearly states when to use the tool: validating a public HTTP(S) URL. It also gives explicit when-not conditions by rejecting private, reserved, credentialed, and nonstandard-port destinations. It stops short of explicitly naming sibling alternatives such as html.local, so it is not a full routing guide.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
links.brokenCheck public linksARead-onlyIdempotentInspect
Resolves and checks up to 25 public HTTP(S) links in supplied HTML. Redirects are reported but not followed, and response bodies are discarded.
| Name | Required | Description | Default |
|---|---|---|---|
| baseUrl | No | Optional public HTTP(S) base URL used to resolve relative links. | |
| maxLinks | No | Maximum number of public HTTP(S) links to check, from 1 to 25. | |
| htmlContent | Yes | Raw HTML markup containing links to check. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | |
| links | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations, the description adds meaningful behavioral details: redirects are reported but not followed, and response bodies are discarded. These are important for understanding how links are checked and align with readOnlyHint and idempotentHint. 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?
Two sentences, front-loaded with the core purpose and followed by concise behavioral constraints. Every clause adds information, and 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?
Given the output schema exists, return values don't need description. The description covers limit, redirect handling, and body handling, which are the key operational details an agent needs before invoking. It doesn't mention possible errors or network dependencies, but annotations and schema cover much of that context.
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 baseline is 3. The description does not directly explain parameters but reinforces maxLinks ('up to 25') and htmlContent ('supplied HTML'), while baseUrl is left to the schema. No extra value beyond schema, but no 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 clearly states the tool checks public HTTP(S) links in supplied HTML, with a precise verb ('checks') and resource ('up to 25 public HTTP(S) links'). It also distinguishes itself by noting redirects are reported but not followed and response bodies are discarded, making its function specific and unambiguous.
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 description implies usage for link checking in HTML but does not explicitly state when to prefer this tool over alternatives or when not to use it. It doesn't mention sibling tools like html.url or report.validation, leaving the selection partly to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
report.validationGenerate a validation reportARead-onlyIdempotentInspect
Combines W3C HTML/CSS validation, local SEO/accessibility checks, JSON-LD syntax checks, and a bounded public-link check into a Markdown and structured report.
| Name | Required | Description | Default |
|---|---|---|---|
| baseUrl | No | Optional public HTTP(S) base URL used to resolve relative links. | |
| cssFilePath | No | Optional absolute or workspace-relative CSS file path. | |
| htmlFilePath | Yes | Absolute or workspace-relative HTML or .xhtml file path. |
Output Schema
| Name | Required | Description |
|---|---|---|
| links | Yes | |
| errors | No | |
| report | Yes | |
| summary | Yes | |
| seoIssues | Yes | |
| cssMessages | Yes | |
| cssTruncated | Yes | |
| failedChecks | Yes | |
| htmlMessages | Yes | |
| schemaIssues | Yes | |
| seoTruncated | Yes | |
| htmlTruncated | Yes | |
| seoTotalIssues | Yes | |
| schemaTruncated | Yes | |
| cssTotalMessages | Yes | |
| htmlTotalMessages | Yes | |
| schemaTotalIssues | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnly, openWorld, idempotent, and non-destructive hints, so the description's burden is lighter. It adds meaningful behavior: it performs combined W3C/local/JSON-LD/public-link checks and produces both Markdown and structured output. The 'bounded public-link check' clue also hints at external network behavior without contradicting 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?
One dense, front-loaded sentence communicates the tool's purpose, scope, and output format with no filler. Every part of the sentence adds useful information.
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 an aggregate validation tool with a rich output schema and strong annotations, the description is largely complete. The main gap is optional-parameter behavior: an agent cannot tell from the description how omitting cssFilePath or baseUrl affects which checks run, nor exactly what 'bounded' means for the public-link check.
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 baseline is 3. The description's check categories map loosely to the parameters, but it adds no explicit detail about whether cssFilePath gates CSS validation or whether baseUrl gates the public-link check. The schema itself already carries the parameter meaning.
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: it combines validations 'into a Markdown and structured report.' It enumerates the exact check categories, which clearly distinguishes this aggregate tool from single-purpose siblings like html.local, css.local, links.broken, schema.markup, and seo.metadata.
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 description implies this is the all-in-one validation tool, but it never explicitly says when to prefer report.validation over the individual sibling tools or when not to use it. The aggregation language gives useful context, but the agent must infer the tool-selection logic.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
schema.markupValidate JSON-LD syntaxARead-onlyIdempotentInspect
Parses JSON-LD blocks in supplied HTML locally and reports empty blocks or JSON syntax errors. It does not validate vocabulary semantics.
| Name | Required | Description | Default |
|---|---|---|---|
| htmlContent | Yes | Raw HTML containing JSON-LD script blocks. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | |
| counts | Yes | |
| issues | Yes | |
| truncated | Yes | |
| totalIssues | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already convey read-only, idempotent, and non-destructive behavior, so the bar is lower. The description adds useful behavioral context beyond annotations: processing is local, not network-based, and it specifically detects empty blocks and JSON syntax errors. No contradiction exists.
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?
Two sentences carry the core action, output scope, and an important limitation with zero filler. The primary behavior is front-loaded, and every sentence earns its place.
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 simple one-parameter tool with rich annotations and an output schema, the description fully covers what the tool does, where it runs, what it reports, and what it deliberately omits. An agent has enough information to invoke it correctly and set expectations.
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 input schema has 100% coverage with a clear description of 'htmlContent' as raw HTML containing JSON-LD script blocks. The tool description mostly restates this relationship and adds context about local parsing and error reporting, but it provides little additional parameter-level meaning beyond 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 description specifies a concrete action ('Parses JSON-LD blocks in supplied HTML'), the exact scope ('locally'), and the kinds of results it reports ('empty blocks or JSON syntax errors'). It also distinguishes itself by explicitly stating what it does not do: 'does not validate vocabulary semantics.'
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 phrase 'in supplied HTML locally' gives a clear context for when to use this tool: when the input is a local HTML string rather than a URL. The explicit non-goal of not validating vocabulary semantics provides a when-not signal, though it does not name any alternative sibling tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
screenshot.captureCapture responsive screenshotsADestructiveIdempotentInspect
Renders a local HTML file or HTTP(S) URL in a sandboxed local Chromium browser and writes PNG screenshots to the requested directory. Downloads the pinned headless browser on first use if it is not already cached. Existing matching files may be replaced.
| Name | Required | Description | Default |
|---|---|---|---|
| outputDir | No | Directory where PNG screenshots will be written. | .mcp-validator/screenshots |
| viewports | No | Optional viewport definitions; defaults to desktop, tablet, and mobile sizes. | |
| targetPath | Yes | Local HTML path or HTTP(S) URL to render. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | |
| screenshots | Yes | |
| outputDirectory | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds meaningful behavioral details beyond the annotations: sandboxed Chromium, first-use browser download, and possible replacement of existing files. These details enrich the destructiveHint and openWorldHint annotations without contradicting them.
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?
Three well-ordered sentences: the core rendering/writing behavior, the runtime browser download behavior, and the destructive caveat. Every sentence earns its place with no filler or repetition.
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?
The schema and annotations cover parameter details, safety, and idempotency, while the description adds the non-obvious runtime facts: sandboxing, first-run browser download, and potential file replacement. Nothing essential for invoking the tool 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 each parameter already has a clear description. The description's reference to the 'requested directory' adds little beyond the schema, so the baseline score of 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?
The description clearly identifies the action ('writes PNG screenshots') and the resource ('local HTML file or HTTP(S) URL'), which distinguishes it from sibling tools focused on HTML, CSS, SEO metadata, and validation. However, it does not explicitly contrast itself with any sibling, so it stops just short of full differentiation.
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 description states what inputs are accepted but gives no guidance about when to use screenshot.capture versus the sibling tools. There is no mention of use cases such as visual verification, or exclusions such as 'use html.local for DOM inspection instead.'
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
seo.metadataAudit SEO metadataARead-onlyIdempotentInspect
Audits supplied HTML offline for on-page SEO metadata, headings, viewport, image alternatives, and Open Graph issues. Use for a quick on-page check; use html.local/html.url for W3C HTML validation, schema.markup for JSON-LD syntax, or report.validation for a combined local-file report.
| Name | Required | Description | Default |
|---|---|---|---|
| htmlContent | Yes | Raw HTML markup to inspect locally. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | |
| counts | Yes | |
| issues | Yes | |
| truncated | Yes | |
| totalIssues | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, and closed-world; the description's 'supplied HTML' and 'offline' wording reinforces that nothing is fetched, which is useful confirmation. It also scopes exactly which audit categories run, but says nothing about the result shape or how issues are counted/severity-ranked — acceptable given an output schema exists.
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?
Two sentences, zero filler. The capability statement is front-loaded and the disambiguation/routing clause follows, which is exactly the order an agent needs.
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 annotations covering the safety profile and an output schema covering return values, the remaining burden on the description is scope and sibling routing — both fully discharged. Nothing an agent needs in order 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?
Only one parameter and the schema already documents it at 100% coverage, so the baseline applies. The description still adds a meaningful disambiguation beyond the schema: the input is 'supplied HTML' inspected locally, making clear the parameter is raw markup rather than a URL or path.
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?
Names a specific verb (audits) and resource (supplied HTML) plus the exact check categories: SEO metadata, headings, viewport, image alternatives, Open Graph. The word 'offline' scopes it against the URL-fetching siblings, so an agent can distinguish it from html.url 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?
Explicitly states the selection rule ('use for a quick on-page check') and then routes three named alternatives to their specific conditions: html.local/html.url for W3C validation, schema.markup for JSON-LD, report.validation for a combined local-file report. Both when-to-use and when-to-look-elsewhere are covered.
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.
3 tool updates
v1.3.40- Changed
css.local1 field changed- added
Output schema / properties / warningsAdded value: +{ + "items": { + "additionalProperties": false, + "properties": { + "compatibility": { + "const": "known-validator-limitation", + "type": "string" + }, + "context": { + "type": "string" + }, + "line": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "message": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "line", + "type", + "message" + ], + "type": "object" + }, + "type": "array" +}
- Changed
html.local1 field changed- changed
Input schema / properties / filePath / descriptionPrevious value: -"Absolute or workspace-relative path to an HTML file."New value: +"Absolute or workspace-relative path to an HTML or .xhtml file."
- Changed
report.validation2 fields changed- changed
Input schema / properties / htmlFilePath / descriptionPrevious value: -"Absolute or workspace-relative HTML file path."New value: +"Absolute or workspace-relative HTML or .xhtml file path." - added
Output schema / properties / summary / properties / cssWarningsAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +}
6 tool updates
v1.3.28- Changed
css.local4 fields changed- added
Output schema / properties / errors / items / properties / compatibilityAdded value: +{ + "const": "known-validator-limitation", + "type": "string" +} - added
Output schema / properties / totalMessagesAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / truncatedAdded value: +{ + "type": "boolean" +} - changed
Output schema / requiredPrevious value: -[ - "errors" -]New value: +[ + "errors", + "totalMessages", + "truncated" +]
- Changed
html.local4 fields changed- added
Output schema / properties / errors / items / properties / subTypeAdded value: +{ + "type": "string" +} - added
Output schema / properties / totalMessagesAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / truncatedAdded value: +{ + "type": "boolean" +} - changed
Output schema / requiredPrevious value: -[ - "errors" -]New value: +[ + "errors", + "totalMessages", + "truncated" +]
- Changed
html.url4 fields changed- added
Output schema / properties / errors / items / properties / subTypeAdded value: +{ + "type": "string" +} - added
Output schema / properties / totalMessagesAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / truncatedAdded value: +{ + "type": "boolean" +} - changed
Output schema / requiredPrevious value: -[ - "errors" -]New value: +[ + "errors", + "totalMessages", + "truncated" +]
- Changed
report.validation17 fields changed- added
Output schema / properties / cssMessages / items / properties / compatibilityAdded value: +{ + "const": "known-validator-limitation", + "type": "string" +} - added
Output schema / properties / cssTotalMessagesAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / cssTruncatedAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / htmlMessages / items / properties / subTypeAdded value: +{ + "type": "string" +} - added
Output schema / properties / htmlTotalMessagesAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / htmlTruncatedAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / schemaIssues / items / properties / codeAdded value: +{ + "description": "Stable machine-readable audit rule identifier.", + "type": "string" +} - changed
Output schema / properties / schemaIssues / items / requiredPrevious value: -[ - "severity", - "category", - "message" -]New value: +[ + "code", + "severity", + "category", + "message" +] - added
Output schema / properties / schemaTotalIssuesAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / schemaTruncatedAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / seoIssues / items / properties / codeAdded value: +{ + "description": "Stable machine-readable audit rule identifier.", + "type": "string" +} - changed
Output schema / properties / seoIssues / items / requiredPrevious value: -[ - "severity", - "category", - "message" -]New value: +[ + "code", + "severity", + "category", + "message" +] - added
Output schema / properties / seoTotalIssuesAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / seoTruncatedAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / summary / properties / cssCompatibilityLimitationsAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - changed
Output schema / properties / summary / requiredPrevious value: -[ - "overallScore", - "htmlScore", - "cssScore", - "seoScore", - "linkScore", - "htmlErrors", - "htmlWarnings", - "cssErrors", - "seoErrors", - "seoWarnings", - "schemaErrors", - "linksChecked", - "brokenLinks" -]New value: +[ + "overallScore", + "htmlScore", + "cssScore", + "seoScore", + "linkScore", + "htmlErrors", + "htmlWarnings", + "cssErrors", + "cssCompatibilityLimitations", + "seoErrors", + "seoWarnings", + "schemaErrors", + "linksChecked", + "brokenLinks" +] - changed
Output schema / requiredPrevious value: -[ - "report", - "summary", - "htmlMessages", - "cssMessages", - "seoIssues", - "schemaIssues", - "links", - "failedChecks" -]New value: +[ + "report", + "summary", + "htmlMessages", + "htmlTotalMessages", + "htmlTruncated", + "cssMessages", + "cssTotalMessages", + "cssTruncated", + "seoIssues", + "seoTotalIssues", + "seoTruncated", + "schemaIssues", + "schemaTotalIssues", + "schemaTruncated", + "links", + "failedChecks" +]
- Changed
schema.markup4 fields changed- added
Output schema / properties / countsAdded value: +{ + "additionalProperties": false, + "properties": { + "error": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "info": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "warning": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "error", + "warning", + "info" + ], + "type": "object" +} - added
Output schema / properties / issues / items / properties / codeAdded value: +{ + "description": "Stable machine-readable audit rule identifier.", + "type": "string" +} - changed
Output schema / properties / issues / items / requiredPrevious value: -[ - "severity", - "category", - "message" -]New value: +[ + "code", + "severity", + "category", + "message" +] - changed
Output schema / requiredPrevious value: -[ - "issues", - "totalIssues", - "truncated" -]New value: +[ + "issues", + "totalIssues", + "truncated", + "counts" +]
- Changed
seo.metadata4 fields changed- added
Output schema / properties / countsAdded value: +{ + "additionalProperties": false, + "properties": { + "error": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "info": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "warning": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "error", + "warning", + "info" + ], + "type": "object" +} - added
Output schema / properties / issues / items / properties / codeAdded value: +{ + "description": "Stable machine-readable audit rule identifier.", + "type": "string" +} - changed
Output schema / properties / issues / items / requiredPrevious value: -[ - "severity", - "category", - "message" -]New value: +[ + "code", + "severity", + "category", + "message" +] - changed
Output schema / requiredPrevious value: -[ - "issues", - "totalIssues", - "truncated" -]New value: +[ + "issues", + "totalIssues", + "truncated", + "counts" +]
8 tool updates
v1.1.0- Added
css.local - Added
html.local - Added
html.url - Added
links.broken - Added
report.validation - Added
schema.markup - Added
screenshot.capture - Added
seo.metadata
7 tool updates
v1.0.1- Removed
audit_seo_metadata - Removed
check_broken_links - Removed
generate_validation_report - Removed
validate_local_css - Removed
validate_local_html - Removed
validate_schema_markup - Removed
validate_url
7 tool updates
v1.0.0- First observed
audit_seo_metadata - First observed
check_broken_links - First observed
generate_validation_report - First observed
validate_local_css - First observed
validate_local_html - First observed
validate_schema_markup - First observed
validate_url
TDQS
Scored across 8 tools
Each tool has a clearly distinct purpose: local CSS validation, local HTML validation, URL HTML validation, SEO metadata audit, broken-link checking, JSON-LD syntax checking, combined reporting, and screenshot capture. The aggregate report.validation tool overlaps with several others, but its description clearly distinguishes it as a combined workflow.
All eight tools use a consistent lowercase dot-separated namespace pattern (resource.action or resource.scope), such as css.local, html.url, links.broken, and report.validation. The convention is predictable throughout the set.
Eight tools is well-scoped for a web validation and audit suite. Each tool covers a meaningful validation or reporting capability without excessive fragmentation.
The surface covers the core domain well: HTML/CSS validation, SEO checks, JSON-LD syntax, broken links, screenshots, and a combined report. Minor gaps exist, such as no direct remote CSS URL validation, but most workflows can be handled or worked around.
Maintenance
Related MCP Connectors
Website health, SEO, security-header, SSL and broken-link audits for AI agents.
Run accessibility, contrast, and design token audits and file QA issues from your AI coding tool.
Scan websites and code for security, performance and SEO issues from your AI assistant.
Live web checks for AI agents: sitemaps, robots.txt, URL status, broken links, feeds, citations.
Related MCP Servers
- AlicenseAqualityAmaintenanceOAuth-protected Google Search Console MCP for analytics, URL inspection, sitemap management, indexing requests, and SEO diagnostics. Open-source Cloudflare Workers implementation with 17 tools.17387 npm7MIT
- AlicenseAqualityBmaintenanceAI visibility tracker MCP server. Track brand citations across ChatGPT, Claude, Perplexity, Gemini & Google AI Overviews. Self-host on Cloudflare Workers. GEO/AEO.12525 npm40MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to crawl live websites, audit AEO readiness, generate Schema.org @graph JSON-LD, llms.txt, ai.txt, and robots.txt, inject structured data into HTML, validate optimizations, and retrieve framework-specific code snippets.MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants and coding agents to audit, compare, and optimize websites for performance, SEO, AEO, GEO, and AI crawler accessibility directly from chat or development workflows.MIT