Statable Analytics
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| STATABLE_API_KEY | No | Your Statable API key. Keys start with stbl_. The server starts without one but every tool call will return a message explaining how to add one. | |
| STATABLE_MCP_URL | No | Remote endpoint URL for the Statable MCP server. | https://mcp.statable.com/mcp |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| list_sitesA | List the sites this API key can read. Response: {"sites":[{"site_id":123,"name":"<as entered by the owner — often a full URL like https://example.com/>","hash":"07k1eD84d2","timezone":"Europe/Amsterdam","hobby":false,"stats_start_date":"YYYY-MM-DD"|null,"created_at":"RFC3339"}]}. hobby=true is a free-plan site: it counts only through the bundled /t/ script get_tracking_snippet returns, so install that snippet verbatim. Use site_id with the other tools. With date_range each site also carries metrics NESTED under stats.metrics (never flat on the site object). Units: visit_duration = average seconds per visit; bounce_rate = percent 0-100; views_per_visit = pageviews/visits ratio; visitors/pageviews/visits = counts. Stats period boundaries are server-time approximations; use query_stats for timezone-exact numbers. |
| query_statsA | Run a read-only analytics query for one site: aggregate totals, a time series, or a top-N breakdown. Returns {"results":[{"dimensions":{...omitted for aggregates},"metrics":{...}}]}. All dates and time buckets are in the site's own timezone (see list_sites .timezone). The event:name breakdown lists custom events (data-statable-event); its |
| top_pagesB | Top pages by visitors for a site. Returns {"results":[{"dimensions":{"event:page":"/path"},"metrics":{"pageviews":N,"visitors":N}}]}. |
| top_sourcesB | Top traffic sources by visitors for a site. Returns {"results":[{"dimensions":{"visit:source":"Google"},"metrics":{"visitors":N,"bounce_rate":percent0to100}}]}. |
| top_countriesA | Top countries by visitors for a site. Returns {"results":[{"dimensions":{"visit:country":"US"},"labels":{"visit:country":"United States"},"metrics":{"visitors":N}}]} — the dimension value is the ISO alpha-2 code (drops straight into a country filter); the display name is in labels. |
| top_custom_eventsA | Top custom events (data-statable-event) by count for a site — pageview/engagement excluded. Returns {"results":[{"dimensions":{"event:name":"Signup"},"metrics":{"events":N,"visitors":N}}]}, where events is the raw occurrence count and visitors is unique users who triggered it. |
| top_goalsA | The site's configured goals ranked by conversions. Returns {"results":[{"dimensions":{"event:goal":"Signup"},"metrics":{"visitors":N,"events":N,"conversion_rate":percent0to100}}]}, where visitors is unique converters, events is total conversions, and conversion_rate is visitors as a percent of all visitors in the period. |
| list_goalsA | The goals CONFIGURED on a site — what it measures, not how those goals performed. Use top_goals for conversion numbers. Response: {"goals":[{"id":7,"name":"Signup","event_name":"Signup"|null,"path":"/thanks"|null,"operator":"e|b|c","scroll_depth":N|null}]}. |
| list_prop_keysA | List the custom-property keys a site has recorded (with the event each belongs to) — discovery for the event:props: breakdown in query_stats. Returns {"props":[{"key":"plan","event":"Signup","count":N,"first_seen":"RFC3339"}]}. |
| list_funnelsA | List the conversion funnels configured for a site (discovery — get a funnel_id for funnel_report). Returns {"funnels":[{"id":45,"name":"Signup flow","scope":"visitor","steps_count":3}]}. |
| funnel_reportA | Run a saved conversion funnel and return its per-step result (NON-tabular). Returns {"funnel":{"id","name","scope"},"entering":N,"all_visitors":N,"steps":[{"index":0,"name":"Visited /pricing","kind":"page","visitors":N,"conversion_rate":percent0to100,"dropoff":N}, ...]}. steps are ORDERED; conversion_rate is cumulative vs the first step (entering), NOT step-to-step; dropoff is visitors lost vs the previous step. Get funnel_id from list_funnels first. |
| current_visitorsA | Realtime count of unique visitors active in the last 5 minutes for a site. Returns {"site_id":123,"visitors":N}. |
| visitors_over_timeA | Daily visitors and pageviews time series for a site, in the site's own timezone. Returns {"results":[{"dimensions":{"time:day":"YYYY-MM-DD"},"metrics":{"visitors":N,"pageviews":N}}]}. |
| get_tracking_snippetA | The script tag to install on a site, and the url it loads. Response: {"site_id":123,"type":"default","script_url":"https://...","snippet":"<script ...>"}. Install snippet verbatim; do not rebuild a tag from script_url. A hobby site's snippet also carries data-id, which is the only place the counter in its bundle reads the site id. Read-only: it reports the code, it does not install or verify anything. |
| get_site_filtersA | Who gets counted on a site, and who may look at the stats. Response: {"site_id":123,"hostnames":{"allowed":[],"blocked":[]},"blocked_ips":["1.2.3.4"],"countries":{"allowed":[{"code":"UA","created_at":"RFC3339"}],"blocked":[]},"public_dashboard":false}. An empty allowed list means "no restriction", not "nothing allowed". public_dashboard true means the stats are readable by anyone with the link. |
| get_subscriptionA | The account's plan state — not a site's. Response: {"status":"trialing"|"active"|"past_due"|"expired"|"trial_expired"|"none","is_trial":true,"ends_at":"RFC3339","only_hobby":false}. ends_at is when the CURRENT state stops being true (trial end while trialing, period end otherwise) and is omitted when unknown. status "none" with only_hobby true means a free account, not a missing one. Takes no arguments. |
| create_siteA | Add a site to this account and get back its id and tracking code. Response: {"site_id":123,"name":"https://example.com","timezone":"Europe/Amsterdam",...}. The url must include the scheme. A url this account already has is REFUSED (site_exists) rather than returned — two sites collecting the same traffic is worse than an error. Retrying with the same arguments replays the first result instead of creating a second site. Follow with get_tracking_snippet to obtain the script tag to install. |
| update_siteA | Change a site's url, timezone or week start. Omitted fields are left alone. Returns the updated site. Changing the url to one this account already has is refused (site_exists). |
| create_goalA | Add a goal to a site. A goal is EITHER a custom event (event_name), OR a page (path with operator), OR a scroll depth — give one of the three, not several. operator: "e" exact, "b" begins with, "c" contains. A duplicate name is refused (goal_exists). |
| update_goalB | Replace a goal's definition. Send the whole goal, not just the changed fields — omitted fields are cleared, not kept. |
| create_funnelA | Add a funnel: an ordered list of 2+ steps. Each step is one of {"type":"page","value":"/pricing"}, {"type":"event","value":"Signup"}, {"type":"entry_page"|"exit_page","value":"/"}. An exit_page step must be last. scope "visitor" (default) or "session". A duplicate name is refused (funnel_exists). Read the result with funnel_report. |
| update_funnelA | Replace a funnel's definition. Send the whole funnel including every step — omitted steps are removed, not kept. |
| get_tracking_settingsA | What the installed script actually does: which tracking features are on, which exist, and what each costs in bytes. Response: {"site_id":123,"version":N,"bundle":"...","enabled":["hash","outbound"],"features":[{"id":"outbound","label":"...","enabled":true,"locked":false,"default":false,"requires":[...],"size_br":123}]}. Locked features cannot be changed; |
| update_tracking_settingsA | Set which tracking features the site's script includes. REPLACES the whole selection: send every feature you want enabled, not just the new one — anything omitted is turned off. Call get_tracking_settings first for the valid ids. Rebuilds and republishes the script, so the change reaches visitors after the CDN cache clears. |
| update_site_filtersA | Change who gets counted, and who may look. Send only the sections you want to change — an omitted section is left untouched. A section you DO send replaces that setting entirely: {"countries":{"blocked":["RU"]}} also clears the country allow list, and {"blocked_ips":[]} empties the blocklist. Read the current state with get_site_filters and send it back with your edit applied. Filtering takes effect on new traffic; it does not remove data already collected. Answers with the resulting state plus "updated":["hostnames",...] naming what changed. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/key-arg/statable-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server