ticket_create
Create new tickets, epics, or issues to track features, bugs, tasks, and other work items in project management workflows.
Instructions
PROJECT MANAGEMENT (TPM): Create a new ticket, epic, or issue to track.
USE THIS TOOL WHEN:
User says ":TPM: Add X feature to the roadmap"
User wants to add a new feature/ticket/issue
User says "add ticket for X" or "create feature for Y"
Breaking down work into trackable items
User asks to scope out or define new work
User discusses new work that should be tracked
Use roadmap_view first to get the project_id. Tickets are high-level work items (like Jira epics/stories).
ID AUTO-GENERATION: IDs are always auto-generated as {PREFIX}-{NNN} (e.g., FEAT-001, ISSUE-042). The number is automatically incremented based on existing tickets with that prefix.
OPTIONAL PREFIX PARAMETER: Provide a prefix to categorize the ticket type:
FEAT: New features or capabilities
ISSUE: Bugs, problems, or issues to fix
TASK: General tasks or chores
INFRA: Infrastructure or DevOps work
DOC: Documentation tasks
If no prefix is provided, uses the project ID as the prefix (e.g., FRONTEND-001, BACKEND-042).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| project_id | Yes | Project ID (use project_list to find) case-insensitive | |
| prefix | No | Optional prefix for ticket ID (e.g., FEAT, ISSUE, INFRA). Number is auto-generated. If omitted, uses project ID as prefix. | |
| title | Yes | Ticket title | |
| description | No | Detailed description of the ticket | |
| status | No | Ticket status (default: backlog) | |
| priority | No | Priority level (default: medium) | |
| tags | No | Tags for categorization | |
| assignees | No | Who is working on this |
Implementation Reference
- src/tpm_mcp/server.py:75-141 (registration)Registration of the 'ticket_create' tool in list_tools(), defining its name, description, and JSON inputSchema matching TicketCreate fields.Tool( name="ticket_create", description="""PROJECT MANAGEMENT (TPM): Create a new ticket, epic, or issue to track. USE THIS TOOL WHEN: - User says ":TPM: Add X feature to the roadmap" - User wants to add a new feature/ticket/issue - User says "add ticket for X" or "create feature for Y" - Breaking down work into trackable items - User asks to scope out or define new work - User discusses new work that should be tracked Use roadmap_view first to get the project_id. Tickets are high-level work items (like Jira epics/stories). ID AUTO-GENERATION: IDs are always auto-generated as {PREFIX}-{NNN} (e.g., FEAT-001, ISSUE-042). The number is automatically incremented based on existing tickets with that prefix. OPTIONAL PREFIX PARAMETER: Provide a prefix to categorize the ticket type: - FEAT: New features or capabilities - ISSUE: Bugs, problems, or issues to fix - TASK: General tasks or chores - INFRA: Infrastructure or DevOps work - DOC: Documentation tasks If no prefix is provided, uses the project ID as the prefix (e.g., FRONTEND-001, BACKEND-042).""", inputSchema={ "type": "object", "properties": { "project_id": { "type": "string", "description": "Project ID (use project_list to find) case-insensitive", }, "prefix": { "type": "string", "description": "Optional prefix for ticket ID (e.g., FEAT, ISSUE, INFRA). Number is auto-generated. If omitted, uses project ID as prefix.", }, "title": {"type": "string", "description": "Ticket title"}, "description": { "type": "string", "description": "Detailed description of the ticket", }, "status": { "type": "string", "enum": ["backlog", "planned", "in-progress", "done", "blocked"], "description": "Ticket status (default: backlog)", }, "priority": { "type": "string", "enum": ["critical", "high", "medium", "low"], "description": "Priority level (default: medium)", }, "tags": { "type": "array", "items": {"type": "string"}, "description": "Tags for categorization", }, "assignees": { "type": "array", "items": {"type": "string"}, "description": "Who is working on this", }, }, "required": ["project_id", "title"], }, ),
- src/tpm_mcp/server.py:525-540 (handler)Handler code in _handle_tool: parses arguments into TicketCreate model and calls db.create_ticket, returns confirmation.if name == "ticket_create": ticket = db.create_ticket( TicketCreate( project_id=args["project_id"], title=args["title"], prefix=args.get("prefix"), description=args.get("description"), status=TicketStatus(args.get("status", "backlog")), priority=Priority(args.get("priority", "medium")), tags=args.get("tags"), assignees=args.get("assignees"), ) ) # Return minimal confirmation to avoid context bleed return f"Created ticket: {ticket.id} - {ticket.title} [{ticket.status.value}]"
- src/tpm_mcp/models.py:87-99 (schema)Pydantic schema definition for TicketCreate, used for input validation in tool handler.class TicketCreate(BaseModel): project_id: str title: str prefix: str | None = None # Optional prefix for auto-generated ID (e.g., FEAT, ISSUE, INFRA) description: str | None = None status: TicketStatus = TicketStatus.BACKLOG priority: Priority = Priority.MEDIUM 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:277-336 (helper)Database helper method TrackerDB.create_ticket: generates sequential ID with prefix, inserts ticket record into SQLite, returns Ticket model.def create_ticket(self, data: TicketCreate) -> Ticket: normalized_project_id = self._normalize_id(data.project_id) # Check if a case-insensitive match already exists for project_id existing_project = self.conn.execute( "SELECT id FROM projects WHERE LOWER(id) = ?", (normalized_project_id,) ).fetchone() if existing_project: project_id = existing_project["id"] # Use existing project ID else: project_id = normalized_project_id # Use normalized project_id for new entries # Determine prefix for ID generation if data.prefix: # Use provided prefix (e.g., FEAT, ISSUE, INFRA) prefix = data.prefix.upper().replace(" ", "").replace("-", "").replace("_", "") else: # Auto-generate prefix from project ID project = self.get_project(project_id) if project: prefix = project.id.upper().replace(" ", "").replace("-", "").replace("_", "") else: prefix = "TICKET" next_num = self._get_next_ticket_number(prefix) id = f"{prefix}-{next_num:03d}" now = self._now() self.conn.execute( """INSERT INTO tickets (id, project_id, title, description, status, priority, created_at, assignees, tags, related_repos, acceptance_criteria, blockers, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", ( id, project_id, data.title, data.description, data.status.value, data.priority.value, now, _to_json(data.assignees), _to_json(data.tags), _to_json(data.related_repos), _to_json(data.acceptance_criteria), _to_json(data.blockers), _to_json(data.metadata), ), ) self.conn.commit() return Ticket( id=id, project_id=project_id, title=data.title, description=data.description, status=data.status, priority=data.priority, created_at=datetime.fromisoformat(now), assignees=data.assignees, tags=data.tags, related_repos=data.related_repos, acceptance_criteria=data.acceptance_criteria, blockers=data.blockers, metadata=data.metadata, )