Skip to content

MCP Reference

Quackback's MCP server exposes 23 tools and 5 resources. Tools perform actions (search, create, update, delete). Resources provide lookup data (boards, statuses, tags) that tools reference by ID.

Tools

Search feedback posts or changelog entries. Returns paginated results with a cursor for the next page.

ParameterTypeDefaultDescription
entity"posts" | "changelogs""posts"Entity type to search
querystring-Text search across titles and content
boardIdstring-Filter posts by board TypeID (ignored for changelogs)
statusstring-Filter by status slug. Posts: "open", "in_progress", etc. Changelogs: "draft", "published", "scheduled", "all"
tagIdsstring[]-Filter posts by tag TypeIDs (ignored for changelogs)
sort"newest" | "oldest" | "votes""newest"Sort order. "votes" only applies to posts
showDeletedbooleanfalseShow soft-deleted posts (team only, last 30 days)
dateFromstring-ISO 8601 date. Filter posts created on or after this date
dateTostring-ISO 8601 date. Filter posts created on or before this date
limitnumber (1-100)20Max results per page
cursorstring-Pagination cursor from a previous response

Scope: read:feedback

search({ query: "dark mode", sort: "votes", limit: 10 })
search({ entity: "changelogs", status: "published" })
search({ boardId: "board_01abc...", status: "open" })
search({ dateFrom: "2026-01-01", dateTo: "2026-02-01" })
search({ showDeleted: true })

get_details

Get full details for any entity by TypeID. The entity type is auto-detected from the ID prefix. No need to specify whether it's a post or changelog.

ParameterTypeDescription
idstringTypeID of the entity (e.g., post_01abc..., changelog_01xyz...)

Scope: read:feedback

Returns all fields including comments (for posts), linked posts (for changelogs), tags, official response, and timestamps.

get_details({ id: "post_01abc..." })
get_details({ id: "changelog_01xyz..." })

triage_post

Update a post's status, tags, or owner. All fields except postId are optional. Only provided fields are updated.

ParameterTypeDescription
postIdstringPost TypeID to update
statusIdstringNew status TypeID
tagIdsstring[]Replace all tags with these TypeIDs
ownerPrincipalIdstring | nullAssign to a team member TypeID, or null to unassign

Scope: write:feedback + team role (admin or member)

triage_post({ postId: "post_01abc...", statusId: "status_01xyz..." })
triage_post({ postId: "post_01abc...", ownerPrincipalId: "principal_01xyz..." })
triage_post({ postId: "post_01abc...", tagIds: ["tag_01a...", "tag_01b..."] })

vote_post

Toggle a vote on a feedback post. Call once to vote, call again to unvote.

ParameterTypeDescription
postIdstringPost TypeID to vote on

Scope: write:feedback

Returns the current vote state and total vote count.

vote_post({ postId: "post_01abc..." })

proxy_vote

Add or remove a vote on behalf of another user. Use this to record votes from external channels (support tickets, Slack messages, sales calls) with source attribution for traceability.

ParameterTypeDefaultDescription
action"add" | "remove""add"Whether to add or remove the proxy vote
postIdstring-Post TypeID to vote on
voterPrincipalIdstring-Principal TypeID of the user to vote on behalf of
sourceTypestring-Attribution source type (e.g. "zendesk", "slack", "intercom")
sourceExternalUrlstring-URL linking to the originating record

Scope: write:feedback + team role (admin or member)

Adding a vote is idempotent — calling it twice for the same user has no effect. Removing a vote works for any vote type (proxy, integration, or direct).

proxy_vote({ postId: "post_01abc...", voterPrincipalId: "principal_01xyz..." })
proxy_vote({
  postId: "post_01abc...",
  voterPrincipalId: "principal_01xyz...",
  sourceType: "zendesk",
  sourceExternalUrl: "https://support.example.com/tickets/1234"
})
proxy_vote({ action: "remove", postId: "post_01abc...", voterPrincipalId: "principal_01xyz..." })

add_comment

Post a comment on a feedback post. Supports threaded replies via parentId.

ParameterTypeDescription
postIdstringPost TypeID to comment on
contentstringComment text (max 5,000 characters)
parentIdstringParent comment TypeID for a threaded reply

Scope: write:feedback

add_comment({ postId: "post_01abc...", content: "Thanks for the feedback!" })
add_comment({
  postId: "post_01abc...",
  content: "Good point.",
  parentId: "comment_01xyz..."
})

update_comment

Edit a comment's content. Team members can edit any comment. Authors can edit their own.

ParameterTypeDescription
commentIdstringComment TypeID to edit
contentstringNew comment text (max 5,000 characters)

Scope: write:feedback

update_comment({ commentId: "comment_01abc...", content: "Updated response." })

delete_comment

Hard-delete a comment and all its replies. This cannot be undone. Authors can delete their own comments. Team members can delete any comment.

ParameterTypeDescription
commentIdstringComment TypeID to delete

Scope: write:feedback

Deleting a comment also deletes all replies. This action is permanent.

delete_comment({ commentId: "comment_01abc..." })

react_to_comment

Add or remove an emoji reaction on a comment.

ParameterTypeDescription
action"add" | "remove"Whether to add or remove the reaction
commentIdstringComment TypeID to react to
emojistringEmoji character (e.g., "👍", "❤️", "🎉")

Scope: write:feedback

react_to_comment({ action: "add", commentId: "comment_01abc...", emoji: "👍" })
react_to_comment({ action: "remove", commentId: "comment_01abc...", emoji: "👍" })

create_post

Submit new feedback on a board. Requires a board ID and title. Content, status, and tags are optional.

ParameterTypeDescription
boardIdstringBoard TypeID (use quackback://boards resource to find IDs)
titlestringPost title (max 200 characters)
contentstringPost body (max 10,000 characters)
statusIdstringInitial status TypeID (defaults to board default)
tagIdsstring[]Tag TypeIDs to apply

Scope: write:feedback

Use the quackback://boards resource to look up board IDs before calling create_post.

create_post({ boardId: "board_01abc...", title: "Add dark mode" })
create_post({
  boardId: "board_01abc...",
  title: "Add dark mode",
  content: "Would love a dark theme option.",
  statusId: "status_01xyz...",
  tagIds: ["tag_01a..."]
})

delete_post

Soft-delete a feedback post. The post is hidden from public views but can be restored within 30 days.

ParameterTypeDescription
postIdstringPost TypeID to delete

Scope: write:feedback + team role (admin or member)

delete_post({ postId: "post_01abc..." })

restore_post

Restore a soft-deleted post. Posts can only be restored within 30 days of deletion.

ParameterTypeDescription
postIdstringPost TypeID to restore

Scope: write:feedback + team role (admin or member)

restore_post({ postId: "post_01abc..." })

merge_post

Merge a duplicate post into a canonical post. Votes are combined. Reversible via unmerge_post.

ParameterTypeDescription
duplicatePostIdstringPost TypeID of the duplicate to merge away
canonicalPostIdstringPost TypeID of the canonical post to merge into

Scope: write:feedback + team role (admin or member)

Use search to find potential duplicates first, then merge them to consolidate votes.

merge_post({
  duplicatePostId: "post_01abc...",
  canonicalPostId: "post_01xyz..."
})

unmerge_post

Restore a merged post to independent state. Recalculates vote counts for both posts.

ParameterTypeDescription
postIdstringPost TypeID of the merged post to restore

Scope: write:feedback + team role (admin or member)

unmerge_post({ postId: "post_01abc..." })

manage_roadmap_post

Add or remove a post from a roadmap.

ParameterTypeDescription
action"add" | "remove"Whether to add or remove the post
roadmapIdstringRoadmap TypeID
postIdstringPost TypeID

Scope: write:feedback + team role (admin or member)

Use the quackback://roadmaps resource to look up roadmap IDs.

manage_roadmap_post({ action: "add", roadmapId: "roadmap_01abc...", postId: "post_01xyz..." })
manage_roadmap_post({ action: "remove", roadmapId: "roadmap_01abc...", postId: "post_01xyz..." })

create_changelog

Create a changelog entry. Saves as a draft by default. Set publish: true to publish immediately.

ParameterTypeDefaultDescription
titlestring-Changelog entry title (max 200 characters)
contentstring-Changelog content, markdown supported (max 50,000 characters)
publishbooleanfalseSet to true to publish immediately

Scope: write:changelog + team role (admin or member)

create_changelog({ title: "v2.1 Release", content: "## New features\n- Dark mode..." })
create_changelog({ title: "v2.1 Release", content: "...", publish: true })

update_changelog

Update an existing changelog entry's title, content, publish state, or linked posts.

ParameterTypeDescription
changelogIdstringChangelog TypeID to update
titlestringNew title (max 200 characters)
contentstringNew content, markdown supported (max 50,000 characters)
publishbooleantrue to publish, false to revert to draft
linkedPostIdsstring[]Replace linked posts with these post TypeIDs

Scope: write:changelog + team role (admin or member)

update_changelog({ changelogId: "changelog_01abc...", title: "v2.1.1 Patch" })
update_changelog({
  changelogId: "changelog_01abc...",
  publish: true,
  linkedPostIds: ["post_01a...", "post_01b..."]
})

delete_changelog

Soft-delete a changelog entry.

ParameterTypeDescription
changelogIdstringChangelog TypeID to delete

Scope: write:changelog + team role (admin or member)

delete_changelog({ changelogId: "changelog_01abc..." })

list_suggestions

List AI-generated feedback suggestions. Suggestions are created when feedback is ingested from external sources (Slack, email, API) and processed by the AI pipeline.

Three suggestion types:

  • create_post - AI extracted new feedback and suggests creating a post
  • vote_on_post - AI matched feedback to an existing post and suggests adding a vote
  • duplicate_post - AI detected two existing posts that may be duplicates
ParameterTypeDefaultDescription
status"pending" | "dismissed""pending"Filter by suggestion status
suggestionType"create_post" | "vote_on_post" | "duplicate_post"-Filter by type
sort"newest" | "relevance""newest"Sort order
limitnumber (1-100)20Max results per page
cursorstring-Pagination cursor from a previous response

Scope: read:feedback + team role (admin or member)

Each suggestion includes the original raw feedback item, matched post (if applicable), AI signal data (summary, evidence, confidence), and source metadata.

list_suggestions()
list_suggestions({ suggestionType: "create_post" })
list_suggestions({ status: "dismissed", sort: "relevance" })

accept_suggestion

Accept an AI-generated suggestion. The result depends on the suggestion type:

  • create_post: Creates a new post from the extracted feedback. Optional edits override the suggested title, body, or board.
  • vote_on_post: Adds a proxy vote to the matched existing post.
  • duplicate_post: Merges the source post into the target post. Use swapDirection to reverse which post is kept.
ParameterTypeDescription
idstringSuggestion TypeID (feedback_suggestion_xxx or merge_sug_xxx)
editsobjectOptional. Override title, body, boardId, or statusId before accepting (create_post only)
swapDirectionbooleanOptional. Reverse merge direction (duplicate_post only)

Scope: write:feedback + team role (admin or member)

accept_suggestion({ id: "feedback_suggestion_01abc..." })
accept_suggestion({
  id: "feedback_suggestion_01abc...",
  edits: { title: "Better title" }
})
accept_suggestion({ id: "merge_sug_01abc...", swapDirection: true })

dismiss_suggestion

Dismiss an AI-generated suggestion. The suggestion can be restored later via restore_suggestion.

ParameterTypeDescription
idstringSuggestion TypeID (feedback_suggestion_xxx or merge_sug_xxx)

Scope: write:feedback + team role (admin or member)

dismiss_suggestion({ id: "feedback_suggestion_01abc..." })
dismiss_suggestion({ id: "merge_sug_01abc..." })

restore_suggestion

Restore a dismissed suggestion back to pending status.

ParameterTypeDescription
idstringSuggestion TypeID (feedback_suggestion_xxx or merge_sug_xxx)

Scope: write:feedback + team role (admin or member)

restore_suggestion({ id: "feedback_suggestion_01abc..." })

get_post_activity

Get the activity log for a post. Shows status changes, merges, tag changes, owner assignments, proxy votes, comment pins, and other events in reverse chronological order (limited to the 200 most recent).

ParameterTypeDescription
postIdstringPost TypeID

Scope: read:feedback + team role (admin or member)

Each activity entry includes the event type, actor name, metadata (e.g., old/new status), and timestamp.

get_post_activity({ postId: "post_01abc..." })

Resources

Resources provide lookup data for boards, statuses, tags, roadmaps, and team members. Use them to find IDs before calling tools like triage_post or create_post.

All resources require the read:feedback scope.

URIReturnsFields
quackback://boardsAll boardsid, name, slug
quackback://statusesAll statusesid, name, slug, color
quackback://tagsAll tagsid, name, color
quackback://roadmapsAll roadmapsid, name, slug
quackback://membersTeam membersid, name, role

A typical workflow: read quackback://statuses to find the "planned" status ID, then call triage_post with that status ID.