webaudit-mcp
Click on "Install 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., "@webaudit-mcpAudit https://web.dev for tracking tags and performance"
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.
webaudit-mcp
MCP server that audits any public web page for tracking tags, duplicate pixels, page weight, header hygiene, and lab performance, from inside Claude Code or Claude Desktop.
![]()
Screenshot | What it shows |
Real | |
The same smoke script pointed at |
Both screenshots are captured from real sessions on 2026-07-19 against the current build. The second one is a selling point, not an error state: point any tool at a private, broken, or non-HTML URL and you get a structured, actionable error, never a crash or a hang.
Error: Refusing to fetch "localhost": local targets are blocked (SSRF protection).Quickstart
Requires Node 20 or newer. From a clean clone:
git clone https://github.com/lpecom/webaudit-mcp.git webaudit-mcp
cd webaudit-mcp
npm install
npm run build # compiles TypeScript into dist/
npm test # 60 tests across 6 files, all offline, ~300 msStarting the server directly prints one line to stderr and then waits for an MCP client on stdio (stop it with Ctrl+C):
node dist/index.js
# webaudit-mcp running on stdio (7 tools registered)Claude Code:
claude mcp add webaudit -- node /absolute/path/to/webaudit-mcp/dist/index.jsClaude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"webaudit": {
"command": "node",
"args": ["/absolute/path/to/webaudit-mcp/dist/index.js"]
}
}
}Then ask: "Audit https://example.com" or "What tracking is installed on web.dev?"
Optional, only needed for measure_performance (lab Core Web Vitals):
npx playwright install chromiumTo see every tool fire against a live site without any MCP client:
npm run smoke -- https://web.devNo API keys, no environment variables, no configuration files.
Related MCP server: mcp-uimax
Why I built this
I have spent years on both sides of this problem: running Google Ads, Meta, and Taboola campaigns, and building the tracking under them myself (GA4, GTM, server-side events). Broken tracking silently burns ad budgets: a duplicate GA4 config doubles every metric, a leftover GTM container re-fires conversions, and nobody notices until the numbers stop making sense. The tools to check for it are scattered across browser extensions, PageSpeed, and manual view-source archaeology.
This server puts the whole check behind one conversational interface, built the way I think an MCP server should be: strict input validation, SSRF-guarded fetching, structured errors instead of crashes, and honest labels on every number (lab vs field, measured vs estimated). The report is written for a developer and a media buyer: which analytics and pixel IDs are installed and where, whether anything double-fires, what the page weighs, and how the response headers look.
Tool reference
All 7 tools take a single url argument (absolute http/https URL) and return Markdown.
Tool | What it does |
| One-shot report: tracking tags, duplicate risks, header hygiene, resource counts. Fast, no browser. |
| Static HTML scan for GA4, GTM, legacy UA, Google Ads, Meta Pixel, TikTok, LinkedIn Insight, Hotjar, Microsoft Clarity, server-side tagging, and consent platforms. Reports IDs and where each was found. |
| Flags double-initialized IDs, multiple GTM containers, GTM plus hardcoded GA4 double-fire patterns, duplicate pixel IDs, dead UA tags. |
| Headless-Chromium lab metrics: TTFB, FCP, LCP, CLS, load times, request count, transfer sizes. Clearly labeled lab data. |
| Counts and byte sizes of scripts, styles, images, fonts, and iframes referenced in the HTML; largest third-party scripts. |
| Caching, compression, HSTS, CSP, clickjacking, referrer policy. Informational grades with explanations, no synthetic scores. |
| Plain-language briefing on the tracking setup, written for a media buyer: what is installed, what it means for campaigns, consent posture, issues to raise. |
All example outputs below are real, captured 2026-07-19 against https://web.dev and trimmed for length.
audit_page
The one call to start with: combines the tracking scan, duplicate check, and header check in a single report.
# Audit of https://web.dev/
- HTTP status: 200
- HTML size: 130.7 KB
- Resources referenced in HTML: 14 (0 scripts, 4 stylesheets, 9 images, 0 fonts, 1 iframes; 5 third-party)
[tracking, duplicate, and header sections follow, same content as the
individual tools below, then pointers to the byte-level and lab tools]detect_tracking_tags
Static scan with evidence: every finding names the vendor, the extracted ID, and the exact place in the HTML that triggered it.
# Tracking tags on https://web.dev/
| Vendor | ID | Found in | Evidence |
|---|---|---|---|
| Google Tag Manager | GTM-MZWCJPP | inline script | `[], "gtm": [{"id": "GTM-MZWCJPP", "purpose": 0}], ...` |
## Distinct IDs
- Google Tag Manager: GTM-MZWCJPP
## Consent signals
- None detected. If this site serves EU users with these tags firing pre-consent,
that is a GDPR/ePrivacy problem.
_Static scan: 6 inline scripts and 0 external script tags inspected. Tags added
at runtime by GTM or a CMP are not visible to this scan._find_duplicate_tags
Checks for the patterns that double-count: the same GA4 ID initialized twice, multiple GTM containers, a hardcoded GA4 tag next to a GTM container, multiple Meta pixel IDs, the gtag.js loader included more than once, and leftover Universal Analytics tags. web.dev is clean:
# Duplicate-tag check for https://web.dev/
No duplicate IDs or double-fire patterns found across 3 detected tag reference(s).When something is found, each issue comes with a severity: HIGH (double-counting almost certain), MEDIUM (likely misconfiguration), INFO (verify manually).
measure_performance
Loads the page once in headless Chromium and reports what that load observed. Numbers vary run to run; the report says so.
# Lab performance metrics for https://web.dev/
**LAB DATA**: one headless-Chromium load from this machine. Not field data (no CrUX/RUM), no INP.
| Metric | Value |
|---|---|
| TTFB (time to first byte) | 495 ms |
| FCP (first contentful paint) | 764 ms |
| LCP (largest contentful paint) | 1.02 s |
| CLS (cumulative layout shift) | 0.088 |
| Load event | 2.34 s |
| Requests | 60 |
| Transferred (compressed) | 152.9 KB |
[transfer-by-initiator table and reference thresholds follow]analyze_page_weight
Static resource inventory with real byte measurements (capped, guarded requests; up to 30 resources, HEAD first, GET fallback):
# Page weight for https://web.dev/
- HTML document: 130.7 KB
- Resources referenced: 14 (0 scripts, 4 stylesheets, 9 images, 0 fonts, 1 iframes)
- Measured 14 of 14 resources: 1.42 MB totalNote the honest gap between this and measure_performance above: the static scan sees 14 referenced resources, the browser load makes 60 requests. JavaScript loads the rest, and each report tells you which view you are looking at.
check_headers
# Header check for https://web.dev/ (HTTP 200)
| Check | Grade | Value | Note |
|---|---|---|---|
| Cache-Control | [OK] | `no-cache, must-revalidate` | Caching policy declared. |
| Compression (Content-Encoding) | [OK] | `gzip` | Response compressed with gzip. |
| HSTS (Strict-Transport-Security) | [OK] | `max-age=63072000; includeSubdomains; preload` | HSTS present with a solid max-age. |
| Referrer-Policy | [MISSING] | n/a | Default referrer behavior leaks full URLs to third parties on some browsers. |
_Grades are informational statements about header presence, not a security score._tracking_summary
The same detection engine, rendered as a briefing for a non-developer. See the hero screenshot above for the full real output; the sections are: What is installed, What this means for media buying, Consent, Issues to raise.
How it works
src/
index.ts entry point: McpServer + stdio transport, registers the tools
tools.ts tool registration, zod input schemas, Markdown renderers,
error mapping (every failure becomes an isError result)
lib/
url-guard.ts SSRF checks: scheme, hostname denylist, private IP ranges, DNS
safe-fetch.ts hardened fetch: timeout, byte cap, manual redirects, content type
tracking.ts static tag detection (regex + node-html-parser) and duplicate analysis
page-weight.ts resource extraction and capped byte measurement
headers.ts response-header checks
performance.ts Playwright Chromium lab metrics
format.ts byte/ms formatting and grade markersSSRF protection is layered. url-guard runs two checks: a synchronous one (http/https only; localhost, .local, .internal, .home.arpa and similar hostnames refused; private, loopback, link-local, and CGNAT IP literals refused, for v4 and v6 including IPv4-mapped forms) and an asynchronous one that resolves the hostname with DNS and refuses if any returned address is private, so a public-looking hostname pointing at 192.168.x.x is also blocked. safe-fetch then follows redirects manually (max 5) and re-runs both checks on every hop, enforces a 15 s wall-clock timeout and a 5 MiB body cap, and rejects non-HTML content types for the HTML tools. Every outbound request in the codebase, including page-weight resource measurements, goes through this one client.
Static analysis vs browser analysis. Six of the seven tools parse the served HTML only: fast, no browser dependency, and honest about the boundary (every report footnotes that runtime-injected tags and JS-loaded resources are invisible to it). measure_performance is the one browser tool: it launches headless Chromium via Playwright, registers buffered PerformanceObservers before navigation, loads the page once, waits 3 s for LCP/CLS to settle, and reads the metrics out.
Graceful degradation without Chromium. Playwright is a devDependency and is imported dynamically only inside measure_performance. If the package or the browser binary is missing, the tool returns a structured error containing the exact fix (npx playwright install chromium) instead of crashing, and the other six tools are unaffected.
Tests
npm test runs 60 vitest tests in 6 files, entirely offline (network and DNS are mocked; nothing leaves the process):
url-guard.test.ts: scheme rejection, hostname denylist, private v4/v6 ranges including IPv4-mapped and CGNATsafe-fetch.test.ts: timeouts, byte-cap truncation, manual redirect following and re-validationtracking.test.ts: tag and consent detection plus duplicate analysis against synthetic fixtures (clean.html,duplicates.html,full-stack.html)page-weight.test.ts: resource extraction, third-party heuristic (includingco.uk-style domains), HEAD/GET measurement fallbackheaders.test.ts: grades for present, missing, and weak headerstools.test.ts: a real MCP client calling the real server over the SDK's in-memory transport, covering both success and error paths
npm run smoke -- <url> is the live counterpart: it drives the built stdio server with a real MCP client against a real site, on purpose.
Design decisions
Never throw from a handler. Every tool wraps its body in try/catch and converts
UrlGuardError,FetchError, andPerformanceUnavailableErrorinto MCPisErrorresults whose message says what to do next.Reports are Markdown a model can relay verbatim. The renderers produce tables and sections a client model can paste into an answer without rework, and each report ends with an honest footnote about what the scan could not see.
Bounded everything. 15 s request timeout, 5 MiB response cap, max 5 redirects, 30-resource measurement cap with concurrency 6, 10 s per-resource timeout, content-type enforcement for HTML tools. The numbers live as constants in
safe-fetch.tsandpage-weight.ts.Honest labels on every number. Lab data is stamped LAB DATA, static scans say they are static, the third-party classifier is documented as a heuristic in the report itself.
Playwright stays a devDependency so the core install is three runtime dependencies (
@modelcontextprotocol/sdk,node-html-parser,zod) and the browser tool degrades gracefully.
Built with the MCP TypeScript SDK (McpServer + registerTool, zod input schemas, stdio transport). Developed with Claude Code.
Limitations
Static scan.
detect_tracking_tags,find_duplicate_tags, andtracking_summaryread the served HTML only. Tags injected at runtime by GTM, a CMP after consent, or client-side routing are invisible to them. The reports say so explicitly.Lab data, not field data.
measure_performanceis one headless load from your machine: no INP (needs real interaction), no CrUX percentiles, and numbers vary run to run. Treat it as a smoke check, not a Core Web Vitals verdict.Single page scope. Every tool audits exactly the URL you give it. No crawling.
Third-party classification is a heuristic. Registrable-domain comparison without a full Public Suffix List;
foo.co.ukstyle domains are handled, exotic suffixes may misclassify.Transfer sizes can read 0 B. Cross-origin resources without
Timing-Allow-Originhide their size from the browser; page-weight measurements reflect what this client was served, which may differ from what your browser gets.Bot protection. Sites behind aggressive bot walls (Cloudflare challenges and similar) may serve this tool different HTML than they serve a real browser.
License
MIT license, see LICENSE.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityDmaintenanceCore Web Vitals analysis powered by Lighthouse. Four tools: analyze a URL, compare two URLs, check against thresholds, or crawl an entire site. Works with Claude Code, Cursor, Windsurf, and any MCP-compatible AI tool.411MIT
- AlicenseBqualityCmaintenanceFrontend expert for Claude Code. Captures screenshots, runs Lighthouse + axe-core accessibility audits + code analysis, generates an expert review, and auto-fixes everything — 12 tools, completely free for Pro plan users.37559MIT
- FlicenseAqualityDmaintenanceEnables Claude Code to capture and analyze web page screenshots, responsive layouts, and page metadata using Puppeteer. It allows developers to perform visual UI inspections and compare designs across various viewports directly within the terminal.3
- AlicenseAqualityAmaintenanceEnables auditing web pages for WCAG violations, applying deterministic fixes and PRs, all through MCP clients like Claude Desktop.7MIT
Related MCP Connectors
Live SEO workflow tools for Claude Code, Codex, and AI agents.
Website QA for your coding agent: audit SEO, performance, security, accessibility over MCP.
Live tech-stack scan of any public site — vendors, account IDs, scripts, JSON-LD. 2 tools.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/lpecom/webaudit-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server