Skip to main content
Glama
clamp-sh

Clamp Analytics MCP Server

Official

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
CLAMP_API_KEYYesProject API key (starts with 'sk_proj...'). Get it from the Clamp dashboard under Settings > API Keys.

Capabilities

Features and capabilities supported by this server

CapabilityDetails
tools
{
  "listChanged": true
}
prompts
{
  "listChanged": true
}

Tools

Functions exposed to the LLM to take actions

NameDescription
projects.list

List all Clamp projects this credential can access. Returns each project's id, name, and plan ('free', 'pro', or 'growth'). Use this when the user asks "which sites do you see" or when the agent needs a project_id to disambiguate before calling another tool — most other tools auto-resolve when the credential has access to exactly one project, so explicit calls are only needed for multi-project setups.

Examples:

  • "which sites are tracked" → projects.list

  • before drilling into a specific project's data when several exist

Limitations: returns an empty array if the credential is org-scoped but has no projects yet. The plan field is the current billing plan, not a permission level.

traffic.overview

High-level snapshot of website traffic over a period: total pageviews, unique visitors, sessions, bounce rate (%), and average session duration (seconds). Always includes a comparison block with the same metrics for the previous period of equal length plus the absolute and percentage delta. Use this as the first call when the user asks how the site is doing, before drilling into channels, pages, or funnels.

Examples:

  • "how is traffic this week" → period="7d"

  • "overview for last month" → period="30d"

  • "organic search performance this quarter" → period="90d", channel="organic_search"

Limitations: bounce_rate and avg_duration are derived from the SDK's pageview_end beacon — for SDK <0.3 they return null. Custom date ranges must be in YYYY-MM-DD:YYYY-MM-DD format. Maximum range is 365 days.

events.list

Get custom event counts. Without a name filter, returns every event name in the period with its total count and unique-visitor count (excludes "pageview" and the SDK-internal "pageview_end"). With a name filter, returns the count for that single event, optionally filtered by a custom property key/value pair and grouped by another property key. Custom events are tracked client-side via clamp.track("event_name", { key: "value" }) or server-side via @clamp-sh/analytics/server.

Property values can be strings, numbers, or booleans (each stored in a separate column). When filtering or grouping by a numeric or boolean property, set value_type / group_by_type so the lookup hits the right column — otherwise the default ("string") will silently miss native number/boolean data. Use the project's event-schema.yaml to know each property's type.

Examples:

  • "what events are being tracked" → no params (lists all event names)

  • "how many signups this week" → name="signup", period="7d"

  • "signups grouped by plan" → name="signup", group_by="plan"

  • "paid signups only" → name="signup", property="plan", value="pro"

  • "checkouts where item count was 5" → name="checkout", property="count", value="5", value_type="number"

  • "events grouped by a numeric tier_id" → name="upgrade", group_by="tier_id", group_by_type="number"

Limitations: only one property/value pair per call. group_by only works when a name filter is set. Returns at most limit rows per group (default 10, max 50). For revenue use revenue.sum, which understands the Money type.

events.observed_schema

Return what's actually firing into ingest as a structured signature, for diffing against the project's authored event-schema.yaml. Different shape from the YAML — this is observation, not declaration.

Response shape:

{
  period: "30d",
  events: [
    { name: "checkout", count: 42,
      properties: {
        plan:  [{ type: "string", occurrences: 42 }],
        count: [{ type: "number", occurrences: 39 },
                { type: "string", occurrences: 3 }]   // ← drift!
      }}
  ]
}

Each property value is an array of typed observations. One entry = the key consistently fired with one type. Two-plus entries = same key fired under multiple storage columns in the period, which is exactly the silent-type-drift signal you want to surface (one call site sending count: 5, another sending count: "5").

Use it to compare declared vs reality:

  • Events declared, missing here → dead instrumentation

  • Events here, not declared → unauthored events firing

  • Properties on a declared event missing from the schema → silent property drift

  • properties[key].length > 1 → type-column collision; one of the call sites is sending the wrong type

Examples:

  • "what events are firing in production" → no params (defaults to 30d, excludes pageview/pageview_end)

  • "did the spec drift this week" → period="7d"

  • "include automatic pageview events too" → include_pageviews=true

Limitations: returns keys + types only, no property values. occurrences is row-level (each event firing counts), not unique visitors. Excludes pageview and pageview_end by default since the SDK extension owns their schema.

Pairs with: events.list for per-event volume context (this tool also returns count, but events.list supports filters and grouping); the local event-schema.yaml for declared-vs-observed diff.

revenue.sum

Sum revenue from Money-typed event properties. Returns per-currency totals, optionally grouped by a traffic dimension (referrer_host, channel, country, device_type, pathname, utm_source/medium/campaign). Different currencies are never mixed in a single sum — each row is one (group, currency) pair. Money properties are tracked via clamp.track("purchase", { total: { amount: 29, currency: "USD" } }) — see /docs/concepts/revenue for the full Money type.

Attribution: attribution_model="last_touch" (default) groups revenue by the dimensions of the session where the revenue event fired — answers "what surface was active at conversion?". attribution_model="first_touch" joins each revenue event with the visitor's earliest-known session and groups by that session's acquisition dimension — answers "where did my paying customers actually come from?". For multi-visit funnels (typical B2B SaaS), first-touch is usually the more honest read on which channels actually drive revenue.

Examples:

  • "total revenue this month" → no group_by, period="30d"

  • "revenue by channel" → group_by="channel", period="30d"

  • "where did paying customers actually come from" → group_by="channel", attribution_model="first_touch"

  • "first-touch revenue per UTM campaign" → group_by="utm_campaign", attribution_model="first_touch"

  • "how much did Stripe purchases bring in from organic search" → event="purchase", channel="organic_search"

  • "top revenue countries" → group_by="country"

Limitations: events without any Money property contribute zero. If property is set, only that one Money key is summed; omitted, every Money property on matched events is included. Stripe-typed revenue (recommended) flows through server-side webhooks; client-only revenue is subject to ad-blocker loss. attribution_model="first_touch" only supports acquisition-dimension group_by (channel, referrer_host, utm_*); first-touch country / device / pathname are rejected because they're rarely what people actually mean by them. First-touch breakdowns are extremely sensitive to small samples — at single-digit paying-customer counts the per-channel rate is dominated by 1-2 users' acquisition history; check visitors before reading the rate, or pair with users.journey to validate against specific customers.

users.journey

Chronological session history for a single visitor (anonymous_id). Each session collapses to one row showing the start and end timestamps, entry page, channel, referrer host, UTMs, country, device type, pageview count, and the distinct custom event names fired in that session. The first row is flagged with is_first_touch: true.

Use this when an aggregate query can't answer the question — multi-touch attribution analysis, support / debugging investigations ("what did this user do before signing up?"), or sanity-checking a specific account's journey before drawing conclusions about a cohort.

Examples:

  • "show me what this user did across all their visits" → anonymous_id="anon_xxx"

  • "where did this paying customer first come from?" → anonymous_id="anon_xxx", read sessions[0].channel

  • "did they convert on their first visit or come back later?" → check if signup-event sessions match is_first_touch=true

Limitations: requires the visitor's anonymous_id, which the SDK exposes via getAnonymousId() on the browser side. Aggregate questions ("which channels drive my best users") use revenue.sum with attribution_model="first_touch" — don't loop this tool over thousands of users. Defaults to a 365-day lookback so first-touch is meaningful; tighten with period if needed.

Pairs with: revenue.sum(attribution_model="first_touch") to validate the aggregate first-touch read against specific high-value customers' actual paths.

errors.list

Recent error events with full context. One row per occurrence, returned newest-first. Each row carries the error itself (message, type, stack, fingerprint, handled flag) plus the standard event context (url, browser/OS/device, country, anonymous_id, session_id) — same shape ingest enriches every other event with, so an agent can correlate "errors here, traffic there" without joining a second tool.

Errors are written to the events table with name = "$error" by the SDKs' captureError() / window.onerror auto-capture. The server adds a stable error.fingerprint at ingest (sha256 of normalized message + first stack frame), so the same bug groups across occurrences regardless of which session or SDK reported it.

Examples:

  • "what errors fired today" → period="today" (no other filters)

  • "show me all TypeError occurrences this week" → message="", or use errors.groups first to find the fingerprint

  • "errors on Safari only" → browser="Safari"

  • "errors on the same fingerprint" → fingerprint=""

  • "only the auto-captured ones, not manual reports" → handled="false"

Limitations: returns up to limit rows (default 50, max 200). Stacks are stored verbatim from the SDK with no source-map resolution — production stacks will be minified for users on a build pipeline. For aggregate counts and dedup, use errors.groups; for breadcrumbs leading to one error, use errors.context.

Pairs with: errors.groups (find a noisy fingerprint, then list its occurrences here); errors.context (drill from one error row into the events from the same session that led to it); users.journey (full multi-session view of a user who hit an error).

errors.groups

Errors deduplicated by server-computed fingerprint, with counts and first/last-seen timestamps. The triage view: which bugs are firing most often, affecting the most users, or showing up newly in the period.

Each group is one fingerprint (a bug). count is total occurrences in the period; users_affected is unique anonymous_ids that hit it; first_seen and last_seen show the time window the bug appeared in. sample_message and sample_type are pulled from one occurrence in the group — useful for the agent to surface a readable label.

Examples:

  • "what's broken right now" → period="today", sort_by="count"

  • "regressions that started this week" → period="7d", sort_by="first_seen"

  • "bugs hitting the most users" → sort_by="users_affected"

  • "what just stopped firing" → check last_seen against expected freshness

Limitations: only fingerprintable errors are grouped; events with neither message nor stack get a null fingerprint and are excluded from this view (they still show up in errors.list). Default sort is by count; pass sort_by to change. Default limit 50, max 200.

Pairs with: errors.list (drill into a fingerprint to see individual occurrences with full context); errors.timeline (chart the rate of one fingerprint to spot regressions or post-deploy regressions); traffic.compare (correlate a count spike with a deploy or campaign).

errors.timeline

Error count over time, bucketed hourly or daily. Optionally scoped to one fingerprint. Use this to spot regressions ("when did this bug start firing?") or post-deploy spikes ("did the deploy at 14:00 break something?").

Returns a series of { bucket, count } rows. The bucket field is an ISO timestamp aligned to the start of the interval. Buckets with no errors are omitted (sparse series); the agent should treat missing buckets as zero.

Examples:

  • "error rate over the last week" → period="7d" (returns hourly buckets)

  • "did errors spike after yesterday's deploy" → period="2d", interval="hour"

  • "is this specific fingerprint getting worse" → fingerprint="", period="30d"

  • "yearly error trend" → period="365d", interval="day"

Limitations: interval defaults to "hour" for periods ≤ 7 days, "day" otherwise. Override only if the default produces too few or too many buckets for the question. No fingerprint filter returns the total error rate across all bugs.

Pairs with: errors.groups (find which fingerprint is worth charting); traffic.timeseries (compare error count to traffic count to see if the rate is real or just a traffic surge); traffic.compare (week-over-week or before-after-deploy comparison).

errors.context

Breadcrumbs leading to one error: the events from the same session, before the error timestamp, in chronological order. The "what was the user doing right before this broke" view that turns a stack trace into a story.

Given an anonymous_id and the error's timestamp, finds the session that was active at that timestamp and returns up to limit events from that session strictly earlier than the error. Each event row has its name, url, pathname, referrer — enough to reconstruct the path the user took.

Examples:

  • "what did this user do right before the error" → anonymous_id from errors.list, before_timestamp = the error's timestamp

  • "show me the last 10 actions before this crash" → limit=10

  • "did the user click anything before the unhandled rejection" → check the events list for cta_click / button_clicked names

Limitations: scoped to the single session that contained the error. If the error fired during a session the user later ended (closed tab), and you pass a timestamp in a later session, you'll get that later session's events instead. Returns events only — not their full property bags (use users.journey if you need the per-event context). Default limit 20, max 100.

Pairs with: errors.list (source of the anonymous_id and timestamp pair); users.journey (multi-session view of the same user, when one-session breadcrumbs aren't enough).

traffic.timeseries

Event counts over time as date buckets. Returns [{ date, count }] sorted ascending. Granularity is automatic based on period length (hourly for ≤2 days, daily for ≤90 days, weekly for ≤365 days, monthly beyond) and can be overridden via granularity. Filterable to a specific event name (defaults to "pageview") and a single custom property key/value pair.

Examples:

  • "pageview trend last week" → period="7d"

  • "signups per day this month" → event="signup", period="30d", granularity="day"

  • "hourly pageviews yesterday" → period="1d", granularity="hour"

Limitations: forcing granularity="hour" over a 90-day period produces hundreds of buckets and may be truncated server-side. Buckets with no matching events return zero (the series does not skip missing dates).

funnels.create

Create and immediately evaluate a conversion funnel. A funnel measures how many unique visitors complete an ordered sequence of steps. Returns step-by-step counts, per-step conversion rates (vs the previous step), and overall conversion (last step / first step). The funnel is saved by name and can be re-evaluated later or for different periods via funnels.list.

Step format: a custom event name like "signup", a pathname-scoped pageview like "pageview:/pricing", and optionally one or more property predicates appended in brackets — "cta_click[location=hero_primary]" matches only cta_click events whose location property equals "hero_primary". Stack predicates to AND them: "cta_click[location=hero_primary][plan=pro]". Predicates work on pageview steps too: "pageview:/pricing[utm_source=google]". Requires Pro plan.

Predicates default to string-typed comparisons (the property is read from the string column). For number- or boolean-typed properties (declared as such in event-schema.yaml), append a type tag: "purchase[count:n=5]" matches numeric 5; "checkout[refunded:b=false]" matches boolean false; "purchase[plan:s=5]" forces string matching when the value looks numeric. Tags: ":n" number, ":b" boolean (true|false|1|0), ":s" string (default).

Examples:

  • pricing-to-signup → name="pricing-to-signup", steps=["pageview:/pricing", "signup"]

  • which CTA actually converts → name="hero-cta-funnel", steps=["cta_click[location=hero_primary]", "signup_completed"]

  • onboarding flow → name="onboarding", steps=["signup", "onboarding_started", "onboarding_completed", "first_purchase"]

  • multi-item checkouts only → name="multi-item-checkout", steps=["pageview:/cart", "checkout_completed[items:n=3]"]

  • non-refunded purchases → name="purchase-net", steps=["pageview:/pricing", "purchase[refunded:b=false]"]

  • blog-to-newsletter → name="blog-newsletter", steps=["pageview:/blog", "newsletter_subscribed"]

Limitations: between 2 and 10 steps; step strings ≤500 chars; names ≤200 chars. Step order matters — once a session skips a step, it cannot complete later steps. Pageview pathnames match exact strings only (no wildcards). Predicate keys must be snake_case; string values may not contain ']' or '['. Number predicates require a finite value; boolean predicates require true|false|1|0. Funnel evaluation is per-session, not per-user across devices.

funnels.list

Retrieve and re-evaluate a previously created funnel against current data for the specified period. Without a name, lists all funnels saved for the project. With a name, returns the same step-by-step counts and conversion rates as funnels.create, recomputed for the requested period and any cohort filters. Cohort filters (channel, country, device_type, utm_*) let you compare conversion across segments — e.g. mobile users from the US who came via organic search.

Examples:

  • list all funnels → no params

  • "how is pricing-to-signup converting this month" → name="pricing-to-signup", period="30d"

  • "mobile conversion for onboarding" → name="onboarding", device_type="mobile"

  • "paid traffic vs organic conversion" → call twice with channel="paid" then channel="organic_search"

Limitations: returns 404 if no funnel exists by that name — call funnels.list with no name first to enumerate. Cohort filters apply at the session level, not retroactively per step. Funnel definitions are immutable after creation (re-create with a new name to change steps).

cohorts.create

Create and persist a named cohort — a group of visitors defined by an event in a period, optionally narrowed by a property filter. The cohort is stored by name; subsequent retention/compare queries reference it without re-specifying the definition. Membership is recomputed at query time, not materialised, so the same cohort always reflects current data. Requires Pro plan.

The 0.x cohort definition is event-based: the user fired event between the period boundaries, optionally with filter.property == filter.value.

Examples:

  • "users who signed up the week of April 14" → name="signups_apr_14", definition={ event: "signup_completed", period: "2026-04-14:2026-04-20" }

  • "free-plan signups last month" → name="free_signups_last_month", definition={ event: "signup_completed", period: "30d", filter: { property: "plan", value: "free" } }

  • "customers who completed checkout in March" → name="checkouts_march", definition={ event: "checkout_completed", period: "2026-03-01:2026-03-31" }

Limitations:

  • Event-based definitions only in 0.x. Behavior cohorts ("did X then Y in order"), exclusion cohorts ("fired X but not Y"), and time-relative cohorts ("did X within N days of signup") aren't supported. The triggering event + period + property-filter shape covers ~95% of practical use cases.

  • Membership is computed at query time, so very large cohorts cost on every retention call.

  • Names must be lowercase alphanumeric with hyphens / underscores.

Pairs with: cohorts.retention to read the curve once the cohort is created; cohorts.compare for two-cohort side-by-side reads; cohorts.list to discover existing cohort handles.

cohorts.list

List saved cohorts for the project. With name, returns one cohort with its current size; without, returns every cohort with their definitions. Use to discover cohort handles before calling retention or compare.

Examples:

  • "what cohorts do I have" → no params

  • "show me the signups_apr_14 cohort" → name="signups_apr_14"

Limitations: size is recomputed at fetch time and reflects current data — a cohort defined as "last 30d" returns a moving size as new events land.

cohorts.retention

Compute the retention curve for a saved cohort. For each requested window (e.g. day 1, 7, 14, 30 after the cohort's anchor event), returns how many cohort members fired any non-pageview-end event in that day's window, and the rate vs the cohort size.

Use this to answer "did this cohort stick around?" and to compare retention across cohorts (via cohorts.compare). The 1-day-window resolution means "7d retention" is "day 7 specifically", not "anywhere in the first 7 days" — the standard product-analytics definition.

Examples:

  • "retention curve for signups_apr_14 at day 1, 7, 14, 30" → name="signups_apr_14" (default periods)

  • "weekly retention for customers_march out to 8 weeks" → name="customers_march", periods="1w,2w,4w,8w"

  • "did onboarding cohort A retain at week 1" → name="onboarding_v2", periods="7d"

Limitations: retention measures any non-pageview-end event presence. Custom retention metrics (e.g. "retained = fired purchase event") are not in 0.x. The numerator is computed per-day, so windows like "30d" return only day-30 activity. Cohort size is the denominator and is included in the response so consumers can apply sample-size discipline.

Pairs with: cohorts.compare for two-cohort side-by-side; cohorts.list to discover available cohort names.

cohorts.compare

Compare two saved cohorts side-by-side on retention. Returns each cohort's size and retention curve over the same period set, so you can read "did this week's signups retain better than last week's?" or "is this experiment cohort behaving differently than control?" without composing the rates manually.

Examples:

  • "did April 14 signups retain better than April 7" → a="signups_apr_14", b="signups_apr_07"

  • "are pro-plan signups stickier than free" → a="pro_signups_q2", b="free_signups_q2"

  • "compare two onboarding variants out to 4 weeks" → a="onboarding_v1", b="onboarding_v2", periods="1w,2w,4w"

Limitations: only two cohorts at a time. The same retention windows are applied to both — there's no way to use different windows per side. Sample-size caveats apply per cohort; check both size values before reading the rate delta.

cohorts.delete

Delete a saved cohort by name. Irreversible — the agent should confirm intent with the user before calling this. The underlying event data isn't touched; only the cohort definition row is removed.

Examples:

  • "delete the test cohort" → name="test_cohort"

Limitations: irreversible. Returns 404 if the cohort doesn't exist. Definition is not returned before deletion — capture it from cohorts.list first if you may need to recreate it.

alerts.create

Create a metric alert that fires when a condition crosses its threshold. The alert monitors one metric (pageviews, visitors, sessions, bounce_rate, or avg_duration) over a rolling period and is re-evaluated every time an MCP session connects — alerts surface in-thread when the agent next checks, not as background pushes. Use to set lightweight monitoring like "alert me if pricing pageviews drop 50% week-over-week" or "alert me if bounce rate exceeds 70%". Requires Pro plan.

Examples:

  • pricing pageview drop → metric="pageviews", condition="drops_by", threshold=50, pathname="/pricing"

  • bounce rate ceiling → metric="bounce_rate", condition="above", threshold=70, period="7d"

  • traffic surge → metric="visitors", condition="increases_by", threshold=100, period="1d"

  • minimum-floor → metric="sessions", condition="below", threshold=100, period="1d"

Limitations: evaluation is on MCP session connect, not background — there are no push notifications, emails, or webhooks. Threshold for above/below is the absolute metric value; for drops_by/increases_by it is the percentage change vs the previous period of the same length. One alert per call — create multiple alerts for multiple conditions.

alerts.list

List all alerts configured for a project. Returns each alert's id (UUID), metric, condition, threshold, period, optional pathname scope, and created_at timestamp. Use before alerts.delete to find the id you want to remove, or to show the user every monitor currently active. Returns an empty array if no alerts have been created yet.

Examples:

  • "what alerts do I have" → no extra params beyond project_id

  • before deleting → call alerts.list, locate the id, pass it to alerts.delete

Limitations: alert state (currently firing vs not) is not included — that surfaces only when the alert is re-evaluated on MCP session connect. There is no pagination; projects with many alerts return all of them in one response.

alerts.delete

Delete an alert by its id. Find the id by calling alerts.list first. The deletion is irreversible — there is no soft-delete or undo, and the agent should confirm intent with the user before calling this on a non-trivial alert. Returns 404 if no alert with that id exists for the project.

Examples:

  • "remove the pricing alert" → alerts.list to find the matching id, then alerts.delete with that id

  • "clear all alerts" → alerts.list, then alerts.delete for each id

Limitations: irreversible. Does not return the deleted alert's prior configuration — capture it from alerts.list first if you may need to recreate it. The alert_id must be the UUID returned by alerts.list, not a metric name.

traffic.breakdown

Aggregate visitors and pageviews grouped by a single dimension. The dimension parameter chooses what to group by — page paths, traffic sources, geography, devices, or marketing attribution. Results are sorted by visitors descending and capped by limit (default 10, max 50). Some dimensions return additional joined columns: dimension="referrer_host" includes the channel for each referrer; dimension="city" includes the ISO country code. All other dimensions return only {name, pageviews, visitors}. Filters narrow the set before aggregation.

Examples:

  • "top pages last week" → dimension="pathname", period="7d"

  • "who is sending traffic" → dimension="referrer_host"

  • "mobile vs desktop split" → dimension="device_type"

  • "best UTM campaigns" → dimension="utm_campaign"

  • "top cities in Germany" → dimension="city", country="DE"

  • "browser version distribution" → dimension="browser_version"

Limitations: aggregates pageview events only — for custom event breakdowns use events.list with group_by. The name column is the raw stored value (lowercase ISO codes for country, exact pathname strings including trailing slash). Per-page time-on-page or bounce rate is not included here — use pages.engagement for that.

traffic.compare

Compare one metric across two arbitrary periods side-by-side. Returns both period values plus absolute delta and percentage delta. Periods do not need to be the same length — the percentage delta normalizes by ratio so longer/shorter comparisons remain meaningful. Use when the user asks month-over-month, before-vs-after-launch, or "how does this week compare to last".

Examples:

  • "this month vs last month" → metric="visitors", a="2026-04-01:2026-04-25", b="2026-03-01:2026-03-31"

  • "is /pricing converting better since the redesign" → metric="pageviews", a="2026-04-16:2026-04-25", b="2026-04-01:2026-04-15", pathname="/pricing"

Limitations: one metric per call — for multi-metric comparison either call repeatedly or use traffic.overview (which always includes the previous period). Period strings must be a preset ("today", "yesterday", "7d", "30d", "90d") or a YYYY-MM-DD:YYYY-MM-DD range; relative phrases like "last quarter" are not parsed.

sessions.paths

Aggregate (entry_page → exit_page) session pairs. Returns the top pairs with how many sessions followed each path, average pages per session, average duration in seconds, and a bounce flag. Use to answer "what do visitors do after landing on /pricing", "where do sessions end", or "which entry pages lead to the deepest engagement". Aggregate-only — no per-user traces, no full pageview chains, no individual session reconstruction.

Examples:

  • "top entry → exit pairs last week" → period="7d"

  • "longest sessions starting from the blog" → pathname="/blog", min_pages=3

  • "where do paid-traffic visitors end up" → channel="paid"

Limitations: shows entry and exit only, not the full pageview chain in between (use events.list for granular event analysis). min_pages=1 (default) includes single-page sessions which always show as bounces; set min_pages=2 to exclude them. Sessions ending without a pageview_end beacon (e.g. browser crash) may have null durations.

pages.engagement

Per-page metrics with a selectable detail level. The view parameter chooses what comes back:

  • view="summary" (default): pathname, pageviews, visitors. Cheap; use as the standard "top pages" call.

  • view="engagement": adds avg_engagement_seconds (active tab time from the SDK's pageview_end beacon) and bounce_rate (% of single-page sessions that started on this path). Use to answer "which pages hold attention" or "which pages bounce".

  • view="sections": returns per-section view counts for the specified pathname. Requires pathname to be set. Each section is a data-clamp-section element on that page, counted once per session when at least 40% scrolls into view. Use to answer "which parts of /pricing get seen" or "is the FAQ being read".

Examples:

  • "top pages this week" → view omitted (or "summary"), period="7d"

  • "which pages bounce hardest" → view="engagement", then sort by bounce_rate

  • "how far down /pricing do people scroll" → view="sections", pathname="/pricing"

Limitations: avg_engagement_seconds is null for pages without pageview_end data (SDK <0.3 or pages closed during navigation). view="sections" requires the section-views SDK extension installed (see /docs/sdk/extensions/section-views) and only counts elements with the data-clamp-section attribute — pages with no instrumented sections return []. view="sections" without pathname returns 400.

traffic.live

See who is on the site in the last N minutes. Returns the active visitor count plus top pages, top referrers, and top countries within that window. Defaults to 5 minutes; max 60. Use during incidents ("is anyone hitting the broken page right now"), launches ("is the new post getting traffic"), or whenever the user asks "who is on the site".

Examples:

  • "who is on the site right now" → window_minutes=5

  • "has anyone visited in the last hour" → window_minutes=60

  • "is the launch page getting hits" → window_minutes=15

Limitations: ingestion lag is ~30 seconds, so "live" is approximate. Visitor count is unique anonymous_ids in the window, not active sessions. For historical questions ("who visited last week"), use traffic.overview instead.

docs.search

Keyword-search the Clamp documentation index for setup, SDK, MCP, concepts, and skills pages. Returns ranked entries with url, title, and a short description. Each match scores higher when query terms appear in the title than the description; results are capped by limit (default 5, max 10). Use when the user asks how to do something — install Clamp in Next.js, add the section-views extension, set up Money revenue, write an alert — rather than what their data shows. For data questions use the analytics tools above.

Examples:

  • "how do I install Clamp in Vite" → query="vite install"

  • "how do I track revenue from Stripe" → query="stripe revenue server"

  • "what does the section-views extension do" → query="section views extension"

  • "how do I set up an alert" → query="alerts setup"

Limitations: keyword (substring) matching only — no semantic search, so synonyms ("webhook" vs "callback") will not match. The index is hand-maintained inside the MCP server and updates only when the server is redeployed. Returns an empty array if no matches; broaden the query rather than retrying with the same terms.

Prompts

Interactive templates invoked by user choice

NameDescription
weekly_reportGenerate a weekly analytics report summarizing traffic, top pages, referral sources, and geographic breakdown. Call this to get a comprehensive snapshot of the past 7 days compared to the prior week.
traffic_diagnosisDiagnose why traffic changed. Investigates which channels, countries, devices, and pages are responsible for a traffic increase or decrease. Use when a metric moved unexpectedly.
conversion_auditAudit conversion performance by analyzing funnels and custom events. Identifies the biggest drop-off points and suggests where to focus optimization efforts.
channel_breakdownDeep-dive into traffic channels to understand which sources drive real engagement vs just visits. Compares organic search, social, referral, direct, paid, and email traffic quality.
page_performanceDeep-dive into a specific page's performance: traffic trends, referral sources, device breakdown, and engagement metrics. Use to understand how a single page is performing.

Resources

Contextual data attached and managed by the client

NameDescription

No resources

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/clamp-sh/mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server