MCP server

Connect Claude, Cursor, VS Code, Windsurf or any Model Context Protocol client to WhichClick — tools, resources, prompts, auth and examples.

Updated 2026-09-02

WhichClick ships a native Model Context Protocol server. An agent connected to it can read the documentation, build tracking templates, inspect campaigns, clicks and fraud stats, create links, validate routing rules and record conversions — all scoped to your organization's API key.

Endpoint#

Text
https://app.whichclick.is/api/mcp
  • Transport: Streamable HTTP (JSON-RPC 2.0 over POST, stateless, JSON responses; no SSE stream is required).
  • Protocol versions: 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05.
  • Auth: Authorization: Bearer wc_live_… (an organization API key). Without a key the server still works but only exposes the documentation tools — useful for public assistants.
  • CORS is open, so browser-based MCP clients can connect directly.

Connect#

Claude Code
claude mcp add --transport http whichclick https://app.whichclick.is/api/mcp \
  --header "Authorization: Bearer wc_live_xxxxxxxx"
Claude Desktop / Cursor / Windsurf (mcp.json)
{
  "mcpServers": {
    "whichclick": {
      "url": "https://app.whichclick.is/api/mcp",
      "headers": { "Authorization": "Bearer wc_live_xxxxxxxx" }
    }
  }
}
VS Code (.vscode/mcp.json)
{
  "servers": {
    "whichclick": { "type": "http", "url": "https://app.whichclick.is/api/mcp", "headers": { "Authorization": "Bearer ${input:whichclick-key}" } }
  },
  "inputs": [ { "id": "whichclick-key", "type": "promptString", "password": true, "description": "WhichClick API key" } ]
}
Clients that only speak stdio
npx -y whichclick-mcp --url https://app.whichclick.is/api/mcp --key wc_live_xxxxxxxx
# (thin bridge in sdk/mcp of the distribution — zero dependencies)
Anthropic Messages API (MCP connector)
const res = await client.beta.messages.create({
  model: "claude-opus-5",
  max_tokens: 2048,
  betas: ["mcp-client-2025-04-04"],
  mcp_servers: [{ type: "url", url: "https://app.whichclick.is/api/mcp", name: "whichclick", authorization_token: process.env.WHICHCLICK_API_KEY }],
  messages: [{ role: "user", content: "Show my invalid click rate for the last 7 days and the top 5 IPs." }],
});

Tools#

ToolWhat it doesAuthEffect
search_docsFull-text search over the WhichClick developer documentation. Returns page + section matches with canonical and Markdown URLs. Use before answering any integration question.none (public)read-only
get_docReturns one documentation page as Markdown. Slugs come from list_docs / search_docs (e.g. 'quickstart', 'tracking/template', 'api/reference', 'ai/mcp').none (public)read-only
list_docsLists every documentation page grouped by section with a one-line description (same content as /llms.txt).none (public)read-only
build_tracking_templateGenerates a Google Ads tracking template and final URL suffix for a tracking domain + link slug that satisfies Google's transparent click tracker guidelines (visible url= next hop, force_transparent=true, ValueTrack capture). Pure function — no account needed.none (public)read-only
validate_routing_rulesValidates a smart-link rules array and optional settings object against the routing schema and reports errors. Use before update_smart_link_routing.none (public)read-only
get_overviewHeadline KPIs for the organization: clicks, installs, conversions, revenue, spend, CPI, ROAS, attribution-method mix, top countries/networks and the per-campaign table for the last N days.API keyread-only
get_pivot_reportClicks, bots, installs, conversions, CVR, spend, CPI, revenue and ROAS grouped by one dimension.API keyread-only
get_metric_timeseriesDaily values of a metric (clicks, installs, conversions, revenue, spend, cpi, cvr, roas, invalid_rate, uninstalls, reengagements or events:<name>) optionally scoped to one campaign.API keyread-only
get_cohortsWeekly install cohorts with D1/D3/D7/D14/D30 retention plus LTV, CPI and ROAS per campaign.API keyread-only
get_protection_statsInvalid/suspicious click rates, reasons, top offending IPs, open incidents, install-fraud flags and CTIT distribution.API keyread-only
list_campaignsCampaigns with id, name, platform, status and external (ad-platform) id.API keyread-only
list_domainsTracking domains with DNS/verification status, Google-certified flag and the CNAME target to configure.API keyread-only
list_tracking_linksGoogle Ads tracking links (GET /c/{slug}) with domain, default final URL, click-id parameter and the ready-to-paste tracking template.API keyread-only
list_smart_linksSmart links (GET /l/{slug}) with store URLs, web fallback, deep-link path, rule count and status.API keyread-only
get_smart_linkFull smart-link configuration including routing rules and settings JSON.API keyread-only
list_appsMobile / CTV apps with platform, bundle id, store URL, deep-link scheme, universal-link host and attribution windows. SDK keys are masked.API keyread-only
list_clicksMost recent click records (ValueTrack fields, next hop, transparency flags, verdict, geo, device) — for debugging a tracking template or exporting offline conversions.API keyread-only
list_conversionsMost recent conversions with matched click id, campaign, value and source.API keyread-only
lookup_ipClassifies an IPv4/IPv6 address using the CIDR intelligence pool: type (residential/datacenter/VPN/proxy/Tor/CDN/search bot), ASN, organisation, geo, risk weight, rate-limit key and the Google Ads exclusion form.API keyread-only
test_smart_link_routeRuns the routing engine for a smart link with a simulated visitor (country, OS, IP, UA, language, params, hour) and returns the decision and the matched rule — without recording a click.API keyread-only
recent_alertsRecently fired alert events and open protection incidents.API keyread-only
create_campaignCreates a campaign container. Set external_id to the ad-platform campaign id so ValueTrack {campaignid} and cost sync line up.API keywrites
create_tracking_linkCreates a Google Ads tracking link on a verified tracking domain and returns the tracking template + final URL suffix to paste into Google Ads.API keywrites
create_smart_linkCreates a smart link (OS routing + store redirect + deferred deep link). Attach an app_id to enable deep-link scheme / universal-link resolution.API keywrites
update_smart_link_routingReplaces the routing rules and/or settings of a smart link after validating them. Cached link config is invalidated immediately.API keywrites
record_conversionRecords a server-side conversion against a click id or gclid (same as POST /api/v1/conversions). Idempotent on order_id + event.API keywrites
set_link_statusSets a tracking link, smart link or campaign to ACTIVE, PAUSED or ARCHIVED.API keywrites
block_ipAdds an IP or CIDR to the organization's protection blocklist (and to Google Ads negative IPs on the next sync).API keywrites

Every tool returns JSON in structuredContent and as text. Write tools are recorded in the audit log with via: "mcp". Tool inputs are validated with the same schemas as the dashboard; invalid input returns isError: true with field-level messages rather than a protocol error.

Resources#

URIContent
whichclick://llms.txtDocumentation index
whichclick://openapi.jsonOpenAPI 3.1 document
whichclick://docs/{slug}Any documentation page as Markdown (template whichclick://docs/{slug})

Prompts#

PromptPurposeArguments
setup_google_ads_trackingGuided setup of certified Google Ads click tracking: domain, link, template, conversion postback and compliance check.tracking_domain, landing_url, campaign_name?
investigate_invalid_clicksAnalyse click-fraud signals for the last N days, list top offenders and recommend blocklist / Google Ads exclusion actions.days?
design_smart_linkDesign a smart link with routing rules (geo, OS, in-app browser, A/B split) for a mobile campaign and validate it with the simulator.goal, app_id?

Raw JSON-RPC examples#

Initialize and list tools (no key needed)
curl -s https://app.whichclick.is/api/mcp -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'

curl -s https://app.whichclick.is/api/mcp -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
Call a tool
curl -s https://app.whichclick.is/api/mcp -H "Content-Type: application/json" -H "Authorization: Bearer wc_live_xxxxxxxx" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"get_protection_stats","arguments":{"days":7}}}'
Response
{ "jsonrpc": "2.0", "id": 3, "result": { "content": [ { "type": "text", "text": "{ \"clicks\": { \"total\": 18422, \"invalid\": 611, \"invalid_rate\": 0.033, … } }" } ], "structuredContent": { "clicks": { "total": 18422, "invalid": 611, "invalid_rate": 0.033 } } } }

Security model#

  • The key's organization is the only tenant visible; there is no cross-organization tool.
  • Read tools are marked readOnlyHint: true; write tools are non-destructive (they create or pause, never delete). Deleting still requires the dashboard.
  • Rate limit: 240 requests / minute per IP on /api/mcp.
  • Revoke the key in Settings → API keys to cut an agent off instantly.

Errors#

JSON-RPC codeMeaning
-32001API key required or invalid for this tool
-32002Resource not found
-32601Unknown method
-32602Invalid params (details in error.data)
-32700Parse error

HTTP 401 with WWW-Authenticate: Bearer is returned when a bearer token is present but invalid; a missing token is not an HTTP error (documentation tools remain available).