Skip to main content
Glama

Search Evidence

Keep search traffic evidence close to the content decisions it informs.

Search Evidence is a local CLI and stdio MCP server for Google Search Console, Bing Webmaster Tools, URL protection, editorial review, and comparison of a reviewed HTML build with a live website. It uses official read-only search APIs and stores observations in a private SQLite database.

Missing data stays unknown. A URL with historical clicks stays protected.

What it does

  • Collect Google totals, pages, queries and dates, with resumable pagination, daily partitions, optional selected-page queries and explicit finality metadata.

  • Collect Bing rank/traffic, page and query records without inventing date ranges or mapping Bing position fields to Google semantics.

  • Import historical JSON collections and page CSVs. Reimporting the same capture is idempotent. GA4 JSON reports can be retained as raw, separate evidence.

  • Compare compatible Google periods. Withheld or absent queries are never given fabricated zero counts.

  • Protect every raw URL with any observed positive clicks; manually protected URLs are also retained. Case, trailing slashes, query strings and fragments are not collapsed.

  • Flag unfinished prose, exact duplicate bodies, date inconsistencies, missing internal build targets, numeric claims and firsthand testing claims for review.

  • Compare live content, metadata, canonical URLs, robots directives, links, navigation, images and structured data with registered build fingerprints. Explicit reviewed HTML aliases include a check of the destination page.

  • Generate private JSON, spreadsheet-safe CSV and escaped HTML reports.

  • Expose the same core operations through ten typed MCP tools.

It does not write to Google/Bing, publish articles, alter an existing collector, request indexing, delete URLs, or predict AdSense approval.

Related MCP server: mcp-seo-auditor

Install

Requires Python 3.12+ and Linux or macOS. Development and integration checks run on Linux; macOS is included in CI. Windows is not supported because collection leases use POSIX file locks.

uv sync --locked
uv run search-evidence --help

Alternatively, install the package in a dedicated virtual environment:

python3 -m venv .venv
.venv/bin/pip install .
.venv/bin/search-evidence --help

For development, uv sync --locked also installs test and lint dependencies. The package does not need Node.js, Docker, a browser server, or a database service.

Try it without credentials

All example data is synthetic and uses reserved example domains.

uv run search-evidence --profile examples/demo.toml import-csv \
  examples/pages.csv --start 2026-01-01 --end 2026-01-28 \
  --observed-at 2026-02-01T00:00:00Z
uv run search-evidence --profile examples/demo.toml protect
uv run search-evidence --profile examples/demo.toml audit
uv run search-evidence --profile examples/demo.toml report

The demo profile creates .state/demo with private directory permissions. Reports are written under that directory and ignored by Git.

Connect your own site

Copy examples/profile.toml to a private location outside this repository. Use absolute paths or ~ paths. Relative paths resolve from the profile directory.

site = "https://example.com/"
state_dir = "~/.local/state/search-evidence"
google_credentials = "~/.config/search-evidence/google.json"
bing_key = "~/.config/search-evidence/bing-key.txt"
content_root = "/path/to/blog/content/posts"
build_root = "/path/to/reviewed-public-build"
allowed_hosts = ["example.com"]
body_selector = ".post-content, main, article"
max_calls = 200
max_seconds = 180

Google supports a service account authorized for the property, an authorized-user OAuth credential file, or Application Default Credentials when google_credentials is omitted. The API scope is webmasters.readonly. Enable the Search Console API in your Google Cloud project and grant the credential access to the exact property. Bing uses the owner's Webmaster API key stored as plain text in a private file. Credentials remain local. Keep credential files mode 0600 and the state directory mode 0700; the application refuses a state directory readable by other users.

Optional desktop OAuth setup, from a machine with a local browser:

search-evidence --profile /private/profile.toml auth-login \
  --client-secrets /private/oauth-client.json \
  --token-output /private/google.json

The loopback login is explicit and times out after 180 seconds. An existing token output is never overwritten. A Google OAuth app in testing mode may require periodic reauthorization; the CLI does not promise indefinite token validity.

export SEARCH_EVIDENCE_PROFILE=/private/profile.toml
search-evidence status --remote
search-evidence finality --start 2026-01-20 --end 2026-01-29
search-evidence collect --start 2026-01-01 --end 2026-01-28

collect defaults to daily Google partitions. A whole-period report is useful for totals and compatibility checks:

search-evidence collect --start 2026-01-01 --end 2026-01-28 --aggregate
search-evidence traffic --source gsc --table totals
search-evidence traffic --source bing --table pages --limit 50

Each traffic response identifies one snapshot and its exact request window. It never implicitly adds daily, overlapping, imported or repeated observations. Use --snapshot-id to pin a result. Daily collection is suitable for archival and resumable backfills; choose --aggregate for a whole-window view.

To resume an incomplete collection, repeat its original options and add --resume JOB_ID from its response. Changed request conditions are rejected. Bing endpoints return their own available window and do not accept these Google start/end dates.

Preserve URLs and inspect changes

search-evidence protect
search-evidence protect --urls https://example.com/posts/article/
search-evidence protect-add --url https://example.com/posts/article/ \
  --reason "Editorial commitment"
search-evidence inspect --urls https://example.com/posts/article/
search-evidence audit
search-evidence prioritize --audit-id AUDIT_ID

Audit and priority results default to 50 rows. To continue, pass the returned --audit-id, --cursor and optionally --limit (maximum 500). Verification results similarly accept --verification-id with a cursor; this reads the saved result without repeating HTTP requests.

Protection survives failed collections and later zero-click observations. Unobserved URLs receive review_required; there is no safe_to_delete state. Duplicate articles with traffic on both URLs retain protection on both. Claim findings identify evidence that a reviewer should check; they do not declare a claim false or establish that its citation is trustworthy.

Verify a reviewed build

Build the site with your existing process first. Point build_root at that reviewed output, then register its expected fingerprints:

search-evidence manifest --urls-file /private/reviewed-urls.json \
  --revision SOURCE_COMMIT
search-evidence verify --manifest-id MANIFEST_ID
search-evidence verify --manifest-id MANIFEST_ID --cache-check
search-evidence report --audit-id AUDIT_ID --verification-id VERIFICATION_ID

reviewed-urls.json is a JSON array of raw absolute URLs. HTML aliases are recognized only when a zero-delay refresh and canonical agree on an in-property target present in the reviewed build. An alias does not remove any protected URL. Multiple alias hops require explicit review.

HTTP 200 alone is insufficient. A changed body, description, schema, canonical, redirect destination, relevant robots directive, or meaningful link fails the comparison. Whitespace outside code is normalized. Reports distinguish a live content match from the unverified Git deployment revision and search index version. --revision records an owner-supplied claim; it is not provenance proof.

The report directory contains report.json, traffic.csv, protected-urls.csv, and report.html. CSV keeps snapshots and provider/date boundaries explicit and leaves unknown values blank. Reports contain private analytics and should not be committed.

MCP

Configure your MCP client to launch this command over stdio:

uv --directory /absolute/path/to/search-evidence run --locked \
  search-evidence --profile /private/profile.toml mcp

There is no HTTP listener. Standard output is reserved for MCP protocol messages. Clients receive input/output schemas, structured results and consistent error envelopes. Tools that persist local state are marked as mutating even though the remote APIs are read-only.

Tool

Purpose

search_status

Availability, last good observations, optional property access check

search_collect

Bounded, resumable Google/Bing collection

search_traffic

Paginated snapshot rows

search_compare

Compatible Google period comparison

search_protect_urls

Conservative raw-URL decisions and evidence

search_prioritize

Audit priorities that preserve URLs with traffic

search_inspect_urls

Bounded indexed-record inspection

search_audit_content

Review candidates from configured local content

search_verify_live

Registered reviewed-build comparison

search_render_report

Private JSON/CSV/HTML report

MCP callers cannot supply arbitrary filesystem roots, API endpoints, SQL or shell commands. Importing files, registering manifests, changing profiles and creating manual protection entries are explicit CLI operations.

Import and backup

search-evidence import-json /private/collection-v2.json
search-evidence import-json /private/history-request-response.json
search-evidence import-csv /private/pages.csv --start 2026-01-01 --end 2026-01-28 \
  --observed-at 2026-02-01T00:00:00Z
search-evidence backup

Canonical CSV columns: url,clicks,impressions,position. Blank cells are unknown. The JSON importer accepts version-2 collections with a sources object and historical Google request/response tables. Property and capture timestamp must be explicit. See data semantics.

Backups use SQLite's online backup API and copy referenced compressed raw files. Restore to a new private directory, validate it, then select it in a separate profile. No existing operational state is replaced.

Development and scope

uv run pytest
uv run ruff check src tests
uv run ruff format --check src tests
uv build

See architecture, security, and validation.

Current boundaries:

  • GA4 imports retain raw responses and timezone/threshold metadata. A GA4 live collector, GA4-derived attribution, and cross-provider metric joins are not implemented.

  • Bing period comparison is intentionally unavailable because the recorded bucket semantics are insufficient for a comparable Google-style date window.

  • Internal Markdown targets are checked against a local build. External link crawling and proof of factual claims require separate editorial verification.

  • Content URL inference assumes posts/slug/, unless frontmatter supplies url. Custom permalink layouts should provide explicit URLs.

  • No scheduler, browser dashboard, publishing integration or automated deletions.

  • Verification does not establish robots.txt access, full rendered JavaScript behavior, deployed Git provenance, or what content Google/Bing currently indexed.

License

Apache-2.0. See LICENSE. Third-party dependencies retain their own licenses and notices as distributed by their packages.

Available Tools

10 tools
search_audit_contentC

Audit the configured content root; never edit its files.

Inputs: limit, cursor, audit_id. Returns: ok, data, error, warnings

search_collectC

Collect read-only Google/Bing reports into private local storage.

Inputs: end (required), start (required), daily, resume, +3 more. Returns: ok, data, error, warnings

search_compareC
Read-onlyIdempotent

Compare compatible equal-length Google periods.

Inputs: after (required), before (required), limit, cursor. Returns: ok, data, error, warnings

search_inspect_urlsC

Read indexed Google/Bing records and persist observations.

Inputs: urls (required). Returns: ok, data, error, warnings

search_prioritizeC
Read-onlyIdempotent

Prioritize audit findings while preserving protected URLs.

Inputs: audit_id (required), limit, cursor. Returns: ok, data, error, warnings

search_protect_urlsC
Read-onlyIdempotent

Show raw URLs protected by any historical positive clicks.

Inputs: urls, limit, cursor. Returns: ok, data, error, warnings

search_render_reportC

Write JSON, safe CSV and escaped HTML under private state.

Inputs: audit_id, verification_id. Returns: ok, data, error, warnings

search_statusC
Read-onlyIdempotent

Show local availability and optionally check account/property access.

Inputs: remote. Returns: ok, data, error, warnings

search_trafficC
Read-onlyIdempotent

Read one explicit snapshot; missing rows are unknown.

Inputs: url, limit, table, cursor, +2 more. Returns: ok, data, error, warnings

search_verify_liveC

Compare a registered reviewed build with public live HTML.

Inputs: limit, cursor, cache_check, manifest_id, +1 more. Returns: ok, data, error, warnings

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3/5.0

    Scored across 10 tools

    Disambiguation4/5

    Each tool targets a fairly distinct stage of an SEO evidence pipeline (collect, inspect, audit, compare, protect, prioritize, verify, report). The main soft overlap is among read-oriented tools like inspect_urls, traffic, and collect, but the descriptions differentiate indexed records vs a single snapshot vs bulk report collection.

    Naming Consistency4/5

    All tools share a consistent snake_case 'search_' namespace prefix, making the set easy to scan. A few second segments are bare nouns (status, traffic, collect) rather than strict verb_noun, a minor deviation.

    Tool Count5/5

    Ten tools is a well-scoped size for a read-only SEO evidence workflow, with each tool covering a distinct step. Nothing feels redundant or padded.

    Completeness4/5

    The surface covers collection, auditing, comparison, protection, prioritization, live verification, and reporting, which is broad for the domain. Minor gaps exist around configuration or account setup beyond the access check in search_status.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables local-first SEO evidence tooling by analyzing Screaming Frog exports, running bounded live and infrastructure checks, and producing structured audits, task backlogs, and reports via CLI and MCP.
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Enables agents to probe URLs and classify bot-wall responses with vendor and signal evidence, perform offline classification, scan for exposed key-like material, and run owner-side access audits through stdio tools.
      4
      98 npm
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Exposes Google Search Console's API as MCP tools for SEO analytics, including up to 25,000-row search analytics, regex filters, quick-win and cannibalization detection, period comparisons, sitemap/site management, and batch URL inspection, accessible over stdio, HTTP/SSE with bearer auth, or Cloudflare Workers.
      6,908 npm
      MIT