From b4fcc023af58f1bb20f28744cca87fe3346c036d Mon Sep 17 00:00:00 2001 From: Alex Ezell Date: Tue, 4 Aug 2026 10:36:08 -0500 Subject: [PATCH 1/2] Add Cursor attribution headers --- README.md | 7 +++++++ plugins/sprites/mcp.json | 6 +++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index afb0b6f..9866704 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,13 @@ This repository is a Cursor Marketplace plugin. It bundles the hosted **Sprites On first use, Cursor prompts you to authorize with Sprites via OAuth. +## Usage attribution + +The plugin marks its hosted MCP requests as Cursor-driven using the coarse, +privacy-safe [`client-signals`](https://github.com/superfly/client-signals) +headers. The marker is advisory analytics only and is never used for access +control, gating, or rate-limiting. + ## What it provides - **`plugins/sprites/mcp.json`** — the remote Sprites MCP server (`https://sprites.dev/mcp`). diff --git a/plugins/sprites/mcp.json b/plugins/sprites/mcp.json index 984a1a4..efd0740 100644 --- a/plugins/sprites/mcp.json +++ b/plugins/sprites/mcp.json @@ -1,7 +1,11 @@ { "mcpServers": { "sprites": { - "url": "https://sprites.dev/mcp" + "url": "https://sprites.dev/mcp", + "headers": { + "Fly-Client-Interactive": "false", + "Fly-Client-Agent": "cursor" + } } } } From a0756ec0dbd313b9afe25f7d68c26d3f0cb8164d Mon Sep 17 00:00:00 2001 From: Alex Ezell Date: Tue, 4 Aug 2026 12:01:28 -0500 Subject: [PATCH 2/2] Document attribution headers and bump plugin version to 0.2.0 Explain why Fly-Client-Interactive is sent as "false" and why it must not be removed: it is the instrumentation sentinel, so a missing or unparseable value classifies the request as uninstrumented and discards Fly-Client-Agent along with it. Both the removal and the "correction" to true are silent failures that zero out attribution. Add a plain-language attribution disclosure to the plugin README, which is what Marketplace users actually read. Bump both manifests to 0.2.0 so the header change is distributed. --- .cursor-plugin/marketplace.json | 2 +- README.md | 30 ++++++++++++++++++++++ plugins/sprites/.cursor-plugin/plugin.json | 2 +- plugins/sprites/README.md | 6 +++++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json index 07443ef..1a5e28c 100644 --- a/.cursor-plugin/marketplace.json +++ b/.cursor-plugin/marketplace.json @@ -6,7 +6,7 @@ }, "metadata": { "description": "Manage remote Sprites development environments from Cursor.", - "version": "0.1.0" + "version": "0.2.0" }, "plugins": [ { diff --git a/README.md b/README.md index 9866704..f0e56fc 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,36 @@ privacy-safe [`client-signals`](https://github.com/superfly/client-signals) headers. The marker is advisory analytics only and is never used for access control, gating, or rate-limiting. +`plugins/sprites/mcp.json` sets two static headers: + +| Header | Value | Why | +|---|---|---| +| `Fly-Client-Agent` | `cursor` | The canonical agent tag from [`spec/markers.json`](https://github.com/superfly/client-signals/blob/main/spec/markers.json). Any other spelling would be classified as `other`. | +| `Fly-Client-Interactive` | `false` | Required. See below. | + +**Don't remove `Fly-Client-Interactive`, and don't "correct" it to `true`.** +Both are easy mistakes to make, and both are silent: + +- It is the *instrumentation sentinel*. Per + [`spec/request-metrics.md`](https://github.com/superfly/client-signals/blob/main/spec/request-metrics.md), + a request missing this header — or carrying an unparseable value — classifies + as `{"operator": "uninstrumented", "agent": "none"}`, and `Fly-Client-Agent` + is discarded along with it. Dropping this header zeroes out all attribution. +- `false` is correct despite Cursor being human-driven. `Interactive` means + "stdout looks attached to a terminal," not "a human is present." These + requests originate from Cursor's MCP client, where no terminal is attached. + The value is also inert for reporting: operator precedence is + `ci > agent > interactive`, so a present `Fly-Client-Agent` yields + `operator="agent"` either way. + +`Fly-Client-Parent` and `Fly-Client-CI` are deliberately omitted — the spec +states that `Parent` must not affect classification, and false-valued `CI` is +omitted rather than sent. + +To confirm attribution is arriving, check `fly_client_signals_requests_total` +server-side: `operator="agent", agent="cursor"` means the headers landed; +`operator="uninstrumented", agent="none"` means the client stripped them. + ## What it provides - **`plugins/sprites/mcp.json`** — the remote Sprites MCP server (`https://sprites.dev/mcp`). diff --git a/plugins/sprites/.cursor-plugin/plugin.json b/plugins/sprites/.cursor-plugin/plugin.json index f8257f7..4aba726 100644 --- a/plugins/sprites/.cursor-plugin/plugin.json +++ b/plugins/sprites/.cursor-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "sprites", "displayName": "Sprites", - "version": "0.1.0", + "version": "0.2.0", "description": "Manage Sprites — remote, isolated development environments — from Cursor: create, exec, run services, and checkpoint.", "author": { "name": "Fly.io", diff --git a/plugins/sprites/README.md b/plugins/sprites/README.md index 7f057e6..7f42892 100644 --- a/plugins/sprites/README.md +++ b/plugins/sprites/README.md @@ -27,6 +27,12 @@ With this plugin enabled, you can ask Cursor to: - **MCP server** (`mcp.json`) — connects Cursor to `https://sprites.dev/mcp` (remote, OAuth-authenticated). - **Skill** (`skills/sprites`) — workflow and safety guidance for operating sprites from Cursor. +## Usage attribution + +This plugin tags its requests to the Sprites MCP server as coming from Cursor, using the coarse, privacy-safe [`client-signals`](https://github.com/superfly/client-signals) headers. Two fixed values are sent — `cursor` as the client name, and a flag marking the request as non-terminal — so Fly.io can estimate how much Sprites traffic comes through Cursor. + +Nothing user-, machine-, or repository-specific is sent, the values never vary between installs, and the tag is advisory analytics only: it is never used for authentication, authorization, access control, gating, or rate-limiting. + ## Learn more - Sprites: https://sprites.dev