Usero Journal
How to Connect User Feedback to Claude Code and Cursor With a Feedback MCP Server
A feedback MCP server lets the agent in your editor read your user feedback directly. Add the server URL to Claude Code or Cursor, approve it in the browser, 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:
- Canny, in beta, Pro plan and above.
- Featurebase.
- Productboard, enabled by a workspace admin.
- Sleekplan, on paid plans, with OAuth.
- Pendo, any paid customer, admin enabled.
- Aha!, a remote server per workspace domain.
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: Connect, or Get a Key
On Claude Code, Cursor, Claude Desktop, OpenCode and Codex there is no key step. Add the server URL (the exact block per client is in step 2), approve the connection in the browser, and you are done. The approval names the permission: read and file feedback, open pull requests, nothing else. The credential stays with the client. After you approve, the agent finishes setup itself: your product client plus the GitHub App install.
Anything older, or anything that needs a static header, connects with an API key instead. Create it on the profile page under API keys, named after the machine it will live on. It is shown once. Or skip the dashboard entirely: with no key the server exposes start_signup and check_signup, and the agent runs the signup itself. It sends a one-button email to your address, you press it within 60 minutes, and the agent collects its key and finishes setup the same way. An existing account that signs in this way gets a new key and nothing else changes.
Step 2: Add the Server to Your Client
Each client wants the same thing: the server URL. On the five below that is the whole OAuth setup, and the keyed form of each block follows for older builds. I have tested all five. If you use a different feedback tool, swap the URL; the shape is the same.
Claude Code
claude mcp add --transport http usero https://usero.io/mcpThen send the agent set me up with usero. It registers, you approve in the browser, and it finishes setup itself.
With a key, export it first and pass a header:
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"
}
}
}Reload the window after editing. Cursor Settings, then MCP, should show the server with a green dot and a tool count. The keyed form adds a headers object:
{
"mcpServers": {
"usero": {
"url": "https://usero.io/mcp",
"headers": { "Authorization": "Bearer usk_live_..." }
}
}
}Claude Desktop
Settings, then Connectors, then Add custom connector. Name it Usero and paste https://usero.io/mcp. Authentication: Sign in now. OAuth client: Register automatically. The Recommended published identity is unsupported, so do not pick it. Click Add, approve in the browser, click the email button, approve again. Restart Desktop and ask again to prove the token refreshes.
Older builds without a header field can use the mcp-remote proxy in claude_desktop_config.json:
{
"mcpServers": {
"usero": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://usero.io/mcp", "--header", "Authorization: Bearer usk_live_..."]
}
}
}OpenCode
Put this in opencode.json:
{
"mcp": {
"usero": {
"type": "remote",
"url": "https://usero.io/mcp"
}
}
}The keyed form adds two fields:
{
"mcp": {
"usero": {
"type": "remote",
"url": "https://usero.io/mcp",
"oauth": false,
"headers": { "Authorization": "Bearer usk_live_..." }
}
}
}Codex
Put this in ~/.codex/config.toml, then run codex mcp login for the browser login:
[mcp_servers.usero]
url = "https://usero.io/mcp"The keyed form adds a headers line instead:
[mcp_servers.usero]
url = "https://usero.io/mcp"
http_headers = { "Authorization" = "Bearer usk_live_..." }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. Each one counts against the month’s draft PR amount, the same one the dashboard button uses: 5 a month on Free, 50 on Pro ($39) and no limit on Team ($89).
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. - Desktop never offers a login. You picked Sign in when needed, which starts keyless with only the signup tools. Go back to Authentication and pick Sign in now.
- 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. The server sits at v1.11.0 with 36 tools: two that sign you up, the rest behind an OAuth approval or a key. It is on every tier including free. Reading and filing feedback is never limited; draft PRs and AI user tests count against the same monthly amounts as the dashboard. Sign up, or tell your agent to sign you up, 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
| Turns | 12 |
| Duration | 45.5s |
| Cost (USD, reported by claude -p) | $0.4092 |
| Output tokens | 3617 |
| Cache read tokens | 543857 |
| Cache creation tokens | 66060 |
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 the client connects over HTTP. On the five OAuth clients there is no key to paste at all. 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 connect with OAuth?
Claude Code, Cursor, Claude Desktop, OpenCode and Codex. You add the URL, approve in the browser, and the client holds the credential. Nothing to paste, no key in a config file. Older builds that still want a static header use an API key instead. Windsurf and VS Code are not covered, so use one of the five.
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. Over OAuth the credential stays with the client and never lands in chat transcripts or config files. On a key setup, create one key per machine, name it after the machine, and revoke exactly that one when the machine goes. Keep the key in an environment variable if you commit the config file for a team.
OAuth or API key?
On Claude Code, Cursor, Claude Desktop, OpenCode and Codex, OAuth: the client registers itself with the server, you approve in the browser, and the tokens expire. API keys remain for older builds and key-first setups, and the agent can mint its own through start_signup and check_signup without a dashboard visit. Keys are created and revoked one at a time on the Usero profile page. 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. Either credential acts as you, so the agent sees the clients you are a member of and nothing more.
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 Canny and Featurebase Carry Customer Demand to the Engineering Ticket, and How We Built Ours
Canny shows voters, companies and MRR on a post, but every tracker integration is on Pro and the docs only describe a link on the issue. Featurebase’s Jira panel shows votes live, and its Copy as prompt includes the author’s email. We built a Demand block for issues and AI pull requests: companies, MRR, must-haves and two voter quotes for Linear, Jira and private repos, counts only for public GitHub repos, no emails ever.
6 min read
How Canny Groups Votes by Company, and How We Built Ours
Canny’s “Show votes grouped by company” request has 198 votes and was marked complete in August 2026 by pointing at a new Ideas view. We tested where Canny and Featurebase show the company behind a vote, then built a company count, a Most companies sort and a grouped voter list.
7 min read
How to Recruit Participants for User Research Without a Panel
Recruit participants for user research by writing a behavioural screener and working through sources cheapest first: your own users, their communities, referrals from people close to them, then a paid panel. How many to recruit, what to pay, and how to run a referral round without paying for junk sign-ups.
6 min read
Build a feedback loop your team actually uses
Usero collects, clusters, and turns user feedback into shipped fixes.
Get started free