Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions packages/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Changelog — affitor (CLI)

## 0.4.2
- Security: the secrets file is written with owner-only permissions, and login URLs are opened safely (#26).
- API key rotation: warnings for a key that must be replaced, a clear error for a retired key, and the `Deprecation`/`Sunset`/`Link` headers are read so a retired key is never silent (#27, #30). A refused key points to Regenerate, not to `affitor init` (#28).
- Exit codes: `affitor onboard` exits 0 only when the integration is verified; `affitor whoami --json` exits 1 when logged out, like the human output (#29).
- Docs links point at affitor.com/docs (#32).

## 0.4.1
- Published 2026-06-15.
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "affitor",
"version": "0.4.1",
"version": "0.4.2",
"description": "CLI-native affiliate tracking. Connect Stripe, track commissions, manage partners — all from your terminal.",
"type": "module",
"bin": {
Expand Down
11 changes: 11 additions & 0 deletions packages/mcp/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Changelog — @affitor/mcp

## 0.2.1
- `affitor_track_sale` and `affitor_track_refund` are only registered when `AFFITOR_MCP_WRITE=1`. Without it the server offers 5 tools, none of which can create a sale or reverse a commission. **If you call `affitor_track_sale` from an agent today, add `AFFITOR_MCP_WRITE=1` to the server's `env`.**
- Every tool carries MCP annotations (`readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`); the two money tools are marked destructive.
- `testMode` on `affitor_track_sale` records an `is_test` sale with no commission, under the transaction id `test_<invoiceId>` so it never blocks the real sale with the same invoice; on `affitor_track_lead` it records a test lead; on `affitor_track_refund` it is a dry run that calls nothing.
- `invoiceId` must not be empty on `affitor_track_sale` and `affitor_track_refund`; `affitor_readiness` is marked `openWorldHint` because the check fetches the brand's site.
- README: onboard, MCP tools and recipes documentation backfilled after 0.2.0.

## 0.2.0
- First public release: 7 tools over stdio.
10 changes: 8 additions & 2 deletions packages/mcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,20 @@ Restart your client and the `affitor` tools will be available to the agent.
| ------------------ | -------- | --------------------------------------------------------------------------- |
| `AFFITOR_API_KEY` | Yes | Your Affitor **program API key** (Bearer). Server-side only — never ship it to a browser. |
| `AFFITOR_API_URL` | No | API base override. Defaults to `https://api.affitor.com`. |
| `AFFITOR_MCP_WRITE` | No | Set to `1` to register the two tools that move money: `affitor_track_sale` and `affitor_track_refund`. Off by default, so an agent exploring tools cannot create a real sale or reverse a commission. |

If `AFFITOR_API_KEY` is not set, the server prints a clear message to stderr and exits.

## Tools

Every tool carries MCP annotations (`readOnlyHint`, `destructiveHint`, `idempotentHint`), so a client can ask before a write. `affitor_track_sale` and `affitor_track_refund` are marked destructive and only exist with `AFFITOR_MCP_WRITE=1`.

| Tool | Description |
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `affitor_readiness` | Check this program's integration/onboarding readiness — returns a 5-gate verdict + blocker + next_action. Poll until `integration_verified` is true. |
| `affitor_track_lead` | Report a lead/signup. Binds the customer to the click so later sales attribute by `customerExternalId` alone. |
| `affitor_track_sale` | Report a sale. Resolves attribution by `customerExternalId` (bound at lead time). |
| `affitor_track_refund` | Report a refund (omit amount = full → commission reversed; partial → refunded). Idempotent by `invoiceId`. |
| `affitor_track_sale` | Needs `AFFITOR_MCP_WRITE=1`. Report a sale: creates a real sale and commission unless `testMode` is true. Resolves attribution by `customerExternalId` (bound at lead time). |
| `affitor_track_refund` | Needs `AFFITOR_MCP_WRITE=1`. Report a refund (omit amount = full → commission reversed; partial → refunded). Idempotent by `invoiceId`. `testMode` is a dry run. |
| `affitor_track_click` | Report a click (usually browser-side; public, no customer needed). |
| `affitor_get_integration_plan` | Return the deterministic payment-tracking integration plan for a stack — install, checkout-metadata snippet, `trackSale` snippet + where to inject it, and the verify step. **Pure** — reads the canonical [`@affitor/recipes`](https://www.npmjs.com/package/@affitor/recipes) registry; no SDK client, no network, no side-effects. The agent follows this instead of guessing a contract. |
| `affitor_run_verification` | Fire the synthetic click → lead → sale verification chain through Affitor's REAL attribution pipeline (isolated `is_test` rows). The agent's proof step: run it, then poll `affitor_readiness` until `integration_verified` is true. Rate-limited to **10/program/hour** — on a `rate_limited` result, wait `retry_after_seconds`, don't hammer. |
Expand All @@ -56,6 +59,7 @@ If `AFFITOR_API_KEY` is not set, the server prints a clear message to stderr and
- `customerExternalId?: string` — your own user id; binds this customer to the click.
- `clickId?: string` — Affitor click id (from the `affitor_click_id` cookie).
- `email?: string`
- `testMode?: boolean` — record a test lead (`is_test`).

**`affitor_track_sale`** (one of `customerExternalId` / `clickId` is required)
- `customerExternalId?: string` — your own user id; resolves attribution (no `clickId` needed once bound at lead time).
Expand All @@ -67,11 +71,13 @@ If `AFFITOR_API_KEY` is not set, the server prints a clear message to stderr and
- `isRecurring?: boolean`
- `subscriptionId?: string`
- `subscriptionInterval?: "monthly" | "quarterly" | "annual"`
- `testMode?: boolean` — record a test sale (`is_test`, no commission), sent as transaction `test_<invoiceId>` so it never blocks the real sale with the same invoice.

**`affitor_track_refund`**
- `invoiceId: string` — the sale's idempotency key (the `invoiceId` you passed to `affitor_track_sale`).
- `refundAmountCents?: number` — integer cents. Omit (or `0`) = full refund → commission reversed; partial → refunded.
- `refundReason?: string`
- `testMode?: boolean` — dry run: returns the refund that would be sent and calls nothing (the API has no test refunds).

**`affitor_track_click`** (all optional)
- `affiliateUrl?: string`
Expand Down
2 changes: 1 addition & 1 deletion packages/mcp/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@affitor/mcp",
"version": "0.2.0",
"version": "0.2.1",
"description": "Model Context Protocol (MCP) stdio server for Affitor — lets AI agents (Claude Desktop, Cursor, …) call Affitor affiliate-tracking capabilities as tools.",
"type": "module",
"main": "./dist/index.js",
Expand Down
Loading
Loading