MCP Server

The @affitor/mcp Model Context Protocol server — let AI agents (Claude Desktop, Cursor) track clicks, leads, sales and refunds, generate per-stack integration plans, and self-verify attribution as tool calls.

@affitor/mcp is a Model Context Protocol stdio server for Affitor. It exposes Affitor's affiliate-tracking capabilities as MCP tools, so an AI agent — Claude Desktop, Cursor, or any MCP client — can report clicks, leads, sales and refunds, fetch a per-stack integration plan, and prove attribution works, all as native tool calls.

Under the hood it wraps the consolidated server client @affitor/sdk/server (the Affitor class). Authentication is your program API key, supplied via the AFFITOR_API_KEY environment variable.

Info

The @affitor/mcp and @affitor/sdk packages are Beta. The documented happy-path works; report issues on GitHub.


Install as a plugin

In Claude Code and Gemini CLI, the plugin is the quickest way to install. It bundles the MCP server with Affitor's integration guide (a skill in Claude Code, a context file in Gemini CLI). Claude Code asks for your program API key when you enable the plugin; Gemini CLI asks during installation.

/plugin marketplace add Affitor/claude-plugins
/plugin install affitor@affitor

Run the Claude Code commands inside a Claude Code session. Claude Code keeps the key in secure storage, and Gemini CLI keeps it in the system keychain. Source: github.com/Affitor/claude-plugins.

The server is also listed in the Official MCP Registry as com.affitor/mcp, so clients that browse the registry can find it there.

Add it to your MCP client

For any other client, or to configure it yourself, pick your client below. Every option runs the same local server with npx -y @affitor/mcp and passes your program API key as AFFITOR_API_KEY. Replace your_program_key with your key.

claude mcp add affitor --env AFFITOR_API_KEY=your_program_key -- npx -y @affitor/mcp

Where each JSON goes:

  • Claude Desktop: claude_desktop_config.json, in ~/Library/Application Support/Claude/ on macOS or %APPDATA%\Claude\ on Windows.
  • Cursor: .cursor/mcp.json in your project, or ~/.cursor/mcp.json for every project.
  • VS Code: .vscode/mcp.json in your project. VS Code asks for the key once and stores it securely.
  • Other clients (Windsurf, Cline and most others): the client's MCP config file, in the same mcpServers shape.

Restart your client (or reload its MCP servers) and the affitor_* tools become available to the agent. To let the agent report sales and refunds, also add "AFFITOR_MCP_WRITE": "1" to env (see below).

Info

Gemini CLI: some Google plans moved from Gemini CLI to Antigravity CLI. If you use Antigravity CLI, follow Google's migration guide.

Environment variables

VariableRequiredDescription
AFFITOR_API_KEYYesYour Affitor program API key (Bearer). Server-side only — never ship it to a browser.
AFFITOR_API_URLNoAPI base override. Defaults to https://api.affitor.com.
AFFITOR_MCP_WRITENoSet to 1 to add the two tools that move money: affitor_track_sale and affitor_track_refund. Off by default, so an agent exploring the 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.

Info

The program API key is a server-side secret. The MCP server runs locally and reads it from your client config — it is never exposed to the browser or sent to the agent's model.


Tools

The server registers five tools by default, and seven with AFFITOR_MCP_WRITE=1. Each returns the Affitor API's JSON payload as text content; a failed request (a thrown error or an { ok: false } envelope) returns an MCP error result with the message.

ToolInputsDescription
affitor_readinessforceRecheck?: booleanCheck this program's integration/onboarding readiness — returns a 5-gate verdict + blocker + next_action. Poll until integration_verified is true.
affitor_track_clickaffiliateUrl?, pageUrl?, referrerUrl?, existingClickId? (all optional strings)Report a click (usually browser-side; public, no customer needed).
affitor_track_leadcustomerExternalId?: string, clickId?: string, email?: string, testMode?: boolean (one of customerExternalId / clickId required)Report a lead/signup. Binds the customer to the click so later sales attribute by customerExternalId alone.
affitor_track_salecustomerExternalId? / clickId? (one required), amount: number (cents), invoiceId: string, currency?, saleType?, isRecurring?, subscriptionId?, subscriptionInterval?, testMode?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_refundinvoiceId: string, refundAmountCents?: number, refundReason?: string, testMode?: booleanNeeds AFFITOR_MCP_WRITE=1. Report one refund with its own amount; amounts add up on the sale (omit amount = refund the rest → commission reversed). A retry with the same amount is ignored.
affitor_get_integration_planframework, provider, mode?Return the deterministic per-stack integration plan — install, checkout-metadata snippet, trackSale snippet + where to inject it, and the verify step.
affitor_run_verification(none)Fire the synthetic click → lead → sale verification chain through the real attribution pipeline (isolated is_test rows).

Tracking tool inputs

affitor_track_lead — one of customerExternalId / clickId is required:

  • 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 — the lead's email address.
  • testMode?: boolean: record a test lead (flagged is_test) instead of a real one.

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).
  • clickId?: string — Affitor click id.
  • amount: number — sale amount in integer cents (e.g. 4999 = $49.99).
  • invoiceId: string — idempotency key; dedups retries (your invoice / transaction id).
  • currency?: string — USD, EUR, or VND; other codes are not supported. Defaults to USD. Amounts are not converted between currencies: commissions and platform fees are calculated on the amount as sent, and invoices are issued in USD.
  • saleType?: "payment" | "subscription" — one-off payment or subscription.
  • isRecurring?: boolean — whether this sale recurs (subscription renewal).
  • subscriptionId?: string — provider subscription id, if applicable.
  • subscriptionInterval?: "monthly" | "quarterly" | "annual" — billing interval for a subscription sale.
  • testMode?: boolean: record a test sale (flagged is_test) that creates no commission. Leave it off for a real sale.

affitor_track_refund:

  • invoiceId: string — the sale's idempotency key (the invoiceId you passed to affitor_track_sale).
  • refundAmountCents?: number — integer cents, this refund's own amount (not a running total). Omit (or 0) = refund everything not yet refunded → commission reversed; otherwise added to earlier refunds → refunded until the total reaches the sale amount.
  • refundReason?: string — optional human-readable refund reason.
  • testMode?: boolean: a dry run that returns the refund that would be sent and calls nothing. The API has no test mode for refunds.

affitor_track_click — all optional:

  • affiliateUrl?: string — the affiliate/referral URL that was clicked.
  • pageUrl?: string — the landing page URL the click arrived on.
  • referrerUrl?: string — the HTTP referrer URL, if any.
  • existingClickId?: string — reuse an existing Affitor click id instead of minting a new one.

affitor_get_integration_plan

A pure tool: it reads the canonical recipe registry (@affitor/recipes) and returns the deterministic integration plan for a given stack. It never touches the network or the client — so the agent follows a fixed contract instead of guessing one.

InputValuesDescription
frameworknext-app, next-pages, fastify, express, node, unknownThe detected app framework. Determines where trackSale is injected.
providerstripe (default), polar, lemonsqueezy, paddle, unknownThe detected payment provider.
modestripe_connect (default), s2sPayment-tracking mode. stripe_connect = Connect autocaptures the sale (metadata only, no trackSale); s2s = inject trackSale in your webhook.

The plan it returns includes:

  1. install — what to add (npm i @affitor/sdk).
  2. metadata — the checkout-session attribution snippet to plant at checkout creation (always required for Stripe).
  3. sale — the trackSale snippet and exactly where to inject it. For mode: "stripe_connect" this is null — Stripe Connect records the sale server-side, so the agent injects metadata only and must not also call trackSale (the double-count guard).
  4. renewals — for Stripe s2s, a separate case 'invoice.paid' handler so subscription renewals are not silently missed.
  5. verify — the self-verify step (synthetic chain → readiness gate).
Info

Because the CLI (affitor init / affitor onboard), this MCP tool, and the public integration guides all read the same recipe registry, the integration contract can never drift between surfaces.


affitor_run_verification

The agent's proof step. It fires Affitor's synthetic click → lead → sale chain through the real attribution pipeline, writing isolated is_test rows that never create real commissions. Run it, then poll affitor_readiness until integration_verified: true.

The recommended agent loop:

  1. Call affitor_run_verification to fire the chain.
  2. Call affitor_readiness and check integration_verified.
  3. If not yet verified, read the blocker and its gate's next_action, self-correct, and repeat.
Rate limit — back off, don't hammer

affitor_run_verification is rate-limited to 10 runs per program per hour. On a rate_limited result, read retry_after_seconds and wait that long before retrying. A non-2xx (including a 429) returns the parsed error body with the HTTP status merged in, so the agent can read retry_after_seconds and back off rather than crash.


  • Agent Integration — how AI agents auto-install tracking from generated AGENTS.md instruction files.
  • CLI Command Reference — npx affitor onboard, the one-shot equivalent of the MCP flow.
  • SDK Reference — the @affitor/sdk package the MCP server wraps.
  • Track Sale — the full API contract behind affitor_track_sale.
Next recommended step
Prefer a single command?

npx affitor onboard runs detect → install → inject → verify in one shot — the CLI equivalent of the MCP flow.

Continue →
© 2026 Affitor