retro
QRetro retrospectives and planning poker over MCP: boards, action items, poker games, estimates.
Should I use this
Quality & Safety
Findings (34)
- LOWin retro.board.actions.list
- LOWin retro.board.insights.list
- LOWin retro.teams.list
- LOWin retro.team.members.list
- LOWin retro.boards.list
- LOWin retro.actions.list
- LOWin retro.board.messages.list
- LOWin retro.board.messages.update
- LOWin retro.board.messages.delete_own
- LOWin retro.board.messages.delete_own
Based on automated analysis of tool definitions and protocol compliance.
Context Cost
This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.
Install
One-Click Install
Add this to your `claude_desktop_config.json` file:
{
"mcpServers": {
"retro": {
"url": "https://mcp.qretro.com"
}
}
}Remote endpoints
https://mcp.qretro.comstreamable-httpWhat it can do
Tool inventory
Tools (29)
🟢retro.teams.list
Returns the list of teams the user belongs to. boards_count is the total number of boards in a team, finished and unfinished alike — use retro.boards.list to tell them apart.
Input Schema
{
"type": "object",
"properties": {}
}🟢retro.team.members.list(team_id)
Returns the members of a team with their id, name and role (owner, admin, facilitator, member). Use the id as assign_to in retro.actions.create, retro.actions.update and retro.board.suggested_actions.promote. This is the team roster, the same one people see in team settings — it says nothing about who wrote which card. Pass team_id when several teams are available; with a single team it can be omitted.
Input Schema
{
"type": "object",
"properties": {
"team_id": {
"description": "Team to list members for. Required when more than one team is available — call retro.teams.list first.",
"type": "string"
}
}
}🟢retro.boards.list(team_id, since, until, finished_only)
Returns retrospectives (boards) of a team, newest first. Unfinished boards are included unless finished_only is set — otherwise check the is_finished flag. Filters by period via since/until. Pass team_id when several teams are available; with a single team it can be omitted.
Input Schema
{
"type": "object",
"properties": {
"team_id": {
"description": "Team to list boards for. Required when more than one team is available — call retro.teams.list first.",
"type": "string"
},
"since": {
"description": "Only boards created on or after this date (ISO 8601, for example 2026-01-01).",
"type": "string"
},
"until": {
"description": "Only boards created on or before this date (ISO 8601).",
"type": "string"
},
"finished_only": {
"description": "Return only finished retrospectives. Default: false, unfinished boards are included.",
"type": "boolean"
}
}
}🟢retro.actions.list(team_id, status, assignee, since, limit)
Returns action items across all retrospectives at once — the answer to "what did we agree on and never finish". Covers every team available unless team_id narrows it down; filters by status, assignee and date. Use this instead of walking boards one by one with retro.board.actions.list.
Input Schema
{
"type": "object",
"properties": {
"team_id": {
"description": "Narrow the search to one team. By default every available team is included.",
"type": "string"
},
"status": {
"description": "open (default), completed or all.",
"type": "string"
},
"assignee": {
"description": "Filter by assignee name, partial match.",
"type": "string"
},
"since": {
"description": "Only items created on or after this date (ISO 8601, for example 2026-01-01).",
"type": "string"
},
"limit": {
"description": "How many items to return, newest first. Default 50, maximum 200. The total field always reports the full count.",
"type": "integer"
}
}
}🟢retro.board.messages.list(board_id)
Returns all participant messages (cards) for a retrospective board, organized by template columns (e.g. "What went well", "What didn't go well"). Includes text, sentiment, category, grouping, and vote counts.
Input Schema
{
"type": "object",
"properties": {
"board_id": {
"description": "The ID of the board to get messages for.",
"type": "string"
}
},
"required": [
"board_id"
]
}⚪retro.board.messages.update(message_id, text)
Updates the text of an existing board message created by the current MCP user.
Input Schema
{
"type": "object",
"properties": {
"message_id": {
"description": "The ID of the message to update.",
"type": "string"
},
"text": {
"description": "New text content for the message.",
"type": "string"
}
},
"required": [
"message_id",
"text"
]
}🔴retro.board.messages.delete_own(message_id)
Deletes a single board message. Access is strictly governed by API policies: users can delete their own messages, or any message if they have board update rights (requires mcp:write scope for the latter).
Input Schema
{
"type": "object",
"properties": {
"message_id": {
"description": "The ID of the message to delete.",
"type": "string"
}
},
"required": [
"message_id"
]
}🟢retro.board.summary.get(board_id)
Returns the summary of a retrospective with participant info and metadata. Works for unfinished boards too — summary is null until the retro is wrapped up, so check is_finished.
Input Schema
{
"type": "object",
"properties": {
"board_id": {
"description": "The ID of the board to get the summary for.",
"type": "string"
}
},
"required": [
"board_id"
]
}🟢retro.board.actions.list(board_id, include_completed)
Returns action items from a retrospective board, including status, priority, assignee, and due date.
Input Schema
{
"type": "object",
"properties": {
"board_id": {
"description": "The ID of the board to get action items for.",
"type": "string"
},
"include_completed": {
"description": "Whether to include completed action items. Default: false.",
"type": "boolean"
}
},
"required": [
"board_id"
]
}🟢retro.board.insights.list(board_id)
Returns insights (clusters) and suggested actions for a retrospective board. Insights include topic clusters with sentiment, urgency, and category analysis.
Input Schema
{
"type": "object",
"properties": {
"board_id": {
"description": "The ID of the board to get insights for.",
"type": "string"
}
},
"required": [
"board_id"
]
}🟢retro.board.health.get(board_id)
Returns the health check of a retrospective: score per category on a 0-10 scale, alignment between participants, turnout, and the same score across the previous retrospectives of the team. Returns health_check: null when the team did not run a health check on this board.
Input Schema
{
"type": "object",
"properties": {
"board_id": {
"description": "The ID of the board to get the health check report for.",
"type": "string"
}
},
"required": [
"board_id"
]
}🟢retro.board.roti.get(board_id)
Returns ROTI (Return on Time Invested) voting metrics for a retrospective board, including average score, distribution, and trend across previous retrospectives.
Input Schema
{
"type": "object",
"properties": {
"board_id": {
"description": "The ID of the board to get ROTI metrics for.",
"type": "string"
}
},
"required": [
"board_id"
]
}🟢retro.boards.search(query, team_id)
Search across retrospectives by keyword: board summaries, action items and participant cards. Cards hidden by private writing during an ongoing retro are excluded. Optionally filter by team.
Input Schema
{
"type": "object",
"properties": {
"query": {
"description": "Search query. Looks into board summaries, action items and participant cards.",
"type": "string"
},
"team_id": {
"description": "Optional: filter search to a specific team.",
"type": "string"
}
},
"required": [
"query"
]
}⚪retro.actions.create(board_id, text, priority, due, assign_to)
Creates a new action item on a retrospective board. Requires mcp:write scope.
Input Schema
{
"type": "object",
"properties": {
"board_id": {
"description": "The ID of the board to create the action item on.",
"type": "string"
},
"text": {
"description": "The text of the action item.",
"type": "string"
},
"priority": {
"description": "Priority: high, medium, or low. Default: medium.",
"type": "string"
},
"due": {
"description": "Due date in ISO 8601 format (e.g. 2025-03-15T00:00:00Z).",
"type": "string"
},
"assign_to": {
"description": "User ID to assign the action item to — call retro.team.members.list to get it — or \"me\" to assign to the current user.",
"type": "string"
}
},
"required": [
"board_id",
"text"
]
}⚪retro.actions.update(action_item_id, text, priority, due, assign_to)
Updates an existing action item: text, priority, due date, or assignee. Requires mcp:write scope.
Input Schema
{
"type": "object",
"properties": {
"action_item_id": {
"description": "The ID of the action item to update.",
"type": "string"
},
"text": {
"description": "New text for the action item.",
"type": "string"
},
"priority": {
"description": "New priority: high, medium, or low.",
"type": "string"
},
"due": {
"description": "New due date in ISO 8601 format.",
"type": "string"
},
"assign_to": {
"description": "User ID to reassign to — call retro.team.members.list to get it — or \"me\" to assign to the current user.",
"type": "string"
}
},
"required": [
"action_item_id"
]
}⚪retro.actions.complete(action_item_id)
Marks an action item as completed. Requires mcp:write scope.
Input Schema
{
"type": "object",
"properties": {
"action_item_id": {
"description": "The ID of the action item to mark as completed.",
"type": "string"
}
},
"required": [
"action_item_id"
]
}⚪retro.board.suggested_actions.promote(board_id, suggested_action_id, assign_to)
Turns a pending suggested action from retro.board.insights.list into a real action item on the board and marks the suggestion accepted, keeping the wording and the link to its cluster. Requires mcp:write scope.
Input Schema
{
"type": "object",
"properties": {
"board_id": {
"description": "The ID of the board the suggestion belongs to.",
"type": "string"
},
"suggested_action_id": {
"description": "The ID of the suggested action to promote, from suggested_actions in retro.board.insights.list. Only suggestions with status \"pending\" can be promoted.",
"type": "string"
},
"assign_to": {
"description": "User ID to assign the action item to — call retro.team.members.list to get it — or \"me\" to assign to the current user.",
"type": "string"
}
},
"required": [
"board_id",
"suggested_action_id"
]
}⚪retro.board.suggested_actions.reject(board_id, suggested_action_id)
Rejects a pending suggested action from retro.board.insights.list: the suggestion moves to rejected and no action item is created. Requires mcp:write scope.
Input Schema
{
"type": "object",
"properties": {
"board_id": {
"description": "The ID of the board the suggestion belongs to.",
"type": "string"
},
"suggested_action_id": {
"description": "The ID of the suggested action to reject, from suggested_actions in retro.board.insights.list. Only suggestions with status \"pending\" can be rejected.",
"type": "string"
}
},
"required": [
"board_id",
"suggested_action_id"
]
}🟢poker.sources.list(team_id)
Returns the issue trackers connected to a team (Jira, Linear) and what each of them can do: search for tasks, list iterations (sprints, cycles), write estimates back. Call this first — the other poker tools depend on what is connected. An empty list means tasks can only be added manually with poker.game.tasks.add.
Input Schema
{
"type": "object",
"properties": {
"team_id": {
"description": "Team to inspect. Required when more than one team is available — call retro.teams.list first.",
"type": "string"
}
}
}🟢poker.iterations.list(team_id, source, query)
Returns the iterations of a connected issue tracker — Jira sprints (active and upcoming), and whatever a future tracker calls the same thing. Filter by name with query, for example "AFT 50". Pass the ref of the iteration you want to poker.game.tasks.import to pull its tasks into a game. Trackers without iteration support (currently Linear) return an empty list — search by text instead.
Input Schema
{
"type": "object",
"properties": {
"team_id": {
"description": "Team whose tracker is queried. Required when more than one team is available.",
"type": "string"
},
"source": {
"description": "Tracker to query, for example jira. Required only when the team has several trackers connected — see poker.sources.list.",
"type": "string"
},
"query": {
"description": "Filter iterations by name, for example \"AFT 50\". Omit to get all active and upcoming ones.",
"type": "string"
}
}
}🟢poker.games.list(team_id, limit)
Returns the planning poker games of a team, newest first, with how many tasks each of them has and how many already carry an estimate. Personal games outside a team are not exposed over MCP.
Input Schema
{
"type": "object",
"properties": {
"team_id": {
"description": "Team to list games for. Required when more than one team is available — call retro.teams.list first.",
"type": "string"
},
"limit": {
"description": "How many games to return. Default: 20, maximum: 50.",
"type": "integer"
}
}
}🟢poker.game.get(game_id)
Returns one planning poker game: its estimation scale, progress, the task currently on the table and the link participants use to join. Use poker.game.tasks.list for the tasks themselves.
Input Schema
{
"type": "object",
"properties": {
"game_id": {
"description": "The ID of the poker game.",
"type": "string"
}
},
"required": [
"game_id"
]
}🟢poker.game.tasks.list(game_id, estimated, limit)
Returns the tasks of a poker game with their estimate, individual votes, tracker key and link. needs_sync tells whether the agreed estimate still differs from the one stored in the tracker — feed those tasks to poker.game.task.sync. Filter with estimated to see what is done or what is left.
Input Schema
{
"type": "object",
"properties": {
"game_id": {
"description": "The ID of the poker game.",
"type": "string"
},
"estimated": {
"description": "true — only tasks that already have an estimate, false — only tasks still to be estimated. Omit for all of them.",
"type": "boolean"
},
"limit": {
"description": "How many tasks to return. Default: 50, maximum: 100.",
"type": "integer"
}
},
"required": [
"game_id"
]
}⚪poker.games.create(name, team_id, scale, scale_values)
Creates a planning poker game for a team and returns the link participants join with. Pick a ready-made scale — fibonacci, modified_fibonacci, tshirts, powers_of_two — or pass your own values in scale_values. Requires mcp:write scope.
Input Schema
{
"type": "object",
"properties": {
"name": {
"description": "Name of the game, for example the sprint it plans.",
"type": "string"
},
"team_id": {
"description": "Team the game belongs to. Required when more than one team is available.",
"type": "string"
},
"scale": {
"description": "Estimation scale preset: fibonacci (default), modified_fibonacci, tshirts, powers_of_two.",
"type": "string"
},
"scale_values": {
"description": "Custom scale, for example [\"1\",\"2\",\"3\",\"5\",\"?\"]. Overrides scale when given.",
"type": "array"
}
},
"required": [
"name"
]
}⚪poker.game.tasks.add(game_id, tasks)
Adds tasks to a poker game by hand — for work that lives outside an issue tracker, or when no tracker is connected. To pull tasks from Jira or Linear use poker.game.tasks.import instead. Requires mcp:write scope.
Input Schema
{
"type": "object",
"properties": {
"game_id": {
"description": "The ID of the poker game.",
"type": "string"
},
"tasks": {
"description": "Tasks to add: a list of objects with name and optional description.",
"type": "array"
}
},
"required": [
"game_id",
"tasks"
]
}🟡poker.game.tasks.import(game_id, iteration_ref, query, source, limit)
Pulls tasks from a connected issue tracker into a poker game. Give it either iteration_ref from poker.iterations.list to take a whole sprint, or query to search by text and issue key. Tasks already in the game are skipped. Only the team owner can change a game. Requires mcp:write scope.
Input Schema
{
"type": "object",
"properties": {
"game_id": {
"description": "The ID of the poker game to import into.",
"type": "string"
},
"iteration_ref": {
"description": "The ref of an iteration from poker.iterations.list — imports every task of that sprint.",
"type": "string"
},
"query": {
"description": "Text or issue key to search for, when importing without an iteration.",
"type": "string"
},
"source": {
"description": "Tracker to import from, for example jira. Required only when the team has several trackers connected.",
"type": "string"
},
"limit": {
"description": "How many tasks to pull at most. Default: 50, maximum: 100.",
"type": "integer"
}
},
"required": [
"game_id"
]
}🟡poker.game.task.select(game_id, task_id)
Puts a task on the table: everyone looking at the game sees it as the one being estimated right now. Only the team owner can change a game. Requires mcp:write scope.
Input Schema
{
"type": "object",
"properties": {
"game_id": {
"description": "The ID of the poker game.",
"type": "string"
},
"task_id": {
"description": "The ID of the task to put on the table — see poker.game.tasks.list.",
"type": "string"
}
},
"required": [
"game_id",
"task_id"
]
}🔴poker.game.task.reveal(game_id, task_id, reveal)
Reveals the cards of a task and computes its estimate from the votes cast — this is the only way an estimate appears, there is no way to set a number directly. Pass reveal=false to hide the cards again and drop the estimate, which also clears the votes for a re-vote. Only the team owner can change a game. Requires mcp:write scope.
Input Schema
{
"type": "object",
"properties": {
"game_id": {
"description": "The ID of the poker game.",
"type": "string"
},
"task_id": {
"description": "The ID of the task to reveal.",
"type": "string"
},
"reveal": {
"description": "true (default) — reveal the cards and compute the estimate. false — hide them, clear the votes and the estimate.",
"type": "boolean"
}
},
"required": [
"game_id",
"task_id"
]
}🟡poker.game.task.sync(game_id, task_id)
Writes the agreed estimate back to the issue tracker — Jira story points, Linear estimate. Works only for tasks imported from a tracker and only when the integration was connected with write permissions; poker.sources.list shows whether it was. Only the team owner can change a game. Requires mcp:write scope.
Input Schema
{
"type": "object",
"properties": {
"game_id": {
"description": "The ID of the poker game.",
"type": "string"
},
"task_id": {
"description": "The ID of the task whose estimate goes to the tracker — see needs_sync in poker.game.tasks.list.",
"type": "string"
}
},
"required": [
"game_id",
"task_id"
]
}Community
Evidence