ticket_update
Update project ticket details including status, priority, assignees, and tags to track progress and manage workflow changes.
Instructions
PROJECT MANAGEMENT (TPM): Update a ticket's status, priority, or details.
USE THIS TOOL WHEN:
User says "I just finished implementing X" - mark related ticket as done
User says "I've pushed commits for X" - update status based on progress
Marking work as in-progress, done, or blocked
Changing priority of a ticket
User completes a ticket and needs to update status
Adding/updating tags or assignees
Use roadmap_view first to find the ticket_id.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| ticket_id | Yes | Ticket ID (e.g., FEAT-001) | |
| title | No | New title | |
| description | No | New description | |
| status | No | New status | |
| priority | No | New priority | |
| tags | No | Updated tags | |
| assignees | No | Updated assignees |
Implementation Reference
- src/tpm_mcp/server.py:142-184 (registration)Registration of the 'ticket_update' tool in the MCP server, including name, description, and input schema.Tool( name="ticket_update", description="""PROJECT MANAGEMENT (TPM): Update a ticket's status, priority, or details. USE THIS TOOL WHEN: - User says "I just finished implementing X" - mark related ticket as done - User says "I've pushed commits for X" - update status based on progress - Marking work as in-progress, done, or blocked - Changing priority of a ticket - User completes a ticket and needs to update status - Adding/updating tags or assignees Use roadmap_view first to find the ticket_id.""", inputSchema={ "type": "object", "properties": { "ticket_id": {"type": "string", "description": "Ticket ID (e.g., FEAT-001)"}, "title": {"type": "string", "description": "New title"}, "description": {"type": "string", "description": "New description"}, "status": { "type": "string", "enum": ["backlog", "planned", "in-progress", "done", "blocked"], "description": "New status", }, "priority": { "type": "string", "enum": ["critical", "high", "medium", "low"], "description": "New priority", }, "tags": { "type": "array", "items": {"type": "string"}, "description": "Updated tags", }, "assignees": { "type": "array", "items": {"type": "string"}, "description": "Updated assignees", }, }, "required": ["ticket_id"], }, ),
- src/tpm_mcp/server.py:580-594 (handler)Handler logic for 'ticket_update' tool call: parses arguments into TicketUpdate model, calls db.update_ticket, and returns confirmation.if name == "ticket_update": update = TicketUpdate( title=args.get("title"), description=args.get("description"), status=TicketStatus(args["status"]) if args.get("status") else None, priority=Priority(args["priority"]) if args.get("priority") else None, tags=args.get("tags"), assignees=args.get("assignees"), ) ticket = db.update_ticket(args["ticket_id"], update) if ticket: # Return minimal confirmation to avoid context bleed return f"Updated ticket: {ticket.id} - {ticket.title} [{ticket.status.value}]" return f"Ticket {args['ticket_id']} not found"
- src/tpm_mcp/models.py:102-112 (schema)Pydantic model TicketUpdate defining the input structure for updating tickets, used for validation.class TicketUpdate(BaseModel): title: str | None = None description: str | None = None status: TicketStatus | None = None priority: Priority | None = None assignees: list[str] | None = None tags: list[str] | None = None related_repos: list[str] | None = None acceptance_criteria: list[str] | None = None blockers: list[str] | None = None metadata: dict[str, Any] | None = None
- src/tpm_mcp/db.py:525-572 (helper)Database method to update a ticket based on TicketUpdate data, dynamically building SQL UPDATE statement for provided fields.def update_ticket(self, ticket_id: str, data: TicketUpdate) -> Ticket | None: updates = [] params = [] if data.title is not None: updates.append("title = ?") params.append(data.title) if data.description is not None: updates.append("description = ?") params.append(data.description) if data.status is not None: updates.append("status = ?") params.append(data.status.value) if data.status == TicketStatus.IN_PROGRESS: updates.append("started_at = ?") params.append(self._now()) elif data.status in (TicketStatus.DONE, TicketStatus.COMPLETED): updates.append("completed_at = ?") params.append(self._now()) if data.priority is not None: updates.append("priority = ?") params.append(data.priority.value) if data.assignees is not None: updates.append("assignees = ?") params.append(_to_json(data.assignees)) if data.tags is not None: updates.append("tags = ?") params.append(_to_json(data.tags)) if data.related_repos is not None: updates.append("related_repos = ?") params.append(_to_json(data.related_repos)) if data.acceptance_criteria is not None: updates.append("acceptance_criteria = ?") params.append(_to_json(data.acceptance_criteria)) if data.blockers is not None: updates.append("blockers = ?") params.append(_to_json(data.blockers)) if data.metadata is not None: updates.append("metadata = ?") params.append(_to_json(data.metadata)) if not updates: return self.get_ticket(ticket_id) params.append(ticket_id) self.conn.execute(f"UPDATE tickets SET {', '.join(updates)} WHERE id = ?", params) self.conn.commit() return self.get_ticket(ticket_id)