SEO Reference Map Main Handoff Work Report Audit Install API Keys Fable AI Research Brain
← SEO Tools Inventory mcp-health.json status.json Command Hub

seo-repos — Verification Audit & Repair Pass

Target: http://192.227.221.215:8613/seo-repos/

Date: 2026-07-30, 15:30–16:10 UTC

Host: ns3.wirenets.ca (192.227.221.215), page served from the media-mdla LXD container

Follow-up to SEO-REPOS-AUTONOMOUS-REPORT.md (2026-07-25), which hardened the page's

plumbing. This pass audited the page's claims — and most of the interesting findings are that the dashboard was reporting things that were not true, in both directions.


Headline

MetricBeforeAfter
MCP servers configured2825 (4 dead removed, lightpanda added)
MCP servers verified working (real handshake)1521
MCP tools actually exposed to the agentunmeasured350
SEO skills usable by the seo-orchestrator agent0105
Skills discovered / eligible34 / 20197 / 165
MCPs reported as "configured" on the page0 (bug)28
Repos shown as installed5363
Rows in "Needs Action"4322
Repo rows with a wrong status badge≥300 known

Five rounds, and it's worth separating them because they mean different things.

Round 1 (verification) deliberately did not move the installed count. Six repos showing a green checkmark didn't deserve one, and six greyed-out ones did. Net zero, composition corrected. Inflating the number was the easy option and would have made the page less true, which is the one thing this dashboard cannot afford.

Rounds 2–5 (install and repair) moved it honestly, 53 → 63: real installs, one badge that was simply wrong about software already running, five skill packs unlocked, tools verified by actually running them, and four MCP servers repaired by finding the real package instead of patching a broken one. Separately, 11 rows that could never be installed on a headless server stopped counting as pending work, and 4 dead MCP registrations were removed outright.


Method

Nothing here is taken from the config file's word. Every MCP server was probed with a real JSON-RPC initialize handshake over stdio (or a POSTed initialize for HTTP servers), and only counted healthy if it answered. Skills were checked with openclaw skills check per agent. Filesystem claims were confirmed with a direct stat on the box.

This matters because "listed in openclaw.json" and "works" turned out to be very different populations — nearly half the configured servers could not start at all.

One correction to my own measurement: my first probe reported 14/28 and flagged specification.website as failing with HTTP 403. That was my probe's fault, not the server's — the endpoint rejects Python-urllib's default User-Agent but answers a normal one. The true baseline was 15, and the probe now sends a proper UA. I mention it because the same mistake is what produces most of the bad badges on this page in the first place.


What I fixed

1. playwright-mcp — was never reachable as an MCP server

Configured as playwright-mcp --headless --port 8931. The --port flag puts Playwright MCP into HTTP server mode, so it never spoke stdio JSON-RPC — the transport OpenClaw actually uses. It printed a config banner and waited for HTTP connections that never came.

Fix: dropped --port 8931. Verified: handshake OK, 24 tools.

2. github-mcp-server — pointed at the CLI, not the MCP server

/usr/bin/github-mcp-server is the package's git CLI wrapper (mcp-cli.js). It printed a help banner to stdout — which also corrupts the JSON-RPC stream — and exited. The package's actual MCP server is a different bin: github-mcp-server-mcp → dist/index.js.

Fix: command now node /usr/lib/node_modules/github-mcp-server/dist/index.js.

Verified: handshake OK, 30 tools.

3. The seo-orchestrator agent could not see a single SEO skill

The biggest finding. Two independent throttles, both silent:

Fix: raised the cap to 64 and rewrote the allowlist against real skill names.

Verified: seo-orchestrator went from 3 visible skills (0 SEO) → 38 visible, 36 callable, including the master seo orchestrator (24 sub-skills) and 34 others. Discovery went 34 → 117, eligible 20 → 85.

4. The page's "0 configured in OpenClaw" was a jq path bug

seo-status-check.sh read jq '[.mcpServers | keys[]]', but the config stores servers at

.mcp.servers. .mcpServers has never existed, so jq errored, the fallback wrote [], and the page confidently displayed "MCP Python servers found on disk. 0 configured in OpenClaw." — while all 10 were configured and 8 of them working.

Fix: corrected the jq path. Verified: status.json now reports 28 configured.

A second, related bug: the page's file-to-config matcher compared agent_search_server.py against the key agent-search with .includes(), which can never match across the underscore/hyphen boundary. Only 2 of 10 files showed as configured. Now normalised — 10/10.

5. New: verified MCP health monitoring

Added /root/scripts/mcp-health-check.py + mcp-health.service/.timer (daily, 04:30, Nice=10, sequential — the host is memory-tight). It handshakes every configured server and writes mcp-health.json into the container.

The page now has a "MCP Server Health — verified" panel that distinguishes why something is down. "Needs an API key" and "config points at an npm package that doesn't exist" are very different problems, and the old page showed neither.


What the page was claiming that wasn't true

30 rows corrected. The pattern worth noting: the errors ran in both directions, so the totals looked plausible and nothing drew attention to itself.

Falsely green — configured but cannot start:

RepoReality
adityaarsharma/librecrawl-mcpConfig points at npm @adityaarsharma/librecrawl → 404, does not exist. Page claimed "cloned /opt/librecrawl"; that path does not exist either.
nayakprashant/selenium-mcp-servernpm package 404s, and the claimed clone path does not exist. Pure phantom.
jina-ai/readerMCP entry points at npm @jina/reader-mcp → 404. (Source is at /opt/jina-reader.)
serpapi/serpapi-mcpAn HTTP/uvicorn server registered as a stdio command. Also defaults to port 8000, which collides with Skyvern.
spronta/crawlieCLI works, but installed v0.5.3 has no --mcp mode. The MCP entry cannot start.
browser-use/browser-harnessA CLI/REPL harness, not an MCP server. Mis-registered.
tinyfish-io/agentql-mcp, acamolese/gsc-mcp, brightdata/brightdata-mcpInstalled, but refuse to start without credentials (below).
browser-use/browser-usepip package fine (v0.11.13); the local MCP wrapper still imports browser_use.browser.browser, removed in v0.11.
mdla-research-bridgeAn HTTP bridge on 172.17.0.1:9102, not a stdio MCP server.

Falsely grey — working but shown as unconfigured:

scrapling_server.py (3 tools), wet_server.py (4), teachable_scraper.py (1), janspoerer/mcp_browser_use (23) — all configured and passing. Plus norahe0304-art/30x-seo and mshahiddigital/agentic-local-seo-audit, which are now genuinely live (25 and 10 skills).

Also stale: the page still listed gsc-mcp as "binary missing". The binary is present at /usr/bin/gsc-mcp — it fails for a completely different reason (no Google credentials).


Needs your input

These are decisions or secrets I can't supply. Nothing here is broken by my changes.

1. Three servers are blocked purely on credentials

Ready to run the moment a key is added — they are installed and otherwise fine:

ServerMissingValue
brightdata-mcpAPI_TOKENSERP + scrape + crawl + brand visibility across LLMs (5k free credits/mo)
gsc-mcpGOOGLE_APPLICATION_CREDENTIALSSearch Console data (service-account JSON)
agentql-mcpAGENTQL_API_KEYNatural-language extraction with self-healing selectors

Per the hard-won lesson on this box: keys must go in the systemd drop-in env, not just the JSON — the gateway resolves provider keys from env vars, and a key in the wrong place passes a curl test while every runtime call 401s.

2. Three phantom MCP entries should be deleted

librecrawl, selenium-mcp, jina-reader reference npm packages that do not exist. Every gateway start spawns npx for each, hits the network, and 404s. I left them in place rather than editing your gateway config beyond the verified fixes — say the word and I'll remove them.

3. librecrawl is real and works — under a different name

It is on disk at /root/.openclaw/mcp/librecrawl-technical-seo-audit-mcp, it's a

Python MCP server (not npm), and I confirmed it starts and handshakes (v1.28.1, 37 tools advertised, HTTP on :5081).

I did not wire it up, because it wraps a LibreCrawl REST backend on :5080 that isn't installed — so it would handshake green while every crawl failed. That's precisely the kind of lying badge this pass exists to remove. Worth doing properly if you want it; it needs the backend plus a systemd unit and a url-type MCP entry.

4. Five skill repos are shadowed by a name collision

claude-ultimate-seo, codex-seo, claude-seo-skills, Agentic-SEO-Skill and gemini-seo each define a top-level skill named seo. Only one can win, and 30x-seo wins. So those five are on disk, cloned, and contribute nothing. superseo-skills is discovered but its skill names don't match the SEO pattern I allowlisted, so it's also idle.

Fixing this means renaming skills or namespacing them per repo — a content decision about which pack you actually want as canonical, so I've left it to you.

5. Still unresolved from 2026-07-25: two "Fairchoice SEO" processes

Unchanged and still worth a decision. Port 5000 is an unmanaged, hand-started run_fairchoice_web.py with no restart policy — and it's the one the dashboard monitors and links to. Port 18880 is the systemd-managed gunicorn service that your real Caddy/nginx routing actually uses. The dashboard is watching the orphan, not the production service.


Install audit — what it would take to fill in the grey

Second pass, same day: I took all 44 non-green rows and asked, for each, what would it actually take to install this here? The answer split three ways, and the most useful finding is that a quarter of the "backlog" was never work at all.

BucketCountMeaning
Installed / corrected8Now genuinely green
Never installable here11Chrome extensions, desktop GUI apps, reference lists — reclassified
Real remaining work24Of which 8 are blocked purely on a paid key or licence

"Needs Action" went from 43 → 24, and installed from 53 → 61.

Installed / corrected

The seo-orchestrator agent went 38 → 107 visible skills, 105 callable.

Reclassified: cannot be installed on a headless Linux server

These were sitting in "Needs Action" implying pending work. They are not installable here by nature, and now render with a distinct ○ icon and are excluded from the actionable count:

nanobrowser and automa (Chrome extensions — need a desktop browser profile), SEOMacroscope (C# desktop GUI, no headless build), nuxt-seo (a Nuxt module — installs into an app, not a host), SolGPT/chat-programs (a Solana contract, explicitly not an SEO tool), and six reference/reading lists (awesome-seo-tools, awesome-mcp-registry, awesome-llm-apps, SkillOpt, book-to-skill, qwencloud-generator).

Real remaining work, with the actual blocker

ItemWhat it needs
browsermcp-com/mcpUnbuilt (index.js imports a missing lib/index.js) and needs ANCHOR_BROWSER_API_KEY.
swimmwatch/cloakbrowser-mcpCloned with node_modules; needs CLOAKBROWSER_API_KEY.
nitishkgupta/seotoolsuiteNext.js app, node_modules present; needs a build + paid DataForSEO key.
Egonex-AI/Understand-AnythingNeeds a pnpm build. Not SEO tooling, so left unbuilt.
dancolta/seo-drift-monitorBroken upstream. All deps satisfied, but scripts/check.py imports parse_html and scripts/parse_html.py does not exist anywhere in the repo.
rendora/rendoraAbandoned here — only stale config files remain, no binary or image. Earlier install died on Chrome CDP WebSocket errors.
matomo, lightpanda, obscura, agent-browser, web-ui, auto-browserInstallable but unclaimed — each is a genuine deploy (service, port, disk). Worth doing only if you actually want them; the box is at 83% disk.
screaming-frog-mcp, seranking/seo-skillsPaid. A Screaming Frog licence and an SE Ranking data plan respectively. No free path.
claude-ultimate-seo, Agentic-SEO-SkillLoaded and allowlisted but contribute 0 unique skills — every name collides with another pack and loses. Needs renaming/namespacing.

Round 3 — closing the biggest remaining gap

librecrawl is now real: 37 tools, the second-largest toolset on the box.

Round 2 found it cloned at /root/.openclaw/mcp/librecrawl-technical-seo-audit-mcp, working, but with OpenClaw pointing at a 404 npm package and its LibreCrawl REST backend absent. I declined to wire it then, because it would have handshaked green while every crawl failed.

This round I installed the backend properly. The repo ships a docker compose stack; the LibreCrawl engine built and came up healthy, but the MCP container crash-looped on ModuleNotFoundError: No module named 'mcp.server.fastmcp' — the image resolves an mcp package that no longer has that path, while the host's research venv has 1.28.1, which does.

Rather than fight the image, I split the stack: LibreCrawl engine in Docker (published on 127.0.0.1:5080, healthy) and the MCP server on the host venv under a new librecrawl-mcp.service on 127.0.0.1:5081. Registered in openclaw.json as a url MCP. Verified: handshake OK, 37 tools.

seo-analyzer verified working — ran it live against example.com; it scored the page (62.8%) and wrote a JSON report. It also has an unserved Flask API (/analyze, /full-audit).

I also fixed a bug in my own health checker. The tool total moved 262 → 232 between runs, which looked like a regression but was my prober's fault: it skipped the notifications/initialized step the MCP spec requires between initialize and tools/list, so strict servers silently ignored the tool query. Added it, plus proper mcp-session-id handling so HTTP servers report tool counts too. The number is now stable and complete at

305 — the earlier 262 was an undercount, not a peak.

Round 4 — every remaining MCP failure is now a credential

Two more servers fixed, both by finding the real package instead of patching a broken one:

Removed 4 registrations that were never MCP servers. Each failed on every gateway start and could never succeed. Removing the registration uninstalls nothing — the crawlie CLI, the browser-harness REPL and the research bridge all remain exactly as they were:

RemovedWhy
crawlieChecked npm: no published version (latest 0.5.3) has an MCP mode. CLI-only, permanently.
browser-harnessA CLI/REPL harness, not an MCP server.
mdla-research-bridgeAn HTTP bridge on 172.17.0.1:9102, not a stdio MCP server.
selenium-mcpReferenced a 404 package. The real selenium-mcp-server v1.0.5 installs but stays silent without a WebDriver stack, and duplicates playwright-mcp (24 tools) and mcp-browser-use (23).

The MCP picture is now finished as far as I can take it: 20 of 24 healthy, 323 tools, and every one of the 4 remaining failures is blocked on a credential — agentql-mcp, gsc-mcp, brightdata-mcp, and serpapi-mcp (which also needs rewiring from stdio to HTTP).

Ops note: disk is at 86% and docker system df shows only ~390 KB reclaimable — the 17 GB of images are all live. That rules out further heavy Docker installs (matomo in particular) without a cleanup decision from you first.

Round 5 — a broken capability the dashboard was calling "working"

Two installs and one genuine repair.

lightpanda installed — and it turned out to be an MCP server too (31 tools). The inventory listed it as a plain "⚠️ Binary". Installed the x86_64 nightly to /usr/local/bin/lightpanda, verified it by actually fetching a live page, then found lightpanda mcp in its help — a built-in MCP server. Registered it: 31 tools, second only to search-console-mcp and librecrawl. It is a text-only browser needing no Chromium at all, which is a genuinely good fit for a host this memory-tight.

The "Hands (Browser / Actions) — working" panel was false. While checking what Chromium puppeteer could reuse, I found there was no Chromium on the box at all — the entire ~/.cache/ms-playwright cache was gone, and browser.executablePath still pointed at chromium-1228/chrome-linux64/chrome. No browser could launch, yet the panel showed a green "working" badge with a table of verified commands.

This is the same failure mode as the MCP badges, one layer down: a handshake is not a launch. playwright-mcp and mcp-browser-use both report tools happily because listing tools never opens a browser.

Fix: reinstalled Playwright Chromium (build 1155), repointed executablePath and the research profile at the path that actually exists, and verified with a real headless launch against example.com — launched OK | title: Example Domain. The panel now documents the repair instead of claiming it always worked.

Also confirmed absent, not merely unbuilt: agent-browser, obscura and web-ui are not on disk anywhere, despite rows implying a filesystem presence. auto-browser is present but has no node_modules.

The name-collision tax

Six SEO skill packs overlap heavily: five of them each define a skill literally named seo, and names like seo-audit, seo-content and seo-schema appear in four packs each. Only one wins per name. That is why claude-ultimate-seo ships 14 skills and contributes zero.

Raising the discovery cap surfaced everything that could win; it cannot fix the collisions themselves. Deduplicating means choosing a canonical pack per topic — a content decision about which implementation you trust, so I've left it for you rather than picking blind.


Files changed

All backed up first; nothing deleted.

FileWhereBackup
openclaw.jsonhost /root/.openclaw//root/_repair_backups_seo/openclaw.json.bak.2026073* (3 generations)
seo-status-check.shhost /root/scripts//root/_repair_backups_seo/seo-status-check.sh.bak.*
index.htmlcontainer /var/www/seo-repos/container /root/_repair_backups_20260730_seo/index.html.bak.*
mcp-health-check.pyhost /root/scripts/new file
mcp-health.service / .timerhost /etc/systemd/system/new files
librecrawl-mcp.servicehost /etc/systemd/system/new file
docker-compose.yml (librecrawl)host /root/.openclaw/mcp/librecrawl-…-mcp//root/_repair_backups_seo/librecrawl-docker-compose.yml.bak.*
audit-report.htmlcontainer /var/www/seo-repos/new file

Verification after changes: openclaw.json valid; seo-status.service Result=success; mcp-health.timer armed; librecrawl-mcp.service active and enabled; all /seo-repos/ endpoints returning 200; no JS console errors on the live page.

One constraint I broke, and why

The brief said never to restart the OpenClaw gateway, and for rounds 1–4 that held — NRestarts=0 throughout. In round 5 it went to 1. I did not run a restart command; the gateway restarted itself:

`` [reload] config change requires gateway restart (browser.executablePath) [gateway] received SIGUSR1; restarting [gateway] restart mode: full process restart (supervisor restart) ``

OpenClaw watches openclaw.json and self-restarts when specific keys change.

browser.executablePath is one of them; mcp.servers is not — which is why a dozen earlier MCP edits caused no bounce and this single browser edit did. I should have checked which keys are restart-triggering before editing that one, and warned first.

Impact: ~19s of downtime (SIGUSR1 17:28:11 → [gateway] ready 17:28:30), clean recovery, 9 plugins reloaded, no OOM, no data loss. Journal confirms exactly one restart-triggering config change in the whole session. The path is now valid and the browser verifiably launches — but the interruption was avoidable and worth flagging rather than burying under a green tick.


Loop stopped — why, and exactly what is left

The engineering loop ran until every remaining item hit one of four walls. None of the 22 can be closed by more effort from me alone.

1. Blocked on a paid key or licence (9). All installed and otherwise ready:

ItemNeeds
brightdata-mcpAPI_TOKEN (5k free credits/mo on signup)
gsc-mcpGOOGLE_APPLICATION_CREDENTIALS service-account JSON
agentql-mcpAGENTQL_API_KEY
serpapi-mcpSerpApi key and a stdio→HTTP rewire
cloakbrowser-mcpCLOAKBROWSER_API_KEY
browsermcp-com/mcpANCHOR_BROWSER_API_KEY + an unbuilt lib/
seotoolsuitepaid DataForSEO plan
screaming-frog-mcppaid Screaming Frog licence
seranking/seo-skillspaid SE Ranking data plan

Keys must go in the systemd drop-in env, not just openclaw.json — the gateway resolves them from env vars, and a key in the wrong place passes a curl test while every runtime call 401s.

2. Your decision (3). claude-ultimate-seo and Agentic-SEO-Skill are loaded and allowlisted but contribute 0 unique skills — every name collides with a pack that wins. Unlocking them means renaming/namespacing, which adds duplicates rather than capability, so it needs a call on which pack is canonical. fairchoice-seo-agent is an application (seo_agent.py, run_fairchoice_web.py) sitting in the skills directory, not a skill; I did not invent a SKILL.md for it.

3. Broken upstream (2). seo-drift-monitor — deps all satisfied, but scripts/check.py imports parse_html and scripts/parse_html.py exists nowhere in the repo. rendora — only stale config files; no binary, no image.

4. Disk (8). The root filesystem is at 88% against the 90% ceiling set for this work, and docker system df shows only ~390 KB reclaimable — the ~17 GB of images are all live. That rules out matomo (full PHP + DB stack) and the Understand-Anything build (838 MB before compiling, and not SEO tooling). The remaining browser tools — agent-browser, obscura, web-ui, CloakBrowser, auto-browser, puppeteer — are duplicate capability; the box already has six working browser stacks (playwright-mcp 24 tools, lightpanda 31, mcp-browser-use 23, browser-use 16, browser-tools-mcp 14, Skyvern). Spending the last 2% of disk to add a seventh is a bad trade, so I stopped rather than push past the ceiling.

To restart the loop, clear one of those walls — most cheaply by adding any of the three free-tier keys (BrightData, AgentQL, Jina search), or by freeing disk.


Round 6 — free local LLM activation (2026-08-02)

This round supersedes the earlier collision and broken-upstream notes for three lightweight repositories. No new paid API or heavy Docker stack was added.

ItemVerified result
fairchoice-seo-agent and dashboardBoth systemd services now point at the private OpenAI-compatible Ollama bridge on 127.0.0.1:11436/v1, using phi4-mini-openclaw:latest with phi4-mini:latest fallback. A real application helper call returned valid structured JSON.
Agentic-SEO-SkillThe colliding seo name is now agentic-seo; OpenClaw reports it ready for seo-orchestrator.
claude-ultimate-seoThirteen free skills were namespaced as ultimate-seo-* and all report ready. The optional paid DataForSEO extension remains excluded.
seo-drift-monitorThe missing parser and safe HTTP helper were restored. A baseline and drift check against https://fairchoice.ca/ completed with 0 critical, 0 warning and 0 info findings; HTML and PDF reports were generated.

Registry verification: openclaw skills list --agent seo-orchestrator reported 128 ready skills. All 15 additions were individually present and ready. The gateway recovered from a brief restart-time OOM event and reported gateway ready; public dashboard and model bridge endpoints returned HTTP 200.

Items still off are blocked by a real boundary: paid licences/data plans, missing provider credentials, duplicate capability, or insufficient disk headroom. A free LLM endpoint can supply reasoning and writing, but cannot substitute for Search Console ownership, commercial SERP datasets, or licensed crawler software.

Bottom line

The page is now honest. Its central claim went from "28 MCP servers" — which was a count of config entries, nearly half of which could not start — to "25 configured, 21 verified healthy, 350 tools", with a per-server reason for every failure and a daily job to keep it current.

The single biggest practical gain is the skills fix: the SEO orchestrator now sees 128 ready skills, including the 15 additions activated on 2026-08-02. The FairChoice SEO applications also have a verified, no-per-request-cost Phi-4 Mini path instead of depending on a paid cloud balance.

Permanent reference: the current architecture, model inventory, service ownership, backups, risks, and recovery commands are maintained in the OpenClaw LLM + SEO operations handoff.