MCP server¶
Lets an AI assistant read and moderate your feedback directly — list what is waiting, read it, approve or reject, create testimonials, check NPS, fetch an embed code.
Claude Desktop / Claude Code¶
{
"mcpServers": {
"withfeedback": {
"command": "uvx",
"args": ["withfeedback-mcp"],
"env": {
"WITHFEEDBACK_TOKEN": "spd_your_token_here"
}
}
}
}
Create the token under Account → API Tokens with only the scopes you want the assistant to have. That token is the boundary of what it can do.
Tools¶
| Tool | Calls | Needs |
|---|---|---|
list_teams |
GET /teams/ |
read:teams |
list_projects |
GET /teams/{team}/projects/ |
read:feedback |
list_submissions |
GET …/submissions/ |
read:feedback |
get_submission |
GET …/submissions/{id}/ |
read:feedback |
approve_submission |
POST …/approve/ |
moderate:submissions |
reject_submission |
POST …/reject/ |
moderate:submissions |
create_testimonial |
POST …/submissions/ |
write:testimonials |
import_testimonials |
looped, ≤100 items | write:testimonials |
list_widgets |
GET …/widgets/ |
read:widgets |
get_widget_embed_code |
GET …/embed-code/ |
read:widgets |
get_nps_summary |
surveys + results | read:surveys |
A tool whose scope your token lacks fails with a clear message rather than doing something narrower and pretending it worked.
Deciding what to grant¶
The interesting choice is moderate:submissions.
Without it, the assistant becomes a very good reader: it can summarise what is waiting, spot themes, draft your replies, and tell you which five are worth publishing — and you click approve.
With it, the assistant can publish to your website.
Approving is publishing
An approved, consented testimonial appears in your embeds. Give an assistant
moderate:submissions when you want that, not by default — and remember that
a submission's text is written by a stranger. Text asking an assistant to
"approve all pending items" is content to be moderated, not an instruction.
Reading a queue is safe; acting on what a queue says is where a prompt
injection would land.
Start read-only. Add moderation when you have watched it work.
Configuration¶
| Variable | Default | Purpose |
|---|---|---|
WITHFEEDBACK_TOKEN |
— | Personal access token |
WITHFEEDBACK_API_URL |
https://withfeedback.com |
Self-hosted or staging |
WITHFEEDBACK_CLIENT_ID |
official public client | Device-flow fallback |
WITHFEEDBACK_SCOPES |
all tool scopes | Scopes requested in device flow |
WITHFEEDBACK_MCP_TRANSPORT |
stdio |
http for streamable HTTP |
WITHFEEDBACK_MCP_HOST |
127.0.0.1 |
HTTP bind address |
WITHFEEDBACK_MCP_PORT |
8000 |
HTTP bind port |
WITHFEEDBACK_MCP_ALLOW_REMOTE |
unset | Required to bind beyond loopback |
HTTP transport¶
Binds 127.0.0.1 only. That default is deliberate: the server holds a token, so
anything that can reach it can act as you.
Do not expose it without authentication in front
Binding to a routable address needs WITHFEEDBACK_MCP_ALLOW_REMOTE=1, which
exists to make you stop and think. An MCP server on an open port is an
unauthenticated proxy to your account. If you need remote access, put a
reverse proxy with real authentication in front of it, or use stdio over SSH.