<- All posts

Usero Journal

How to Connect User Feedback to Claude Code and Cursor With a Feedback MCP Server

Will Smith··7 min read

A feedback MCP server lets the agent in your editor read your user feedback directly. Add one config block to Claude Code or Cursor and the agent can pull the open clusters, quote the users word for word, and in one case ask the tool to open the pull request.

The usual way feedback reaches an agent is a paste. You read a few reports in the dashboard, summarise them into the prompt, and the agent fixes the version of the bug you remembered. The exact wording, the one that names the button or the card type, is usually the part that got dropped. An MCP server skips the paste. The agent calls a tool, gets the reports back as data, and works from those.

This guide covers what a feedback MCP server gives you, which tools ship one, how to connect it to each client, and a worked example using Usero’s server, which I build, so the example is the one I can show you end to end.

What MCP Is, in One Paragraph

The Model Context Protocol is a standard way for an AI client to discover and call tools on a server. The client asks the server what tools it has, gets back a list with names, descriptions and argument schemas, and from then on the model can call any of them mid conversation. A remote server is a URL. A local server is a process the client starts. Either way, once it is configured, the agent decides when to call it. You do not.

Which Feedback Tools Have One

As of September 2026, six feedback tools ship an official MCP server, so if you already use one of these you may not need to switch anything:

Plus Usero, on every tier including free. Linear has one too, and it is worth knowing about because a lot of teams keep their feedback in Linear issues. The read side is much the same across all of them: list items, search, get one in full. The differences are in what the agent can do after reading. Most stop at read. A couple let it file an item. One lets it ask for a pull request.

Step 1: Get a Credential

Every remote server needs something in the request that says who you are. For OAuth servers (Sleekplan, Linear) the client opens a browser window on first connect and you approve it. For API key servers, you create a key in the tool and paste it into the config. In Usero that is the profile page, under API keys. Name the key after the machine it will live on, because you will want to revoke exactly that one later. It is shown once.

Step 2: Add the Server to Your Client

Each client has its own config file, and each wants the same three things: a name for the server, the URL, and the authorization header. Here is the Usero server in each of the five clients I have tested. Swap the URL and header format for whichever tool you use; the shape is the same.

Claude Code

export USERO_API_KEY=usk_live_...   # in your shell profile
claude mcp add --transport http usero https://usero.io/mcp \
  --header 'Authorization: Bearer ${USERO_API_KEY}'

Single quotes matter: the shell leaves the placeholder alone, Claude Code stores it as written, and expands it each time it connects. I checked this on Claude Code 2.1.261 by adding the server, running claude mcp get usero with and without the variable set: the stored header is the literal placeholder, the connection succeeds with the variable and gets a 401 plus a "Missing environment variables" warning without it. Anthropic’s docs only promise the expansion for a committed .mcp.json, so that is the form to use for a team config. Pasting the key in place of the placeholder also works; it then sits in plain text in ~/.claude.json. Add --scope user to make it available in every project. Check it with claude mcp list, then try claude -p "list my usero clients".

Cursor

Create .cursor/mcp.json in the project, or ~/.cursor/mcp.json for all of them:

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

Reload the window after editing. Cursor Settings, then MCP, should show the server with a green dot and a tool count.

Claude Desktop

Settings, then Connectors, then Add custom connector. Paste the URL and add an Authorization header with the Bearer value. Older builds without a header field can use the mcp-remote proxy; the docs page has that config.

Windsurf and VS Code

Windsurf reads ~/.codeium/windsurf/mcp_config.json and calls the URL field serverUrl. VS Code with Copilot agent mode reads .vscode/mcp.json and wants "type": "http" next to the URL. Otherwise identical.

If you commit a project-level config for a team, put the key in an environment variable and reference it from the file. A key in git is a key everyone with the repo has.

Step 3: Ask a Question That Needs the Data

The first prompt should be one the agent cannot answer without calling the server, so you can see the calls happen. "What are users complaining about most right now? Give me the top 3 with a quote each, and tell me whether the biggest cluster is one bug or several." is a good one. Here is what that did against Usero’s own production inbox, 376 items, from a claude -p session with Claude Sonnet 5 on 2026-09-04.

The agent called list_clients first, which is what the server instructions tell it to do, and got back 125 clients. Claude Code spilled that result to a file, and the agent spent four Bash and Read calls grepping it before it found "Usero prod". Then list_clusters, ten clusters biggest first, each with a severity, an urgency score and up to three verbatim quotes. The biggest by count was a low-severity layout request, so it skipped down to the three high-severity bugs and opened each with get_cluster. Five Usero tool calls in all, 12 turns, 45 seconds, $0.41.

The interesting bit was the second half of the answer, quoted here as the model wrote it:

Is the biggest cluster one bug or several? Several, in every one of these, once you look at the individual members, the AI clustering has lumped together loosely-related complaints rather than repeats of one root cause: - Cluster #1 mixes the actual container-limit 500 error with unrelated things: PR generation timeouts, a stuck/slow PR revision flow, a duplicated "Creating pull request..." message, a 404-instead-of-login-redirect bug, and a mobile modal going off-screen. - Cluster #2 mixes the export failure with a search error, wrong "unresolved" counts, a resolved-count graph stuck at 0, duplicate notification emails, and one user pointing out clusters "aren't really clusters when they each have 1 item" (worth noting given what you're looking at right now). - Cluster #3 mixes the landing-page button bug with several unrelated mobile/overflow layout complaints (text/buttons running off screen, keyboard hiding the send button). So treat these cluster titles as themes, not single tickets, each one likely needs to be split into 3-5 discrete fixes rather than one PR.

That is our own clustering it is picking apart, from the member quotes it pulled. Handing the agent the data instead of a summary is what makes that possible. The full transcript is at the end of this post, every tool call included.

Step 4: Close the Loop

Reading is the easy half. What happens next depends on the server. With a read-only server the agent has the quotes and you fix the bug in the repo you have open, which for a developer in Cursor is the normal case and works fine. The difference with Usero is one extra tool, request_ai_pr. The agent passes a feedback id and optional guidance, and Usero clones the connected repo in its own container, writes the change on a branch and opens a normal pull request on GitHub. The caller gets a PR id and can poll get_pr_status. No local checkout, and the agent never holds your GitHub credentials. You review the diff and merge, or not.

When would you use that over a local fix? A PM in Claude Desktop with no checkout. A bug in a repo you are not working in today. Five small fixes you want as five separate PRs while you keep going on something else. It is capped at 5 per key per day so a looping agent cannot burn the month’s PR allowance in an afternoon.

Things That Went Wrong for Me

  • The server shows but has no tools. In Claude Code that is almost always the transport. Run claude mcp list; if it says sse, remove it and re-add with --transport http.
  • Cursor shows a red dot. A trailing comma in the JSON, every time. Reload the window after fixing it.
  • curl returns 406. The streamable HTTP transport requires Accept: application/json, text/event-stream, both types in one header. Clients send it; hand-written curl does not.
  • An empty client list. The key is valid but the account behind it is not a member of anything. A teammate’s key sees the teammate’s clients.

The full list, with the 401 versus 403 cases, is on the Usero MCP docs.

If You Want To Try Usero

The feature page has the tools in plain words, the setup snippets and a shorter cut of the same transcript. It is on every tier including free, and the only metered thing is the PR allowance, which is the same one the dashboard button uses. Sign up, create a key, and ask your editor what users are complaining about.

Full Transcript

The run quoted in step 3, from claude -p --model sonnet against https://usero.io/mcp on 2026-09-04. Tool inputs and the model’s prose are verbatim, with em dashes replaced by commas. Tool results are summarised from the leading portion the model saw; the 125-client list is redacted. Click a call to expand it.

Prompt

What are users complaining about most in Usero right now? Give me the top 3 with a quote each, and tell me whether the biggest cluster is one bug or several.
Tool call 1: Skillerror

Input

{ "skill": "usero", "args": "top complaints / clusters right now, with quotes" }

Result

Execute skill: usero
Tool call 2: ToolSearch

Input

{ "query": "select:mcp__usero__list_clients,mcp__usero__list_clusters,mcp__usero__get_cluster", "max_results": 5 }

Result

Three tool schemas loaded into context.
Tool call 3: mcp__usero__list_clients

Input

{}

Result

125 clients returned; list redacted. The one used below is "Usero prod".
Tool call 4: Bash, Read, Bash, Bash

Input

Four calls. Claude Code had spilled the 125-client result to a local file, so the model tried a python one-liner over it (needed an approval it did not have), read the first two lines, then grepped it twice. The first grep matched nothing.

Result

The second grep found the client list; redacted.

Assistant

Found it, "Usero prod" (client_43592bfc-50ce-427a-a61c-98dd25f3ed4b), 376 feedback items. Pulling its clusters now.

Tool call 5: mcp__usero__list_clusters

Input

{ "clientId": "client_43592bfc-50ce-427a-a61c-98dd25f3ed4b", "limit": 10 }

Result

10 clusters, biggest first. #1 "Compact Header Layout Request", 20 reports, feature_request, severity low, urgency 72, no sample quotes. #2 "Test Issue GitHub Submission", 17 reports, general, urgency 15. #3 "Client Analytics Visualization Enhancement", 16 reports, one sample quote: "In trays can we highlight in the bottom scroller thing somehow where they submitted feedback if they did?". Seven more clusters followed, including the three bugs the model chose below. Result trimmed at 6243 chars.
Tool call 6: mcp__usero__get_cluster

Input

{ "clusterId": "cmm9vw2c1007pss0eplp4n8v2", "memberLimit": 15 }

Result

"Container Instance Limit Errors", bug, severity high, urgency 88, sentiment -0.9, 13 members (5 open). First members: "Error Details: Container returned 500: Maximum number of running container instances exceeded..." (GitHub, resolved), "PR generation timed out after 15 minutes. The container may have crashed or experienced an error. Please try again." (widget, rating 1, resolved), then the same 500 again. Result trimmed at 8074 chars.
Tool call 7: mcp__usero__get_cluster

Input

{ "clusterId": "cmm9vwpbd009pss0er6ewdjzb", "memberLimit": 15 }

Result

"Analytics Export Functionality Failure", bug, severity high, urgency 88, sentiment -0.9, 12 members (7 open). First members: "Export fails", "Tried to search feedback but got unexpected error", and "this is incorrect: All Feedback, 15 unresolved, 0 resolved, Showing 15 items. there are 100 unresolved." Result trimmed at 6604 chars.
Tool call 8: mcp__usero__get_cluster

Input

{ "clusterId": "cmm9vwcm6008jss0eh6zce5yt", "memberLimit": 15 }

Result

"Get Started Button Navigation Bug", bug, severity high, urgency 78, sentiment -0.8, 9 members (9 open). First members: "The get started button on landing page shouldn't go to landing page.", "The feedback text in these cards is going off to the right", "Recent activity thing is pushing it off the screen on mobile too wide?". Result trimmed at 4496 chars.

Assistant

Here's the top 3 by feedback count for Usero itself, pulled straight from the clusters (excluding the noise clusters, "Test Issue GitHub Submission" and "Unclear Low Rating Feedback", which aren't real complaints): 1. Container Instance Limit Errors, 13 items, severity high, sentiment -0.9 "Container returned 500: Maximum number of running container instances exceeded. Try again later, or try configuring a higher value for max_instances" 2. Analytics Export Functionality Failure, 12 items, severity high, sentiment -0.9 "Export fails" 3. Get Started Button Navigation Bug, 9 items, severity high, sentiment -0.8 "The get started button on landing page shouldn't go to landing page." Is the biggest cluster one bug or several? Several, in every one of these, once you look at the individual members, the AI clustering has lumped together loosely-related complaints rather than repeats of one root cause: - Cluster #1 mixes the actual container-limit 500 error with unrelated things: PR generation timeouts, a stuck/slow PR revision flow, a duplicated "Creating pull request..." message, a 404-instead-of-login-redirect bug, and a mobile modal going off-screen. - Cluster #2 mixes the export failure with a search error, wrong "unresolved" counts, a resolved-count graph stuck at 0, duplicate notification emails, and one user pointing out clusters "aren't really clusters when they each have 1 item" (worth noting given what you're looking at right now). - Cluster #3 mixes the landing-page button bug with several unrelated mobile/overflow layout complaints (text/buttons running off screen, keyboard hiding the send button). So treat these cluster titles as themes, not single tickets, each one likely needs to be split into 3-5 discrete fixes rather than one PR.

Run stats

Turns12
Duration45.5s
Cost (USD, reported by claude -p)$0.4092
Output tokens3617
Cache read tokens543857
Cache creation tokens66060

Frequently Asked Questions

What is a feedback MCP server?

A server that exposes a feedback tool over the Model Context Protocol, so an AI coding agent such as Claude Code or Cursor can call it as a tool. Instead of you pasting reports into a prompt, the agent asks the server for the open feedback, the clusters and the quotes, and works from that. Canny, Featurebase, Productboard, Sleekplan, Pendo, Aha and Usero all run one.

Do I need to install anything locally?

For a remote server, no. You add one config block with the URL and a credential and the client connects over HTTP. Some servers are local and run through npx; those need Node on your machine and a process per client. Check which kind your tool ships before you start.

Which clients support remote MCP servers?

Claude Code, Cursor, Claude Desktop, Windsurf and VS Code with Copilot agent mode all accept a URL plus a header. Codex and most newer agents do too. The config file differs per client but the fields are the same three: a name, the URL, and the authorization header.

Can the agent change things in my feedback tool?

Depends on the server. Most expose read tools only. Some add a create tool for filing feedback from the agent. Usero also exposes request_ai_pr, which asks the tool to open a pull request on the connected repo. Look for tools marked read-only in the tool list; clients that prompt before side effects skip the prompt on those.

Is connecting my feedback to an agent safe?

The credential acts as you, so the agent sees whatever you can see. Create a key per client, name it after the machine it lives on, and revoke it from the tool when you stop using that machine. Keep the key in an environment variable if you commit the config file for a team.

Why does Usero use an API key and not OAuth?

Every client in this guide accepts a static header today, and not all of them finish an OAuth flow, so a key was the shortest path to working everywhere. Keys are created and revoked one at a time on the Usero profile page: make one per client, name it after the machine, and revoke exactly that one when the machine goes. Usero stores the SHA-256 hash of the key plus its first 12 characters for display. On each request the key in the header is hashed and matched against that hash; the raw key is never written anywhere. The key acts as you, so the agent sees the clients you are a member of and nothing more. OAuth, with per-client consent and expiring tokens, is the planned next step.

How much of my context window does a feedback MCP server use?

For Usero, measured against the live server on 2026-09-05 with cl100k tokenisation, so approximate: about 300 tokens in Claude Code, about 3,200 in Cursor or Claude Desktop. Claude Code 2.1 defers MCP tool definitions and loads only the tool names and the server instructions at session start, which for 13 tools is 43 tokens of names plus 252 of instructions. Clients that load every schema up front take the whole tools/list response, 2,957 tokens of JSON, plus the instructions.

Continue reading

How Frill’s Widget Editor Works: The Preview Is the Production Widget

Inside Frill’s widget editor: a preview that boots the production widget with the real key, sub-550ms on every control, and no mobile preview.

8 min read

How the AnnounceKit Email Digest Works: We Waited for the Draft That Never Came

We enabled the AnnounceKit email digest, set it to send Saturday, and came back on Saturday. No draft, no digest, and nothing in the product showing whether it ran: no draft view, no send history, and a config that froze into upgrade modals mid-trial while staying armed. Plus the weekly digest we built for Usero the same night: a cadence choice instead of a second channel, a draft-preview email with a one-click skip, and an admin page that always shows the next digest and what happened to the last one. Free.

8 min read

How AnnounceKit Boosts Announcements: Four Megaphones, No Front Door

A second night inside a live AnnounceKit trial, this time on boosters and the email digest. The modal booster collects reactions and feedback right where the announcement lands, then fires again on reload at someone who already answered. The digest emails you a draft 12 hours before it sends. And every path a reader could take to become an email subscriber failed in our workspace, so the email side had nobody to send to. Plus what we built the same night: changelog email subscriptions on Usero, with a confirmation link before anyone is subscribed and requesters deduped out of the broadcast. Free on every plan.

9 min read

Build a feedback loop your team actually uses

Usero collects, clusters, and turns user feedback into shipped fixes.

Get started free