SEO MCP is an open-source Model Context Protocol (MCP) server that turns any AI agent — Claude, Codex, Cursor, or your own — into a full technical SEO crawler. Point it at a website and it crawls the site like Screaming Frog, collects on-page SEO data, and returns a prioritized audit your model can reason about.
It ships as a single Docker image with an admin UI, a REST API, and an MCP endpoint — self-host it on your own server in minutes.
Built and maintained alongside topify.app — SEO automation for Shopify stores.
LLMs are great at explaining SEO but blind to what a site actually looks like at crawl time. This SEO MCP gives your agent real eyes on a website: it fetches every page, parses the HTML, follows links and redirects, respects robots.txt, and stores structured results you can query by tool call. Ask Claude to "crawl example.com and tell me what's hurting my SEO" — and it will, with real data.
- 🕷️ Screaming-Frog-style crawler — concurrent, polite (per-host limits + robots.txt), depth-aware.
- 🔎 Full on-page SEO extraction per URL:
- Status code, redirect chains, content type, response time, size, crawl depth
- Title + length, meta description + length, H1/H2, word count,
lang - Canonical (+ self/other),
meta robots&X-Robots-Tag, indexability with reason - Internal/external outlinks, inlinks, images + missing
alt, hreflang count - Structured data (JSON-LD
@type), viewport & charset presence, Open Graph
- 🗺️ Sitemap crawling & orphan detection — discovers
sitemap.xml(index + nested +.gz) androbots.txtSitemap:directives, seeds those URLs, and flags orphan pages (in the sitemap but not linked internally) and indexable pages missing from the sitemap. - 🩺 Automatic SEO audit — aggregated issues (broken pages, duplicate/missing titles & meta, missing/multiple H1, thin content, redirects, canonicalized/noindex pages, images without alt, orphan pages) with severity and counts.
- 🛍️ Shopify-aware — auto-detects Shopify stores and pulls the full catalog via
/products.jsonand/collections.json(variants, prices, vendors, product types, tags, collection sizes). - 🧑💻 Admin UI — launch crawls, watch live queues, browse per-URL results, filter by issue, export CSV, and copy your MCP connection config.
- 🔐 Auth built in — admin login (JWT) for the UI + a Bearer API token for the MCP endpoint and REST API.
- 💾 Persistent — every crawl and page is stored in embedded SQLite; queues survive restarts.
- 🐳 One container — pure-Go binary + embedded UI, runs anywhere Docker does. No external database.
| Tool | What it does |
|---|---|
crawl_site |
Start a crawl of a URL. Optional wait_seconds blocks and returns the audit summary inline. |
get_crawl_status |
Live progress/stats for a job. |
list_crawls |
Recent crawl jobs. |
get_crawl_summary |
Aggregated SEO audit: status buckets, indexability, avg response time, ranked issues. |
get_crawl_pages |
Per-URL records, filterable to issues/broken/redirects/noindex/missing_title/missing_meta. |
get_shopify_data |
Products & collections collected from a Shopify store. |
git clone https://github.com/ozhehkovski/seomcp.git
cd seomcp
cp .env.example .env
# edit .env and set ADMIN_PASSWORD (and BASE_URL if hosting publicly)
docker compose up -d --buildOpen the admin UI at http://localhost:8080 and sign in with the credentials from .env.
The MCP endpoint is served at /mcp. The API token is shown in the UI (Connect MCP) and printed in the container logs on first boot.
docker build -t seomcp .
docker run -d -p 8080:8080 -v seomcp_data:/data \
-e ADMIN_PASSWORD=your-strong-password \
-e BASE_URL=https://mcp.example.com \
seomcpThis server speaks MCP over Streamable HTTP. Add it as a remote MCP server with a Bearer token.
Claude Code (CLI):
claude mcp add --transport http seomcp https://mcp.example.com/mcp \
--header "Authorization: Bearer YOUR_API_TOKEN"Config block (Claude / Codex mcpServers):
{
"mcpServers": {
"seomcp": {
"url": "https://mcp.example.com/mcp",
"headers": { "Authorization": "Bearer YOUR_API_TOKEN" }
}
}
}Then just ask your agent:
Crawl https://example.com and give me the top SEO issues to fix. Is https://minoti.com on Shopify? List its collections and how many products each has.
| Env var | Default | Description |
|---|---|---|
PORT |
8080 |
HTTP port |
DB_PATH |
/data/seomcp.db |
SQLite file path |
BASE_URL |
http://localhost:8080 |
Public URL, used for the MCP connect hint |
ADMIN_USER |
admin |
Admin username |
ADMIN_PASSWORD |
(generated) | Admin password — set this in production |
API_TOKEN |
(generated) | Bearer token for MCP + API |
JWT_SECRET |
(generated) | Signing secret for UI sessions |
USER_AGENT |
SEOMCPBot/1.0 |
Crawler user-agent |
POST /api/login · POST /api/jobs · GET /api/jobs · GET /api/jobs/{id}/summary · GET /api/jobs/{id}/pages?filter=issues · GET /api/jobs/{id}/shopify · GET /api/jobs/{id}/export (CSV). All protected by the Bearer token or an admin JWT.
ui/ React + Tailwind admin (built and embedded into the Go binary)
api/ Go server: crawler + SQLite store + REST + MCP (Streamable HTTP)
Single binary, single container. Crawl state lives in SQLite under /data.
# backend
cd api && go run .
# frontend (proxies /api and /mcp to :8080)
cd ui && npm install && npm run devPushing to main triggers .github/workflows/deploy.yml, which builds the Docker image and ships it to the host over SSH (docker save | ssh). To wire it to your own server, set three repo secrets: DEPLOY_SSH_KEY (private key), DEPLOY_HOST, DEPLOY_USER — the public key goes in the host user's authorized_keys (ideally behind a restricted command=). The deploy is health-gated with automatic rollback.
- JS rendering (headless) for SPA sites
- Scheduled recurring crawls + diffs
MIT — free to self-host and modify. Anyone can run their own instance.
Made by the team behind topify.app — AI-powered SEO for Shopify. If this SEO MCP saves you time, a ⭐ on the repo helps others find it.