MCP
Remote MCP at https://api.linkdash.dev/mcp. Sign in with OAuth from Claude, ChatGPT, Cursor, and Codex, or use an API key.
Remote MCP at https://api.linkdash.dev/mcp. Add the URL to your client and sign in with your Linkdash account. For agents that run without a person at a browser, use an API key instead. Plain markdown: mcp.md.
Connect
Give the client only the URL https://api.linkdash.dev/mcp. It opens a Linkdash sign-in, then a consent screen that names the app and the site it returns to. Allow it, and the client gets a token for your account.
- claude.ai and Claude Desktop: Settings → Connectors → Add custom connector, with the URL above.
- ChatGPT: add a custom connector in developer mode with the URL above.
- Claude Code:
claude mcp add --transport http linkdash https://api.linkdash.dev/mcp, thenclaude mcp login linkdash(or/mcpin a session). - Cursor: Add to Cursor installs it in one click, then sign in when Cursor asks. Or add the server to
mcp.jsonwith"url"and noheaders. - Codex:
codex mcp add linkdash --url https://api.linkdash.dev/mcp, thencodex mcp login linkdash.
The app gets the same access as an API key. Connected apps are listed under Dashboard → API keys, where Disconnect revokes them at once.
Automation and headless agents
Signing in needs a person at a browser. For CI jobs, scheduled agents, servers, and code that calls MCP directly, send an API key instead: Authorization: Bearer ldash_..., the same keys as the HTTP API.
Cursor (~/.cursor/mcp.json or .cursor/mcp.json):
{
"mcpServers": {
"linkdash": {
"url": "https://api.linkdash.dev/mcp",
"headers": { "Authorization": "Bearer ${env:LINKDASH_API_KEY}" }
}
}
}
Claude Code: claude mcp add --transport http linkdash https://api.linkdash.dev/mcp --header "Authorization: Bearer $LINKDASH_API_KEY" (JSON needs "type": "http").
Codex: codex mcp add linkdash --url https://api.linkdash.dev/mcp --bearer-token-env-var LINKDASH_API_KEY
OpenCode: opencode mcp add linkdash --url https://api.linkdash.dev/mcp --header Authorization="Bearer $LINKDASH_API_KEY"
Local: Convex .site URL + /mcp.
Files
Do not send bytes through MCP JSON. Mint a URL ({uploadUrl,storageId}), PUT the file from the host, then create the link:
curl https://api.linkdash.dev/v1/uploads \
-H "Authorization: Bearer ldash_..." \
-H "Content-Type: application/json" \
-d '{"fileSize":12345}'
curl -X PUT -H "Content-Type: video/mp4" --data-binary @clip.mp4 "$uploadUrl"
curl https://api.linkdash.dev/v1/links \
-H "Authorization: Bearer ldash_..." \
-H "Content-Type: application/json" \
-d '{"storageId":"…","fileName":"clip.mp4","fileType":"video/mp4","fileSize":12345}'
MCP tools: files_upload_url returns {uploadUrl,storageId} → host PUTs to uploadUrl → links_create with that storageId. Optional unfurl card: previewName, previewDescription, previewImageStorageId (same upload). Optional maxOpenings pauses after that many openings; links_update can raise it or pass clearMaxOpenings. Do not print uploadUrl to the user.
Tools
| CLI | HTTP | MCP |
|---|---|---|
auth whoami |
GET /me |
whoami |
links list |
GET /links (?q=&tag=&kind=&status=) |
links_list |
links get <id> |
GET /links/:id (?domain=) |
links_get |
links create --url/--file/--text |
POST /links |
links_create |
links update <id> |
PATCH /links/:id |
links_update |
links delete <id> |
DELETE /links/:id |
links_delete |
links stats --last 24h |
GET /links/:id/stats?last=24h |
links_stats |
links export |
GET /links/export |
links_export |
links import |
POST /links/import |
links_import |
links variants list <id> |
GET /links/:id/variants |
variants_list |
links variants add <id> |
POST /links/:id/variants |
variants_add |
links variants update <id> <name> |
PATCH /links/:id/variants/:name |
variants_update |
links variants remove <id> <name> |
DELETE /links/:id/variants/:name |
variants_remove |
| (host PUT after mint) | POST /uploads |
files_upload_url |
DELETE /uploads/:storageId |
files_discard |
|
webhooks list/create/get/rotate/delete |
GET/POST /webhooks, GET/DELETE /webhooks/:id, POST /webhooks/:id/rotate |
webhooks_* |
domains list/add/connect/verify/remove |
GET/POST /domains, GET /domains/:host/connect, POST /domains/:host/verify, DELETE /domains/:host |
domains_* |
Variants
Every link is a container of one or more variants: content (url | file | text) plus its own gate (password, starts, expires, maxOpenings, paused), a weight, and optional visitor conditions when. Without variants a link has one variant named main. The link gate wins over variant gates. A visitor gets one variant: variants whose when matches form the pool (else the unconditional ones), then a weighted pick; sticky (default true) keeps a returning visitor on the same variant and restartSplit reshuffles. Link kind is group for several variants; link status is mixed when variants differ. Max 20 variants per link. Shapes: HTTP API.
links_create takes variants: [{ name, url | text | storageId (+ fileName, fileType, fileSize), password?, starts?, expires?, maxOpenings?, utm?, weight?, when? }] instead of shorthand, plus sticky and forwardParams. links_update takes sticky, forwardParams, and restartSplit. links_list filters kind (adds group) and status (adds mixed). links_stats returns variants totals. links_export / links_import use the variant CSV (one row per variant).
| Tool | Input |
|---|---|
variants_list |
{ id, domain? } |
variants_add |
{ id, domain?, name, url | text | storageId (+ fileName, fileType, fileSize), password?, starts?, expires?, maxOpenings?, utm?, weight?, when? } |
variants_update |
{ id, name, domain?, newName?, url?, text?, storageId?, password?, clearPassword?, starts?, clearStarts?, expires?, clearExpires?, maxOpenings?, clearMaxOpenings?, status?, weight?, when?, clearWhen?, utm? } |
variants_remove |
{ id, name, domain? } |
when keys: countries, devices, os, browsers, languages, referrerHosts (arrays of strings; every set key must match), plus params.
Query parameter rules. when.params is an array of up to 10 rules on the visitor’s query string, every rule must hold: { "params": [{ "key": "src", "op": "equals", "value": "newsletter" }] }. op: equals | notEquals | includes | startsWith | endsWith | in (value is a |-separated list) | exists | missing (no value for the last two). Keys are case-sensitive, values compare exactly. Parameter values are never stored in analytics.
Forward query parameters. forwardParams (boolean on links_create / links_update, default false) appends the visitor’s whole query string to URL variants; visitor values override stored ones, utm included. URL variants only. Routing, not access control.
auth create / auth login / auth logout are not MCP tools. Mapping: api.md.

