@apex-inc/mcp-server 0.40.0 → 0.41.1

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 (74) hide show
  1. package/README.md +1 -1
  2. package/dist/api-client.d.ts +21 -1
  3. package/dist/api-client.d.ts.map +1 -1
  4. package/dist/api-client.js +55 -2
  5. package/dist/api-client.js.map +1 -1
  6. package/dist/auth.js +2 -1
  7. package/dist/auth.js.map +1 -1
  8. package/dist/base-url.d.ts +8 -0
  9. package/dist/base-url.d.ts.map +1 -0
  10. package/dist/base-url.js +10 -0
  11. package/dist/base-url.js.map +1 -0
  12. package/dist/index.js +3 -0
  13. package/dist/index.js.map +1 -1
  14. package/dist/prompts.d.ts +14 -0
  15. package/dist/prompts.d.ts.map +1 -1
  16. package/dist/prompts.js +31 -6
  17. package/dist/prompts.js.map +1 -1
  18. package/dist/repo-binding.d.ts +8 -0
  19. package/dist/repo-binding.d.ts.map +1 -0
  20. package/dist/repo-binding.js +13 -0
  21. package/dist/repo-binding.js.map +1 -0
  22. package/dist/resources.d.ts +13 -0
  23. package/dist/resources.d.ts.map +1 -1
  24. package/dist/resources.js +16 -0
  25. package/dist/resources.js.map +1 -1
  26. package/dist/setup-catchup-tools.d.ts +279 -1
  27. package/dist/setup-catchup-tools.d.ts.map +1 -1
  28. package/dist/setup-catchup-tools.js +350 -24
  29. package/dist/setup-catchup-tools.js.map +1 -1
  30. package/dist/setup-checklist.d.ts +68 -0
  31. package/dist/setup-checklist.d.ts.map +1 -0
  32. package/dist/setup-checklist.js +128 -0
  33. package/dist/setup-checklist.js.map +1 -0
  34. package/dist/setup-flow.d.ts +14 -0
  35. package/dist/setup-flow.d.ts.map +1 -0
  36. package/dist/setup-flow.js +52 -0
  37. package/dist/setup-flow.js.map +1 -0
  38. package/dist/tool-groups.d.ts.map +1 -1
  39. package/dist/tool-groups.js +10 -0
  40. package/dist/tool-groups.js.map +1 -1
  41. package/dist/tool-shared.d.ts.map +1 -1
  42. package/dist/tool-shared.js +11 -4
  43. package/dist/tool-shared.js.map +1 -1
  44. package/dist/tools/ad-platforms.d.ts +1 -1
  45. package/dist/tools/ad-platforms.js +23 -23
  46. package/dist/tools/ad-platforms.js.map +1 -1
  47. package/dist/tools/adoption.js +2 -2
  48. package/dist/tools/adoption.js.map +1 -1
  49. package/dist/tools/context.d.ts.map +1 -1
  50. package/dist/tools/context.js +15 -33
  51. package/dist/tools/context.js.map +1 -1
  52. package/dist/tools/experiments.d.ts +2 -2
  53. package/dist/tools/experiments.d.ts.map +1 -1
  54. package/dist/tools/experiments.js +21 -21
  55. package/dist/tools/experiments.js.map +1 -1
  56. package/dist/tools/letters.d.ts +6 -6
  57. package/dist/tools/letters.js +1 -1
  58. package/dist/tools/letters.js.map +1 -1
  59. package/dist/tools/measurement.d.ts +2 -2
  60. package/dist/tools/measurement.d.ts.map +1 -1
  61. package/dist/tools/measurement.js +4 -3
  62. package/dist/tools/measurement.js.map +1 -1
  63. package/dist/tools.d.ts +307 -11
  64. package/dist/tools.d.ts.map +1 -1
  65. package/package.json +3 -2
  66. package/skills/apex-adoption/SKILL.md +1 -1
  67. package/skills/apex-communications/SKILL.md +2 -2
  68. package/skills/apex-experimentation/SKILL.md +6 -6
  69. package/skills/apex-growth-intelligence/SKILL.md +6 -6
  70. package/skills/apex-growth-tracking/SKILL.md +4 -4
  71. package/skills/apex-integration-cookbook/SKILL.md +11 -15
  72. package/skills/apex-journeys/SKILL.md +3 -3
  73. package/skills/apex-partner-network/SKILL.md +1 -1
  74. package/skills/apex-setup/SKILL.md +69 -0
@@ -337,15 +337,11 @@ financial boundary with no API-key lane).
337
337
 
338
338
  ## Recipe: Set up Apex from this repo
339
339
 
340
+ The full flow lives in the `apex-setup` skill and the `/setup-apex` prompt: sign in, which workspace this repo is, name it, install, watch events arrive, conversion, checklist, browser steps, first value.
341
+
340
342
  If get_setup_state shows first-run incomplete, name the merchant before inventing events.
341
343
 
342
- 1. Call `get_setup_state`. If the shop has no name, no vertical, or no conversion model, stop.
343
- 2. `update_organization` with the shop's real name. `update_workspace` with `workspace_name`, `vertical`, `conversion_model`, and `website_url` when you know them. The rail finishes from those saves — do not look for a mark-complete tool.
344
- 3. Name Production (and optional Beta) sites with `list_workspace_environments` / `set_workspace_environments` before you trust the Production slice.
345
- 4. Install the snippet or SDK and wire the events the shop actually fires. Do not invent event names to make a step look done.
346
- 5. Finish writable setup with the matching tools (`claim_links_subdomain`, `set_consent_posture`, webhooks, scoring, invitations, engagement, app platforms, attribution, sender domain, push keys, protect auto-pause). Consent answers are not a live-site tap. Sender-domain records issued are not green — poll `get_sender_domain` until verified.
347
- 6. Hop only when the next incomplete step is a hop: `start_integration_install` for GitHub, Stripe, Meta, Google, LinkedIn, or TikTok. Legal acknowledgements stay on the opened page. You cannot click the ad consoles or the DNS registrar for them.
348
- 7. After ads are connected, make a paid Apex Link before inventing UTMs. Do not stamp conversion ack. `create_apex_link` writes the paid medium. `set_ad_measurement_events` chooses which sales to forward and returns a URL if the legal sentence is still open. `set_conversion_source_of_truth` picks who owns the sale. The rail finishes when those things exist — there is no mark-complete tool.
344
+ After ads are connected, make a paid Apex Link before inventing UTMs. Do not stamp conversion ack. `create_apex_link` writes the paid medium. `set_ad_measurement_events` chooses which sales to forward and returns a URL if the legal sentence is still open. `set_conversion_source_of_truth` picks who owns the sale. The rail finishes when those things exist — there is no mark-complete tool.
349
345
 
350
346
  ## Recipe: Apex Links for app installs (Mobile Measurement)
351
347
 
@@ -358,7 +354,7 @@ const apex = createManagementClient({ apiKey, workspaceKey, apiUrl });
358
354
  // One link per campaign. UTMs become the campaign on the Mobile home's table.
359
355
  const link = await apex.links.create({
360
356
  slug: "spring-bows",
361
- destinationUrl: "https://shop.example.com/spring",
357
+ destinationUrl: "https://www.example.com/spring",
362
358
  utmSource: "meta",
363
359
  utmMedium: "paid_social",
364
360
  utmCampaign: "spring-bows",
@@ -372,18 +368,18 @@ Experiments live under `apex.experiments.*` (`list`, `get`, `getResults`, `activ
372
368
 
373
369
  ## Recipe: Buyer lists on ad platforms (MCP)
374
370
 
375
- A buyer list is one of the shop's segments, kept on Meta, Google or LinkedIn by Apex and refreshed every day. The shop picks it on an ad set once, to leave buyers out of prospecting or to find more people like them. Same as Attribution → Ad platforms → Who sees your ads.
371
+ A buyer list is one of the workspace's segments, kept on Meta, Google or LinkedIn by Apex and refreshed every day. The owner picks it on an ad set once, to leave buyers out of prospecting or to find more people like them. Same as Attribution → Ad platforms → Who sees your ads.
376
372
 
377
373
  1. `list_audiences` shows each list, its segment, the goal it was made for, the platforms it goes to, the platforms it actually reached, and how many people it holds back.
378
- 2. `update_audience` changes where a list goes (`platforms`) or how many people are held back (`holdout_percent`: 0, 5, 10 or 20). 0 stops holding anyone back. Dropping a platform the list already reached deletes the list there, which cannot be undone. Without `confirm_delete: true` the tool changes nothing and lists those platforms in `would_delete_from`; ask the shop, then call again with it. A platform that refuses the delete comes back in `refused`.
379
- 3. `remove_audience` takes the list off every platform it reached. It cannot be undone and any ad set using it stops using it, so ask the shop first and pass `confirm: true` only after they say yes. A platform that refuses comes back in `refused`; tell the shop to delete it there by hand.
374
+ 2. `update_audience` changes where a list goes (`platforms`) or how many people are held back (`holdout_percent`: 0, 5, 10 or 20). 0 stops holding anyone back. Dropping a platform the list already reached deletes the list there, which cannot be undone. Without `confirm_delete: true` the tool changes nothing and lists those platforms in `would_delete_from`; ask the owner, then call again with it. A platform that refuses the delete comes back in `refused`.
375
+ 3. `remove_audience` takes the list off every platform it reached. It cannot be undone and any ad set using it stops using it, so ask the owner first and pass `confirm: true` only after they say yes. A platform that refuses comes back in `refused`; tell the owner to delete it there by hand.
380
376
 
381
377
  A held-back list that belongs to an Ad holdout experiment is the experiment's. These tools refuse it; pause or archive the experiment instead.
382
378
 
383
- When someone asks to be deleted or opts out of ads, Apex takes them off every list right away. If a platform refuses or isn't connected, they stay on it, and `list_audience_removals` shows them: how many each list still owes per platform, why, and what the platform said. Apex retries every day for 30 days, then stops (`stopped_retrying`) and waits for the shop. Tell the shop plainly that people who asked to be removed are still being shown ads there. If `why` is `not_connected`, the shop reconnects the platform; then call `retry_audience_removals` with the list's id, which also tries the ones Apex stopped on. Its `still_owed` says who is left.
379
+ When someone asks to be deleted or opts out of ads, Apex takes them off every list right away. If a platform refuses or isn't connected, they stay on it, and `list_audience_removals` shows them: how many each list still owes per platform, why, and what the platform said. Apex retries every day for 30 days, then stops (`stopped_retrying`) and waits for the owner. Tell the owner plainly that people who asked to be removed are still being shown ads there. If `why` is `not_connected`, the owner reconnects the platform; then call `retry_audience_removals` with the list's id, which also tries the ones Apex stopped on. Its `still_owed` says who is left.
384
380
 
385
- To add a list, start from what the shop wants its ads to do. `list_audience_goals` returns four goals: `win_back` (bought, but not within `window_days`, which comes from the shop's kind of business), `stop_paying` (everyone who ever bought, left out of ads for new people), `interested` (added to cart or started checkout in the last 30 days and never bought; `locked` until those events arrive) and `lookalike` (everyone who bought, with what each spent, for a Meta value-based lookalike). Each says where its list can go now (`networks`) and which lists the shop already made for it (`lists`). If a goal already has a list, ask whether they want another rather than a copy. Tell the shop who goes and where, then call `add_audience` with the goal and `confirm: true`. Apex saves the goal's rule as a segment named after the list, so the shop can change who's on it in Segments, and sends the list right away unless `send_now: false`. The result's `sent` says how many people each platform took. Spend goes only to Meta: neither LinkedIn's nor Google's list upload takes it, so a list that carries spend reaches them as the same people without it. Say so rather than calling a Google or LinkedIn list value-based.
381
+ To add a list, start from what the owner wants its ads to do. `list_audience_goals` returns four goals: `win_back` (bought, but not within `window_days`, which comes from the workspace's kind of business), `stop_paying` (everyone who ever bought, left out of ads for new people), `interested` (added to cart or started checkout in the last 30 days and never bought; `locked` until those events arrive) and `lookalike` (everyone who bought, with what each spent, for a Meta value-based lookalike). Each says where its list can go now (`networks`) and which lists the workspace already made for it (`lists`). If a goal already has a list, ask whether they want another rather than a copy. Tell the owner who goes and where, then call `add_audience` with the goal and `confirm: true`. Apex saves the goal's rule as a segment named after the list, so the owner can change who's on it in Segments, and sends the list right away unless `send_now: false`. The result's `sent` says how many people each platform took. Spend goes only to Meta: neither LinkedIn's nor Google's list upload takes it, so a list that carries spend reaches them as the same people without it. Say so rather than calling a Google or LinkedIn list value-based.
386
382
 
387
- Before sending one of the shop's own events (a trial start, a booked demo) to its ad platforms, call `preview_ad_platform_send` with the event name and what it means (`purchase`, `lead`, `signup`, `subscription`, `add_to_cart`, or `something_else`). Show the shop which platforms would hear it, under what name, and which can't and why, plus the `estimate`: how often it happened in the last 30 days and what a month of sends costs at the shop's price. It saves and sends nothing.
383
+ Before sending one of the workspace's own events (a trial start, a booked demo) to its ad platforms, call `preview_ad_platform_send` with the event name and what it means (`purchase`, `lead`, `signup`, `subscription`, `add_to_cart`, or `something_else`). Show the owner which platforms would hear it, under what name, and which can't and why, plus the `estimate`: how often it happened in the last 30 days and what a month of sends costs at the workspace's price. It saves and sends nothing.
388
384
 
389
- When the shop says yes, call `add_ad_platform_send` with the same event and meaning and `confirm: true`. It saves the send on the shop's Conversion for that event, so experiments and goals count the same thing. If that Conversion already means something else, the tool is refused; change the meaning on Conversions first rather than picking a different meaning to get around it. For `something_else`, Apex makes the conversion on Meta itself so campaigns can optimize for it; if `couldnt_make` comes back, tell the shop Meta's reason (usually a reconnect). A platform showing `not_agreed` only hears it after the shop agrees on Attribution → Ad platforms; the tool never agrees for them. If `without_consent_answer` is `not_sent`, only events that carry a yes go out. `list_ad_platform_sends` shows what is being sent, and `remove_ad_platform_send` stops one and keeps the Conversion.
385
+ When the owner says yes, call `add_ad_platform_send` with the same event and meaning and `confirm: true`. It saves the send on the workspace's Conversion for that event, so experiments and goals count the same thing. If that Conversion already means something else, the tool is refused; change the meaning on Conversions first rather than picking a different meaning to get around it. For `something_else`, Apex makes the conversion on Meta itself so campaigns can optimize for it; if `couldnt_make` comes back, tell the owner Meta's reason (usually a reconnect). A platform showing `not_agreed` only hears it after the owner agrees on Attribution → Ad platforms; the tool never agrees for them. If `without_consent_answer` is `not_sent`, only events that carry a yes go out. `list_ad_platform_sends` shows what is being sent, and `remove_ad_platform_send` stops one and keeps the Conversion.
@@ -97,19 +97,19 @@ This is the canonical journey-skill workflow. **Always involve apex-communicatio
97
97
  The first install letter is a seeded template, not a journey to author from scratch. It starts on `app_install`, waits 24 hours, leaves the moment the person signs up, and sends one letter over push and email with an Apex Link back into the app.
98
98
 
99
99
  ```
100
- 1. get_setup_state → the Mobile Measurement step "first-letter" says whether the shop can reach installers at all
100
+ 1. get_setup_state → the Mobile Measurement step "first-letter" says whether the workspace can reach installers at all
101
101
  (push keys or a verified sender). If neither: stop and send them to Set up Apex. publish_journey refuses
102
102
  a letter it cannot deliver; do not work around that.
103
103
  2. list_journeys → is a mobile-install-nudge journey already there? Turning it on twice sends two letters.
104
104
  3. create_journey_from_template({ template_id: "mobile-install-nudge" }) → a draft with the trigger, wait,
105
105
  exit and send already in place. Do not add_journey_step; review with get_journey.
106
106
  4. Reach is honest by construction: push goes to the device token, so an installer with no account still gets
107
- it; email only goes to people the shop already knows. Say that — "everyone who installs gets the push;
107
+ it; email only goes to people the workspace already knows. Say that — "everyone who installs gets the push;
108
108
  only known people also get the email."
109
109
  5. publish_journey (after check_live_tests). Sends bill the communications meter.
110
110
  ```
111
111
 
112
- The setup step in the dashboard does steps 1–5 in one click with a reach preview; prefer sending the shop there when they are not in the editor.
112
+ The setup step in the dashboard does steps 1–5 in one click with a reach preview; prefer sending the owner there when they are not in the editor.
113
113
 
114
114
  ### "Clean up journeys we don't use"
115
115
 
@@ -188,5 +188,5 @@ Policies:
188
188
 
189
189
  - `apex-integration-cookbook` — end-to-end patterns combining partner network + communications + experiments
190
190
  - MCP tools: `list_partner_programs`, `create_partner_program`, `invite_partner`, `approve_payouts`, `vouch_for_partner`, `get_effective_fees`
191
- - Stripe Connect for the shop is a hop: `start_integration_install` with `type: "stripe"`. Legal acknowledgements stay on the opened page.
191
+ - Stripe Connect for the workspace is a hop: `start_integration_install` with `type: "stripe"`. Legal acknowledgements stay on the opened page.
192
192
  - Docs: `/docs/partner-network/` for concept walkthroughs + integration guides
@@ -0,0 +1,69 @@
1
+ ---
2
+ name: apex-setup
3
+ description: Set up Apex in a repo from the editor. Sign in by browser approval, find or create the workspace this repo belongs to, name it, install and wire events, pick the conversion, work the Set up Apex checklist, stop for browser steps, and end on a first experiment or message. Use when someone says "set up Apex", "install Apex", "connect Apex", or runs /setup-apex.
4
+ ---
5
+
6
+ # Set up Apex in this repo
7
+
8
+ The owner should be looking at live data a few minutes after asking. They only open a browser when a person has to sign in, pay, or own a console or DNS.
9
+
10
+ Three rules hold the whole way:
11
+
12
+ - **No tool marks a step done.** Steps finish when the real thing happens: the name is saved, events arrive, the domain verifies. If a step looks stuck, the thing it waits on has not happened.
13
+ - **The owner's "no" is theirs.** Record a skip or decline only after they say so, in their words.
14
+ - **Every setup reply names the workspace it wrote to** (`workspace`). If it is not this repo's workspace, stop and switch before the next write.
15
+
16
+ The same steps run as the `/setup-apex` prompt.
17
+
18
+ ## 1. Sign in
19
+ Call get_setup_state. If Apex is not connected yet, the reply carries an approval link: show it, call wait_for_apex_approval, then carry on. Sign-in is browser approval only. Never ask for, paste, or save an API key to set up. If a reply starts with APEX_WAITING_FOR_ACCESS, say so in one sentence, give the link it names, and stop.
20
+
21
+ ## 2. Which workspace is this repo
22
+ Read .apex/workspace.json. If it exists, switch_workspace to its workspace_key. If not, look for an Apex snippet or SDK workspace key in the code; that key is the workspace, and you write the file. If neither, ask the owner once: one of their workspaces (list_orgs shows them by organization), a new workspace in one of their organizations (create_workspace), or a separate company (create_organization). Ask "separate company, or another site of the same business?" before creating either. Write and commit the file. Every setup reply names the workspace it wrote to; if it is not this repo's workspace, stop and switch.
23
+
24
+ ## 3. Name the workspace from the repo
25
+ If get_setup_state shows first-run incomplete, name the merchant before inventing events. Read the repo (package name, README, site config) and propose the organization name, workspace name, what the organization does, how people convert, and the website. Confirm with the owner, then save with update_organization and update_workspace. Set site_install to codebase when you install from this repo.
26
+
27
+ ## 4. Install and wire events
28
+ Install the SDK or snippet the checklist names. Read get_event_spec before writing track calls, scan the code for what the site actually does, and report it with propose_wiring_plan. Wire those events. Do not invent event names to make a step look done. Then watch them arrive with apex_recent_events and get_wiring_status before moving on.
29
+
30
+ ## 5. Pick what counts as a conversion
31
+ Ask the owner which event is the sale, signup, or lead that matters. Save it with create_conversion and set_primary_conversion.
32
+
33
+ ## 6. Work the checklist
34
+ Call get_setup_state after every write and work the next step with the tool it names. When the owner says a step or area is not for them, record it with skip_setup_step or decline_setup_area, in their words. Never record one to make progress look finished. No tool marks a step done; steps finish when the real thing happens.
35
+
36
+ ## 7. Browser steps
37
+ When the next step needs a person (payment, an ad or app store console, DNS, legal acknowledgements), give the link and the reason from the checklist and wait. Use start_integration_install for GitHub, Stripe, ad platforms, and Google Analytics; it polls until connected. After ads are connected, make a paid Apex Link before inventing UTMs.
38
+
39
+ ## 8. First value
40
+ Once events are live, show the owner what arrived with apex_recent_events, and give them the live stream link it returns so they can watch their own site talk to Apex. Then propose exactly one first step from what you learned about the organization: one experiment with plan_experiment, or one message with recommend_communications. Say why it fits this workspace in a sentence. Create nothing live without the owner's yes; a draft they can open is fine.
41
+
42
+ ## Things that look done and are not
43
+
44
+ - Name Production (and optional Beta) sites with `list_workspace_environments` / `set_workspace_environments` before you trust the Production numbers.
45
+ - Consent answers (`set_consent_posture`) are not a tap on the live site. The owner still taps Allow there.
46
+ - Sender-domain records issued are not verified. Poll `get_sender_domain` until it is.
47
+ - Legal acknowledgements stay on the page `start_integration_install` opens. You cannot click the ad consoles or the DNS registrar for them.
48
+
49
+ ## The repo binding file
50
+
51
+ `.apex/workspace.json` is committed with the repo:
52
+
53
+ ```json
54
+ {
55
+ "workspace_key": "atlas-provisions-x1",
56
+ "workspace_name": "Atlas Provisions",
57
+ "org_name": "Acme Co"
58
+ }
59
+ ```
60
+
61
+ The workspace key is not a secret; it already ships in the site's snippet. One editor install serves every workspace the person can reach, and each repo's file decides which one it is. `create_workspace` and `create_organization` return this file's contents in `repo_binding`.
62
+
63
+ ## Example: two companies, one person
64
+
65
+ Noah is signed in with his personal workspace. He opens his company's repo and says "set up Apex in this repo." There is no binding file and no snippet, so the agent asks which workspace. He picks "a separate company". The agent creates the "Acme Co" organization, switches to its workspace, writes `.apex/workspace.json`, and runs setup. Back in his personal repo, that repo's file sends the agent to his personal workspace with no question asked.
66
+
67
+ ## Keys are for servers
68
+
69
+ An API key is for a server or CI job that cannot do browser approval (`/apex-keys`). Never put one in a committed file. Receipt keys and server keys go in the host's secret store.