Skip to main content
Glama

ticket_search

Search for project tickets by keywords in title or description with filters for project, status, priority, and tags to find relevant tickets across projects.

Instructions

PROJECT MANAGEMENT (TPM): Search tickets by keyword.

USE THIS TOOL WHEN:

  • User asks "find tickets about X" or "search for Y"

  • Looking for tickets by keywords in title or description

  • Need to discover relevant tickets across projects

Searches title and description. Supports prefix matching (e.g., "org" matches "organization"). Case-insensitive. All filters are combinable.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYesSearch query (keywords to search in title/description)
project_idNoFilter by project ID (optional, case-insensitive)
statusNoFilter by status (optional)
priorityNoFilter by priority (optional)
tagsNoFilter by tags - ticket must have all specified tags (optional)
limitNoMaximum results to return (default: 20, max: 100)

Implementation Reference

  • Tool registration for 'ticket_search' including name, description, and input schema definition.
    Tool( name="ticket_search", description="""PROJECT MANAGEMENT (TPM): Search tickets by keyword. USE THIS TOOL WHEN: - User asks "find tickets about X" or "search for Y" - Looking for tickets by keywords in title or description - Need to discover relevant tickets across projects Searches title and description. Supports prefix matching (e.g., "org" matches "organization"). Case-insensitive. All filters are combinable.""", inputSchema={ "type": "object", "properties": { "query": { "type": "string", "description": "Search query (keywords to search in title/description)", }, "project_id": { "type": "string", "description": "Filter by project ID (optional, case-insensitive)", }, "status": { "type": "string", "enum": ["backlog", "planned", "in-progress", "done", "blocked"], "description": "Filter by status (optional)", }, "priority": { "type": "string", "enum": ["critical", "high", "medium", "low"], "description": "Filter by priority (optional)", }, "tags": { "type": "array", "items": {"type": "string"}, "description": "Filter by tags - ticket must have all specified tags (optional)", }, "limit": { "type": "integer", "description": "Maximum results to return (default: 20, max: 100)", "default": 20, }, }, "required": ["query"], }, ),
  • Handler implementation for the 'ticket_search' tool: processes input arguments, invokes database search, and returns JSON-formatted results.
    if name == "ticket_search": limit = min(args.get("limit", 20), 100) status = TicketStatus(args["status"]) if args.get("status") else None priority = Priority(args["priority"]) if args.get("priority") else None results = db.search_tickets( query=args["query"], project_id=args.get("project_id"), status=status, priority=priority, tags=args.get("tags"), limit=limit, ) return _json({ "results": results, "total": len(results), "query": args["query"], })
  • Database helper method implementing the core ticket search logic using SQLite FTS5 full-text search, with support for filters on project, status, priority, tags, and prefix matching.
    def search_tickets( self, query: str, project_id: str | None = None, status: TicketStatus | None = None, priority: Priority | None = None, tags: list[str] | None = None, limit: int = 20, ) -> list[dict]: """Search tickets using full-text search with optional filters. Args: query: Search query (supports prefix matching) project_id: Filter by project ID (case-insensitive) status: Filter by ticket status priority: Filter by priority level tags: Filter by tags (ticket must have all specified tags) limit: Maximum results to return (default 20) Returns: List of dicts with: id, title, project_id, status, priority, tags, snippet """ if not query or not query.strip(): return [] # Build FTS5 query with prefix matching for each term terms = query.strip().split() fts_query = " ".join(f"{term}*" for term in terms) # Build the SQL query with joins and filters sql = """ SELECT t.id, t.title, t.project_id, t.status, t.priority, t.tags, snippet(tickets_fts, 1, '<b>', '</b>', '...', 32) as snippet FROM tickets_fts JOIN tickets t ON tickets_fts.ticket_id = t.id WHERE tickets_fts MATCH ? """ params: list = [fts_query] # Add filters if project_id: project_id = self._normalize_id(project_id) sql += " AND LOWER(t.project_id) = ?" params.append(project_id) if status: sql += " AND t.status = ?" params.append(status.value) if priority: sql += " AND t.priority = ?" params.append(priority.value) if tags: # Check that ticket has all specified tags using json_each for tag in tags: sql += " AND EXISTS (SELECT 1 FROM json_each(t.tags) WHERE value = ?)" params.append(tag) # Order by relevance (FTS5 rank) and limit sql += " ORDER BY rank LIMIT ?" params.append(limit) try: rows = self.conn.execute(sql, params).fetchall() return [ { "id": r["id"], "title": r["title"], "project_id": r["project_id"], "status": r["status"], "priority": r["priority"], "tags": _from_json(r["tags"]), "snippet": r["snippet"], } for r in rows ] except Exception: # Handle FTS5 syntax errors gracefully return []

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/urjitbhatia/tpm-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server