Get started
MCP server
UpVoiced runs a remote Model Context Protocol server, so an AI assistant can read and triage your feedback with the same API keys, scopes and rate limits as the REST API.
Connect a client
- Endpoint:
https://api.upvoiced.com/mcp(Streamable HTTP). - Credentials: an API key as a bearer token. Use the
readscope for a read-only assistant andwriteto let it triage, reply, merge and publish; no tool needsadmin. - With an operator-wide key, tools take a
workspaceargument (slug or id) unless only one workspace is reachable;list_workspacesshows the choices.
Most clients accept a configuration like this one; keep the key in an environment variable or your client’s secret store:
{
"mcpServers": {
"upvoiced": {
"url": "https://api.upvoiced.com/mcp",
"headers": { "Authorization": "Bearer <your uv_live_… API key>" }
}
}
}Confirmation before risky writes
Merging posts, publishing a changelog entry that notifies people or moves posts to done, and moving a post to a done status first return a preview of what would change and change nothing. The assistant must show you the preview and repeat the call with "confirm": true only after you agree.
Tools
18 tools. Each one runs the same code as its REST operation, so validation, permissions and errors are the REST ones. Outputs never contain your customers’ email addresses, API keys or signed media URLs.
list_workspaces: List workspaces
Read-only · REST: GET /v1/workspace
List the UpVoiced workspaces this API key can work in (id, slug, name, plan). Call it first when another tool says a workspace is required, then pass the slug as `workspace`. Example: {} → {"workspaces":[{"slug":"acme","name":"Acme","plan":"growth",…}]}
{}list_boards: List boards
Read-only · REST: GET /v1/boards
List feedback boards with their visibility and post counts (total and still open). Use a board id as `board` in list_posts or `board_id` in create_post. Example: {"workspace":"acme"}
{"workspace":"0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d"}list_posts: List posts
Read-only · REST: GET /v1/posts
List feedback posts, newest first by default. Filters take ids from list_boards / list_statuses / list_tags; `q` searches titles and bodies; `since` is an ISO time; sort is new, top, trending, updated or relevance (needs q). At most 50 per call; pass `next_cursor` back as `cursor` for more. Examples: {"sort":"top","limit":10} · {"status":"<status id>","since":"2026-10-14T00:00:00Z"} · {"q":"dark mode","sort":"relevance"}
{"board":"0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d"}get_post: Get a post
Read-only · REST: GET /v1/posts/{id}
Get one post in full: body, status, tags, votes, the last 20 comments, internal notes, the follower count and up to 5 similar posts (possible duplicates to merge). Example: {"id":"019a…"}
{"id":"0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d"}create_post: Create a post
Write · REST: POST /v1/posts
Create a feedback post on a board (board_id from list_boards). Optionally on behalf of a customer by email (they become the author and a follower), with status_id / tag_ids from list_statuses / list_tags. Example: {"board_id":"019a…","title":"Export to CSV","body_md":"Asked by three customers on calls.","on_behalf_of_email":"pat@example.com"}
{"title":"Dark mode","board_id":"0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d"}update_post: Update a post
Write, destructive, asks for confirmation · REST: PATCH /v1/posts/{id}
Edit a post: title, body_md, board_id, status_id, tag_ids (replaces the list) or eta_quarter ("2027-Q1"). Followers are notified of status changes after a 30-second undo window. Moving a post to a status whose category is done needs confirm: true; without it you get a preview and nothing changes. Examples: {"id":"019a…","status_id":"<planned status id>"} · {"id":"019a…","tag_ids":["019a…"],"eta_quarter":"2027-Q1"}
{"id":"0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d"}merge_posts: Merge duplicate posts
Write, destructive, asks for confirmation · REST: POST /v1/posts/{id}/merge
Merge a duplicate (source_id) into the post to keep (target_id): votes, followers and comments move to the target and the source closes as merged (undo within 30 days in the dashboard). Always needs confirm: true; without it you get a preview of what would move and nothing changes. Example: {"source_id":"019a…dup","target_id":"019a…keep"}
{"source_id":"0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d","target_id":"0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d"}reply_to_post: Reply to a post
Write · REST: POST /v1/posts/{id}/comments
Post a public reply on a post as the API key's creator. official (default true) marks it as the team's answer; parent_id replies to a comment. Markdown is sanitized; followers are notified. Example: {"id":"019a…","body_md":"Thanks! This is planned for Q1."}
{"body_md":"It would help our night shift.","id":"0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d"}add_note: Add an internal note
Write · REST: POST /v1/posts/{id}/notes
Add an internal note to a post: only teammates see it, customers never do. mention_ids (operator ids) notify those teammates. Example: {"id":"019a…","body_md":"Same request came from two enterprise trials."}
{"body_md":"It would help our night shift.","id":"0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d"}list_statuses: List statuses
Read-only · REST: GET /v1/statuses
List the workspace statuses in board order with their category (open, active, done, closed). Use an id as `status` in list_posts or `status_id` in update_post; moving to a done status needs confirm. Example: {}
{"workspace":"0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d"}list_tags: List tags
Read-only · REST: GET /v1/tags
List the workspace tags. Use ids as `tag` in list_posts or in `tag_ids` of create_post / update_post. Example: {}
{"workspace":"0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d"}get_roadmap: Get the roadmap
Read-only · REST: GET /v1/roadmap
Get the roadmap: one column per roadmap status (in order) with its cards (posts) and totals, optionally for one board, up to `limit` cards per column. Move a card with update_post. Example: {"limit":10}
{"board":"0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d"}list_changelog: List changelog entries
Read-only · REST: GET /v1/changelog
List changelog entries, newest first, optionally by state (draft, scheduled, published), with linked posts and reaction counts. Example: {"state":"draft"}
{"state":"draft"}draft_changelog: Draft a changelog entry with AI
Write · REST: POST /v1/changelog/draft
Write a changelog entry with UpVoiced AI from shipped posts and save it as a draft linked to them. Pass post_ids (from list_posts / get_roadmap, e.g. the posts you just moved) or since: "last_entry" (everything shipped since the last published entry, the default) or an ISO time. tone is friendly (default), neutral or technical. Nothing is published or emailed: show the draft to the user, then publish it with publish_changelog (which previews first and needs their confirmation). Uses 5 AI credits on UpVoiced credits, none when the workspace runs AI on its own provider key; credits_used says what it cost. Examples: {"post_ids":["019a…"]} · {"since":"last_entry","tone":"technical"} · {"since":"2026-10-01T00:00:00Z"}
{"post_ids":["0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d"]}publish_changelog: Publish a changelog entry
Write, destructive, asks for confirmation · REST: POST /v1/changelog/{id}/publish
Publish a draft or scheduled changelog entry now. Its linked posts move to the done status (their followers are notified) and, with notify (default true), subscribers are emailed. Needs confirm: true whenever it notifies or moves posts; without it you get a preview (posts that would move, followers to notify) and nothing changes. Publishing an already published entry changes nothing. Example: {"id":"019a…","notify":true}
{"id":"0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d"}get_end_user: Get a customer profile
Read-only
Look up one customer (end-user) by id or by email address and get their profile and activity: posts, votes, comments, follows and their latest posts. The response never contains email addresses. Examples: {"email":"pat@example.com"} · {"id":"019a…"}
{"workspace":"0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d"}search: Search feedback
Read-only · REST: GET /v1/posts
Search feedback posts by meaning-bearing words (full-text in titles and bodies plus fuzzy title matching), best matches first. Phase 2 searches posts; comments, testimonials and survey responses join later. Example: {"query":"single sign-on","limit":5}
{"query":"dark mode"}get_usage: Get plan and usage
Read-only · REST: GET /v1/billing
Get the workspace plan, subscription status, plan limits (entitlements), current usage and AI credit balance with recent credit movements. Example: {}
{"workspace":"0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d"}Limits
MCP calls share the key’s rate limits with the REST API: a call to a write tool counts as a write, everything else as a read. On the Free plan write tools answer plan_required.