If you have spent any time with Claude Desktop or Cursor in the last six months, you have probably noticed the tools panel — a list of named actions the agent can invoke mid-conversation. Those tools come from an MCP server. This post explains what that means, why a URL shortener is a natural fit, and how to wire @elido/mcp-server into both clients so the agent can shorten URLs, generate QR codes, and pull click breakdowns without you leaving the editor.
What MCP is#
The Model Context Protocol is a small open standard that lets an AI client — Claude Desktop, Cursor, or any compatible agent framework — discover and call external tools through a uniform JSON-RPC interface. The server process runs locally on your machine (or on a host you control), exposes a list of typed tools, and communicates with the client over standard input/output. The client sends a tool call request, the server executes the work, and the result flows back into the conversation as context. The model never sees your API key; the server does. The whole wire protocol fits in a few kilobytes per message; there is no SDK you must install on the client side, and the server can be written in any language that can read stdin and write stdout.
The short version: MCP is a standardised way for an AI client to call code you control. The agent describes the intent, the tool does the work, the agent incorporates the result.
Why a URL shortener fits well here#
The friction point with short links in any content workflow is the same: you are in the middle of drafting an email or campaign brief, you need a branded short URL for the CTA, and you have to tab out to the dashboard, create the link, copy it, tab back, and paste it. That context switch costs thirty seconds but, more importantly, it breaks the drafting flow.
MCP eliminates the context switch. When @elido/mcp-server is connected, the agent can call create_link inline — the short URL appears in the conversation and you carry on. The same applies to less obvious cases:
- Drafting a product launch announcement that needs five per-channel UTM links: the agent can call
create_linkfive times in sequence with different tags, then inline all five in the copy. - Asking the agent to produce a QR code for a printed piece:
generate_qrreturns an SVG artifact the agent surfaces in-context. - Reviewing last week's campaign performance:
query_analyticspulls a click timeseries for any link or the whole workspace, timezone-corrected, without you logging into the dashboard.
None of these require the model to understand your API. They require @elido/mcp-server to translate a typed tool call into an authenticated REST request and hand the result back.
The Elido MCP server fits this model straightforwardly. It is a local Node process that sits between the AI client and the Elido REST API. When the agent calls create_link, the server translates that tool call into an authenticated POST /v1/workspaces/{id}/links request, handles workspace resolution, and returns the result as structured text the agent can read. The API key never leaves the server process; the client only sees the tool result.
What the server ships today#
@elido/mcp-server is published as @elido/mcp-server on npm (Apache-2.0, version 0.1.x). The source lives at packages/mcp-server/ in the Elido monorepo. It speaks the stdio MCP transport — line-delimited JSON-RPC 2.0 on stdin/stdout — and has no runtime dependencies beyond Node 20+. It does not use the official @modelcontextprotocol/sdk package; the wire is hand-rolled to keep the package small and easy to audit before you give it an API key.
The five tools available in 0.1.x:
| Tool | What it does |
|---|---|
create_link | Shortens a URL with optional slug, domain, title, and tags. Returns the full link record including the short URL. |
list_links | Lists recent links in the workspace, paginated. |
query_analytics | Click-count timeseries for the workspace or a single link, bucketed by hour or day in any IANA timezone. |
generate_qr | Generates a QR code (SVG or PNG) for an existing link. |
list_workspaces | Enumerates workspaces the API key can see. |
Workspace admin operations — inviting members, rotating API keys, configuring custom domains, managing billing — are intentionally not in the MCP surface. Those stay in the dashboard. The tool surface is scoped to the things an agent doing content or campaign work actually needs inline.
Getting an API key#
Before configuring either client you need an API key scoped to the workspace the agent should operate in.
- Open Settings → API Keys in the Elido dashboard.
- Click New key, give it a name that identifies the agent (e.g.
claude-desktop-mcp), and select Link read/write + Analytics read scope. Do not grant workspace admin scope unless you have a specific reason to. - Copy the key — it is shown once. You will also need the numeric workspace ID, visible in Settings → Workspace → General.
Keep the key out of version control. The MCP config files described below live in your home directory or in a project-local path; do not commit either to a shared repo.
For more on API key scopes and the audit log that surfaces every tool call, see the API keys documentation.
Configuring Claude Desktop#
Claude Desktop reads its MCP server list from a JSON file at:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
If the file does not exist, create it. Add the elido server block inside mcpServers:
{
"mcpServers": {
"elido": {
"command": "npx",
"args": ["-y", "@elido/mcp-server"],
"env": {
"ELIDO_API_KEY": "elido_pk_your_key_here",
"ELIDO_WORKSPACE_ID": "42"
}
}
}
}
Replace elido_pk_your_key_here with your actual key and 42 with your workspace ID.
ELIDO_WORKSPACE_ID is optional if the key has access to exactly one workspace — the server will auto-resolve it. Set it explicitly when the key can see more than one workspace; without it the server has to make an extra round-trip on every tool call that needs a workspace, and the behaviour is unpredictable if access later expands to a second workspace.
After saving the file, quit and relaunch Claude Desktop. The Elido tools appear in the tool panel. If they do not appear, check the Claude Desktop developer console (Help → Show developer tools) for stderr output from the server process — the most common cause is a typo in the key or a command path that does not resolve.
If you prefer to pin the exact package version rather than pulling latest through npx, install it globally first:
npm install -g @elido/mcp-server@0.1
Then replace the command / args pair:
{
"command": "elido-mcp-server",
"args": []
}
Configuring Cursor#
Cursor supports project-local MCP configuration via a .cursor/mcp.json file at the root of the workspace. The format is identical to Claude Desktop's mcpServers block:
{
"mcpServers": {
"elido": {
"command": "npx",
"args": ["-y", "@elido/mcp-server"],
"env": {
"ELIDO_API_KEY": "elido_pk_your_key_here",
"ELIDO_WORKSPACE_ID": "42"
}
}
}
}
Create .cursor/mcp.json at the project root (add it to .gitignore if the repo is shared — the file contains a live API key). Open Cursor Settings → Features → MCP, verify the server is listed and shows a green status indicator, then restart the agent panel. The Elido tools will appear in the Composer tool list.
You can also configure a global Cursor MCP config at ~/.cursor/mcp.json if you want the tools available across all projects without per-project config files. The precedence rules follow the same pattern as Claude Desktop.
Example session: drafting a campaign email and shortening the CTA#
Here is what a real interaction looks like once the server is connected. The agent transcript is condensed but reflects the actual tool call shape.
User: Draft a short campaign email for our spring sale. The CTA should link to https://shop.example.com/spring-2026 — shorten it with the tag spring-2026 and use the slug spring if it's available.
Claude: I will shorten the URL first, then draft the email around the result.
[Tool call: create_link]
{
"destination_url": "https://shop.example.com/spring-2026",
"slug": "spring",
"title": "Spring 2026 sale CTA",
"tags": ["spring-2026"]
}
[Tool result]
{
"id": 1847,
"short_url": "https://s.elido.me/spring",
"destination_url": "https://shop.example.com/spring-2026",
"slug": "spring",
"tags": ["spring-2026"],
"created_at": "2026-05-11T09:14:22Z"
}
Claude: The short link is https://s.elido.me/spring. Here is the email draft:
Subject: Spring sale — up to 40% off, this week only
Hi [First name],
Our spring sale is live. New arrivals, clearance lines, and a few things we've been saving for the right moment.
Shop the sale → https://s.elido.me/spring
Ends Sunday. No code needed.
The agent called create_link with the parameters from your prompt, received the canonical link record back, and used the short_url field in the draft. If the slug spring had been taken, the API would have returned a 409 and the agent would have tried an alternative or surfaced the conflict for you to resolve.
Notice that domain_id was not supplied in the tool call. The server auto-resolves it: if no domain_id is given, it fetches the workspace's domain list and picks the first verified domain. For free-plan workspaces that is f.elido.me; for paid workspaces it is s.elido.me or a custom domain if one is configured. If you want a specific domain, pass its numeric ID explicitly — you can look it up with list_workspaces or from the dashboard.
You can also ask the agent to handle multiple links in a single turn. "Create UTM-tagged links for email, Twitter, and LinkedIn — all pointing to the spring sale page" will result in three sequential create_link calls with different tag sets, and the agent will present all three short URLs in a table you can paste directly into a campaign brief. That pattern replaces a manual UTM builder session in the dashboard for routine campaign setup, though it does not yet support the workspace-level UTM template system (covered in the UTM tracking guide) — that level of automation still goes through the REST API.
Example session: querying click breakdowns#
The second pattern is pulling analytics during a campaign review without opening the dashboard.
User: How did the spring-2026 links perform last week? Break it down by day, Berlin time.
Claude: Let me pull the timeseries for that link.
[Tool call: query_analytics]
{
"link_id": 1847,
"from": "2026-05-04",
"to": "2026-05-10",
"interval": "day",
"tz": "Europe/Berlin"
}
[Tool result]
{
"items": [
{ "bucket": "2026-05-04", "clicks": 312 },
{ "bucket": "2026-05-05", "clicks": 489 },
{ "bucket": "2026-05-06", "clicks": 701 },
{ "bucket": "2026-05-07", "clicks": 1204 },
{ "bucket": "2026-05-08", "clicks": 988 },
{ "bucket": "2026-05-09", "clicks": 623 },
{ "bucket": "2026-05-10", "clicks": 417 }
],
"total": 4734,
"tz": "Europe/Berlin"
}
Claude: The spring link received 4,734 clicks last week. Wednesday–Thursday was the peak (701 → 1,204), which aligns with mid-week email sends. Traffic dropped off through the weekend. If you sent the campaign email Thursday morning Berlin time, the spike tracks.
To compare multiple links, ask the agent to call query_analytics once per link and compile the results. It is a few more tool calls but the agent handles the loop; you get a side-by-side table without opening the dashboard or writing a script.
The tz parameter ensures day buckets align with your local midnight, not UTC. A campaign email sent at 9am CET that you query in UTC will have its first-day traffic split across two UTC days — tz: Europe/Berlin avoids that. The timezone support is from the Phase 6.A analytics work described in the MCP server page.
Security — scoping the key, what the server requests, the audit log#
A few things worth knowing before putting this in front of a team.
Scope the key narrowly. The create_link and generate_qr tools need link write access. query_analytics needs analytics read. list_links and list_workspaces need link read. If your workflow is read-only — pulling metrics during a review — create a key with analytics read + link read only and pass it to the server. The server will call only the endpoints the key permits; everything else returns a 403 that surfaces as an error in the agent response.
What the server sends. Every tool call becomes an authenticated request to api.elido.app with Authorization: Bearer <key>. The server sends the User-Agent: elido-mcp-server/0.1.0 header on every request; that string is visible in the audit log. No data is sent to Anthropic or any third-party service by the server itself — the MCP server is a local process mediating between the client and the Elido API. What data the AI client sends to its own backend (your Claude Desktop prompt, the tool results that flow back into context) is governed by Anthropic's or Cursor's own data policies, not by Elido.
Audit log. Every API call the MCP server makes appears in Settings → Audit Log in the dashboard, tagged with the key name and the originating IP. If you see unexpected tool calls, rotate the key immediately from Settings → API Keys. The audit log is available on Pro and Business plans.
The key in the config file. The env block in claude_desktop_config.json and .cursor/mcp.json stores the key in plaintext. On a personal machine this is acceptable; in a shared or managed environment prefer injecting the key via the system keychain or a secrets manager and referencing it through an environment variable that the MCP config reads indirectly. For team setups, each member should have their own key — shared keys make audit log attribution meaningless.
Honest limits#
A few things the MCP server does not do, by design.
No workspace admin operations. Inviting team members, configuring custom domains, managing plan billing, creating or deleting workspaces — none of these are in the tool surface. Those operations are consequential enough that requiring a logged-in human in the dashboard is the right control. The MCP surface is intentionally scoped to the work a content or campaign agent needs inline. If you need to automate workspace provisioning, the REST API and Terraform provider are the right tools.
No real-time streaming. The current transport is stdio with synchronous request/response. SSE transport is on the roadmap. For most agent workflows — create a link, get a QR code, pull a weekly timeseries — the synchronous model is fine. For a use case that requires streaming a large link list or watching a live click counter, the dashboard or the REST API is the right tool today.
Rate limits apply. The Elido API enforces per-key rate limits regardless of whether the caller is a human, a script, or an MCP server. The limits by plan tier are in the API reference. Agent workflows that call create_link in tight loops — bulk-creating hundreds of links programmatically — should use the REST bulk-import endpoint (POST /v1/links/bulk) directly rather than issuing hundreds of individual create_link tool calls. The MCP server is optimised for interactive, inline use; bulk operations belong to the scripting surface.
query_analytics returns click counts only. The timeseries the query_analytics tool returns is click counts bucketed by time. It does not return geographic breakdowns, device splits, referrer data, or conversion attribution. Those are available in the dashboard and through the full analytics REST API but are not part of the current MCP tool surface. If your agent workflow requires a country breakdown by link, call the REST API directly.
Where to go next#
The server source and issue tracker are at packages/mcp-server/ in the Elido monorepo. The package is published with npm provenance, so every release is cryptographically tied to the commit it was built from — auditing the publish artifact is straightforward.
The MCP integration page has the tool reference, scope matrix, and the self-host configuration for pointing ELIDO_API_BASE at a private Elido instance. If you are on a plan that includes workspace MCP configuration, the page also covers the team key-rotation workflow.
The two setups most worth trying first:
-
Wire up Claude Desktop as described above, open a new conversation, and type "shorten
https://example.com/testwith the tagmcp-test". Watch the tool call fire and the short URL appear in the response. The whole setup should take under five minutes. -
If you already use Cursor for content or docs work, drop
.cursor/mcp.jsonin the project root and ask the Composer to "summarise last week's top links by click count". Thelist_linksandquery_analyticscalls happen inline and the agent writes the summary directly into the chat.
Both are beta (0.1.x) — the tool surface will grow, but existing tool inputs will not break within the 0.1.x range. If something does not work as described here, open an issue with the area:mcp label and we will treat it as a regression.
Related on the blog#
- Hitting p95 < 15ms for redirects from FRA, ASH, and SGP
- Bulk-import short links from a Google Sheet (the real campaign workflow)
- Why we use ClickHouse for click analytics (and not Postgres)
- URL shorteners for SaaS: lifecycle, onboarding, in-product comms
If you are evaluating Elido on cost, the MCP server is available on all plans — the tool calls count against the same API rate limits as any other client. The audit log visibility described above requires Pro or above. See the pricing page for the full plan comparison.
— Marius