Getting started

Claude Code, Cursor and MCP

Usero runs a remote Model Context Protocol server at https://usero.io/mcp. Point Claude Code, Cursor, Claude Desktop, Windsurf or VS Code at it and the agent can read your feedback inbox, pull the clusters with verbatim quotes, file feedback, and ask Usero to open an AI-written pull request, all from inside your editor.

Nothing to install. One config block with the URL and your API key. Fixes ship on our side. No account yet? The agent can sign you up itself, see the next section.

Set up from inside the agent

You do not need a Usero account, an API key or a dashboard visit to start. Add the server without a key and ask the agent to set you up:

bash
claude mcp add --transport http usero https://usero.io/mcp
claude -p "set me up with usero, my email is you@example.com"

Without a key the server exposes two tools, start_signup and check_signup, and the agent runs this flow:

  1. start_signup(email, clientName) emails you a sign-in link and returns a poll token. The email names the agent that asked ("Claude Code", "Cursor", or "an MCP client" for anything we do not recognise) and the IP it came from. Any earlier link for the same address stops working the moment a new one is sent.
  2. You open the link. The page repeats who asked, from where, and for which account, and has one button, "Yes, connect Claude Code", plus "This was not me". Opening the page does nothing on its own (link scanners open emailed URLs); pressing the button signs you in, creating the account if the email is new. The page never shows a key.
  3. The agent polls check_signup(pollToken). After you press the button it receives an API key named after the agent, minted at that moment and exactly once. The poll token is dead after that, and both the link and the token expire 15 minutes after start_signup. No key exists until the agent collects it, so an unpolled confirmation leaves nothing behind.
  4. The agent saves the key into its MCP config (for Claude Code, claude mcp remove usero then claude mcp add with the --header from the next section, since Claude Code will not overwrite a server name in place) and, now authenticated, calls create_client(name, repo?) for your product and connect_github(clientId) for the GitHub App install URL, then check_github(clientId) until the install lands.

An existing account signing in this way gets a new key and nothing else changes. Limits: 5 links per email per hour, 10 per IP per hour. Every other tool answers 401 until a key is sent.

Get an API key

  1. Sign in and open your profile.
  2. Under API keys, create a key. Name it after the tool that will use it ("Claude Code on my laptop").
  3. Copy it once. Keys look like usk_live_... and are only shown at creation.

The key acts as you: the agent sees every client you are a member of and nothing else. Revoke it from the same page.

Connect your client

Replace usk_live_... with your key in each snippet.

Claude Code

bash
claude mcp add --transport http usero https://usero.io/mcp --header "Authorization: Bearer usk_live_..."

Add --scope user to make it available in every project, or --scope project to commit a .mcp.json for your team (put the key in an environment variable in that case, not in the file). Check it with claude mcp list, then try claude -p "list my usero clients".

Cursor

Create or edit .cursor/mcp.json in your project (or ~/.cursor/mcp.json for every project):

json
{
	"mcpServers": {
		"usero": {
			"url": "https://usero.io/mcp",
			"headers": {
				"Authorization": "Bearer usk_live_..."
			}
		}
	}
}

Open Cursor Settings, then MCP, and confirm "usero" shows its tools.

Claude Desktop

Settings, then Connectors, then Add custom connector. Enter https://usero.io/mcp as the URL. When asked for authentication, add a header named Authorization with the value Bearer usk_live_.... If your version of Claude Desktop has no header field, use the claude_desktop_config.json form below with mcp-remote:

json
{
	"mcpServers": {
		"usero": {
			"command": "npx",
			"args": ["-y", "mcp-remote", "https://usero.io/mcp", "--header", "Authorization: Bearer usk_live_..."]
		}
	}
}

Windsurf

Edit ~/.codeium/windsurf/mcp_config.json:

json
{
	"mcpServers": {
		"usero": {
			"serverUrl": "https://usero.io/mcp",
			"headers": {
				"Authorization": "Bearer usk_live_..."
			}
		}
	}
}

VS Code (GitHub Copilot agent mode)

Create .vscode/mcp.json:

json
{
	"servers": {
		"usero": {
			"type": "http",
			"url": "https://usero.io/mcp",
			"headers": {
				"Authorization": "Bearer usk_live_..."
			}
		}
	}
}

Anything else

Any client that speaks MCP over streamable HTTP works. The server is stateless JSON-RPC 2.0 over POST, no session id, no SSE. A raw call looks like this:

bash
curl -s https://usero.io/mcp \
  -H "Authorization: Bearer usk_live_..." \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Tools

Every tool is scoped to the clients your key can access. Read tools are marked read-only so clients that ask before running side effects can skip the prompt. Argument schemas are strict: an unknown argument is an error, not a silent no-op. Date arguments accept a full ISO datetime or a bare YYYY-MM-DD (read as midnight UTC).

Tool Arguments What it returns
start_signup email, clientName? No key needed. Emails a sign-in link naming the agent and replaces any earlier pending link for that address; returns pollToken and expiresInMinutes. 5 per email per hour, 10 per IP per hour.
check_signup pollToken No key needed. pending until the user confirms on the emailed page, then ready with apiKey (minted at that moment) exactly once; the token is dead afterwards. Expired tokens return an error naming the fix.
create_client name, repo? Creates a client (one per product) and returns its clientId and dashboard URL. repo only works if the GitHub App already reaches it; otherwise leave it out and use connect_github.
connect_github clientId, repo? Returns the GitHub App install URL bound to the client. Once installed, repo picks which of the covered repositories PRs go to (single-repo installs are picked automatically).
check_github clientId pending until the install lands, then connected with the chosen repo (or null) and every repos the installation covers.
list_clients nameContains?, limit? (default 25, max 100), offset? A page of your clients, newest first, each with id, name, open feedback count, environment names (busiest first) and dashboard URL, plus totalCount, hasMore and nextOffset. Call this first.
search_feedback clientId, environment?, query?, status? (open, resolved, all), source?, since? (created), resolvedSince? (resolved), sort? (newest, oldest, severity), hasScreenshot?, limit? (max 50) Feedback with AI summary, category, severity, verbatim quotes, sender, screenshot count, replay flag, resolvedAt and resolutionMessage, and dashboard URL. Defaults to open items, newest first. Comment bodies cut at 400 chars.
get_feedback id One item in full: comment, quotes, person, screenshots, session replay link, clusters, pull requests.
list_clusters clientId, includeAddressed?, limit? (max 100) Feedback clusters biggest first with severity, urgency, AI summary, up to three sample verbatim quotes each, and PR state. Clusters span environments.
get_cluster clusterId, memberLimit? (default 50, max 200) The cluster with its members (highest confidence first), each with quotes and sender, open and total member counts, plus its pull request if any.
create_feedback clientId, environment?, title, body, pageUrl?, userEmail? Files a feedback item with source mcp. It is classified and clustered like any other item.
get_pr_status feedbackId Whether an AI pull request exists for the item, its status, URL and progress.
request_ai_pr feedbackId, guidance? Usero's agent writes and opens a pull request server-side on the client's connected GitHub repo; the caller needs no local checkout. Returns a prId. Capped at 5 per key per day.
list_forms clientId Hosted forms and surveys with response counts and public URLs.
list_form_responses clientId, formId, page?, limit? (max 50) Responses to one form, newest first, with every answer.

The environment argument takes the environment name you send from the widget. Omit it to search every environment. Use the literal no-env for feedback that was sent without one.

Resources

Two resource templates let an agent pin data into its context without a tool call:

  • usero://clients/{clientId}/clusters: the open clusters for a client, same JSON as list_clusters.
  • usero://feedback/{id}: one feedback item, same JSON as get_feedback.

Prompts

Three prompt templates. Each takes an optional clientId; when omitted and your key has exactly one client, that client is used, otherwise the prompt tells the agent to pick one via list_clients:

  • triage_inbox: read the open feedback, group it into themes with verbatim quotes, recommend what to fix first.
  • fix_top_complaint: pick the biggest concrete cluster, find the cause in the current repo, fix it or call request_ai_pr.
  • write_changelog_from_feedback: turn the last two weeks of resolved feedback into a short user-facing changelog entry.

In Claude Code they appear as /usero:triage_inbox and so on once the server is added.

What agents can and cannot do

Can: sign you up and mint their own key; create clients and connect GitHub to them; read every feedback item, cluster, form and response for your clients; file new feedback; request an AI pull request on a client that has GitHub connected.

Cannot: resolve or delete feedback, change client settings, connect other integrations, invite members, touch billing, or see clients you are not a member of. Those stay in the dashboard on purpose. If your workflow needs one of them from an agent, tell us through the contact page.

Rate limits and caps

Limit Value What happens past it
Tool calls 120 per API key per minute The tool returns an error naming the seconds to wait.
start_signup 5 per email and 10 per IP, hourly The tool returns an error; check the inbox for an earlier link.
request_ai_pr 5 per API key per UTC day The tool returns an error; open the PR from the dashboard.
AI pull requests overall your plan's monthly allowance Same as the dashboard and REST API; the error names the plan.
search_feedback results 50 per call Narrow with query, since, resolvedSince or environment.
get_cluster members 50 by default, 200 max membersTruncated is true and memberCount has the full size.

Troubleshooting

HTTP 401 on every call. The Authorization header is missing or the key is wrong. It must read exactly Bearer usk_live_.... Keys are shown once at creation; if you lost it, create a new one on your profile, or remove the header and let the agent call start_signup for a fresh one.

check_signup says the token is unknown or expired. Links and poll tokens last 15 minutes from start_signup, and sending a new link expires the previous one. Ask the agent to call start_signup again and open the newest email.

HTTP 406 from curl. The transport requires Accept: application/json, text/event-stream on every POST (both types, in one header). Copy the curl example above.

list_clients returns an empty list. The key is valid but its user is not a member of any client. Sign in to the dashboard with the same account and check you can see the client there. Keys from a teammate's account see the teammate's clients, not yours.

A tool says "Client ... not found". Either the id is mistyped (ids start with client_) or the key's user is not a member of that client. The same message covers both so ids cannot be probed.

request_ai_pr says GitHub is not connected. Connect the repo on the client's Integrations page (the error includes the link), then call again. The PR is opened by the Usero GitHub App, not by your agent's credentials.

Claude Code shows the server but no tools. Run claude mcp list and check the transport is http, not sse. Remove and re-add with --transport http if needed.

Cursor shows a red dot. Cursor reads .cursor/mcp.json on startup. Reload the window after editing it, and make sure the file is valid JSON (a trailing comma is the usual culprit).

Responses are slow the first time. The first call after a quiet period warms the Worker and the database. Later calls in the same minute are fast.

Privacy and security

The MCP server is the same Worker and database as the dashboard. Your key is hashed at rest; we never see it after creation. The server makes no LLM calls of its own: it is a deterministic interface over your data, and the agent on your side does the thinking.

Changelog

Date Change
2026-09-04 v1.2.1: the emailed link opens a confirm page with a button; opening the page alone no longer signs anyone in, and the key is minted only when check_signup collects it. A new start_signup replaces any earlier pending link for that address. list_clients pages (limit, offset, nameContains) and returns totalCount and hasMore; per-client feedbackCount, githubRepo and createdAt dropped.
2026-09-04 v1.2.0: sign up from inside the agent. start_signup and check_signup work with no API key (emailed confirm page, key minted when the agent collects it, once). create_client, connect_github and check_github finish setup. Server instructions lead with the no-key path.
2026-09-04 v1.1.0: create_pr renamed request_ai_pr. search_feedback gains resolvedSince, sort, hasScreenshot, screenshotCount, resolvedAt, resolutionMessage and 400-char bodies. list_clusters gains sampleQuotes. get_cluster gains memberLimit (default 50). list_clients gains openFeedbackCount and dashboardUrl. Strict argument schemas, server instructions.
2026-09-04 v1.0.0: server launched with 10 tools, 2 resources, 3 prompts. API key auth, 120 calls/min, create_pr capped at 5 per key per day.

Tools are never removed inside 90 days of being announced. A tool on its way out gets "deprecated" in its description first. create_pr was renamed before launch, so no deprecation window applies.