Skip to main content
Glama
README.md
# seocli — SEO Crawling & Auditing CLI for AI Agents

> **"审计一下 example.com 的 SEO"** → agent invokes `seocli`, returns structured issue report.

**seocli** is a dual-mode SEO auditing tool built for **AI agent integration**:

- **CLI mode** — `seocli https://example.com` → structured JSON on stdout
- **MCP mode** — tools for [Claude Code](https://claude.ai/code) and any MCP-compatible agent framework

Crawl any website, extract SEO data, detect issues, get actionable JSON output.

---

## Install

```bash
pip install seocli[js,mcp]

# Optional: JS rendering for SPAs
pip install playwright && playwright install chromium
```

---

## Quick Start

```bash
# Quick audit — JSON printed to stdout
seocli https://example.com --quiet

# Deep crawl with output file
seocli https://example.com --depth 5 --json report.json

# Local dev server (no delay)
seocli http://localhost:3000 --delay 0

# JavaScript-rendered SPA
seocli https://spa-site.com --js
```

---

## MCP Integration

seocli ships with an MCP server — register it in your agent's MCP configuration:

### Claude Code

Add to `~/.claude/mcp.json`:

```json
{
  "mcpServers": {
    "seocli": {
      "command": "python3",
      "args": ["-m", "seocli.server"]
    }
  }
}
```

Then restart Claude Code. These tools become available:

| Tool | Description |
|------|-------------|
| `seocli_audit` | Full crawl + audit. Returns pages, issues, links, stats as JSON. |
| `seocli_issues_summary` | Quick shallow crawl + grouped issue summary. Faster. |
| `seocli_audit_start` | Start async crawl (large sites). Returns `session_id` immediately. |
| `seocli_audit_poll` | Poll async session for incremental results + progress. |
| `seocli_audit_results` | Get final results of an async session. |
| `seocli://audit/latest` | Resource: most recent audit result as JSON. |
| `seocli://audit/score` | Resource: 0-100 site health score with letter grade. |

### Async Audits (Large Sites)

For sites with 50+ pages, use the async flow to avoid long blocking waits:

```
1. seocli_audit_start(url) → session_id
2. seocli_audit_poll(session_id) → incremental issues + progress
3. seocli_audit_results(session_id) → final report
```

### Agent Prompt Templates

Ready-to-use prompt snippets for AI agents: see [`prompts/`](prompts/) directory.

| File | For |
|------|-----|
| `prompts/claude-code.md` | Claude Code |
| `prompts/cursor.md` | Cursor IDE |
| `prompts/generic-mcp.md` | Any MCP agent |

### Any MCP Host

seocli uses the standard [Model Context Protocol](https://modelcontextprotocol.io) — it works with any MCP-compatible client. Just point your MCP host at `python3 -m seocli.server`.

### Agent Prompt Example

When configuring an agent to use seocli, describe it like this:

```
You have access to the `seocli_audit` MCP tool. When the user says
"audit example.com for SEO issues", call it with the URL. Parse the
`issues` array from the result and present:
- Errors first (🔴), grouped by category
- Warnings second (🟡), grouped by category
- Key stats: pages crawled, response time, issue count
```

---

## Agent Decision Guide

### When to use `--js`
- The site is a known SPA (React/Vue/Angular with client-side rendering)
- Tags don't appear in raw HTML: `curl <url>` returns no meta tags
- **Default**: no JS (faster, lighter, fewer dependencies)

### When to use `--delay`
- **Own/local site**: `--delay 0` (fastest, no artificial wait)
- **Other people's sites**: `--delay 1.0` at minimum (be polite)
- The delay is seconds between requests — `1.0` = 1 request/second

### When to use `--respect-robots`
- **Other people's sites**: keep enabled (default: on)
- **Own site** with restrictive robots.txt: use `--no-robots`

### Finding Priority (high → low)

| Priority | Type | Category | Example |
|----------|------|----------|---------|
| 🔴 1 | error | SEO | Missing title tag |
| 🔴 2 | error | Technical | 404, 5xx status codes |
| 🔴 3 | error | Indexability | noindex on critical pages |
| 🟡 4 | warning | SEO | Title too long/short |
| 🟡 5 | warning | Social | Missing OG/Twitter tags |
| 🟡 6 | warning | Technical | Missing canonical URL |
| 🔴 7 | error | Content | Broken image, missing alt text |
| 🟡 8 | warning | Content | Thin content (< 300 words) |
| 🟡 9 | warning | Performance | Slow page load (> 2s) |
| 🔵 10 | info | Technical | Redirect detected (verify) |

---

## JSON Output Structure

```json
{
  "url": "https://example.com",
  "stats": {
    "crawled": 42,
    "discovered": 85,
    "depth": 3,
    "speed": 5.2,
    "elapsed_seconds": 8.1
  },
  "pages": [
    {
      "url": "https://example.com/",
      "status_code": 200,
      "title": "Page Title",
      "meta_description": "Description...",
      "h1": "Heading",
      "h2": ["Subheading"],
      "word_count": 450,
      "lang": "en",
      "canonical_url": "...",
      "og_tags": { "og:title": "...", "og:description": "...", "og:image": "..." },
      "twitter_tags": { "twitter:card": "summary_large_image" },
      "json_ld": [{ "@type": "WebSite", ... }],
      "analytics": { "gtag": true, "ga4_id": "G-XXXXX" },
      "images": [{ "src": "...", "alt": "...", "width": "", "height": "" }],
      "hreflang": [{ "hreflang": "en", "href": "..." }],
      "internal_links": 15,
      "external_links": 3,
      "response_time": 234.5,
      "size": 12450,
      "viewport": "width=device-width, initial-scale=1",
      "robots": "index, follow",
      "is_internal": true,
      "depth": 0,
      "linked_from": ["https://example.com/other"]
    }
  ],
  "links": [
    {
      "source_url": "https://example.com/",
      "target_url": "https://example.com/about",
      "anchor_text": "About us",
      "is_internal": true,
      "target_domain": "example.com",
      "target_status": 200,
      "placement": "body"
    }
  ],
  "issues": [
    {
      "url": "https://example.com/page",
      "type": "error",
      "category": "SEO",
      "issue": "Missing Title Tag",
      "details": "Page has no title tag"
    }
  ]
}
```

---

## Issue Classification

### Issue Types

| Type | Meaning | Action |
|------|---------|--------|
| `error` | Must fix | Missing title, 404, noindex, broken images |
| `warning` | Should fix | Title too long/short, thin content, slow page |
| `info` | Note | Redirect detected, informative findings |

### Issue Categories

SEO · Technical · Content · Mobile · Accessibility · Social · Structured Data · Performance · Indexability · Duplication

---

## What's New in v0.4.0

### GEO (Generative Engine Optimization) — AI Search Readiness

First-of-its-kind GEO category: checks if pages are optimized for AI search engines (ChatGPT, Perplexity, Google AI Overviews). 8 new rules covering: AI crawler blocking, content structure for AI models, source citations, author attribution (E-E-A-T), publish dates, FAQ schema detection, and more.

### Custom Rules DSL

Define your own SEO checks in `.seocli-rules.yaml` — no Python code needed. 8 check types: field_exists, field_matches_regex, list_min_items, and more. URL include/exclude patterns via glob. See `.seocli-rules.example.yaml`.

### GitHub Action

Official CI/CD integration: auto-audit on PRs, comment results, fail on errors. See `.github/workflows/seo-audit.yml`.

### What's New in v0.3.0

### MCP Deepening — AI Agent Native

- **Async audits**: `seocli_audit_start` / `seocli_audit_poll` / `seocli_audit_results` — incremental reporting for large sites
- **MCP Resources**: `seocli://audit/score` (0-100 health score) and `seocli://audit/latest` (cached result)
- **Prompt templates**: Ready-to-use agent prompts for Claude Code, Cursor, and any MCP agent in `prompts/`

### What's New in v0.2.0

### New Rule Categories

| Category | New Rules | Type |
|----------|-----------|------|
| **Security** | HSTS, CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Page Served Over HTTP, HTTP on Form Pages | error |
| **Accessibility** | ARIA Landmarks, Positive Tabindex, Missing Skip Link, Potential Contrast Issues | error/warning |
| **Structured Data** | JSON-LD @context validation, @type validation, Schema.org itemtype | warning |
| **Performance** | Images Without Dimensions (CLS), Large DOM Size, Missing font-display, No Preconnect Hints, Render-Blocking Resources | warning/info |
| **SSL** | HTTPS usage check | error |

### New Output Formats

| Format | Flag | Description |
|--------|------|-------------|
| JSON | `--format json` (default) | Structured JSON for AI agents and programmatic use |
| CSV | `--format csv` | Issues + Pages as CSV for spreadsheet analysis |
| Markdown | `--format markdown` | Human-readable report with emoji-coded issues |
| HTML | `--format html` | Standalone HTML report with styled table |

### CI/CD Integration

```bash
# Fail if any errors found (exit code 1)
seocli https://example.com --fail-on error

# Fail if any warnings or errors found
seocli https://example.com --fail-on warning
```

### Testing

seocli now includes a comprehensive test suite. Run with:

```bash
pip install seocli[dev]
python -m pytest tests/ -v
```

### Rule Count: 25 → 60+

v0.2.0 more than doubles the number of SEO audit rules from 25 to over 60, covering security headers, accessibility deep-dive, structured data quality, SSL/HTTPS, and Core Web Vitals static signals.

---

## CLI Usage

| Scenario | Command |
|----------|---------|
| Quick audit | `seocli https://example.com` |
| Quiet (agent) | `seocli https://example.com --quiet` |
| Save to file | `seocli https://example.com --json report.json` |
| Local dev | `seocli http://localhost:3000 --delay 0` |
| Polite crawl | `seocli https://other.com --delay 1.0 --respect-robots` |
| SPA audit | `seocli https://spa.com --js` |
| Deep crawl | `seocli https://big.com --depth 5 --max-urls 2000` |
| No duplication check | `seocli https://big.com --no-duplicate-check` |

---

## Options

```
seocli <url> [options]

positional:
  url                   Website URL to audit

options:
  --depth N             Max crawl depth (default: 3)
  --max-urls N          Max URLs to crawl (default: 500)
  --delay SECONDS       Seconds between requests (default: 0 = no limit)
  --js                  Enable JavaScript rendering (requires playwright)
  --respect-robots      Respect robots.txt (default: on)
  --no-robots           Ignore robots.txt
  --concurrency N       Max concurrent requests (default: 5)
  --json FILE           Save JSON output to file
  --quiet, -q           Suppress progress output
  --no-duplicate-check  Skip duplicate content detection (faster on large sites)
  --format {json,csv,markdown,md,html}   Output format (default: json)
  --fail-on {error,warning,info,none}    CI gate: exit 1 if issues at this level exist
  --rules FILE          Custom rules config (.yaml or .json)
  --help                Show this help
```

---

## Custom Rules

Define your own SEO checks in `.seocli-rules.yaml`:

```bash
# Run with custom rules
seocli https://example.com --rules .seocli-rules.yaml

# Example: check all product pages have >300 words
# See .seocli-rules.example.yaml for more examples
```

8 check types: `field_exists`, `field_not_empty`, `field_min_length`, `field_max_length`, `field_matches_regex`, `field_not_matches_regex`, `list_min_items`, `url_matches_pattern`. URL include/exclude patterns via glob.

### GitHub Action

```yaml
# .github/workflows/seo-audit.yml
# Auto-audits on PR, comments results, fails on errors
# See .github/workflows/seo-audit.yml
```

---

## Extras

### JS Rendering

```bash
pip install seocli[js]
playwright install chromium
seocli https://spa-site.com --js
```

### MCP Only

```bash
pip install seocli[mcp]
python -m seocli.server
```

---

## License

MIT


---

## Related Tools

| Project | Description |
|---|---|
| [seo-review-board](https://github.com/lennney/seo-review-board) (archived) | Multi-agent SEO 评审框架模板 — 角色定义、场景模板、评分系统 |
| [crawlweaver](https://github.com/lennney/crawlweaver) | 12-Factor AI 爬虫,可与 seocli 配合做内容审计 |
| [agent-search-mcp](https://github.com/lennney/agent-search-mcp) | 多源搜索 MCP,seocli 可调用做关键词研究 |