On this page
Site knowledge
Last updated
Query your indexed website through MCP — semantic search over pages and uploaded references, full page reads, sitemap browse, change history and impact attribution, structured element inventory, business context, and VQL over site_pages, site_knowledge_chunks, site_page_elements, and site_page_versions.
Site knowledge exposes your customer website corpus to MCP agents — product copy, pricing, docs, policies, in-app UI text indexed from HTTP crawl and session recordings, plus operator-uploaded references (briefs, PDFs, markdown). It is separate from vTilt platform docs (search_docs) and separate from per-visitor replay transcripts (recording_summaries).
The site-knowledge toolset appears automatically when site knowledge is enabled on your pinned project. Enable it under Project → Site Knowledge if the tools are missing from get_context. No enable_toolset step is required once the feature is on.
#How it works
Three capture sources feed one index:
- HTTP crawl — public, externally reachable pages.
- Session-recording DOM — pages reconstructed from session recordings, covering auth-gated / internal pages the crawler can't reach.
- Operator references — uploaded
.txt/.md/ text-layer.pdffiles indexed through the same chunker.
Each capture is cleaned to markdown, chunked, embedded, and stored. The storage is split into three families:
- Latest / serving (
site_pages,site_knowledge_chunks,site_page_elements,site_overview) — the current state of each page plus reference chunks. Embeddings + the vector index live here, so semantic search always runs against current content. (site_page_chunksis accepted as a VQL alias forsite_knowledge_chunks.) - History / append-on-change (
site_page_versions,site_page_version_chunks) — one row per detected page change, text-only (no embeddings). Powers change history and change→impact attribution. - Extension (brand profile, mirrored media) — populated during crawl. Event snapshots remain planned.
Dual change signal: a new page version is captured when either content_hash (page text) or elements_hash (the ordered CTA/link/nav fingerprint, by document order + above-fold) changes — so a layout move like "the CTA moved above the fold" is detected even when the copy is identical. site_page_versions.change_kind records which fired (created / content / layout / both).
#The tools
| Tool | Use when |
|---|---|
get_site_overview | You need a high-level company/site synopsis before diving into pages |
list_site_pages | You want to browse the indexed sitemap, search pathnames, or sort by freshness |
list_site_references | You want to browse operator-uploaded references (briefs, PDFs, notes) |
get_site_reference | You need the extracted text of one uploaded reference |
get_site_page | You need the full content + metadata + desktop/mobile screenshot URLs of one pathname or URL |
get_site_page_screenshots | You must see the page (layout/CTA/hero) — returns MCP image pixels for agent vision (viewport desktop|mobile) |
list_page_versions | You want a page's change timeline with human change_summary diffs |
get_page_version | You want one historical version's content, CTA fingerprint, and desktop/mobile screenshots |
diff_page_versions | You want a structured before/after diff (sections + CTAs) between two version ids |
search_site_knowledge | You have a semantic question and want ranked chunks with citations (pages and/or references) |
get_site_brand_profile | You need logo, palette, typography, and OG imagery for on-brand output (theme_color is browser chrome, not brand primary) |
list_site_page_media | You need mirrored image inventory for a page |
correlate_page_change_impact | You want before/after metric rates around a page change (automated attribution) |
get_event_page_context | You need HTML/markdown for what a visitor saw at a session timestamp |
get_site_elements | You want the raw CTA/link/form inventory (CRO audit, funnel-gap, enrichment) |
get_site_business_context | You want the operator-provided settings text (project description + business instructions) |
run_site_cro_audit | You want automated meta/OG/CTA/link findings across indexed pages |
detect_funnel_instrumentation_gaps | Crawled CTAs/forms with no matching $autocapture clicks in the window |
diagnose_funnel_dropoff | Ordered funnel steps with step rates plus page-aware drop-off diagnosis |
suggest_ad_creative | Meta-style headline/primary-text variants from landing pages + brand profile |
check_landing_ad_consistency | Compare Meta ad copy (or manual text) to the destination landing page |
All require analytics:read and site knowledge enabled on the project. Check get_context.features.site_knowledge.
#get_site_overview
Returns the LLM-generated project synopsis, taxonomy JSON, indexed page count, and last update time. Call this first when orienting on an unfamiliar project.
{
"synopsis": "B2B analytics platform focused on privacy-first web tracking…",
"taxonomy_json": "{\"product_areas\":[…],\"audiences\":[…]}",
"page_count": 47,
"updated_at": "2026-06-24T04:12:00Z"
}#list_site_pages
Paginated sitemap with crawl metadata.
| Input | Description |
|---|---|
skip / limit | Pagination (default limit applies) |
auth_gated | Filter pages indexed only via recording fallback |
source | http, recording, or hybrid |
search | Case-insensitive substring match on pathname |
order | last_seen_desc (default), last_seen_asc (stalest first — site health), last_changed_desc |
Returns page_type, version_count, last_changed_at, and last_seen_at per row alongside the title and summary.
Not for: top pages by traffic — use get_kpis or run_query on events.
#get_site_page
Full page metadata plus every content chunk. Provide pathname (e.g. /pricing) or url.
{
"page": {
"url": "https://www.example.com/pricing",
"pathname": "/pricing",
"title": "Pricing",
"source": "hybrid",
"auth_gated": false,
"summary": "Three-tier SaaS pricing with annual billing…",
"meta_description": "…",
"og_title": "Pricing",
"og_image_url": "https://www.example.com/og/pricing.png",
"json_ld_types": ["Product", "Offer"],
"canonical_url": "https://www.example.com/pricing",
"lang": "en",
"page_type": "marketing",
"http_status": 200,
"chunk_count": 6,
"version_count": 4,
"last_changed_at": "2026-06-21T09:00:00Z",
"last_seen_at": "2026-06-24T04:12:00Z",
"screenshot_desktop_url": "https://…signed…/pricing-desktop.png",
"screenshot_mobile_url": "https://…signed…/pricing-mobile.png"
},
"chunks": [
{
"chunk_index": 0,
"chunk_kind": "pricing",
"heading_path": "Pricing > Plans",
"content": "## Plans\n\nStarter includes…"
}
]
}screenshot_desktop_url and screenshot_mobile_url are Class B workspace-authenticated URLs for humans to open in a browser (null when that viewport was not captured). Legacy screenshot_url aliases the desktop URL when present. Do not HTTP-fetch these URLs from agent egress (Claude.ai blocks external hosts) — call get_site_page_screenshots for vision pixels. Returns resource_not_found when the pathname was never indexed — try list_site_pages or trigger a re-crawl in the dashboard.
#get_site_page_screenshots
Opt-in agent vision for one crawl screenshot. Pass pathname and viewport (desktop | mobile, default desktop). Optional version_id for a historical shot.
Returns:
- JSON metadata (
pathname,viewport,tile_count, Class Burlfor humans,images[]with tile dimensions) - MCP image content blocks (WebP base64) — the full page, width-scaled ≤1568px and auto-split into up to 6 vertical tiles when tall
Use this when you must see layout / CTAs. Use get_site_page for copy and SEO without loading pixels into context. Tiling improves fidelity; it does not remove host payload/session limits.
#search_site_knowledge
Semantic search over chunk embeddings across crawled pages and uploaded references.
| Input | Description |
|---|---|
query | Natural-language question (2–500 chars) |
source | Optional: page or reference (omit to search both) |
pathname | Optional filter for crawled pages, e.g. /docs |
chunk_kind | Optional filter: body, pricing, faq, form, … |
limit | Max chunks (default 5, max 20) |
{
"results": [
{
"source": "page",
"reference_id": null,
"url": "https://www.example.com/pricing",
"pathname": "/pricing",
"title": "Pricing",
"heading_path": "Pricing > Plans",
"chunk_kind": "pricing",
"content": "Starter includes…",
"distance": 0.12
}
]
}#list_site_references / get_site_reference
Browse and read operator-uploaded references (.txt / .md / text-layer .pdf). list_site_references returns id, title, filename, status, and chunk counts. get_site_reference takes reference_id and returns metadata plus extracted content when ready.
Not for: short project description / business instructions in settings — use get_site_business_context.
Lower distance = closer semantic match (cosine distance).
#get_site_brand_profile
Resolved brand kit for on-brand creative (emails, ads, reports). No inputs beyond project scope.
| Field | Meaning |
|---|---|
primary_color | Brand identity hex — never from browser theme-color |
secondary_color | Supporting ink/support hex |
accent_color | CTA/accent hex (may equal primary) |
background_color | Page surface / paper hex |
theme_color | Browser chrome summary only — not brand identity |
theme_colors | Light/dark/default meta theme-color map (chrome provenance) |
css_color_vars | Resolved semantic CSS tokens (brand, accent, ink, …) |
color_sources | Role → source label (e.g. primary → css_var:--color-brand) |
palette | Ordered chromatic hexes for the kit |
heading_font / body_font / font_families | Typography |
logo_url / favicon_url / og_image_url | Stored asset URLs (often s3://) |
signed / public | Fetchable asset URLs (prefer these when downloading) |
color_confidence | high | medium | low |
provenance_json | Engine "v1" extraction metadata JSON — not a second kit (holds theme/css_vars/sources/ai) |
#list_page_versions
The change timeline for one page. Provide pathname (required) and optional limit (default 20, max 50). Returns captured versions newest-first with change_kind, human-readable change_summary, content_hash + elements_hash, cta_fingerprint_count, chunk_count, and signed screenshot_desktop_url + screenshot_mobile_url — no chunk text.
#get_page_version
One historical version's full content, CTA fingerprint, and desktop/mobile screenshots. Provide pathname and version_id (both required; get version_id from list_page_versions). Use for restore or "what did the hero say before the change".
#diff_page_versions
Structured before/after between two version ids without pulling full chunk text twice. Provide pathname, version_id_a, and version_id_b. Returns summary, cta_changes[], section_changes[], inferred_change_kind, and both versions' screenshot pairs.
#correlate_page_change_impact
Automated change→impact attribution — compare a metric before vs after a page version's captured_at without hand-rolling VQL.
| Input | Description |
|---|---|
pathname | Required — page to attribute (e.g. /workshops/teen-startup) |
metric_event | Required — event to count (e.g. signup_completed, $autocapture) |
denominator_event | Optional — rate denominator on the same pathname (default $pageview) |
window_days | Optional — symmetric days before/after the change (default 7, max 90) |
version_id | Optional — anchor version; default is the latest non-initial change |
Returns before / after counts and rates, rate_change_percent, the version's change_summary, and a one-line insight narrative (e.g. "signup_completed rate rose 32% after the hero CTA moved…").
Tip: list_recent_events and run_query also add properties.$site_element_label on $autocapture rows when the crawl index resolves a human button/CTA label.
#get_site_elements
Raw structured element inventory for one page — CTAs, links, forms, buttons, nav, headings, images in document order.
| Input | Description |
|---|---|
pathname | Required |
kind | Optional: cta, link, form, button, nav, image, input, heading |
contains | Case-insensitive substring over element text + selector (semantic-enrichment lookups) |
limit | Max elements (default 200, max 500) |
Returns text, href, tag, role, selector, elements_chain, document_order, above_fold, and link health per element. Use it for CRO audits (missing/weak CTA), funnel-gap detection (compare against tracked $autocapture events), and turning a clicked selector / $elements_chain into its human label.
#get_site_business_context
The operator-provided tier-0 business context — short text from project settings (project description + business instructions), as opposed to crawled pages or uploaded reference files. Returns project_description and business_instructions. Use for onboarding, grounding, and on-brand outbound.
Not for: uploaded PDF/md briefs — use list_site_references / get_site_reference / search_site_knowledge with source=reference.
#VQL tables
Site knowledge tables use the same :embed('text') macro as AI memory when site knowledge is enabled. See AI intelligence for macro rules and error codes.
| Table | What it holds | Permission |
|---|---|---|
site_knowledge_chunks | Latest markdown chunks from pages + references — source, source_id, heading_path, chunk_kind, 1536-d embedding | analytics:read |
site_pages | One row per pathname — title, summary, auth_gated, source, content_hash, elements_hash, embedding | analytics:read |
site_page_elements | Structured CTAs/links/forms/nav — kind, text, href, selector, elements_chain, document_order | analytics:read |
site_page_versions | Append-on-change history — version_id, captured_at, change_kind, cta_fingerprint_json (no embedding) | analytics:read |
site_overview | Project synopsis + taxonomy JSON | analytics:read |
site_page_chunks is accepted as a VQL alias and rewritten to site_knowledge_chunks.
Every table is tenant-scoped — do not add project_id to your WHERE clause.
Change detection → impact attribution: site_page_versions gets one row each time a page's text (content_hash) or layout (elements_hash) changes. Join captured_at against events.timestamp to correlate a site change with a metric shift (e.g. a conversion lift after a CTA moved). site_page_elements inventories the interactive elements on each page for CRO audits and funnel-gap checks.
#Example: semantic search with a source filter
SELECT
source,
source_id,
heading_path,
chunk_kind,
content,
cosineDistance(embedding, :embed('enterprise SSO pricing')) AS distance
FROM site_knowledge_chunks
WHERE source = 'page' AND source_id = '/pricing'
ORDER BY distance ASC
LIMIT 10#Example: join page content with session behavior
Combine indexed copy with AI memory when analyzing whether visitors read pricing before converting:
SELECT
s.session_id,
s.narrative,
JSONExtractString(s.ai, 'pages_visited') AS pages,
r.engagement_score,
r.behavior_pattern
FROM session_summaries s
JOIN recording_summaries r ON r.session_id = s.session_id
WHERE s.started_at > now() - INTERVAL 7 DAY
AND has(JSONExtractArrayRaw(s.ai, 'pages_visited'), '"/pricing"')
ORDER BY s.started_at DESC
LIMIT 25For section-level "what did they read on pricing?", query recording_chunks instead — see AI intelligence.
#When to use which surface
| You want to… | Best surface |
|---|---|
Answer "what does /pricing say about enterprise?" | search_site_knowledge or get_site_page |
| Browse what pages are indexed | list_site_pages |
| See what changed on a page, and when | list_page_versions (+ diff_page_versions or get_page_version) |
| Attribute a metric shift to a site change | correlate_page_change_impact (or list_page_versions + run_query for custom joins) |
| Audit CTAs / forms, or find a funnel-gap | get_site_elements + run_query on events $autocapture |
| Orient on the company/product quickly | get_site_overview (+ get_site_business_context) |
| Combine semantic page search with SQL filters | run_query on site_knowledge_chunks with :embed() |
| What one visitor actually read in a session | recording_summaries / recording_chunks — not site knowledge |
| vTilt SDK or MCP setup docs | search_docs — not site knowledge |
| Top landing pages by traffic | get_kpis or run_query on events — not list_site_pages |
#Example agent prompts
| Prompt | Tools |
|---|---|
| "What does our pricing page say about annual billing?" | get_site_page with pathname /pricing |
| "Find every page that mentions GDPR or data retention." | search_site_knowledge |
| "Which indexed pages came from session recordings only?" | list_site_pages with source: recording |
| "Summarise our product for a cold outreach email." | get_site_overview + get_site_business_context |
| "Did conversion rate change after we updated pricing?" | correlate_page_change_impact with your conversion event name |
| "What did our hero CTA say before the June redesign?" | list_page_versions → diff_page_versions / get_page_version |
| "Is there a form on /pricing with no submission event?" | get_site_elements (kind: form) + run_query on events $autocapture |
| "Compare our landing page promise with this Google Ads headline." | get_site_page + Google Ads tools |
#Cost model
| Component | Cost |
|---|---|
search_site_knowledge | One query embedding + ClickHouse vector search |
get_site_page / list_site_pages / get_site_overview / list_page_versions / get_page_version / get_site_elements / get_site_business_context | ClickHouse (or Postgres, for business context) reads only; screenshot URLs are signed on read |
VQL with :embed('text') | One embedding API call per distinct literal (see AI intelligence) |
| Background crawl | Runs on vTilt infrastructure; embedding cost on index updates only when content changes |
#Related
- Site knowledge (guide) — crawl pipeline, sources, dashboard, prerequisites
- Agent skills — the
/vtilt:site-knowledgeslash-command prompt (full architecture + query patterns) - AI intelligence — AI memory, recording summaries,
:embed()macro - MCP server overview — authentication, toolsets, and full tool catalog