krystalview-mcp 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- krystalview_mcp-0.1.0/.gitignore +13 -0
- krystalview_mcp-0.1.0/LICENSE +21 -0
- krystalview_mcp-0.1.0/PKG-INFO +121 -0
- krystalview_mcp-0.1.0/README.md +100 -0
- krystalview_mcp-0.1.0/pyproject.toml +32 -0
- krystalview_mcp-0.1.0/src/krystalview_mcp/__init__.py +3 -0
- krystalview_mcp-0.1.0/src/krystalview_mcp/server.py +258 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 KrystalView
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: krystalview-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: KrystalView MCP Server — AI agent access to website analytics, session replay, friction scoring, and anomaly detection.
|
|
5
|
+
Project-URL: Homepage, https://krystalview.com
|
|
6
|
+
Project-URL: Documentation, https://docs.krystalview.com/integrations/mcp
|
|
7
|
+
Project-URL: Repository, https://github.com/McSlaine/krystalview-mcp
|
|
8
|
+
Author-email: KrystalView <support@krystalview.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: ai,analytics,krystalview,mcp,session-replay
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Requires-Dist: httpx>=0.27.0
|
|
19
|
+
Requires-Dist: mcp[cli]>=1.0.0
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# KrystalView MCP Server
|
|
23
|
+
|
|
24
|
+
Give your AI agents direct access to website analytics. Query visitor sessions, investigate UX friction, analyze conversion funnels, and get anomaly alerts — all from Claude, Cursor, or any MCP-compatible client.
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
### Install
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install krystalview-mcp
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Configure
|
|
35
|
+
|
|
36
|
+
Generate an API key in your [KrystalView console](https://app.krystalview.com) under **Settings > API Keys**.
|
|
37
|
+
|
|
38
|
+
#### Claude Desktop
|
|
39
|
+
|
|
40
|
+
Add to your `claude_desktop_config.json`:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"mcpServers": {
|
|
45
|
+
"krystalview": {
|
|
46
|
+
"command": "krystalview-mcp",
|
|
47
|
+
"env": {
|
|
48
|
+
"KRYSTALVIEW_API_KEY": "your-api-key-here"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
#### Claude Code
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
claude mcp add krystalview -- krystalview-mcp
|
|
59
|
+
# Then set your API key:
|
|
60
|
+
export KRYSTALVIEW_API_KEY="your-api-key-here"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
#### Cursor
|
|
64
|
+
|
|
65
|
+
Add to your MCP settings:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"krystalview": {
|
|
70
|
+
"command": "krystalview-mcp",
|
|
71
|
+
"env": {
|
|
72
|
+
"KRYSTALVIEW_API_KEY": "your-api-key-here"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Available Tools
|
|
79
|
+
|
|
80
|
+
| Tool | Description |
|
|
81
|
+
|------|-------------|
|
|
82
|
+
| `get_sessions` | List/search visitor sessions with filters (device, location, friction, rage clicks) |
|
|
83
|
+
| `get_session_detail` | Deep dive into a specific session — full timeline, events, navigation path |
|
|
84
|
+
| `get_site_stats` | Aggregate performance metrics — sessions, friction, devices, top pages |
|
|
85
|
+
| `get_anomalies` | AI-detected anomalies with explanations (traffic spikes/drops, friction surges) |
|
|
86
|
+
| `get_funnels` | List defined conversion funnels |
|
|
87
|
+
| `get_funnel_analysis` | Step-by-step funnel conversion rates and drop-off analysis |
|
|
88
|
+
|
|
89
|
+
## Example Prompts
|
|
90
|
+
|
|
91
|
+
Once connected, try asking your AI assistant:
|
|
92
|
+
|
|
93
|
+
- *"How's my site performing this week?"*
|
|
94
|
+
- *"Show me frustrated mobile users from the last 24 hours"*
|
|
95
|
+
- *"Why did our traffic drop yesterday?"*
|
|
96
|
+
- *"Where are users dropping off in the checkout funnel?"*
|
|
97
|
+
- *"Find sessions with rage clicks on the pricing page"*
|
|
98
|
+
- *"Are there any anomalies I should know about?"*
|
|
99
|
+
|
|
100
|
+
## Environment Variables
|
|
101
|
+
|
|
102
|
+
| Variable | Required | Default | Description |
|
|
103
|
+
|----------|----------|---------|-------------|
|
|
104
|
+
| `KRYSTALVIEW_API_KEY` | Yes | — | Your KrystalView API key |
|
|
105
|
+
| `KRYSTALVIEW_BASE_URL` | No | `https://app.krystalview.com/api` | API base URL |
|
|
106
|
+
| `KRYSTALVIEW_TIMEOUT` | No | `15` | Request timeout in seconds |
|
|
107
|
+
|
|
108
|
+
## Rate Limits
|
|
109
|
+
|
|
110
|
+
API keys have configurable rate limits (default: 60 requests per minute). Rate limit headers are included in every response. If you hit the limit, the server returns a clear error with retry timing.
|
|
111
|
+
|
|
112
|
+
## Security
|
|
113
|
+
|
|
114
|
+
- API keys are scoped to a single site — agents can only access data for the site the key was created for
|
|
115
|
+
- All requests use HTTPS
|
|
116
|
+
- Keys can be rotated or revoked in the KrystalView console
|
|
117
|
+
- No data is stored by the MCP server — it proxies directly to the KrystalView API
|
|
118
|
+
|
|
119
|
+
## License
|
|
120
|
+
|
|
121
|
+
MIT
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# KrystalView MCP Server
|
|
2
|
+
|
|
3
|
+
Give your AI agents direct access to website analytics. Query visitor sessions, investigate UX friction, analyze conversion funnels, and get anomaly alerts — all from Claude, Cursor, or any MCP-compatible client.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
### Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install krystalview-mcp
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Configure
|
|
14
|
+
|
|
15
|
+
Generate an API key in your [KrystalView console](https://app.krystalview.com) under **Settings > API Keys**.
|
|
16
|
+
|
|
17
|
+
#### Claude Desktop
|
|
18
|
+
|
|
19
|
+
Add to your `claude_desktop_config.json`:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"mcpServers": {
|
|
24
|
+
"krystalview": {
|
|
25
|
+
"command": "krystalview-mcp",
|
|
26
|
+
"env": {
|
|
27
|
+
"KRYSTALVIEW_API_KEY": "your-api-key-here"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
#### Claude Code
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
claude mcp add krystalview -- krystalview-mcp
|
|
38
|
+
# Then set your API key:
|
|
39
|
+
export KRYSTALVIEW_API_KEY="your-api-key-here"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
#### Cursor
|
|
43
|
+
|
|
44
|
+
Add to your MCP settings:
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"krystalview": {
|
|
49
|
+
"command": "krystalview-mcp",
|
|
50
|
+
"env": {
|
|
51
|
+
"KRYSTALVIEW_API_KEY": "your-api-key-here"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Available Tools
|
|
58
|
+
|
|
59
|
+
| Tool | Description |
|
|
60
|
+
|------|-------------|
|
|
61
|
+
| `get_sessions` | List/search visitor sessions with filters (device, location, friction, rage clicks) |
|
|
62
|
+
| `get_session_detail` | Deep dive into a specific session — full timeline, events, navigation path |
|
|
63
|
+
| `get_site_stats` | Aggregate performance metrics — sessions, friction, devices, top pages |
|
|
64
|
+
| `get_anomalies` | AI-detected anomalies with explanations (traffic spikes/drops, friction surges) |
|
|
65
|
+
| `get_funnels` | List defined conversion funnels |
|
|
66
|
+
| `get_funnel_analysis` | Step-by-step funnel conversion rates and drop-off analysis |
|
|
67
|
+
|
|
68
|
+
## Example Prompts
|
|
69
|
+
|
|
70
|
+
Once connected, try asking your AI assistant:
|
|
71
|
+
|
|
72
|
+
- *"How's my site performing this week?"*
|
|
73
|
+
- *"Show me frustrated mobile users from the last 24 hours"*
|
|
74
|
+
- *"Why did our traffic drop yesterday?"*
|
|
75
|
+
- *"Where are users dropping off in the checkout funnel?"*
|
|
76
|
+
- *"Find sessions with rage clicks on the pricing page"*
|
|
77
|
+
- *"Are there any anomalies I should know about?"*
|
|
78
|
+
|
|
79
|
+
## Environment Variables
|
|
80
|
+
|
|
81
|
+
| Variable | Required | Default | Description |
|
|
82
|
+
|----------|----------|---------|-------------|
|
|
83
|
+
| `KRYSTALVIEW_API_KEY` | Yes | — | Your KrystalView API key |
|
|
84
|
+
| `KRYSTALVIEW_BASE_URL` | No | `https://app.krystalview.com/api` | API base URL |
|
|
85
|
+
| `KRYSTALVIEW_TIMEOUT` | No | `15` | Request timeout in seconds |
|
|
86
|
+
|
|
87
|
+
## Rate Limits
|
|
88
|
+
|
|
89
|
+
API keys have configurable rate limits (default: 60 requests per minute). Rate limit headers are included in every response. If you hit the limit, the server returns a clear error with retry timing.
|
|
90
|
+
|
|
91
|
+
## Security
|
|
92
|
+
|
|
93
|
+
- API keys are scoped to a single site — agents can only access data for the site the key was created for
|
|
94
|
+
- All requests use HTTPS
|
|
95
|
+
- Keys can be rotated or revoked in the KrystalView console
|
|
96
|
+
- No data is stored by the MCP server — it proxies directly to the KrystalView API
|
|
97
|
+
|
|
98
|
+
## License
|
|
99
|
+
|
|
100
|
+
MIT
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "krystalview-mcp"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "KrystalView MCP Server — AI agent access to website analytics, session replay, friction scoring, and anomaly detection."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [{ name = "KrystalView", email = "support@krystalview.com" }]
|
|
13
|
+
keywords = ["mcp", "analytics", "krystalview", "ai", "session-replay"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Topic :: Software Development :: Libraries",
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
"mcp[cli]>=1.0.0",
|
|
23
|
+
"httpx>=0.27.0",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.scripts]
|
|
27
|
+
krystalview-mcp = "krystalview_mcp.server:main"
|
|
28
|
+
|
|
29
|
+
[project.urls]
|
|
30
|
+
Homepage = "https://krystalview.com"
|
|
31
|
+
Documentation = "https://docs.krystalview.com/integrations/mcp"
|
|
32
|
+
Repository = "https://github.com/McSlaine/krystalview-mcp"
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
"""KrystalView MCP Server.
|
|
2
|
+
|
|
3
|
+
Gives AI agents direct access to website analytics — sessions, visitor
|
|
4
|
+
behavior, friction scores, anomalies, and funnel analysis.
|
|
5
|
+
|
|
6
|
+
Authenticates against the KrystalView API using the same API keys
|
|
7
|
+
generated in the KrystalView console.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import os
|
|
12
|
+
from typing import Any, Optional
|
|
13
|
+
|
|
14
|
+
import httpx
|
|
15
|
+
from mcp.server.fastmcp import FastMCP
|
|
16
|
+
|
|
17
|
+
# ---------------------------------------------------------------------------
|
|
18
|
+
# Configuration
|
|
19
|
+
# ---------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
API_KEY = os.environ.get("KRYSTALVIEW_API_KEY", "")
|
|
22
|
+
BASE_URL = os.environ.get(
|
|
23
|
+
"KRYSTALVIEW_BASE_URL", "https://app.krystalview.com/api"
|
|
24
|
+
).rstrip("/")
|
|
25
|
+
TIMEOUT = int(os.environ.get("KRYSTALVIEW_TIMEOUT", "15"))
|
|
26
|
+
|
|
27
|
+
mcp = FastMCP(
|
|
28
|
+
"KrystalView",
|
|
29
|
+
instructions=(
|
|
30
|
+
"KrystalView provides real-time website analytics with session replay, "
|
|
31
|
+
"friction scoring, anomaly detection, and funnel analysis. "
|
|
32
|
+
"Use these tools to investigate visitor behavior, diagnose UX issues, "
|
|
33
|
+
"and answer questions about site performance."
|
|
34
|
+
),
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# ---------------------------------------------------------------------------
|
|
38
|
+
# HTTP helpers
|
|
39
|
+
# ---------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _headers() -> dict[str, str]:
|
|
43
|
+
return {"X-API-Key": API_KEY, "Accept": "application/json"}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
async def _get(path: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
47
|
+
"""Make an authenticated GET request to the KrystalView API."""
|
|
48
|
+
url = f"{BASE_URL}{path}"
|
|
49
|
+
# Strip None values from params
|
|
50
|
+
if params:
|
|
51
|
+
params = {k: v for k, v in params.items() if v is not None}
|
|
52
|
+
async with httpx.AsyncClient(timeout=TIMEOUT) as client:
|
|
53
|
+
resp = await client.get(url, headers=_headers(), params=params)
|
|
54
|
+
resp.raise_for_status()
|
|
55
|
+
return resp.json()
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _format_error(exc: Exception) -> str:
|
|
59
|
+
if isinstance(exc, httpx.HTTPStatusError):
|
|
60
|
+
status = exc.response.status_code
|
|
61
|
+
if status == 401:
|
|
62
|
+
return "Authentication failed. Check your KRYSTALVIEW_API_KEY."
|
|
63
|
+
if status == 403:
|
|
64
|
+
return "API key does not have the required 'read' scope."
|
|
65
|
+
if status == 429:
|
|
66
|
+
retry = exc.response.headers.get("Retry-After", "?")
|
|
67
|
+
return f"Rate limited. Retry after {retry} seconds."
|
|
68
|
+
try:
|
|
69
|
+
detail = exc.response.json().get("detail", exc.response.text)
|
|
70
|
+
except Exception:
|
|
71
|
+
detail = exc.response.text
|
|
72
|
+
return f"API error {status}: {detail}"
|
|
73
|
+
return f"Request failed: {exc}"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# ---------------------------------------------------------------------------
|
|
77
|
+
# Tools
|
|
78
|
+
# ---------------------------------------------------------------------------
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@mcp.tool()
|
|
82
|
+
async def get_sessions(
|
|
83
|
+
query: Optional[str] = None,
|
|
84
|
+
limit: int = 20,
|
|
85
|
+
offset: int = 0,
|
|
86
|
+
country: Optional[str] = None,
|
|
87
|
+
device_type: Optional[str] = None,
|
|
88
|
+
min_friction: Optional[int] = None,
|
|
89
|
+
min_duration: Optional[int] = None,
|
|
90
|
+
has_rage_clicks: Optional[bool] = None,
|
|
91
|
+
) -> str:
|
|
92
|
+
"""List recent visitor sessions with filtering.
|
|
93
|
+
|
|
94
|
+
Each session includes: duration, page count, entry/exit URLs, device info,
|
|
95
|
+
screen size, IP address, location (country/city), friction score, and
|
|
96
|
+
rage click count.
|
|
97
|
+
|
|
98
|
+
Use this to find sessions matching specific criteria — e.g. frustrated
|
|
99
|
+
mobile users, visitors from a specific country, or high-friction sessions.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
query: Search entry/exit URLs (e.g. "/pricing", "/checkout")
|
|
103
|
+
limit: Max results (1-100, default 20)
|
|
104
|
+
offset: Pagination offset
|
|
105
|
+
country: Filter by country name
|
|
106
|
+
device_type: "mobile" or "desktop"
|
|
107
|
+
min_friction: Minimum friction score (0-10)
|
|
108
|
+
min_duration: Minimum session duration in seconds
|
|
109
|
+
has_rage_clicks: Only sessions with rage clicks
|
|
110
|
+
"""
|
|
111
|
+
try:
|
|
112
|
+
data = await _get("/v1/api/sessions", {
|
|
113
|
+
"q": query,
|
|
114
|
+
"limit": min(limit, 100),
|
|
115
|
+
"offset": max(offset, 0),
|
|
116
|
+
"country": country,
|
|
117
|
+
"device_type": device_type,
|
|
118
|
+
"min_friction": min_friction,
|
|
119
|
+
"min_duration": min_duration,
|
|
120
|
+
"has_rage_clicks": has_rage_clicks,
|
|
121
|
+
})
|
|
122
|
+
return json.dumps(data["data"], indent=2, default=str)
|
|
123
|
+
except Exception as exc:
|
|
124
|
+
return _format_error(exc)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@mcp.tool()
|
|
128
|
+
async def get_session_detail(session_id: str) -> str:
|
|
129
|
+
"""Get full details for a specific session.
|
|
130
|
+
|
|
131
|
+
Returns the complete session record including: all page visits with
|
|
132
|
+
timestamps, event timeline, device/browser info, IP address, geographic
|
|
133
|
+
location, friction breakdown, rage clicks, errors encountered, and
|
|
134
|
+
navigation path.
|
|
135
|
+
|
|
136
|
+
Use this to deep-dive into a specific session after finding it via
|
|
137
|
+
get_sessions.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
session_id: The session primary key (UUID) from get_sessions results
|
|
141
|
+
"""
|
|
142
|
+
try:
|
|
143
|
+
data = await _get(f"/v1/api/sessions/{session_id}")
|
|
144
|
+
return json.dumps(data["data"], indent=2, default=str)
|
|
145
|
+
except Exception as exc:
|
|
146
|
+
return _format_error(exc)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
@mcp.tool()
|
|
150
|
+
async def get_site_stats(days: int = 7) -> str:
|
|
151
|
+
"""Get aggregate site statistics and performance metrics.
|
|
152
|
+
|
|
153
|
+
Returns: total sessions, average duration, average friction score,
|
|
154
|
+
bounce rate, rage click sessions, device breakdown (desktop/mobile),
|
|
155
|
+
browser breakdown, top entry pages, top exit pages, daily session
|
|
156
|
+
counts, and friction score distribution.
|
|
157
|
+
|
|
158
|
+
Use this for an overview of site health and trends.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
days: Lookback period in days (7-90, default 7)
|
|
162
|
+
"""
|
|
163
|
+
try:
|
|
164
|
+
data = await _get("/v1/api/stats", {"days": min(max(days, 7), 90)})
|
|
165
|
+
return json.dumps(data["data"], indent=2, default=str)
|
|
166
|
+
except Exception as exc:
|
|
167
|
+
return _format_error(exc)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
@mcp.tool()
|
|
171
|
+
async def get_anomalies(
|
|
172
|
+
limit: int = 20,
|
|
173
|
+
unacknowledged_only: bool = False,
|
|
174
|
+
) -> str:
|
|
175
|
+
"""Get detected anomalies for the site.
|
|
176
|
+
|
|
177
|
+
Anomalies are automatically detected when metrics deviate significantly
|
|
178
|
+
from their 7-day rolling average (>2 standard deviations). Types include:
|
|
179
|
+
traffic_spike, traffic_drop, friction_surge, and bounce_spike.
|
|
180
|
+
|
|
181
|
+
Each anomaly includes: type, severity (warning/critical), metric name,
|
|
182
|
+
expected vs actual values, deviation percentage, and an AI-generated
|
|
183
|
+
explanation of what likely caused it.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
limit: Max results (1-200, default 20)
|
|
187
|
+
unacknowledged_only: Only show unacknowledged anomalies
|
|
188
|
+
"""
|
|
189
|
+
try:
|
|
190
|
+
data = await _get("/v1/api/anomalies", {
|
|
191
|
+
"limit": min(limit, 200),
|
|
192
|
+
"unacknowledged": unacknowledged_only,
|
|
193
|
+
})
|
|
194
|
+
return json.dumps(data["data"], indent=2, default=str)
|
|
195
|
+
except Exception as exc:
|
|
196
|
+
return _format_error(exc)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
@mcp.tool()
|
|
200
|
+
async def get_funnels() -> str:
|
|
201
|
+
"""List all conversion funnels defined for this site.
|
|
202
|
+
|
|
203
|
+
Returns funnel definitions with their name, steps (URLs/patterns),
|
|
204
|
+
and creation date. Use the funnel ID with get_funnel_analysis to see
|
|
205
|
+
conversion rates and drop-off points.
|
|
206
|
+
"""
|
|
207
|
+
try:
|
|
208
|
+
data = await _get("/v1/api/funnels")
|
|
209
|
+
return json.dumps(data["data"], indent=2, default=str)
|
|
210
|
+
except Exception as exc:
|
|
211
|
+
return _format_error(exc)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
@mcp.tool()
|
|
215
|
+
async def get_funnel_analysis(funnel_id: int, days: int = 30) -> str:
|
|
216
|
+
"""Analyze a conversion funnel — see where users drop off.
|
|
217
|
+
|
|
218
|
+
Returns step-by-step conversion rates showing how many sessions
|
|
219
|
+
reached each step, the conversion rate between steps, and the
|
|
220
|
+
overall funnel completion rate.
|
|
221
|
+
|
|
222
|
+
Use this to identify which step in a user flow (e.g. landing ->
|
|
223
|
+
signup -> checkout -> payment) loses the most visitors.
|
|
224
|
+
|
|
225
|
+
Args:
|
|
226
|
+
funnel_id: Funnel ID from get_funnels results
|
|
227
|
+
days: Lookback period in days (7-90, default 30)
|
|
228
|
+
"""
|
|
229
|
+
try:
|
|
230
|
+
data = await _get(f"/v1/api/funnels/{funnel_id}/analysis", {
|
|
231
|
+
"days": min(max(days, 7), 90),
|
|
232
|
+
})
|
|
233
|
+
return json.dumps(data["data"], indent=2, default=str)
|
|
234
|
+
except Exception as exc:
|
|
235
|
+
return _format_error(exc)
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
# ---------------------------------------------------------------------------
|
|
239
|
+
# Entry point
|
|
240
|
+
# ---------------------------------------------------------------------------
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def main():
|
|
244
|
+
"""Run the KrystalView MCP server (stdio transport)."""
|
|
245
|
+
if not API_KEY:
|
|
246
|
+
import sys
|
|
247
|
+
print(
|
|
248
|
+
"Error: KRYSTALVIEW_API_KEY environment variable is required.\n"
|
|
249
|
+
"Generate an API key in your KrystalView console under "
|
|
250
|
+
"Settings > API Keys.",
|
|
251
|
+
file=sys.stderr,
|
|
252
|
+
)
|
|
253
|
+
sys.exit(1)
|
|
254
|
+
mcp.run()
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
if __name__ == "__main__":
|
|
258
|
+
main()
|