@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.
Files changed (94) hide show
  1. package/README.md +149 -0
  2. package/dist/client.d.ts +45 -0
  3. package/dist/client.d.ts.map +1 -0
  4. package/dist/client.js +136 -0
  5. package/dist/client.js.map +1 -0
  6. package/dist/errors.d.ts +10 -0
  7. package/dist/errors.d.ts.map +1 -0
  8. package/dist/errors.js +55 -0
  9. package/dist/errors.js.map +1 -0
  10. package/dist/index.d.ts +1 -6
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +122 -781
  13. package/dist/index.js.map +1 -0
  14. package/dist/resources/tracking-guide.d.ts +13 -0
  15. package/dist/resources/tracking-guide.d.ts.map +1 -0
  16. package/dist/resources/tracking-guide.js +479 -0
  17. package/dist/resources/tracking-guide.js.map +1 -0
  18. package/dist/tools/alerts.d.ts +5 -0
  19. package/dist/tools/alerts.d.ts.map +1 -0
  20. package/dist/tools/alerts.js +80 -0
  21. package/dist/tools/alerts.js.map +1 -0
  22. package/dist/tools/audience.d.ts +7 -0
  23. package/dist/tools/audience.d.ts.map +1 -0
  24. package/dist/tools/audience.js +146 -0
  25. package/dist/tools/audience.js.map +1 -0
  26. package/dist/tools/bots.d.ts +4 -0
  27. package/dist/tools/bots.d.ts.map +1 -0
  28. package/dist/tools/bots.js +52 -0
  29. package/dist/tools/bots.js.map +1 -0
  30. package/dist/tools/channels.d.ts +5 -0
  31. package/dist/tools/channels.d.ts.map +1 -0
  32. package/dist/tools/channels.js +88 -0
  33. package/dist/tools/channels.js.map +1 -0
  34. package/dist/tools/content.d.ts +3 -0
  35. package/dist/tools/content.d.ts.map +1 -0
  36. package/dist/tools/content.js +47 -0
  37. package/dist/tools/content.js.map +1 -0
  38. package/dist/tools/conversions.d.ts +6 -0
  39. package/dist/tools/conversions.d.ts.map +1 -0
  40. package/dist/tools/conversions.js +178 -0
  41. package/dist/tools/conversions.js.map +1 -0
  42. package/dist/tools/funnel.d.ts +3 -0
  43. package/dist/tools/funnel.d.ts.map +1 -0
  44. package/dist/tools/funnel.js +27 -0
  45. package/dist/tools/funnel.js.map +1 -0
  46. package/dist/tools/index.d.ts +16 -0
  47. package/dist/tools/index.d.ts.map +1 -0
  48. package/dist/tools/index.js +79 -0
  49. package/dist/tools/index.js.map +1 -0
  50. package/dist/tools/manage.d.ts +3 -0
  51. package/dist/tools/manage.d.ts.map +1 -0
  52. package/dist/tools/manage.js +55 -0
  53. package/dist/tools/manage.js.map +1 -0
  54. package/dist/tools/overview.d.ts +3 -0
  55. package/dist/tools/overview.d.ts.map +1 -0
  56. package/dist/tools/overview.js +26 -0
  57. package/dist/tools/overview.js.map +1 -0
  58. package/dist/tools/pages.d.ts +7 -0
  59. package/dist/tools/pages.d.ts.map +1 -0
  60. package/dist/tools/pages.js +207 -0
  61. package/dist/tools/pages.js.map +1 -0
  62. package/dist/tools/properties.d.ts +5 -0
  63. package/dist/tools/properties.d.ts.map +1 -0
  64. package/dist/tools/properties.js +107 -0
  65. package/dist/tools/properties.js.map +1 -0
  66. package/dist/tools/segments.d.ts +4 -0
  67. package/dist/tools/segments.d.ts.map +1 -0
  68. package/dist/tools/segments.js +49 -0
  69. package/dist/tools/segments.js.map +1 -0
  70. package/dist/tools/shared.d.ts +45 -0
  71. package/dist/tools/shared.d.ts.map +1 -0
  72. package/dist/tools/shared.js +139 -0
  73. package/dist/tools/shared.js.map +1 -0
  74. package/dist/tools/sites.d.ts +4 -0
  75. package/dist/tools/sites.d.ts.map +1 -0
  76. package/dist/tools/sites.js +36 -0
  77. package/dist/tools/sites.js.map +1 -0
  78. package/dist/tools/tracking.d.ts +3 -0
  79. package/dist/tools/tracking.d.ts.map +1 -0
  80. package/dist/tools/tracking.js +220 -0
  81. package/dist/tools/tracking.js.map +1 -0
  82. package/dist/tools/traffic.d.ts +10 -0
  83. package/dist/tools/traffic.d.ts.map +1 -0
  84. package/dist/tools/traffic.js +273 -0
  85. package/dist/tools/traffic.js.map +1 -0
  86. package/dist/tools/webhooks.d.ts +5 -0
  87. package/dist/tools/webhooks.d.ts.map +1 -0
  88. package/dist/tools/webhooks.js +101 -0
  89. package/dist/tools/webhooks.js.map +1 -0
  90. package/dist/types.d.ts +118 -0
  91. package/dist/types.d.ts.map +1 -0
  92. package/dist/types.js +22 -0
  93. package/dist/types.js.map +1 -0
  94. 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
@@ -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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"}
@@ -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":""}