@sealmetrics/mcp 0.1.0 → 1.2.0
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.
- package/README.md +149 -0
- package/dist/client.d.ts +45 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +136 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +10 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +55 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +1 -6
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +122 -781
- package/dist/index.js.map +1 -0
- package/dist/resources/tracking-guide.d.ts +13 -0
- package/dist/resources/tracking-guide.d.ts.map +1 -0
- package/dist/resources/tracking-guide.js +479 -0
- package/dist/resources/tracking-guide.js.map +1 -0
- package/dist/tools/alerts.d.ts +5 -0
- package/dist/tools/alerts.d.ts.map +1 -0
- package/dist/tools/alerts.js +80 -0
- package/dist/tools/alerts.js.map +1 -0
- package/dist/tools/audience.d.ts +7 -0
- package/dist/tools/audience.d.ts.map +1 -0
- package/dist/tools/audience.js +146 -0
- package/dist/tools/audience.js.map +1 -0
- package/dist/tools/bots.d.ts +4 -0
- package/dist/tools/bots.d.ts.map +1 -0
- package/dist/tools/bots.js +52 -0
- package/dist/tools/bots.js.map +1 -0
- package/dist/tools/channels.d.ts +5 -0
- package/dist/tools/channels.d.ts.map +1 -0
- package/dist/tools/channels.js +88 -0
- package/dist/tools/channels.js.map +1 -0
- package/dist/tools/content.d.ts +3 -0
- package/dist/tools/content.d.ts.map +1 -0
- package/dist/tools/content.js +47 -0
- package/dist/tools/content.js.map +1 -0
- package/dist/tools/conversions.d.ts +6 -0
- package/dist/tools/conversions.d.ts.map +1 -0
- package/dist/tools/conversions.js +178 -0
- package/dist/tools/conversions.js.map +1 -0
- package/dist/tools/funnel.d.ts +3 -0
- package/dist/tools/funnel.d.ts.map +1 -0
- package/dist/tools/funnel.js +27 -0
- package/dist/tools/funnel.js.map +1 -0
- package/dist/tools/index.d.ts +16 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +79 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/manage.d.ts +3 -0
- package/dist/tools/manage.d.ts.map +1 -0
- package/dist/tools/manage.js +55 -0
- package/dist/tools/manage.js.map +1 -0
- package/dist/tools/overview.d.ts +3 -0
- package/dist/tools/overview.d.ts.map +1 -0
- package/dist/tools/overview.js +26 -0
- package/dist/tools/overview.js.map +1 -0
- package/dist/tools/pages.d.ts +7 -0
- package/dist/tools/pages.d.ts.map +1 -0
- package/dist/tools/pages.js +207 -0
- package/dist/tools/pages.js.map +1 -0
- package/dist/tools/properties.d.ts +5 -0
- package/dist/tools/properties.d.ts.map +1 -0
- package/dist/tools/properties.js +107 -0
- package/dist/tools/properties.js.map +1 -0
- package/dist/tools/segments.d.ts +4 -0
- package/dist/tools/segments.d.ts.map +1 -0
- package/dist/tools/segments.js +49 -0
- package/dist/tools/segments.js.map +1 -0
- package/dist/tools/shared.d.ts +45 -0
- package/dist/tools/shared.d.ts.map +1 -0
- package/dist/tools/shared.js +139 -0
- package/dist/tools/shared.js.map +1 -0
- package/dist/tools/sites.d.ts +4 -0
- package/dist/tools/sites.d.ts.map +1 -0
- package/dist/tools/sites.js +36 -0
- package/dist/tools/sites.js.map +1 -0
- package/dist/tools/tracking.d.ts +3 -0
- package/dist/tools/tracking.d.ts.map +1 -0
- package/dist/tools/tracking.js +220 -0
- package/dist/tools/tracking.js.map +1 -0
- package/dist/tools/traffic.d.ts +10 -0
- package/dist/tools/traffic.d.ts.map +1 -0
- package/dist/tools/traffic.js +273 -0
- package/dist/tools/traffic.js.map +1 -0
- package/dist/tools/webhooks.d.ts +5 -0
- package/dist/tools/webhooks.d.ts.map +1 -0
- package/dist/tools/webhooks.js +101 -0
- package/dist/tools/webhooks.js.map +1 -0
- package/dist/types.d.ts +118 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +22 -0
- package/dist/types.js.map +1 -0
- package/package.json +35 -27
package/README.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# @sealmetrics/mcp-server
|
|
2
|
+
|
|
3
|
+
MCP server for querying [SealMetrics](https://sealmetrics.com) analytics from Claude Code, Claude Desktop, or any MCP-compatible client.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
### 1. Get an API key
|
|
8
|
+
|
|
9
|
+
Go to **Settings > API Tokens** in your SealMetrics dashboard and generate a new API key.
|
|
10
|
+
|
|
11
|
+
### 2. Configure your MCP client
|
|
12
|
+
|
|
13
|
+
Add to your project's `.mcp.json` or `~/.claude/settings.json`:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"mcpServers": {
|
|
18
|
+
"sealmetrics": {
|
|
19
|
+
"command": "npx",
|
|
20
|
+
"args": ["-y", "@sealmetrics/mcp-server"],
|
|
21
|
+
"env": {
|
|
22
|
+
"SEALMETRICS_API_KEY": "sm_xxxx...",
|
|
23
|
+
"SEALMETRICS_SITE_ID": "my-site"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Environment variables
|
|
31
|
+
|
|
32
|
+
| Variable | Required | Description |
|
|
33
|
+
|----------|----------|-------------|
|
|
34
|
+
| `SEALMETRICS_API_KEY` | Yes | Your API key (starts with `sm_`) |
|
|
35
|
+
| `SEALMETRICS_SITE_ID` | No | Default site ID (skips needing to pass `site_id` to every tool) |
|
|
36
|
+
| `SEALMETRICS_BASE_URL` | No | API base URL (default: `https://my.sealmetrics.com/api/v1`) |
|
|
37
|
+
|
|
38
|
+
## Available tools
|
|
39
|
+
|
|
40
|
+
### list_sites
|
|
41
|
+
|
|
42
|
+
List all sites accessible with your API key.
|
|
43
|
+
|
|
44
|
+
### get_overview
|
|
45
|
+
|
|
46
|
+
Dashboard KPIs: pageviews, entrances, bounce rate, conversions, revenue. Includes time series data and optional period comparison.
|
|
47
|
+
|
|
48
|
+
**Parameters:** `site_id`, `period`, `compare`
|
|
49
|
+
|
|
50
|
+
### get_traffic_sources
|
|
51
|
+
|
|
52
|
+
Traffic broken down by source (utm_source): google, facebook, direct, etc.
|
|
53
|
+
|
|
54
|
+
**Parameters:** `site_id`, `period`, `compare`, `limit`, `sort_by`, `sort_order`
|
|
55
|
+
|
|
56
|
+
### get_traffic_mediums
|
|
57
|
+
|
|
58
|
+
Traffic broken down by medium (utm_medium): organic, cpc, email, referral, etc.
|
|
59
|
+
|
|
60
|
+
**Parameters:** `site_id`, `period`, `compare`, `limit`, `sort_by`, `sort_order`
|
|
61
|
+
|
|
62
|
+
### get_campaigns
|
|
63
|
+
|
|
64
|
+
Campaign performance (utm_campaign) with entrances, conversions, and revenue.
|
|
65
|
+
|
|
66
|
+
**Parameters:** `site_id`, `period`, `compare`, `limit`, `sort_by`, `sort_order`, `utm_source`, `utm_medium`
|
|
67
|
+
|
|
68
|
+
### get_pages
|
|
69
|
+
|
|
70
|
+
Metrics per page URL path: pageviews, entrances, conversions.
|
|
71
|
+
|
|
72
|
+
**Parameters:** `site_id`, `period`, `compare`, `limit`, `sort_by`, `sort_order`, `path_filter`
|
|
73
|
+
|
|
74
|
+
### get_landing_pages
|
|
75
|
+
|
|
76
|
+
Landing page performance: entrances, bounce rate, conversions.
|
|
77
|
+
|
|
78
|
+
**Parameters:** `site_id`, `period`, `compare`, `limit`, `sort_by`, `sort_order`, `path_filter`
|
|
79
|
+
|
|
80
|
+
### get_conversions
|
|
81
|
+
|
|
82
|
+
Conversions by type (purchase, signup) with count, revenue, and average order value.
|
|
83
|
+
|
|
84
|
+
**Parameters:** `site_id`, `period`, `compare`, `limit`, `sort_by`, `sort_order`, `utm_source`, `utm_medium`, `country`
|
|
85
|
+
|
|
86
|
+
### get_microconversions
|
|
87
|
+
|
|
88
|
+
Microconversions (add_to_cart, newsletter_signup, etc.) by type with counts.
|
|
89
|
+
|
|
90
|
+
**Parameters:** `site_id`, `period`, `compare`, `limit`, `sort_by`, `sort_order`, `conversion_type`
|
|
91
|
+
|
|
92
|
+
### get_countries
|
|
93
|
+
|
|
94
|
+
Traffic by country with entrances, conversions, and revenue.
|
|
95
|
+
|
|
96
|
+
**Parameters:** `site_id`, `period`, `compare`, `limit`, `sort_by`, `sort_order`
|
|
97
|
+
|
|
98
|
+
### get_devices
|
|
99
|
+
|
|
100
|
+
Device type (desktop/mobile/tablet), browser, and OS breakdown in a single call.
|
|
101
|
+
|
|
102
|
+
**Parameters:** `site_id`, `period`, `compare`
|
|
103
|
+
|
|
104
|
+
### get_funnel
|
|
105
|
+
|
|
106
|
+
Funnel analysis with step-by-step conversion rates and dropoff.
|
|
107
|
+
|
|
108
|
+
**Parameters:** `site_id`, `period`, `country`
|
|
109
|
+
|
|
110
|
+
### get_tracking_code
|
|
111
|
+
|
|
112
|
+
Get the tracking pixel code for a site and the full JavaScript API reference for implementing pageviews, conversions, microconversions, and content grouping. Use this when you need to install tracking on a website.
|
|
113
|
+
|
|
114
|
+
**Parameters:** `site_id`
|
|
115
|
+
|
|
116
|
+
## Common parameters
|
|
117
|
+
|
|
118
|
+
| Parameter | Values | Default | Description |
|
|
119
|
+
|-----------|--------|---------|-------------|
|
|
120
|
+
| `site_id` | string | `$SEALMETRICS_SITE_ID` | Site to query |
|
|
121
|
+
| `period` | `today`, `yesterday`, `7d`, `30d`, `90d`, `this_month`, `last_month`, `this_year`, etc. | `30d` | Time period |
|
|
122
|
+
| `compare` | `previous`, `yoy` | none | Comparison mode |
|
|
123
|
+
| `limit` | 1-100 | 20 | Max rows returned |
|
|
124
|
+
| `page` | number | 1 | Page number for paginated results |
|
|
125
|
+
| `sort_by` | varies per tool | varies | Sort field |
|
|
126
|
+
| `sort_order` | `asc`, `desc` | `desc` | Sort direction |
|
|
127
|
+
|
|
128
|
+
## Example usage
|
|
129
|
+
|
|
130
|
+
Once configured, you can ask Claude:
|
|
131
|
+
|
|
132
|
+
- "Show me an overview of my site for the last 7 days"
|
|
133
|
+
- "What are the top traffic sources this month?"
|
|
134
|
+
- "Compare this month's conversions with last month"
|
|
135
|
+
- "Which landing pages have the highest bounce rate?"
|
|
136
|
+
- "Show me revenue by country for Q1"
|
|
137
|
+
|
|
138
|
+
## Development
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
npm install
|
|
142
|
+
npm run build # Compile TypeScript
|
|
143
|
+
npm test # Run tests
|
|
144
|
+
npm run dev # Run with tsx (dev mode)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
MIT
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** Raw JSON response from the API before envelope unwrapping. */
|
|
2
|
+
export interface RawAPIResponse {
|
|
3
|
+
success: boolean;
|
|
4
|
+
data: unknown;
|
|
5
|
+
total?: number;
|
|
6
|
+
page?: number;
|
|
7
|
+
page_size?: number;
|
|
8
|
+
has_next?: boolean;
|
|
9
|
+
has_prev?: boolean;
|
|
10
|
+
comparison?: unknown;
|
|
11
|
+
totals?: unknown;
|
|
12
|
+
[key: string]: unknown;
|
|
13
|
+
}
|
|
14
|
+
export declare class SealMetricsClient {
|
|
15
|
+
private readonly apiKey;
|
|
16
|
+
private readonly baseUrl;
|
|
17
|
+
constructor(apiKey: string, baseUrl: string);
|
|
18
|
+
/**
|
|
19
|
+
* Send an authenticated GET request. Unwraps the API envelope
|
|
20
|
+
* and returns just the `data` field.
|
|
21
|
+
*/
|
|
22
|
+
request<T>(path: string, params?: Record<string, string | undefined>): Promise<T>;
|
|
23
|
+
/**
|
|
24
|
+
* Send an authenticated GET request and return the full JSON body
|
|
25
|
+
* without unwrapping. Use this for endpoints that don't use the
|
|
26
|
+
* standard APIResponse envelope (e.g. alerts, webhooks).
|
|
27
|
+
*/
|
|
28
|
+
requestDirect<T>(path: string, params?: Record<string, string | undefined>): Promise<T>;
|
|
29
|
+
/**
|
|
30
|
+
* Send an authenticated GET request and return the full response
|
|
31
|
+
* including pagination fields (total, page, has_next, etc.).
|
|
32
|
+
* Use this for paginated endpoints.
|
|
33
|
+
*/
|
|
34
|
+
requestPaginated<T>(path: string, params?: Record<string, string | undefined>): Promise<{
|
|
35
|
+
data: T[];
|
|
36
|
+
total: number;
|
|
37
|
+
page: number;
|
|
38
|
+
page_size: number;
|
|
39
|
+
has_next: boolean;
|
|
40
|
+
comparison?: unknown;
|
|
41
|
+
totals?: unknown;
|
|
42
|
+
}>;
|
|
43
|
+
private requestRaw;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAMA,iEAAiE;AACjE,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IAEd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAK3C;;;OAGG;IACG,OAAO,CAAC,CAAC,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAC1C,OAAO,CAAC,CAAC,CAAC;IAKb;;;;OAIG;IACG,aAAa,CAAC,CAAC,EACnB,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAC1C,OAAO,CAAC,CAAC,CAAC;IAKb;;;;OAIG;IACG,gBAAgB,CAAC,CAAC,EACtB,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAC1C,OAAO,CAAC;QACT,IAAI,EAAE,CAAC,EAAE,CAAC;QACV,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,OAAO,CAAC;QAClB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB,CAAC;YAsBY,UAAU;CAkGzB"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { mapHttpError, SealMetricsAPIError } from "./errors.js";
|
|
2
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
3
|
+
const MAX_RETRIES = 2;
|
|
4
|
+
const RETRY_BASE_MS = 1_000;
|
|
5
|
+
export class SealMetricsClient {
|
|
6
|
+
apiKey;
|
|
7
|
+
baseUrl;
|
|
8
|
+
constructor(apiKey, baseUrl) {
|
|
9
|
+
this.apiKey = apiKey;
|
|
10
|
+
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Send an authenticated GET request. Unwraps the API envelope
|
|
14
|
+
* and returns just the `data` field.
|
|
15
|
+
*/
|
|
16
|
+
async request(path, params) {
|
|
17
|
+
const raw = await this.requestRaw(path, params);
|
|
18
|
+
return raw.data;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Send an authenticated GET request and return the full JSON body
|
|
22
|
+
* without unwrapping. Use this for endpoints that don't use the
|
|
23
|
+
* standard APIResponse envelope (e.g. alerts, webhooks).
|
|
24
|
+
*/
|
|
25
|
+
async requestDirect(path, params) {
|
|
26
|
+
const raw = await this.requestRaw(path, params);
|
|
27
|
+
return raw;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Send an authenticated GET request and return the full response
|
|
31
|
+
* including pagination fields (total, page, has_next, etc.).
|
|
32
|
+
* Use this for paginated endpoints.
|
|
33
|
+
*/
|
|
34
|
+
async requestPaginated(path, params) {
|
|
35
|
+
const raw = await this.requestRaw(path, params);
|
|
36
|
+
const result = {
|
|
37
|
+
data: raw.data,
|
|
38
|
+
total: raw.total ?? 0,
|
|
39
|
+
page: raw.page ?? 1,
|
|
40
|
+
page_size: raw.page_size ?? 0,
|
|
41
|
+
has_next: raw.has_next ?? false,
|
|
42
|
+
};
|
|
43
|
+
if (raw.comparison != null)
|
|
44
|
+
result.comparison = raw.comparison;
|
|
45
|
+
if (raw.totals != null)
|
|
46
|
+
result.totals = raw.totals;
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
async requestRaw(path, params) {
|
|
50
|
+
const url = new URL(`${this.baseUrl}${path}`);
|
|
51
|
+
if (params) {
|
|
52
|
+
for (const [key, value] of Object.entries(params)) {
|
|
53
|
+
if (value !== undefined && value !== "") {
|
|
54
|
+
url.searchParams.set(key, value);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
let lastError;
|
|
59
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
60
|
+
if (attempt > 0) {
|
|
61
|
+
const delay = RETRY_BASE_MS * Math.pow(2, attempt - 1);
|
|
62
|
+
await sleep(delay);
|
|
63
|
+
}
|
|
64
|
+
const controller = new AbortController();
|
|
65
|
+
const timeout = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS);
|
|
66
|
+
try {
|
|
67
|
+
const response = await fetch(url.toString(), {
|
|
68
|
+
method: "GET",
|
|
69
|
+
headers: {
|
|
70
|
+
"X-API-Key": this.apiKey,
|
|
71
|
+
Accept: "application/json",
|
|
72
|
+
},
|
|
73
|
+
signal: controller.signal,
|
|
74
|
+
});
|
|
75
|
+
if (response.ok) {
|
|
76
|
+
const text = await response.text();
|
|
77
|
+
try {
|
|
78
|
+
return JSON.parse(text);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
throw new SealMetricsAPIError(response.status, "API returned invalid JSON.", text.slice(0, 500));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const body = await response.text();
|
|
85
|
+
// Retry on 429 (respect Retry-After) or 5xx
|
|
86
|
+
if (response.status === 429 || response.status >= 500) {
|
|
87
|
+
if (response.status === 429) {
|
|
88
|
+
const retryAfter = parseRetryAfter(response.headers.get("Retry-After"));
|
|
89
|
+
if (retryAfter > 0) {
|
|
90
|
+
await sleep(retryAfter);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
lastError = mapHttpError(response.status, body);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
// Non-retryable error
|
|
97
|
+
const siteId = params?.["site_id"] ?? params?.["account_id"] ?? undefined;
|
|
98
|
+
throw mapHttpError(response.status, body, siteId);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
if (error instanceof SealMetricsAPIError) {
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
if (error instanceof Error &&
|
|
105
|
+
error.name === "AbortError") {
|
|
106
|
+
lastError = new SealMetricsAPIError(0, "Request timed out after 30 seconds.");
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
lastError =
|
|
110
|
+
error instanceof Error
|
|
111
|
+
? error
|
|
112
|
+
: new Error("Unknown error occurred");
|
|
113
|
+
// Network errors are retryable
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
finally {
|
|
117
|
+
clearTimeout(timeout);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
throw (lastError ??
|
|
121
|
+
new SealMetricsAPIError(0, "Request failed after retries."));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function sleep(ms) {
|
|
125
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
126
|
+
}
|
|
127
|
+
function parseRetryAfter(header) {
|
|
128
|
+
if (!header)
|
|
129
|
+
return 0;
|
|
130
|
+
const seconds = parseInt(header, 10);
|
|
131
|
+
if (!isNaN(seconds) && seconds > 0 && seconds <= 120) {
|
|
132
|
+
return seconds * 1000;
|
|
133
|
+
}
|
|
134
|
+
return 0;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** SealMetrics API error with user-friendly message. */
|
|
2
|
+
export declare class SealMetricsAPIError extends Error {
|
|
3
|
+
readonly statusCode: number;
|
|
4
|
+
readonly userMessage: string;
|
|
5
|
+
readonly detail?: string | undefined;
|
|
6
|
+
constructor(statusCode: number, userMessage: string, detail?: string | undefined);
|
|
7
|
+
}
|
|
8
|
+
/** Map HTTP status codes to user-friendly error messages. */
|
|
9
|
+
export declare function mapHttpError(status: number, body: string, siteId?: string): SealMetricsAPIError;
|
|
10
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,qBAAa,mBAAoB,SAAQ,KAAK;aAE1B,UAAU,EAAE,MAAM;aAClB,WAAW,EAAE,MAAM;aACnB,MAAM,CAAC,EAAE,MAAM;gBAFf,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,MAAM,YAAA;CAKlC;AAED,6DAA6D;AAC7D,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,GACd,mBAAmB,CAkDrB"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** SealMetrics API error with user-friendly message. */
|
|
2
|
+
export class SealMetricsAPIError extends Error {
|
|
3
|
+
statusCode;
|
|
4
|
+
userMessage;
|
|
5
|
+
detail;
|
|
6
|
+
constructor(statusCode, userMessage, detail) {
|
|
7
|
+
super(userMessage);
|
|
8
|
+
this.statusCode = statusCode;
|
|
9
|
+
this.userMessage = userMessage;
|
|
10
|
+
this.detail = detail;
|
|
11
|
+
this.name = "SealMetricsAPIError";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/** Map HTTP status codes to user-friendly error messages. */
|
|
15
|
+
export function mapHttpError(status, body, siteId) {
|
|
16
|
+
switch (status) {
|
|
17
|
+
case 401:
|
|
18
|
+
return new SealMetricsAPIError(401, "Invalid API key. Generate one at Settings > API Tokens in your SealMetrics dashboard.", body);
|
|
19
|
+
case 403:
|
|
20
|
+
return new SealMetricsAPIError(403, siteId
|
|
21
|
+
? `Access denied to site "${siteId}". Your API key may not have access to this site.`
|
|
22
|
+
: "Access denied. Your API key does not have the required permissions.", body);
|
|
23
|
+
case 404:
|
|
24
|
+
return new SealMetricsAPIError(404, siteId
|
|
25
|
+
? `Site "${siteId}" not found. Use list_sites to see available sites.`
|
|
26
|
+
: "Resource not found.", body);
|
|
27
|
+
case 422:
|
|
28
|
+
return new SealMetricsAPIError(422, `Invalid request parameters: ${extractValidationMessage(body)}`, body);
|
|
29
|
+
case 429:
|
|
30
|
+
return new SealMetricsAPIError(429, "Rate limit exceeded. Please wait a moment before retrying.", body);
|
|
31
|
+
default:
|
|
32
|
+
if (status >= 500) {
|
|
33
|
+
return new SealMetricsAPIError(status, "SealMetrics API is temporarily unavailable. Please try again later.", body);
|
|
34
|
+
}
|
|
35
|
+
return new SealMetricsAPIError(status, `API request failed with status ${status}.`, body);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function extractValidationMessage(body) {
|
|
39
|
+
try {
|
|
40
|
+
const parsed = JSON.parse(body);
|
|
41
|
+
if (parsed.detail) {
|
|
42
|
+
if (Array.isArray(parsed.detail)) {
|
|
43
|
+
return parsed.detail
|
|
44
|
+
.map((d) => `${d.loc?.join(".") ?? "field"}: ${d.msg ?? "invalid"}`)
|
|
45
|
+
.join("; ");
|
|
46
|
+
}
|
|
47
|
+
return String(parsed.detail);
|
|
48
|
+
}
|
|
49
|
+
return body;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return body;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAE1B;IACA;IACA;IAHlB,YACkB,UAAkB,EAClB,WAAmB,EACnB,MAAe;QAE/B,KAAK,CAAC,WAAW,CAAC,CAAC;QAJH,eAAU,GAAV,UAAU,CAAQ;QAClB,gBAAW,GAAX,WAAW,CAAQ;QACnB,WAAM,GAAN,MAAM,CAAS;QAG/B,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,6DAA6D;AAC7D,MAAM,UAAU,YAAY,CAC1B,MAAc,EACd,IAAY,EACZ,MAAe;IAEf,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,GAAG;YACN,OAAO,IAAI,mBAAmB,CAC5B,GAAG,EACH,uFAAuF,EACvF,IAAI,CACL,CAAC;QACJ,KAAK,GAAG;YACN,OAAO,IAAI,mBAAmB,CAC5B,GAAG,EACH,MAAM;gBACJ,CAAC,CAAC,0BAA0B,MAAM,mDAAmD;gBACrF,CAAC,CAAC,qEAAqE,EACzE,IAAI,CACL,CAAC;QACJ,KAAK,GAAG;YACN,OAAO,IAAI,mBAAmB,CAC5B,GAAG,EACH,MAAM;gBACJ,CAAC,CAAC,SAAS,MAAM,qDAAqD;gBACtE,CAAC,CAAC,qBAAqB,EACzB,IAAI,CACL,CAAC;QACJ,KAAK,GAAG;YACN,OAAO,IAAI,mBAAmB,CAC5B,GAAG,EACH,+BAA+B,wBAAwB,CAAC,IAAI,CAAC,EAAE,EAC/D,IAAI,CACL,CAAC;QACJ,KAAK,GAAG;YACN,OAAO,IAAI,mBAAmB,CAC5B,GAAG,EACH,4DAA4D,EAC5D,IAAI,CACL,CAAC;QACJ;YACE,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC;gBAClB,OAAO,IAAI,mBAAmB,CAC5B,MAAM,EACN,qEAAqE,EACrE,IAAI,CACL,CAAC;YACJ,CAAC;YACD,OAAO,IAAI,mBAAmB,CAC5B,MAAM,EACN,kCAAkC,MAAM,GAAG,EAC3C,IAAI,CACL,CAAC;IACN,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,CAAC,IAAY;IAC5C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClB,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;gBACjC,OAAO,MAAM,CAAC,MAAM;qBACjB,GAAG,CACF,CAAC,CAAmC,EAAE,EAAE,CACtC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,KAAK,CAAC,CAAC,GAAG,IAAI,SAAS,EAAE,CAC1D;qBACA,IAAI,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC;YACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* SealMetrics MCP Server
|
|
4
|
-
*
|
|
5
|
-
* A Model Context Protocol server that provides access to SealMetrics analytics data.
|
|
6
|
-
* Allows AI assistants to query traffic, conversions, sales, and generate tracking pixels.
|
|
7
|
-
*/
|
|
8
2
|
export {};
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|