SiteWide MCP
Every marketing data source, one connector.
Что умеет
- Capabilities: What this connector can do, and what is already connected for YOUR token. Returns the tool catalogue grouped by data source (GA4, Search Console, Google Ads, Bing/Copilot, Ahrefs, the si
- Connect Site: Connect one of the user's own domains to this token, so the site-scoped tools (GA4, Search Console, the crawler, Ahrefs, Bing, Ads) can be used for it. Call this when list_sites or capab
- List Sites: List the sites configured for GA4/Search Console reporting (from sites.json), with their GA4 property IDs and GSC site identifiers.
Какие данные видит
Нужен ли аккаунт
Не нужен: сервер работает без входа
Every marketing data source, one connector. Connect AI agents to analytics, search rankings, ad spend, crawl health, backlinks, and site speed through 46 tools.
Как подключить
Как подключить SiteWide MCP к Claude
Адрес сервера, который нужно вставить в настройках Claude:
https://sitewide--a6bfvl.run.tools
- Откройте Claude (сайт claude.ai или приложение для компьютера).
- Перейдите в Настройки → Коннекторы (в английском интерфейсе: Settings → Connectors).
- Нажмите Добавить пользовательский коннектор (Add custom connector).
- Вставьте адрес сервера, скопированный ниже, в поле URL удалённого MCP-сервера и нажмите Добавить.
- В чате нажмите + → Коннекторы и включите новый коннектор.
Пользовательские коннекторы доступны на тарифах Free, Pro, Max, Team и Enterprise. На Free можно добавить только один. В Team и Enterprise коннектор сначала добавляет владелец организации в Настройки организации → Коннекторы.
Авторизация
После нажатия Добавить откроется окно входа в сервис. Войдите под своим аккаунтом и подтвердите доступ. Пароль Claude не видит.
Как подключить SiteWide MCP к ChatGPT
Адрес сервера, который нужно вставить в настройках ChatGPT:
https://sitewide--a6bfvl.run.tools
- Откройте ChatGPT в браузере (chatgpt.com). Нужен тариф Plus, Pro, Business, Enterprise или Edu.
- Один раз включите режим разработчика: Настройки → Приложения → Дополнительные настройки → Режим разработчика (Settings → Apps → Advanced settings → Developer mode).
- Откройте Настройки → Коннекторы и нажмите Создать (Create).
- Заполните форму: Название (любое), Описание (одна фраза, что делает сервис), URL MCP-сервера (скопируйте ниже).
- В поле Аутентификация выберите OAuth, если сервис требует вход, иначе Нет. Нажмите Создать.
- В новом чате откройте + → Приложения/Коннекторы и включите коннектор.
Название раздела у OpenAI менялось (Connectors → Apps/Plugins). Если пункт называется иначе, ищите «режим разработчика» в настройках. В рабочих пространствах Business/Enterprise администратор должен разрешить пользовательские коннекторы.
Авторизация
При первом использовании ChatGPT откроет окно входа в сервис. Войдите и подтвердите доступ.
Как подключить SiteWide MCP к Cursor
Адрес сервера, который нужно вставить в настройках Cursor:
https://sitewide--a6bfvl.run.tools
Быстрый способ: нажмите кнопку Открыть в Cursor ниже, Cursor сам предложит добавить сервер.
Вручную:
- В Cursor откройте Settings → Cursor Settings → MCP и нажмите Add new global MCP server.
- Вставьте JSON, скопированный ниже, в открывшийся файл
~/.cursor/mcp.json(для одного проекта:.cursor/mcp.jsonв корне проекта). - Сохраните файл. Сервер появится в списке MCP; при необходимости пройдите авторизацию по кнопке рядом с ним.
Авторизация
Если сервис требует вход, рядом с сервером в списке MCP появится кнопка авторизации.
Список инструментов сервера (46)
Технические названия из tools/list. Нужны только разработчикам.
| capabilities | What this connector can do, and what is already connected for YOUR token. Returns the tool catalogue grouped by data source (GA4, Search Console, Google Ads, Bing/Copilot, Ahrefs, the site crawler, speed & history), each tool tagged with the question it answers and its access tier — "included" (works now), "grant" (needs the Google service account added to your property) or "byo" (needs your own vendor API key) — plus which of your sites are connected, whether Ahrefs and Bing keys are attached, exactly what is still missing, and example questions worth asking. Call this FIRST when the user asks what this server can do, or when a tool errors with a setup message and you want to know what else is available. |
| connect_site | Connect one of the user's own domains to this token, so the site-scoped tools (GA4, Search Console, the crawler, Ahrefs, Bing, Ads) can be used for it. Call this when list_sites or capabilities shows no connected site, or when a tool says a domain is not on your plan. It attaches the domain ONLY if this server's Google service account can already read that domain's GA4 property or Search Console property — that grant is the proof of control, and it is needed for the GA4/GSC tools anyway — AND no other account on this server has already connected that domain: a domain belongs to one account, and the first to connect it keeps it. If verification fails, nothing is changed and the error names the exact service-account address to add and where. If the domain is not configured on this server at all, it says so: that is a deploy-time step for the operator, not something this tool can do. |
| list_sites | List the sites configured for GA4/Search Console reporting (from sites.json), with their GA4 property IDs and GSC site identifiers. |
| health_check | Diagnose the MCP setup: verifies the service-account key loads and a token exchanges, then checks GA4 and GSC API access for each configured site (or one site). Use to confirm a new site is wired up, or to diagnose permission/propagation issues. |
| ga4_report | Google Analytics 4 report for a configured site over a date range: active users, new users, RETURNING users, sessions, engaged sessions and engagement rate, avg engagement time per active user, sessions by default channel group (Organic Search, Direct, etc.), and top pages by views. Leads with a traffic_quality verdict (plausible | mixed | implausible) with named signals: automated traffic that GA4's always-on bot filtering does not catch shows up as sessions here, and on several properties in one sweep it read as growth. ALWAYS relay that verdict when quoting a session or user count. Counts are never filtered or adjusted — the verdict annotates them, so they still reconcile with the GA4 UI. Pass compare_start_date/compare_end_date to also get a prior-period comparison with deltas (week-over-week), which additionally carries a change_quality verdict (broad | concentrated | inconclusive): a headline decline that is really one spam-prone channel collapsing to near-zero is reported as concentrated, so a -42% that is junk STOPPING is not relayed as lost traffic. Pass include_ad_cost:true to also get Google Ads spend (cost, clicks, impressions, CPC) totals and top campaigns — free, no extra HTTP call. Pass cross_check_crux:true to corroborate the traffic_quality verdict against CrUX, which is the one signal here not derived from this same GA4 property. |
| ga4_tech | What browsers, operating systems and devices a configured site's visitors actually run — the dimensions ga4_report does not carry. Breakdowns: browser, browser_version, os, os_version, device, screen_resolution. Its real job is the SUPPORT-FLOOR question: pass min_versions (with breakdown browser_version or os_version) and it returns a baseline_support block saying what share of traffic falls BELOW that floor, which old versions they are, and a verdict (safe <0.5% | caution <2% | risky | inconclusive). Use it before shipping anything with a hard version cliff — oklch(), @property, color-mix(), :has(), container queries, Tailwind v4 (whose own floor is {"Chrome":111,"Edge":111,"Safari":"16.4","Firefox":128}). Two things to relay: every percentage is SESSION-based because GA4 de-duplicates activeUsers across dimension values so the users column does not sum to the property total; and if the tail was truncated the verdict is "inconclusive" and below-share is a floor, not a total — never round that up to "safe". |
| ga4_ad_cost | Google Ads spend for a configured site from GA4: total cost, ad clicks, impressions and cost-per-click, broken down by campaign (default) or by ad group, keyword, or search query. Optionally returns a per-day/week/month time series and a prior-period comparison. Use this for paid-media questions (what did we spend, which campaigns burned budget, what is CPC trending at); use ga4_report with include_ad_cost:true when you just want spend alongside traffic. |
| gsc_search_analytics | Google Search Console search analytics for a configured site over a date range: total clicks, impressions, CTR, average position, plus top queries and top pages. Supports search type, data freshness, dimension filters, and an optional prior-period comparison (week-over-week). |
| ga4_realtime | Google Analytics 4 REALTIME report for a configured site: active users on the site right now, plus a breakdown by a dimension (page/screen, country, city, device, platform). |
| gsc_inspect_url | Google Search Console URL Inspection for one URL on a configured site: index verdict, coverage state, indexing/robots/page-fetch state, last crawl time, Google vs user canonical, mobile usability and rich-results verdicts. |
| gsc_sitemaps | List sitemaps submitted for a configured site in Search Console: path, last submitted/downloaded, pending state, warnings/errors, and the submitted URL count per content type. It does NOT report indexation: Search Console's `indexed` field has been deprecated by Google for years and returns 0 for every property, so it is returned as `indexed_deprecated` with a note and must never be read as "N pages indexed". For indexation use gsc_inspect_url (coverage_state for one URL) or gsc_search_analytics (a page earning impressions is indexed). |
| pagespeed_report | Google PageSpeed Insights (Lighthouse) report for a single URL: CrUX real-world field data where it exists, a lab_vs_field verdict with an explicit act_on, then scores for all four Lighthouse categories (Performance, Accessibility, Best Practices, SEO) and lab Core Web Vitals (LCP, CLS, Total Blocking Time, First Contentful Paint, Speed Index). READ lab_vs_field FIRST: Lighthouse mobile applies simulated throttling and routinely reports LCP 4-10x worse than real Chrome users, so ranking pages or sites by the lab score comes out backwards. A null field_data_crux distinguishes "no data for this URL" from "no data for the origin" and points at crux_history. Works for ANY public URL — no GA4/GSC permission or site config needed. |
| crux_history | Real-world Core Web Vitals HISTORY from the Chrome UX Report: ~6 months of weekly p75 values for LCP, INP, CLS, FCP and TTFB, plus the good/needs-improvement/poor split and a trend verdict. Accepts up to 5 origins at once for competitor comparison, and returns a `comparison` block that ranks them per metric and names which are failing or regressing — that block is usually the whole answer. Defaults to detail:"summary" (verdict fields only, no weekly series) because the 5-origin call it advertises returns ~59 KB at full detail; pass detail:"full" only when you need the series to plot it or to find the week a regression started. This is real Chrome-user data — what Google actually ranks on — unlike the one-shot lab simulation from pagespeed_report. Needs NO permission and NO site config: works on any public origin with enough Chrome traffic. |
| cwv_compare | Mobile vs desktop Core Web Vitals for one URL, in a single call, already diffed. Returns BOTH form factors of the real-user CrUX field data AND the Lighthouse lab data, with the per-metric delta (LCP, INP, CLS, FCP, TTFB), which metric diverges most between the two devices, a plain statement of which device is worse and by how much, and the Core Web Vitals pass/fail assessment per device. Field (CrUX, real users, may be missing on low-traffic URLs) and lab (Lighthouse, synthetic, always available) are reported separately and never merged — if there is no CrUX data it says so instead of falling back to lab numbers. Use this instead of two pagespeed_report calls or two crux_history calls whenever the question is "is mobile worse than desktop, and where". Works for ANY public URL — no permission, no site config. |
| wayback_changes | When a page actually CHANGED, from the Internet Archive: dates on which the archived content differed from the previous capture, newest first, with an archive URL for each. Consecutive identical captures are collapsed, so this is a change log rather than a crawl log. Use it to find when a competitor repositioned, changed pricing, or rewrote a page. No key and no permission needed — works on any URL that has ever been archived. |
| wayback_snapshot | What a page SAID on a given date: title, meta description, og:title, canonical, H1s, word count and a text sample, read from one Internet Archive capture. Pair with wayback_changes — that gives you the timestamps, this reads them. The title and H1 alone usually answer "when did they change their positioning". |
| domain_rating | Ahrefs Domain Rating: backlink-profile strength for a domain, 0-100 on a logarithmic scale, compared to every other site in Ahrefs' index. Works for any public domain, including a competitor's — one number to sanity-check "are we actually a stronger site than them, or does it just feel that way". No customer permission needed. |
| site_audit_issues | Ahrefs Site Audit crawl issues for a configured site: health score, URL counts by severity, and the individual issues (name, category, importance, affected-URL count, new/resolved since the last crawl), sorted worst-first. This is a different question from pagespeed_report/crux_history — those measure ONE page's speed, this is a full-site crawl covering indexability, redirects, duplicates, broken links, and more. Requires the caller's own Ahrefs API key attached to their token (see AHREFS setup), and a Site Audit project already configured for the site — if either is missing, the error says which. |
| rank_tracker_overview | Ahrefs Rank Tracker keyword-level rankings for a configured site: position, week-over-week change, search volume, estimated traffic and SERP features for every tracked keyword. Requires the caller's own Ahrefs API key AND an existing Rank Tracker project for the site (create one with ahrefs_create_project, add keywords with ahrefs_add_keywords). |
| rank_tracker_serp_overview | Full SERP for ONE tracked keyword — every ranking URL with its position, title, Domain/URL Rating, backlinks and referring domains. Answers "who is actually beating me for this keyword, and how strong are they". Requires the caller's own Ahrefs API key and an existing Rank Tracker project. |
| rank_tracker_competitors | Competitive benchmarking across your tracked keyword set, from Ahrefs Rank Tracker. `view` picks the slice: "stats" (one summary row per competitor — traffic, share of voice, position distribution), "keywords" (competitor URLs per tracked keyword), "pages" (which competing pages are gaining/losing), or "domains" (which competing domains are gaining/losing). Requires the caller's own Ahrefs API key and an existing Rank Tracker project. |
| ahrefs_create_project | Create an Ahrefs Rank Tracker project for one of your configured sites — the first step of self-serve setup (follow with ahrefs_add_keywords). Uses the caller's own Ahrefs API key, so this creates the project in the CUSTOMER's own Ahrefs account, never Ale's. A no-op (returns the existing project) if one already exists for this site. |
| ahrefs_add_keywords | Add tracked keywords (optionally tagged) to an existing Ahrefs Rank Tracker project for one of your configured sites. Additive only — there is no delete-keywords tool, by design; use the Ahrefs UI directly if you want to remove tracked keywords. Uses the caller's own Ahrefs API key, so this only ever modifies the CUSTOMER's own account. |
| keywords_explorer_overview | Ahrefs Keywords Explorer metrics for keywords you're CONSIDERING — volume, difficulty, CPC, clicks and traffic potential. No configured site or existing project needed: any keyword, any account, including ones you don't rank for yet. Requires the caller's own Ahrefs API key. |
| keywords_explorer_ideas | Keyword ideas seeded from one keyword — content/topic research. `source` picks the angle: "related" (semantically adjacent terms top-ranking pages also rank for), "matching" (broader terms containing the seed), "questions" (matching terms phrased as questions — ready-made subheadings/FAQ content). Requires the caller's own Ahrefs API key. |
| site_explorer_metrics | Ahrefs Site Explorer domain-level summary for ANY public domain, including a competitor's: organic traffic, organic/paid keyword counts, estimated traffic value. Complements domain_rating (which measures backlink strength, not traffic). Requires the caller's own Ahrefs API key. |
| site_explorer_organic_keywords | Every keyword a domain already ranks for organically, sorted by estimated traffic — distinct from rank_tracker_overview (only reports on keywords you chose to track) and gsc_search_analytics (actual clicks on YOUR verified property only). Works for any public domain, so this doubles as "what is this competitor ranking for that I'm not". Requires the caller's own Ahrefs API key. |
| site_explorer_referring_domains | Every domain linking to a target, sorted by the linking domain's own strength — one level past the single domain_rating number, into who is actually doing the linking. Works for any public domain, including a competitor's. Requires the caller's own Ahrefs API key. |
| bing_search_performance | Bing Webmaster Tools search performance for a configured site: daily clicks, impressions, CTR and indexed-page counts, plus totals. Bing powers Copilot and part of ChatGPT's web results, so this is the visibility Search Console cannot show you. Requires the customer's own Bing Webmaster API key to be attached to their token. |
| bing_top_queries | Top Bing search queries for a configured site: clicks, impressions, CTR and average position per query. A query ranking here is a query that can be cited by Copilot. |
| bing_crawl_stats | Bing crawl and index health for a configured site: pages crawled, pages actually in the Bing index, crawl errors, robots.txt blocks, 404s, 5xxs, DNS failures and timeouts, as a daily series. Use this to diagnose why a site is missing from Copilot answers. |
| ads_account_summary | Google Ads account totals over a date range: spend, impressions, clicks, CTR, average CPC, conversions, conversion value, cost per conversion and ROAS, with the account currency and timezone. Read-only. This reads the Google Ads API directly, so unlike ga4_ad_cost it is not limited to what GA4 imported. |
| ads_campaigns | Google Ads campaigns with their daily budget, status, channel type and bid strategy, alongside spend and conversion performance for a date range, ordered by spend. Read-only. Answers "where is the budget going and which strategy is each campaign on". |
| ads_search_terms | The Google Ads SEARCH TERMS report: the literal queries users typed, with match type, campaign, ad group, spend and conversions — as opposed to the keywords being bid on. The highest-value read-only report in the API: terms with spend and zero conversions are negative-keyword candidates. Also returns total spend on non-converting terms. Read-only. |
| ads_keywords | Google Ads keyword performance with QUALITY SCORE and its three components (ad relevance, landing page experience, expected CTR), plus spend and conversions per keyword. Returns the average quality score and how much is being spent on keywords scoring 5 or below. Read-only. |
| site_health | START HERE for "how are my technicals / is my SEO setup healthy". Full technical-SEO health check for a configured site: runs robots.txt, sitemap, llms.txt and a bounded first-party crawl (default 50 pages), then returns a prioritized findings list — each with a severity (critical/warning/notice), a CONFIDENCE (confirmed/likely/hypothesis), the number of affected URLs, up to 5 examples and a concrete fix — plus a SERP preview showing how Google would truncate each title and description. Checks missing/duplicate/truncated titles and descriptions, missing or multiple H1s, noindex pages that are in the sitemap, canonicals pointing elsewhere, redirect chains, 4xx/5xx, thin content, missing alt text, missing schema, unrendered template tokens, the five security response headers (HSTS, CSP, X-Content-Type-Options, Referrer-Policy, X-Frame-Options), and image attributes (explicit width/height, loading, modern vs legacy formats). Deliberately reports NO single 0-100 score, and confidence is not a score either. ALWAYS relay the confidence with the finding: `hypothesis` means the observation may just be an artifact of not running JavaScript, so say "the server HTML does not contain X" rather than "X is missing". The response carries a confidence_legend explaining all three levels. By default reads server HTML only — no JavaScript is executed, so client-rendered (Framer/React/Next-CSR) sites will under-report; the response says so. Set render:true to additionally re-fetch the suspicious pages through a real headless browser and get a CSR-delta report: which titles, descriptions, H1s, canonicals and JSON-LD exist ONLY after hydration, and therefore are invisible to GPTBot, PerplexityBot, ClaudeBot and any first-pass crawler. Rendering also settles the confidence: a check that would be `hypothesis` on a framework-hinted page is reported as `confirmed` once that page has actually been rendered. |
| crawl_site | Crawl up to 100 pages of a configured site and return a row per page: final status, the full redirect chain (naming the URLs in the cycle when it loops back on itself), title and its character count, meta description, canonical (and whether it is self-referencing), H1s, the heading outline as levels (heading_levels, e.g. [1,2,2,3]) plus any skipped level, meta-robots AND X-Robots-Tag directives, hreflang, word count, JSON-LD @type list, internal vs external link counts, any unrendered template tokens, the five security response headers read off the same response (HSTS, CSP, X-Content-Type-Options, Referrer-Policy, X-Frame-Options — null means NOT CHECKED, never "none set"), per-page image counts broken down by missing alt, loading=lazy/eager/absent, explicit width+height, and file-format bucket (raster / modern / svg / unknown_extension / inside_picture), and a framework_hint naming any client-side framework marker found in the HTML. Seeds from the sitemap, or crawls breadth-first from the homepage when there is none. Obeys robots.txt. 100 pages is a hard cap and a truncated crawl always says so. Use site_health instead if you want findings rather than raw rows. By default reads server HTML only — no JavaScript is executed, so a non-null framework_hint means missing titles/H1s/copy on that page may simply be injected by JavaScript. Set render:true to re-fetch pages through a headless browser; each rendered row then carries a csr_delta showing what only exists after hydration, which turns that framework_hint from a guess into a measurement. |
| robots_txt | Read and audit a configured site's robots.txt: every user-agent group with its allow/disallow rules and crawl-delay, the declared Sitemap: URLs, and specifically whether Googlebot, Bingbot, GPTBot, ClaudeBot and PerplexityBot are blocked. Flags the expensive footguns — a blanket "Disallow: /", rules that also block CSS/JS/image paths Google needs to render the page, and a missing sitemap declaration. |
| sitemap_audit | Audit a configured site's XML sitemaps, discovered from robots.txt and /sitemap.xml. Follows sitemap INDEX files one level deep (max 10 documents fetched). Reports total and per-sitemap URL counts, lastmod freshness including how many are stale by more than 12 months, malformed entries, URLs pointing off-host, whether any sitemap exceeds the 50,000-URL or 50MB limits, and the HTTP status of a small SAMPLE of listed URLs (it does not fetch them all — use crawl_site for that). |
| llms_txt | Fetch a configured site's /llms.txt and validate it against the llmstxt.org spec: a single H1 on the first line, an optional blockquote summary, then H2 sections containing markdown link lists. Reports each violation with its line number and what is wrong, lists the sections and their link counts, and notes whether /llms-full.txt also exists. |
| wp_preflight | RUN THIS FIRST for anything WordPress. Checks the connection to a configured site's WordPress end to end and names exactly what is missing: is the REST API reachable (including the /?rest_route= fallback when permalinks are Plain), do the Application Password credentials authenticate, may that user edit posts, is Rank Math or Yoast installed, and — the big one — is the SEO meta actually EXPOSED to the REST API. Rank Math hides its meta from REST by default and Yoast's keys are protected meta, so a stock install of either reads as "nothing there"; this tool says so and gives the exact plugin or register_post_meta() snippet that fixes it. Also detects security plugins (Wordfence/Sucuri) that 403 authenticated REST calls before WordPress sees them, and page/object caches that will serve a stale value back after a write. Reports ready_to_read and ready_to_write, both derived from the individual checks. |
| wp_list_content | List a configured site's WordPress posts or pages with their SEO metadata: the SEO title and meta description (with character counts and whether Google will truncate them), canonical, focus keyword, status, last-modified date and public URL — plus which fields are actually writable on this install. Reads Rank Math meta, Yoast meta, or (when Yoast's protected meta is not exposed) Yoast's computed yoast_head_json, and says which of the three each value came from, because a computed value is what the site currently outputs rather than a stored setting you can change. Paginated (X-WP-Total/X-WP-TotalPages are reported). Pass issues_only:true for just the items missing a title or description. Never returns post content. |
| wp_get_content | Full SEO detail for ONE WordPress post or page: every SEO field with its stored value, its meta key, its source and whether it is writable; the post title, status, URL and last-modified date; the body WORD COUNT and how many images in the body are missing alt text; and the attached media items with their alt text, which is where alt text is actually fixed. Deliberately does not return the post body — this connector reads and writes metadata only. |
| wp_propose_fixes | STEP 1 OF 2, AND IT CHANGES NOTHING. Takes the SEO metadata edits you want to make and returns exactly what WOULD change — every before and after, the meta key each one lands in, warnings (SERP truncation, an empty value clearing a field), and a proposal_id. Show the user the before/after, then call wp_apply_fixes with the id. Apply takes IDS ONLY, so nothing can be written that was not first shown here. Editable fields (title, meta_description, canonical, focus_keyword, og_title, og_description, schema_type, alt_text) are an allowlist: post content cannot be changed by this connector at all. Up to 25 changes per proposal. Each change is also SAFETY-GATED against the page it came from: if the live page carries a client-side framework marker, the value being "fixed" may simply be injected by JavaScript that a server-HTML read never runs, so the change is BLOCKED until the page has been render-verified — pass render:true to render it and settle the question. Every change carries a confidence (confirmed = rendered and measured, likely = server HTML read cleanly with no framework marker). Works even when writes are not enabled for the site, so you can always see what would happen. |
| wp_apply_fixes | STEP 2 OF 2: apply a proposal from wp_propose_fixes. Takes the proposal_id (and optionally a subset of its change ids) — never values, so it can only ever write what the proposal already showed. Refuses: any change the safety gate blocked, any change whose live value has moved on since the proposal was created (that guard is what stops it overwriting an edit nobody reviewed), and every change on a site whose writes have not been explicitly opted in. Records the previous value of every write BEFORE making it, so wp_revert_fixes can restore it, and returns the apply_id that undoes this batch. Each write is verified by reading it back; a write WordPress accepted but that reads back stale is reported as unverified with the cache explanation, never as success. |
| wp_revert_fixes | UNDO. Restores the values replaced by a previous wp_apply_fixes, from the undo log recorded at write time. Called with NO apply_id it lists the write history for this site instead — every batch, when, how many changes, and whether it has already been reverted — so the undo log is discoverable rather than something you needed to keep an id for. A revert is itself a write: it is verified by reading back and recorded in the audit log too. |