# geo-audit-mcp Lightweight MCP server for GEO (Generative Engine Optimization) site audits. Checks **31 signals across 6 pillars** — Technical Crawlability, Content Structure, Schema & Metadata, E-E-A-T, Citation Readiness, and Governance — and returns a score, pillar breakdowns, and an actionable fix prompt. This server provides **one tool only**: `geo_site_audit` ## Output format ```json { "score": 72, "pillars": { "technical": { "pass": 4, "fail": 1, "warn": 0, "na": 0, "total": 5, "pct": 80 }, "content": { "pass": 3, "fail": 0, "warn": 1, "na": 0, "total": 4, "pct": 88 }, "schema": { "pass": 2, "fail": 1, "warn": 1, "na": 0, "total": 4, "pct": 63 }, "eeat": { "pass": 4, "fail": 1, "warn": 2, "na": 0, "total": 7, "pct": 71 }, "citations": { "pass": 6, "fail": 1, "warn": 3, "na": 0, "total": 10, "pct": 75 }, "governance": { "pass": 1, "fail": 0, "warn": 0, "na": 0, "total": 1, "pct": 100 } }, "checks": [ { "id": "T1", "pillar": "technical", "title": "Page reachable over HTTPS", "status": "pass", "message": "Page returned HTTP 200." }, { "id": "B1", "pillar": "content", "title": "Answer-first opening mentions brand", "status": "fail", "message": "Add a 2–3 sentence opening that names your brand...", "evidence": "Welcome to our platform..." } ], "fixPrompt": "You are improving GEO readiness for MyBrand...", "summary": "- [Content] Improve heading hierarchy...", "stats": { "words": 1523, "headings": 14, "externalLinks": 8, "jsonLdBlocks": 2 }, "auditedUrl": "https://example.com/page" } ``` ### What each part means | Field | Description | |-------|-------------| | `score` | Overall GEO readiness score (0–100), weighted across 6 pillars | | `pillars` | Per-pillar pass/fail/warn counts and percentage | | `checks` | All 31 individual check results with status, message, and evidence | | `fixPrompt` | Actionable fix prompt — paste into Claude, Cursor, or your site editor | | `summary` | Human-readable summary (LLM-generated if `OPENAI_API_KEY` is set, else auto-generated) | | `stats` | Page-level statistics: word count, headings, external links, JSON-LD blocks | | `auditedUrl` | The normalized URL that was audited | ## BYOK This server uses **your own API keys**. Usage and billing are tied to your provider accounts. No API key is strictly required — the audit runs fully offline using static HTML analysis. Optionally set `OPENAI_API_KEY` for LLM-powered summary. ## Required environment variables | Variable | Required | Description | |----------|----------|-------------| | `OPENAI_API_KEY` | Optional | OpenAI API key for LLM-generated audit summary. Without it, the summary is auto-generated from check results. | | `OPENAI_BASE_URL` | Optional | Custom OpenAI-compatible endpoint (default: `https://api.openai.com/v1`). | | `OPENAI_HTTPS_PROXY` | Optional | HTTPS proxy URL for OpenAI API calls (e.g. `http://127.0.0.1:7890`). | | `WEBSITE_HTTPS_PROXY` | Optional | HTTPS proxy URL for fetching the target website. | ## Quick Start ```bash npm install npm run build ``` ## MCP Config Example ### Claude Desktop (`claude_desktop_config.json`) ```json { "mcpServers": { "geo-audit-mcp": { "command": "node", "args": ["/geo-audit-mcp/dist/index.js"], "env": { "OPENAI_API_KEY": "" } } } } ``` ### Cursor / Windsurf / Other MCP clients ```json { "mcpServers": { "geo-audit-mcp": { "command": "node", "args": ["/geo-audit-mcp/dist/index.js"], "env": { "OPENAI_API_KEY": "", "OPENAI_HTTPS_PROXY": "http://127.0.0.1:7890" } } } } ``` ## Tool Input ```json { "url": "https://example.com/pricing", "brand_name": "Example", "page_type": "product" } ``` | Parameter | Required | Description | |-----------|----------|-------------| | `url` | Yes | Full URL to audit. Must start with `https://` or `http://`. | | `brand_name` | No | Brand name — improves the accuracy of the opening-content check (B1). | | `page_type` | No | Hint: `homepage`, `product`, or `article`. Auto-detected from URL path if omitted. | ## What gets checked (31 signals, 6 pillars) ### Technical Crawlability (5 checks) T1–T5: HTTPS reachability, AI crawler robots.txt rules, llms.txt presence, readable text without JavaScript, canonical URL. ### Content Structure (4 checks) B1–B4: Answer-first brand mention, heading hierarchy, paragraph chunking, quotable blocks (lists/FAQ). ### Schema & Metadata (4 checks) C1–C4: Title + meta description, Organization/WebSite JSON-LD, page-type structured data, FAQPage schema. ### E-E-A-T (7 checks) E1–E7: Author/entity signals, visible byline, About/Contact links, Organization JSON-LD with sameAs, Privacy/Terms links, authority review links, publication date. ### Citation Readiness (10 checks) R1–R10: External reference links, authoritative review domains, link diversity, in-content links, citable blocks, quotable facts, source attribution, entity sameAs, page citability score, citation-ready passage ratio. ### Governance (1 check) G1: Sitemap reachability. ## Notes - The audit fetches the target page via direct HTTP request (with browser-like User-Agent). Some sites with aggressive bot protection may block the request. - The audit is **stateless** — no data is stored or logged. - SSRF protection is built in: internal IPs, localhost, and cloud metadata endpoints are blocked. - If `OPENAI_API_KEY` is set, the summary uses GPT-4.1-mini by default. Set `OPENAI_MODEL` to override. - Fix prompts are designed to be pasted directly into Claude, Cursor, or your site editor — they target HTML, meta tags, and JSON-LD only. - **Never commit real credentials into git. Use env vars only.** Built by [gptmelo.com](https://gptmelo.com) — the GEO brand monitor for ChatGPT.