Web Validator by DigestSEO
Web Validator by DigestSEO is an MCP server for validating HTML/CSS, auditing SEO and accessibility signals, checking JSON-LD syntax, finding broken links, generating validation reports, and capturing responsive screenshots.
Validate local or public HTML/XHTML files with the W3C Nu HTML Checker (including .xhtml parsing semantics).
Validate local CSS files with the W3C Jigsaw CSS Validator.
Audit on-page SEO metadata: titles, descriptions, canonicals, robots/noindex, headings, viewport, image alt text, and Open Graph tags.
Check JSON-LD script blocks in HTML for JSON syntax errors and empty blocks.
Check up to 25 public HTTP(S) links extracted from supplied HTML, reporting redirects without following them.
Generate combined Markdown and structured validation reports with scores for HTML, CSS, SEO, schema, and link checks.
Capture responsive screenshots (desktop, tablet, mobile, or custom viewports) of local HTML files or public URLs using a sandboxed Chromium browser.
Hosted tools also support auditing an authorized public webpage or a bounded sitemap-based site audit, plus validating raw markup supplied in conversation.
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: aria51 MCP Server
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. |
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.
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.
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 metadataBRead-onlyIdempotentInspect
Analyzes supplied HTML locally for metadata, heading structure, viewport configuration, image alternatives, and Open Graph fields.
| 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 readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds the behavioral detail that analysis is performed 'locally' (no network calls), which is beyond annotations. However, it does not mention what happens with invalid HTML, output structure, or any edge cases. Given the annotation coverage, a 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence that front-loads the action ('Analyzes supplied HTML locally') and then lists the specific areas checked. There is no redundant phrasing, and every word contributes to the core purpose. It is exemplary in conciseness.
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 (one parameter) and an output schema exists, so the description need not explain return values. The description covers the key scope of analysis and the local execution context. It does not mention size limits (covered by schema maxLength) or potential limitations, but given the output schema and simple input, it is sufficiently complete for an agent to invoke 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 provides a full description of the single parameter (htmlContent: 'Raw HTML markup to inspect locally'), so schema coverage is 100%. The tool description adds no additional meaning to the parameter beyond what the schema already states, meeting the baseline for high coverage. It does not elaborate on format constraints or examples.
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 (Analyzes) and resource (supplied HTML) and enumerates the exact aspects examined (metadata, heading structure, viewport configuration, image alternatives, Open Graph fields). This is clear and specific, but it does not explicitly differentiate itself from siblings like html.local or schema.markup, so it earns a 4 rather than a 5.
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 provides no guidance on when to use this tool versus its alternatives. It does not mention conditions, prerequisites, or exclusions, and it fails to reference any sibling tool. An agent must infer from the title and parameter that this is for SEO auditing, but no explicit routing advice is given.
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 targets a distinct validation concern (HTML, CSS, links, schema, SEO, screenshots), and the two HTML validators are clearly separated by local vs. URL source. Minor overlap exists between report.validation and the individual tools it aggregates, but the descriptions make the difference explicit (combined report vs. single-purpose check).
All tool names follow a consistent dot-separated pattern where the first segment identifies the resource (html, css, links, schema, seo, report) and the second segment specifies the action or variant (local, url, broken, markup, metadata, validation). This is highly predictable and readable.
Eight tools is well-scoped for a web validation server. Each tool addresses a meaningful aspect of validation or analysis, and none feel redundant or superfluous. The count supports a coherent workflow without overwhelming the agent.
The tool surface covers HTML validation from file and URL, CSS file validation, broken link checking, JSON-LD syntax, SEO metadata analysis, screenshots, and an aggregate report. A minor gap is the lack of a CSS URL validation tool, but the core validation workflows are well covered for the apparent domain.
Maintenance
Related MCP Connectors
Live web checks for AI agents: sitemaps, robots.txt, URL status, broken links, feeds, citations.
Web tools for AI agents: scrape pages to Markdown, audit SEO, detect tech stacks, check sitemaps
Run SEO + AI-visibility (GEO) audits from Claude, Cursor & other AI clients.
Real SEO data for AI assistants: page audits, Keyword Planner volumes, Search Console history.
Related MCP Servers
- AlicenseAqualityBmaintenanceIntegrates SEO analysis and Google Search Console data directly into Claude Code and Cursor. Performs real-time site audits, detects technical SEO issues, validates meta tags, generates structured data, and provides AI-powered recommendations for both production sites and local development servers.19135 npm3MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI coding assistants to test web accessibility by scanning URLs, detecting violations, and running focused audits on keyboard navigation, screen reader compatibility, and WCAG criteria — all within the assistant's loop.MIT
- AlicenseAqualityBmaintenanceOAuth-protected Google Search Console MCP for analytics, URL inspection, sitemap management, indexing requests, and SEO diagnostics. Open-source Cloudflare Workers implementation with 17 tools.171,772 npm5MIT
- AlicenseAqualityAmaintenanceAI visibility tracker MCP server. Track brand citations across ChatGPT, Claude, Perplexity, Gemini & Google AI Overviews. Self-host on Cloudflare Workers. GEO/AEO.2122,344 npm46MIT