mcp-ga4 2.0.6 → 2.0.8

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 CHANGED
@@ -92,6 +92,8 @@ Multi-client mode:
92
92
  }
93
93
  ```
94
94
 
95
+ **Claude Desktop:** Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows).
96
+
95
97
  ## Common Query Patterns
96
98
 
97
99
  **Top pages:**
@@ -1 +1 @@
1
- {"sha":"9f7d432","builtAt":"2026-04-09T21:37:39.488Z"}
1
+ {"sha":"c294c67","builtAt":"2026-04-09T21:59:03.043Z"}
package/dist/errors.d.ts CHANGED
@@ -10,4 +10,8 @@ export declare class Ga4ServiceError extends Error {
10
10
  readonly cause?: unknown | undefined;
11
11
  constructor(message: string, cause?: unknown | undefined);
12
12
  }
13
+ export declare function validateCredentials(): {
14
+ valid: boolean;
15
+ missing: string[];
16
+ };
13
17
  export declare function classifyError(error: any): Error;
package/dist/errors.js CHANGED
@@ -9,7 +9,7 @@ export class Ga4AuthError extends Error {
9
9
  export class Ga4RateLimitError extends Error {
10
10
  retryAfterMs;
11
11
  constructor(retryAfterMs, cause) {
12
- super(`Rate limited, retry after ${retryAfterMs}ms`);
12
+ super(`GA4 rate limited, retry after ${retryAfterMs}ms`);
13
13
  this.retryAfterMs = retryAfterMs;
14
14
  this.name = "Ga4RateLimitError";
15
15
  this.cause = cause;
@@ -23,13 +23,21 @@ export class Ga4ServiceError extends Error {
23
23
  this.name = "Ga4ServiceError";
24
24
  }
25
25
  }
26
+ export function validateCredentials() {
27
+ const missing = [];
28
+ if (!process.env.GA4_PROPERTY_ID?.trim())
29
+ missing.push("GA4_PROPERTY_ID");
30
+ if (!process.env.GOOGLE_APPLICATION_CREDENTIALS?.trim())
31
+ missing.push("GOOGLE_APPLICATION_CREDENTIALS");
32
+ return { valid: missing.length === 0, missing };
33
+ }
26
34
  export function classifyError(error) {
27
35
  const message = error?.message || String(error);
28
36
  const code = error?.code || error?.status;
29
37
  if (code === 401 || code === 403 || code === 7 || code === 16 ||
30
38
  message.includes("PERMISSION_DENIED") || message.includes("UNAUTHENTICATED") ||
31
39
  message.includes("invalid_grant")) {
32
- return new Ga4AuthError(`Auth failed: ${message}. Check credentials.`, error);
40
+ return new Ga4AuthError(`GA4 auth failed: ${message}. Check credentials.`, error);
33
41
  }
34
42
  if (code === 429 || code === 8 || message.includes("RESOURCE_EXHAUSTED") || message.includes("rateLimitExceeded")) {
35
43
  return new Ga4RateLimitError(60_000, error);
package/dist/index.js CHANGED
@@ -411,6 +411,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
411
411
  error: true,
412
412
  error_type: error.name,
413
413
  message: error.message,
414
+ server: __cliPkg.name,
414
415
  };
415
416
  if (error instanceof Ga4AuthError) {
416
417
  response.action_required = "Check service account or OAuth credentials and GA4 property access.";
@@ -426,8 +427,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
426
427
  response.details = rawError.stack;
427
428
  }
428
429
  return {
429
- content: [{ type: "text", text: JSON.stringify(response, null, 2) }],
430
430
  isError: true,
431
+ content: [{ type: "text", text: JSON.stringify(response, null, 2) }],
431
432
  };
432
433
  }
433
434
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mcp-ga4",
3
3
  "mcpName": "io.github.mharnett/ga4",
4
- "version": "2.0.6",
4
+ "version": "2.0.8",
5
5
  "description": "MCP server for Google Analytics 4 - query GA4 data with natural language via Claude.",
6
6
  "main": "dist/index.js",
7
7
  "bin": {