@attrkit/mcp 0.4.2 → 0.4.3

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 (2) hide show
  1. package/dist/cli.js +28 -21
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -14059,7 +14059,12 @@ async function callApi(config, path, options = {}) {
14059
14059
  return {
14060
14060
  ok: false,
14061
14061
  status: 0,
14062
- json: { error: { code: "network_error", message: error instanceof Error ? error.message : String(error) } }
14062
+ json: {
14063
+ error: error instanceof Error && error.name === "AbortError" ? {
14064
+ code: "timeout",
14065
+ message: `no response within ${REQUEST_TIMEOUT_MS / 1000}s. The request may still have been applied on the server; retry with the same idempotency_key rather than a new one.`
14066
+ } : { code: "network_error", message: error instanceof Error ? error.message : String(error) }
14067
+ }
14063
14068
  };
14064
14069
  } finally {
14065
14070
  clearTimeout(timer);
@@ -14071,10 +14076,12 @@ function toToolResult(result) {
14071
14076
  const code = envelope?.error?.code ?? `http_${result.status}`;
14072
14077
  const message = envelope?.error?.message ? `: ${envelope.error.message}` : "";
14073
14078
  const retryAfter = result.status === 429 && result.retryAfter ? ` (Retry-After: ${result.retryAfter})` : "";
14079
+ const excerpt = !envelope?.error?.message && result.rawBody ? ` — body: ${result.rawBody.replace(/\s+/g, " ").trim().slice(0, 300)}` : "";
14080
+ const hint = result.status === 401 ? " Check ATTRKIT_API_KEY: this is the same error for a missing, wrong, revoked or expired key." : "";
14074
14081
  return {
14075
14082
  content: [{
14076
14083
  type: "text",
14077
- text: `AttrKit API error (${result.status || "network"}): ${code}${message}${retryAfter}`
14084
+ text: `AttrKit API error (${result.status || "network"}): ${code}${message}${retryAfter}${excerpt}${hint}`
14078
14085
  }],
14079
14086
  isError: true
14080
14087
  };
@@ -14103,16 +14110,16 @@ ${body}`
14103
14110
  structuredContent: structured
14104
14111
  };
14105
14112
  }
14106
- var SERVER_VERSION = "0.4.2";
14113
+ var SERVER_VERSION = "0.4.3";
14107
14114
  var periodSchema = z4.enum(["7d", "30d", "90d", "all"]).describe("Reporting window. Defaults to 30d.").optional();
14108
14115
  var appIdSchema = z4.string().describe("Optional app id to scope the result to one app.").optional();
14109
14116
  var requiredAppIdSchema = z4.string().describe("The AttrKit app id.");
14110
14117
  var idempotencyKeySchema = z4.string().max(255).describe("Stable retry key for this exact mutation.").optional();
14111
14118
  var ownersSchema = z4.record(z4.string(), z4.enum(["attrkit", "revenuecat", "customer"]));
14112
14119
  var spendRowSchema = z4.object({
14113
- campaign_id: z4.string().optional().describe("Required AttrKit campaign id. Preferred snake_case spelling."),
14120
+ campaign_id: z4.string().optional().describe("The AttrKit campaign UUID, NOT the ad network's own campaign id. It is the opposite of create_campaign_link.campaign_id and is the most common mistake here: read it from list_campaigns. The API rejects a network id by name. Preferred snake_case spelling."),
14114
14121
  campaignId: z4.string().optional().describe("Accepted camelCase alias for campaign_id."),
14115
- adset_id: z4.string().optional().nullable(),
14122
+ adset_id: z4.string().optional().nullable().describe("Ad set id. Must be sent together with ad_id; either one alone is rejected."),
14116
14123
  adsetId: z4.string().optional().nullable(),
14117
14124
  ad_id: z4.string().optional().nullable(),
14118
14125
  adId: z4.string().optional().nullable(),
@@ -14397,24 +14404,24 @@ function createServer(config, fetchImpl) {
14397
14404
  description: "Freeze a scale/cut/hold decision and its exact model inputs for later maturity evaluation.",
14398
14405
  inputSchema: {
14399
14406
  app_id: requiredAppIdSchema,
14400
- campaign_id: z4.string(),
14401
- call: z4.enum(["scale", "cut", "hold"]),
14402
- actor: z4.enum(["dashboard", "auto_suggested"]).optional(),
14403
- p05: z4.number(),
14404
- p50: z4.number(),
14405
- p95: z4.number(),
14406
- spend_minor_units: z4.number().nonnegative(),
14407
- currency: z4.string().length(3),
14408
- band_width_pct: z4.number().nonnegative(),
14409
- threshold: z4.number(),
14410
- model_version: z4.string(),
14411
- cost_model_version: z4.number().int().positive().nullable(),
14412
- revenue_per_install_minor_units: z4.number().nonnegative().nullable(),
14407
+ campaign_id: z4.string().describe("The AttrKit campaign uuid, as returned by list_campaigns or get_campaign_decision. Not the ad network's own campaign id."),
14408
+ call: z4.enum(["scale", "cut", "hold"]).describe("The decision being frozen. Report get_campaign_decision's own call verbatim rather than forming your own."),
14409
+ actor: z4.enum(["dashboard", "auto_suggested"]).optional().describe("Who made the call. Use auto_suggested when an agent proposed it without a human confirming."),
14410
+ p05: z4.number().describe("Low end of the profit range from get_campaign_decision, in minor units. Pass through unchanged."),
14411
+ p50: z4.number().describe("Central profit estimate from get_campaign_decision, in minor units. Pass through unchanged."),
14412
+ p95: z4.number().describe("High end of the profit range from get_campaign_decision, in minor units. Pass through unchanged."),
14413
+ spend_minor_units: z4.number().nonnegative().describe("Spend the decision was taken against, in minor units of `currency`."),
14414
+ currency: z4.string().length(3).describe("ISO 4217 code for spend and revenue on this decision, e.g. USD. Three letters."),
14415
+ band_width_pct: z4.number().nonnegative().describe("Width of the profit band as a percentage, from get_campaign_decision. It is how the maturity check later judges whether the range was tight enough to act on."),
14416
+ threshold: z4.number().describe("The profit threshold the call was made against, in minor units."),
14417
+ model_version: z4.string().describe("Model version string from get_campaign_decision. Recorded so a later evaluation knows which model produced the range."),
14418
+ cost_model_version: z4.number().int().positive().nullable().describe("Cost model version from get_campaign_decision, or null when no cost model applied."),
14419
+ revenue_per_install_minor_units: z4.number().nonnegative().nullable().describe("Revenue per install used in the estimate, in minor units, or null when revenue was unavailable."),
14413
14420
  revenue_per_install_quality: z4.enum([
14414
14421
  "campaign_verified_cohort",
14415
14422
  "app_verified_cohort_fallback",
14416
14423
  "unavailable"
14417
- ]),
14424
+ ]).describe("How that revenue figure was derived: from this campaign's own verified cohort, from the app-wide fallback, or not at all. Pass through from get_campaign_decision."),
14418
14425
  idempotency_key: idempotencyKeySchema
14419
14426
  }
14420
14427
  }, async ({
@@ -14629,7 +14636,7 @@ function createServer(config, fetchImpl) {
14629
14636
  network: z4.enum(["meta", "google", "tiktok"]),
14630
14637
  account_ref: z4.string().min(1),
14631
14638
  credential: z4.string().min(1),
14632
- owners: ownersSchema,
14639
+ owners: ownersSchema.describe("Which destination owns each event family. Enabling a destination requires ALL eight families to be present, or the API rejects the call."),
14633
14640
  enable: z4.boolean().optional(),
14634
14641
  idempotency_key: idempotencyKeySchema
14635
14642
  }
@@ -14676,7 +14683,7 @@ function createServer(config, fetchImpl) {
14676
14683
  description: "Store the RevenueCat provider app id and encrypted authorization secret for an app.",
14677
14684
  inputSchema: {
14678
14685
  app_id: requiredAppIdSchema,
14679
- provider_app_id: revenueCatProviderAppIdSchema,
14686
+ provider_app_id: revenueCatProviderAppIdSchema.describe("RevenueCat's PROJECT app id from their dashboard app settings, not the SDK key."),
14680
14687
  authorization_secret: z4.string().min(16).max(1024),
14681
14688
  idempotency_key: idempotencyKeySchema
14682
14689
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@attrkit/mcp",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "AttrKit's stdio MCP server for its public Management API",
5
5
  "keywords": [
6
6
  "attrkit",