@attrkit/mcp 1.3.0 → 1.4.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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.4.0 (2026-10-21)
4
+
5
+ ### Added
6
+
7
+ - `create_integration` accepts two optional options for a Meta or TikTok integration:
8
+ `delivery_scope` (`all` or `attributed`) and `renewal_event` (`purchase` or `custom`). Each is
9
+ sent only when you give it, so a create without them sends exactly what 1.3.0 sent, and the API
10
+ applies its defaults, `all` and `purchase`. Existing integrations are unchanged.
11
+ - `update_integration` has a new action, `set_delivery_options`, which sets `delivery_scope`,
12
+ `renewal_event` or both in any status and leaves the credential and status as they were. The
13
+ API refuses the action when it names neither option, and refuses `attributed` or `custom` on a
14
+ Google integration.
15
+ - `list_event_deliveries` names `attributed_only_suppressed` among the reasons it can return: the
16
+ connection sends only the events of installs attributed to its network, and this install is
17
+ organic or attributed to another network.
18
+
3
19
  ## 1.3.0 (2026-10-20)
4
20
 
5
21
  ### Added
package/README.md CHANGED
@@ -28,6 +28,16 @@ The server provides 39 tools.
28
28
  `get_campaign_decision` returns the engine's call verbatim. The model reports it;
29
29
  it does not recompute it.
30
30
 
31
+ A Meta or TikTok integration has two delivery options. `delivery_scope` is `all`
32
+ (the default: every install with measurement consent, organic ones included) or
33
+ `attributed` (only installs AttriKit attributes to that network: a click ID, a link
34
+ token, or a device match at or above the delivery floor). `renewal_event`
35
+ is `purchase` (the default: a renewal is sent as Purchase) or `custom` (it is
36
+ sent as the custom event `subscription_renewed`, with its value). Set them on
37
+ `create_integration`, or later with `update_integration` and the action
38
+ `set_delivery_options`, which leaves the credential and status as they are. A
39
+ Google integration refuses `attributed` and `custom`.
40
+
31
41
  ## Before you connect
32
42
 
33
43
  Install Node.js 18 or newer. The `npx -y @attrkit/mcp` command downloads and
package/dist/cli.js CHANGED
@@ -13730,6 +13730,13 @@ var META_NOT_SERVING_CODES = new Set([
13730
13730
  80014
13731
13731
  ]);
13732
13732
  var META_TOKEN_CODES = new Set([102, 190]);
13733
+ var META_ACCESS_CODES = new Set([
13734
+ 10,
13735
+ ...Array.from({ length: 100 }, (_, offset) => 200 + offset)
13736
+ ]);
13737
+ var META_ACCESS_SUBCODES = new Map([
13738
+ [100, new Set([33])]
13739
+ ]);
13733
13740
  // ../shared/src/canonical-events.ts
13734
13741
  var LEDGER_ONLY_CANONICAL_EVENT_NAMES = Object.freeze(["refund_reversed"]);
13735
13742
  // ../shared/src/derived-events.ts
@@ -15075,13 +15082,15 @@ ${body}`
15075
15082
  structuredContent: structured
15076
15083
  }, result.nextCursor);
15077
15084
  }
15078
- var SERVER_VERSION = "1.3.0";
15085
+ var SERVER_VERSION = "1.4.0";
15079
15086
  var periodSchema = z5.enum(["7d", "30d", "90d", "all"]).describe("Reporting window. Omit to use the endpoint's documented default.").optional();
15080
15087
  var appIdSchema = z5.string().describe("Optional app id to scope the result to one app.").optional();
15081
15088
  var requiredAppIdSchema = z5.string().min(1).describe("The AttriKit app id.");
15082
15089
  var encodeOpaquePathSegment = (value) => encodeURIComponent(value).replaceAll(".", "%252E");
15083
15090
  var idempotencyKeySchema = z5.string().max(255).describe("Stable retry key for this exact mutation.").optional();
15084
15091
  var ownersSchema = z5.record(z5.string(), z5.enum(["attrkit", "revenuecat", "customer"]));
15092
+ var deliveryScopeSchema = z5.enum(["all", "attributed"]).optional().describe("Which events a Meta or TikTok integration sends. all (the API's default): the events of every install with measurement consent, organic ones included. attributed: send only events of installs AttriKit attributes to this connection's network (click ID, link token, or device match at or above the delivery floor); others are suppressed with attributed_only_suppressed. Meta and TikTok only: a Google integration refuses attributed.");
15093
+ var renewalEventSchema = z5.enum(["purchase", "custom"]).optional().describe("How a renewal reaches Meta website and TikTok web events. purchase (the API's default): as Purchase with its price and currency. custom: as the custom event subscription_renewed with its price and currency, so Purchase counts one-time purchases only. App events are unchanged. A Google integration refuses custom.");
15085
15094
  var cursorSchema = z5.string().optional().describe("Pass the next_cursor from the previous response to fetch the following page. Omit for the first page.");
15086
15095
  var listLimitSchema = z5.number().int().min(1).max(200).optional().describe("Rows per page, 1-200. The API defaults to 50, so a workspace with more than that needs paging.");
15087
15096
  var calendarDaySchema = z5.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Use a UTC calendar day, YYYY-MM-DD.");
@@ -15436,7 +15445,7 @@ function createServer(config, fetchImpl) {
15436
15445
  server.registerTool("list_event_deliveries", {
15437
15446
  annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
15438
15447
  title: "List what happened to each event sent to ad networks",
15439
- description: "Return one row per delivery of an event to a network connection, newest first: its state (held, queued, sending, retrying, sent, suppressed or failed), the reason with a one-line explanation (for example consent_suppressed or destination_event_too_old), attempts, the last HTTP status, and for a held row when it is expected to be released. Use it to answer why an event did not reach Meta, TikTok or Google. Read scope is enough.",
15448
+ description: "Return one row per delivery of an event to a network connection, newest first: its state (held, queued, sending, retrying, sent, suppressed or failed), the reason with a one-line explanation (for example consent_suppressed, attributed_only_suppressed or destination_event_too_old), attempts, the last HTTP status, and for a held row when it is expected to be released. Use it to answer why an event did not reach Meta, TikTok or Google. Read scope is enough.",
15440
15449
  inputSchema: {
15441
15450
  app_id: requiredAppIdSchema,
15442
15451
  install_id: z5.string().optional().describe("Only this install: the install epoch id the events feed and the export call the install id."),
@@ -15710,33 +15719,48 @@ function createServer(config, fetchImpl) {
15710
15719
  server.registerTool("create_integration", {
15711
15720
  annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
15712
15721
  title: "Create an ad-network integration",
15713
- description: "Store encrypted network credentials and choose, for each of the eight event families (install, session, trial, subscription, purchase, refund, paywall, business), which source's copy AttriKit forwards to the network. AttriKit always does the sending; the owner only picks the copy. attrkit = the events your app reports through the AttriKit SDK (the RevenueCat copy of that family is dropped). revenuecat = the events AttriKit received from your RevenueCat webhook (the SDK copy is dropped); RevenueCat itself sends nothing to the network. customer = events your own servers post to AttriKit. If your app reports subscriptions only through RevenueCat, set trial, subscription, purchase and refund to revenuecat, or none of them reach the network.",
15722
+ description: "Store encrypted network credentials and choose, for each of the eight event families (install, session, trial, subscription, purchase, refund, paywall, business), which source's copy AttriKit forwards to the network. AttriKit always does the sending; the owner only picks the copy. attrkit = the events your app reports through the AttriKit SDK (the RevenueCat copy of that family is dropped). revenuecat = the events AttriKit received from your RevenueCat webhook (the SDK copy is dropped); RevenueCat itself sends nothing to the network. customer = events your own servers post to AttriKit. If your app reports subscriptions only through RevenueCat, set trial, subscription, purchase and refund to revenuecat, or none of them reach the network. For Meta and TikTok, delivery_scope and renewal_event are optional; left out, the integration sends every install's events and renewals as Purchase.",
15714
15723
  inputSchema: {
15715
15724
  network: z5.enum(["meta", "google", "tiktok"]),
15716
15725
  account_ref: z5.string().min(1),
15717
15726
  credential: z5.string().min(1),
15718
15727
  owners: ownersSchema.describe("For each event family, whose copy is forwarded: attrkit, revenuecat or customer (see the tool description). Enabling a destination requires ALL eight families to be present, or the API rejects the call."),
15719
15728
  enable: z5.boolean().optional(),
15729
+ delivery_scope: deliveryScopeSchema,
15730
+ renewal_event: renewalEventSchema,
15720
15731
  idempotency_key: idempotencyKeySchema
15721
15732
  }
15722
- }, async ({ network, account_ref, credential, owners, enable, idempotency_key }) => toToolResult(await call("/api/v1/integrations", {
15723
- method: "POST",
15724
- idempotencyKey: idempotency_key,
15725
- body: { network, account_ref, credential, owners, enable: enable ?? false }
15726
- })));
15733
+ }, async ({ network, account_ref, credential, owners, enable, delivery_scope, renewal_event, idempotency_key }) => {
15734
+ const body = { network, account_ref, credential, owners, enable: enable ?? false };
15735
+ if (delivery_scope !== undefined)
15736
+ body.delivery_scope = delivery_scope;
15737
+ if (renewal_event !== undefined)
15738
+ body.renewal_event = renewal_event;
15739
+ return toToolResult(await call("/api/v1/integrations", {
15740
+ method: "POST",
15741
+ idempotencyKey: idempotency_key,
15742
+ body
15743
+ }));
15744
+ });
15727
15745
  server.registerTool("update_integration", {
15728
15746
  annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
15729
15747
  title: "Update an ad-network integration",
15730
- description: "Rotate credentials or enable/disable an integration.",
15748
+ description: "Rotate credentials or enable/disable an integration. set_delivery_options changes delivery_scope, renewal_event or both on a Meta or TikTok integration, in any status, without touching its credential or status; give at least one of the two.",
15731
15749
  inputSchema: {
15732
15750
  connection_id: z5.string(),
15733
- action: z5.enum(["rotate", "disable", "enable"]),
15751
+ action: z5.enum(["rotate", "disable", "enable", "set_delivery_options"]),
15734
15752
  credential: z5.string().optional(),
15735
15753
  owners: ownersSchema.optional(),
15754
+ delivery_scope: deliveryScopeSchema,
15755
+ renewal_event: renewalEventSchema,
15736
15756
  idempotency_key: idempotencyKeySchema
15737
15757
  }
15738
- }, async ({ connection_id, action, credential, owners, idempotency_key }) => {
15758
+ }, async ({ connection_id, action, credential, owners, delivery_scope, renewal_event, idempotency_key }) => {
15739
15759
  const body = { action };
15760
+ if (delivery_scope !== undefined)
15761
+ body.delivery_scope = delivery_scope;
15762
+ if (renewal_event !== undefined)
15763
+ body.renewal_event = renewal_event;
15740
15764
  if (credential !== undefined)
15741
15765
  body.credential = credential;
15742
15766
  if (owners)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@attrkit/mcp",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "AttriKit's stdio MCP server for its public Management API",
5
5
  "keywords": [
6
6
  "attrkit",
@@ -32,7 +32,7 @@
32
32
  "scripts": {
33
33
  "build": "bun build ./src/cli.ts --outdir ./dist --target=node --format=esm --external @modelcontextprotocol/sdk --external zod",
34
34
  "prepack": "bun run build",
35
- "typecheck": "../../node_modules/typescript-7/bin/tsc --noEmit",
35
+ "typecheck": "tsrs --noEmit",
36
36
  "lint": "node ../../scripts/checks/code-quality-eslint.mjs --workspace packages/mcp",
37
37
  "test": "cd ../.. && vitest run packages/mcp/src"
38
38
  },