web-presence-audit
by AxRS37
README.md
# web-presence-audit — lead-leak audit tools for AI agents
An [MCP](https://modelcontextprotocol.io) server that turns a proven, **£0 lead-leak audit methodology** for UK local service businesses into six tools your AI agent can call. No API keys, no accounts, no paid services — every data source is free to read.
This is the audit methodology behind real paid audits (built for B2B prospect research): it finds the fixable issues that measurably cost local businesses leads — untappable phone numbers, un-findable websites, mismatched phone numbers across directories, and forms on platforms where automated outreach simply cannot work.
- **Audience:** agencies and web-audit sellers, local-SEO freelancers, lead-gen sellers, any agent doing prospect or client website research.
- **Cost: £0.** Bing's public RSS search output + free UK directories (thomsonlocal, TrustATrader, 3BestRated) + the target site itself. No API keys, no signups, no cards.
- **Config-free:** no environment variables, no accounts. Install and add to your MCP client — done.
## What it does — the six tools
| Tool | What it answers |
|---|---|
| `check_form_platform(url)` | Which platform a site's forms run on (WPForms, Contact Form 7, Wix, Squarespace, Jotform, Gravity Forms, HubSpot, Typeform, Drupal, or `unknown`) — **and what that predicts for outreach**: Wix forms fire no network traffic on automated submits (verified in live campaigns), so that prospect needs email or social instead. Also counts *visible* form fields (hidden honeypots excluded). |
| `check_tap_to_call(url)` | Is the phone number a clickable `tel:` link? Plain-text numbers lose mobile callers. Returns every `tel:` link, plain-text numbers found, and a verdict (`ok` / `leak` / `no_phone_found`). |
| `check_nap_consistency(business, city, trade?, website_url?)` | Is the phone number identical on the business's own site and the free directories (thomsonlocal, TrustATrader)? Mismatched numbers confuse Google and customers. Verdict: `consistent` / `inconsistent` / `insufficient data`. |
| `audit_website(url)` | Quick hygiene checks: reachable?, HTTPS?, mobile viewport tag?, page weight, load time, title + meta description. |
| `find_website(business, city)` | Find a business's own website via Bing's public RSS search — only a result with a *distinguishing* word counts (trade words like "plumbing" prove nothing). |
| `run_full_audit(business, city, trade?, website_url?)` | Everything at once: search presence, website hygiene, form platform, tap-to-call, NAP, plus the 3BestRated top-3 competitors. Returns a prioritized leak list. |
Matching honesty (kept from the live-proven methodology): a directory listing or search result only counts as the business when it contains a **distinguishing word** (e.g. "driver" in "Driver Plumbing") plus 2+ name words — trade words and city names alone never count. Masked directory numbers (`+447****5682`) are excluded from NAP comparison.
## 5-minute setup
Requirements: Python 3.10+ and either [`uv`](https://docs.astral.sh/uv/) or `pip`. Nothing else — no Node, no database, no API keys.
**1. Install.**
```bash
# with uv (fastest):
uv venv && uv pip install -e .
# or with plain pip:
python3 -m venv .venv && .venv/bin/pip install -e .
```
**2. Test the install (30 seconds).**
```bash
.venv/bin/python -m pytest tests/ -q
```
You'll see `63 passed` — all tests are fully offline (canned pages + a localhost site; no live internet needed).
**3. Wire it into your MCP client.**
Example for Claude Desktop / Cursor / any MCP client with JSON config:
```json
{
"mcpServers": {
"web-presence-audit": {
"command": "/ABSOLUTE/PATH/TO/web-presence-audit/.venv/bin/python",
"args": ["-m", "web_presence_audit"]
}
}
}
```
No `env` block needed — the server requires nothing but a working network at call time.
**4. Try it.** Ask your agent:
> What form platform does example.co.uk run, and can I tap its phone number to call?
or
> Run a full presence audit on "Driver Plumbing & Heating" in Leicester.
## Example tool calls and responses
These are real outputs from this server's test suite (canned fixture pages; see `tests/fake_pages.py` — the shapes are exactly what the live tools return against real sites).
`check_form_platform("https://example.co.uk")` →
```json
{
"url": "https://example.co.uk",
"platform": "wpforms",
"outreach_note": "WordPress site with the WPForms plugin. Contact forms accept standard fill-and-submit automation cleanly; leave the honeypot field empty.",
"evidence": "wpforms-container",
"visible_form_fields": 3,
"http_status": 200
}
```
`check_tap_to_call("https://example.co.uk")` → (a plain-text number)
```json
{
"verdict": "leak",
"tel_links": [],
"plain_phones": ["0116 264 5115"],
"note": "LEAK — phone number 0116 264 5115 appears as plain text with no tel: link. Mobile visitors cannot tap to call; most will not retype it.",
"url": "https://example.co.uk"
}
```
`check_nap_consistency("Driver Plumbing & Heating", "Leicester")` → (site and directory agree)
```json
{
"business": "Driver Plumbing & Heating",
"city": "Leicester",
"trade": "plumber",
"website": "https://www.driverplumbing.co.uk/",
"website_phone": "0116 264 5115",
"directory_phones": [
{ "source": "thomsonlocal", "phone": "0116 264 5115" }
],
"verdict": "consistent",
"note": "Phone number identical across all sources found."
}
```
`run_full_audit(...)` returns all of the above plus `search_presence`, `website` hygiene, `top3_competitors`, a `leaks` list, and a `score_note` summarizing what to fix first.
## How it's tested (and why you can trust the README)
63 tests in three layers — **all offline** (no live internet required to pass):
1. **Engine tests** (`tests/test_audit.py`) — platform detection per signature, honeypot exclusion from field counts, tap-to-call verdicts, phone normalisation (+44 → 0), the matching-honesty rules, Bing RSS parsing, NAP consistency logic, hygiene checks, and the full pipeline end-to-end against canned pages.
2. **Tool layer tests** (`tests/test_server_tools.py`) — each tool's output shape, URL scheme upgrading, error results (never crashes), all six tools registered with docstrings.
3. **Protocol tests** (`tests/test_protocol.py`) — launch the real server as a subprocess, speak MCP JSON-RPC over stdio (initialize → tools/list → tools/call), and verify responses against a localhost fake site. The production fetch path runs for real; only the target is pretend.
Run them yourself:
```bash
.venv/bin/python -m pytest tests/ -v
```
A note on live sources: Bing RSS, thomsonlocal, TrustATrader and 3BestRated were all reachable and parseable from our build environment. **Checkatrade is deliberately not queried** — it returns HTTP 403 to datacenter IPs, so the methodology reports honestly rather than scraping it. (Checkatrade support confirmed no public API for non-customers.) Live directory pages can change markup; the parser tests protect the logic, and any site that blocks or changes is reported as an honest error, never fabricated data.
## Works with both MCP SDK generations
The official Python SDK renamed its main class between versions: 1.x exposes `mcp.server.fastmcp.FastMCP`, 2.x renamed it to `mcp.server.mcpserver.MCPServer`. This server imports whichever is installed, so `pip install mcp` gives you either and it still runs. (Protocol-tested against 1.14.0 and 2.2.0.)
## Who it's for
- **Agencies and web-audit sellers** — run structured findings-first audits on any UK local business in minutes, with zero tooling cost.
- **Local-SEO freelancers** — NAP consistency and presence checks without paid tools.
- **Lead-gen sellers** — the form-platform check tells you which outreach channel can even work before you spend time on a prospect.
- **Any MCP client user** doing UK B2B prospect research (pairs with our [uk-company-check](../uk-company-check/) server for registry facts).
## Licence
MIT (see `LICENSE`).This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues