From e511808b8744090172f6d775b0dade1d4ca8dbea Mon Sep 17 00:00:00 2001 From: Franco Zalamena Date: Fri, 23 Oct 2026 11:14:53 +0100 Subject: [PATCH 1/3] Fix the Cursor install steps: import the marketplace, then install The old steps treated "From GitHub Repository" as the install itself. In Cursor it opens an Import Marketplace dialog: the repository becomes a marketplace in the user's account, and the plugin is then installed from it. The steps now cover the dialog's Repository, Scope and Import fields, where the plugin shows up afterwards, and how to confirm the skills and the Context7 server loaded. Also adds the plan differences from Cursor's docs (community plugin import is off by default on Enterprise), the team-marketplace path for admins, and corrects Allow Local Plugin Imports to an Enterprise setting. Steps that Cursor's docs don't name are marked for a check in the live UI. Co-Authored-By: Claude Opus 5.5 --- README.md | 83 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 70 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 551c022..e779221 100644 --- a/README.md +++ b/README.md @@ -135,16 +135,66 @@ select **iterable**, and select **Enable auto-update**. ### Cursor -Cursor requires version 3.9 or later. Install the skills as a plugin: +Cursor installs plugins from a marketplace, so you first add this repository +as a marketplace and then install the plugin from it. Before you start, sign +in to Cursor and update it to the latest version. -1. Open **Customize** in the sidebar. +1. Open **Customize** in the sidebar, then open **Plugins**. 2. Select **+ Add**, then **From GitHub Repository**. -3. Enter `https://github.com/Iterable/iterable-sdk-skill`. -4. Find **iterable-sdk**, select **Install**, and choose the project or user - scope. +3. In **Import Marketplace**, enter + `https://github.com/Iterable/iterable-sdk-skill` under **Repository**. Leave + **Scope** set to **User**, then select **Import**. +4. Cursor switches to the marketplace browser. Select **Personal** or + **Iterable**, whichever the marketplace is listed under, to see its plugins. + Then open **iterable-sdk**. +5. On the plugin's page, select **Install**. If Cursor asks for a scope, choose + the project or user scope. The plugin installs the skills, the scripts they run, and the Context7 MCP -server. Team admins can also add the repository as a team marketplace. +server. To confirm the install, open **Customize** and check that: + +- **Plugins** lists **iterable-sdk**. +- **Skills** lists the six `iterable-*` skills. +- **MCPs** lists `context7`. + +Then start a new Agent chat. + +If **From GitHub Repository** is missing, open the marketplace from +**Customize**, select **Add Marketplace**, then **Import from GitHub**. + +Who can import depends on your plan: + +- **Free and Pro:** follow the steps above. +- **Teams:** the steps above work, because community plugin import is on by + default. +- **Enterprise:** community plugin import is off by default. Ask an admin to + allow it, or to add the repository as a team marketplace. + +If your organization blocks the Context7 MCP server, the plugin still installs, +but its documentation lookups can't run. + +If you installed the plugin in Claude Code, Cursor also loads that copy while +**Include Third-Party Plugins, Skills, and Other Configs** is on, in +**Cursor Settings → Agents → Third-Party Imports**. That copy updates through +Claude Code. + +#### Team marketplace + +On Teams and Enterprise, an admin can share the plugin with the whole team: + +1. Go to **Dashboard → Plugins & MCPs**. +2. In **Team Marketplaces**, click **Add Marketplace**, choose + **Import from Repo**, and paste the repository URL. +3. Add **iterable-sdk** with **Add to Marketplace**. +4. Under **Marketplace Settings**, set **Marketplace Access**, then save. +5. Choose how the plugin is distributed: **Default Off**, **Default On**, or + **Required**. + +Teammates then find the plugin in **Customize**. The Teams plan allows one +imported team marketplace. Auto Refresh needs the Cursor GitHub App on the +repository, so select **Refresh** to pick up a new version. + +#### Local checkout To test a local checkout, clone it into Cursor's local plugin folder: @@ -153,8 +203,10 @@ git clone https://github.com/Iterable/iterable-sdk-skill.git ~/.cursor/plugins/l ``` Run **Developer: Reload Window**, then confirm the skills in **Customize**. -Cursor skips a symlink in that folder that points to a clone elsewhere. On -Teams and Enterprise plans, an admin must allow local plugin imports. +Cursor skips a symlink in that folder that points to a clone elsewhere. If +**iterable-sdk** is also installed from a marketplace, that install takes +precedence over the local copy. On Enterprise, an admin must turn on +**Allow Local Plugin Imports**. #### Fallback: link the skill directories @@ -295,9 +347,12 @@ codex plugin marketplace upgrade iterable Then start a new Codex session. -For Cursor, manage the installed plugin from **Customize**. For a local -plugin checkout, run `git pull` in `~/.cursor/plugins/local/iterable-sdk` and -reload the window. For the clone-and-link fallback: +For Cursor, the plugin is indexed when you import the repository. To get a +newer version, refresh the marketplace from **Customize**, or remove it and +import it again. For a team marketplace, an admin +selects **Refresh** in **Dashboard → Plugins & MCPs**. For a local plugin +checkout, run `git pull` in `~/.cursor/plugins/local/iterable-sdk` and reload +the window. For the clone-and-link fallback: ```bash cd ~/iterable-skills @@ -319,8 +374,10 @@ codex plugin remove iterable-sdk@iterable codex plugin marketplace remove iterable ``` -For Cursor, uninstall the plugin from **Customize**, or delete -`~/.cursor/plugins/local/iterable-sdk` for a local checkout. For the +For Cursor, open **iterable-sdk** in **Customize** and select **Uninstall**. +You can then remove the marketplace. That removes it from your Cursor account +and leaves the repository unchanged. For a local +checkout, delete `~/.cursor/plugins/local/iterable-sdk`. For the clone-and-link fallback, delete the links in `~/.cursor/skills/` and the `~/iterable-skills` clone. From 1f7ae9c1163be21cca5d89c075a33e49f852823a Mon Sep 17 00:00:00 2001 From: Franco Zalamena Date: Fri, 23 Oct 2026 12:37:42 +0100 Subject: [PATCH 2/3] Stop bundling the Context7 MCP server No skill calls it: the skills answer from the docs they ship in reference/, and iterable-android tells agents not to reach for Context7. Bundling it still added a third-party server to every install, one more tool for an agent to wander into, and one an organization may have to approve. The context7.json library listing stays, so Context7 users can still look these docs up. Co-Authored-By: Claude Opus 5.5 --- .mcp.json | 8 ------- README.md | 13 ++++------- mcp.json | 8 ------- pipeline/src/validate-plugins.ts | 40 +++----------------------------- tests/plugin-manifests.sh | 11 --------- tools/install-local | 4 +--- 6 files changed, 8 insertions(+), 76 deletions(-) delete mode 100644 .mcp.json delete mode 100644 mcp.json diff --git a/.mcp.json b/.mcp.json deleted file mode 100644 index c5280c5..0000000 --- a/.mcp.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "mcpServers": { - "context7": { - "type": "http", - "url": "https://mcp.context7.com/mcp" - } - } -} diff --git a/README.md b/README.md index e779221..8e9a231 100644 --- a/README.md +++ b/README.md @@ -150,12 +150,11 @@ in to Cursor and update it to the latest version. 5. On the plugin's page, select **Install**. If Cursor asks for a scope, choose the project or user scope. -The plugin installs the skills, the scripts they run, and the Context7 MCP -server. To confirm the install, open **Customize** and check that: +The plugin installs the skills and the scripts they run. To confirm the +install, open **Customize** and check that: - **Plugins** lists **iterable-sdk**. - **Skills** lists the six `iterable-*` skills. -- **MCPs** lists `context7`. Then start a new Agent chat. @@ -170,9 +169,6 @@ Who can import depends on your plan: - **Enterprise:** community plugin import is off by default. Ask an admin to allow it, or to add the repository as a team marketplace. -If your organization blocks the Context7 MCP server, the plugin still installs, -but its documentation lookups can't run. - If you installed the plugin in Claude Code, Cursor also loads that copy while **Include Third-Party Plugins, Skills, and Other Configs** is on, in **Cursor Settings → Agents → Third-Party Imports**. That copy updates through @@ -211,7 +207,7 @@ precedence over the local copy. On Enterprise, an admin must turn on #### Fallback: link the skill directories If you can't install plugins, clone the repository and link the skill -directories. This installs the skills without the Context7 MCP server: +directories: ```bash git clone --depth 1 https://github.com/Iterable/iterable-sdk-skill.git ~/iterable-skills @@ -291,8 +287,7 @@ notifications afterwards is optional. - Push proof creates or updates one proof template in your Iterable project and sends it only to the test user. The test identity becomes a real user profile in that project. -- The plugin also adds the Context7 MCP server (no API key) for documentation - lookups and, in Claude Code, five helper subagents. +- In Claude Code, the plugin also adds five helper subagents. - You authenticate in your own browser or `gcloud` session. The scripts do not collect account passwords or attempt to bypass sign-in, CAPTCHA, or terms-of-service screens. diff --git a/mcp.json b/mcp.json deleted file mode 100644 index c5280c5..0000000 --- a/mcp.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "mcpServers": { - "context7": { - "type": "http", - "url": "https://mcp.context7.com/mcp" - } - } -} diff --git a/pipeline/src/validate-plugins.ts b/pipeline/src/validate-plugins.ts index 9607545..b2995d3 100644 --- a/pipeline/src/validate-plugins.ts +++ b/pipeline/src/validate-plugins.ts @@ -1,11 +1,11 @@ /** - * Validates Cursor/Claude plugin manifests and MCP config files. + * Validates Cursor/Claude plugin manifests. * * Checks: * - `.cursor-plugin/plugin.json` and `.cursor-plugin/marketplace.json` parse * and have required fields. * - `.claude-plugin/plugin.json` and `.claude-plugin/marketplace.json` parse. - * - `mcp.json` and `.mcp.json` exist and have identical `mcpServers` content. + * - No manifest declares MCP servers; the skills read the docs they ship. * - Declared skill paths exist on disk. * - Every manifest declares the same, valid version. * @@ -93,7 +93,7 @@ function validateCursorPlugin(): void { if ("mcpServers" in manifest) { fail( file, - "omit `mcpServers` — Cursor auto-discovers `mcp.json` at the plugin root", + "omit `mcpServers` — the plugin bundles no MCP server", ); } } @@ -151,39 +151,6 @@ function validateClaudeMarketplace(): void { } } -function validateMcpConfigs(): void { - const cursorMcp = readJson("mcp.json"); - const claudeMcp = readJson(".mcp.json"); - if (!isRecord(cursorMcp) || !isRecord(claudeMcp)) return; - - const cursorServers = cursorMcp.mcpServers; - const claudeServers = claudeMcp.mcpServers; - - if (!isRecord(cursorServers)) { - fail("mcp.json", "`mcpServers` must be an object"); - return; - } - if (!isRecord(claudeServers)) { - fail(".mcp.json", "`mcpServers` must be an object"); - return; - } - - const cursorJson = JSON.stringify(cursorServers); - const claudeJson = JSON.stringify(claudeServers); - if (cursorJson !== claudeJson) { - fail("mcp.json", "`mcpServers` must match `.mcp.json` exactly"); - } - - const context7 = cursorServers.context7; - if (!isRecord(context7)) { - fail("mcp.json", "`mcpServers.context7` is required"); - return; - } - if (context7.url !== "https://mcp.context7.com/mcp") { - fail("mcp.json", "`mcpServers.context7.url` must point at Context7"); - } -} - /** * Hosts decide whether to update by comparing this string to what is already * installed, so a disagreement means some hosts update and others silently do @@ -240,7 +207,6 @@ function main(): void { validateCursorMarketplace(); validateClaudePlugin(); validateClaudeMarketplace(); - validateMcpConfigs(); validateVersions(); if (issues.length === 0) { diff --git a/tests/plugin-manifests.sh b/tests/plugin-manifests.sh index 5901d72..b59abeb 100755 --- a/tests/plugin-manifests.sh +++ b/tests/plugin-manifests.sh @@ -139,17 +139,6 @@ want="$(tr ' ' '\n' <<< "$SHIPPED" | sort | tr '\n' ' ')" && ok "$(printf '%-48s %s' "only client-facing agents are shipped" "$(wc -w <<< "$want" | tr -d ' ') of them")" \ || bad "agents/ has changed" "shipped='${have% }' expected='${want% }' — build roles belong in tools/agents/" -# ------------------------------------------------------------------- the MCP files -# Two names for one file because the hosts look in different places. They drifted -# once; a client on one host would then get doc fetching the other host's client does not. -if [[ -f mcp.json && -f .mcp.json ]]; then - cmp -s mcp.json .mcp.json \ - && ok "mcp.json and .mcp.json are identical" \ - || bad "the two MCP files have drifted" "one host would get different servers" -else - bad "an MCP file is missing" "mcp.json and .mcp.json must both exist" -fi - # ---------------------------------------------------------------- the host's paths # Everything below is read verbatim by a client's agent. An absolute path from this # machine in it is an instruction to use a directory the client does not have — and it diff --git a/tools/install-local b/tools/install-local index 6ab4c32..fba0223 100755 --- a/tools/install-local +++ b/tools/install-local @@ -249,15 +249,13 @@ for s in iterable-provision iterable-android iterable-android-verify iterable-io check "$s/SKILL.md" done check .claude-plugin/plugin.json -check mcp.json -check .mcp.json check agents/ios-provisioner.md for c in onboard wizard gates agent provision teardown discover iterable-keys proof-push handoff config.sh ios-provision ios-prepare-proof ios-install ios-launch ios-observe ios-send ios-deliver ios-verify; do [[ -x "$DEST/bin/$c" || "$c" == config.sh ]] || MISSING="$MISSING bin/$c(not executable)" check "bin/$c" done [[ -z "$MISSING" ]] || die "the build is missing:$MISSING" -say "six skills, the iOS specialist, both MCP files, and every entry point present and executable" +say "six skills, the iOS specialist, and every entry point present and executable" INSTALLED_NAME="$(node -e 'process.stdout.write(require(process.argv[1]).name)' "$MKT_DIR/.claude-plugin/marketplace.json")" [[ "$INSTALLED_NAME" == "$MKT" ]] || die "the marketplace still calls itself '$INSTALLED_NAME'" From baaa1b9c6c838ad9843e40afd90feb6d5b2874ee Mon Sep 17 00:00:00 2001 From: Franco Zalamena Date: Sun, 25 Oct 2026 21:19:06 +0000 Subject: [PATCH 3/3] Bump the plugin to 26.10.11-beta after rebasing onto main The Context7 MCP removal ships on top of 26.10.10-beta; skip the stale 26.10.9-beta bump from the pre-rebase branch. Co-authored-by: Cursor --- .claude-plugin/plugin.json | 2 +- .cursor-plugin/marketplace.json | 2 +- .cursor-plugin/plugin.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index d5a2275..8284e67 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "iterable-sdk", - "version": "26.10.10-beta", + "version": "26.10.11-beta", "description": "Takes an Android or iOS app — native or React Native — from nothing to a push notification proven on a device: Firebase or Apple (APNs) provisioning, version-pinned SDK integration, silent-failure pitfalls, and device-side proof that a push actually arrived. Android proof runs on a device or emulator; iOS proof runs on the iOS Simulator.", "author": { "name": "Iterable" }, "repository": "https://github.com/Iterable/iterable-sdk-skill", diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json index 02ee9d6..3f3fd1b 100644 --- a/.cursor-plugin/marketplace.json +++ b/.cursor-plugin/marketplace.json @@ -3,7 +3,7 @@ "owner": { "name": "Iterable" }, "metadata": { "description": "Iterable's official skills for AI coding assistants — mobile SDK integration guidance.", - "version": "26.10.10-beta" + "version": "26.10.11-beta" }, "plugins": [ { diff --git a/.cursor-plugin/plugin.json b/.cursor-plugin/plugin.json index f02ae5c..c8bb958 100644 --- a/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "iterable-sdk", - "version": "26.10.10-beta", + "version": "26.10.11-beta", "description": "Takes an Android or iOS app — native or React Native — from nothing to a push notification proven on a device: Firebase or Apple (APNs) provisioning, version-pinned SDK integration, silent-failure pitfalls, and device-side proof that a push actually arrived. Android proof runs on a device or emulator; iOS proof runs on the iOS Simulator.", "author": { "name": "Iterable" }, "repository": "https://github.com/Iterable/iterable-sdk-skill",