Skip to main content
Glama
competlab

competlab-mcp-server

by competlab

list_tickets

Read-only

Retrieve a project's Strategic Tickets page by page and filter by status, owner, priority, due date, or origin to see what the team is deciding on or working on.

Instructions

List a project's Strategic Tickets, a page at a time — what its team is deciding on and working on, whether a person opened a ticket, the customer's own automation did, or a Strategic Briefing did. Every tool that takes a ticketId also takes a ticket's number as a person writes it, '#14'; here, a person's #14 is number=14. Returns { items, pagination: { page, limit, total, totalPages, hasMore }, byStatus }. pagination.total counts every match across pages — quote it, never the length of items; hasMore says a next page exists — ask for page+1. byStatus counts the matches per column whatever status you passed, narrowed by every other filter, so limit=1 with no other filter is the board's census. Each row is a summary: every field except the Markdown description, which is not on the row until you pass include=['description'] — get_ticket always has it. The parameters carry the one-call recipes: sort='priority' with status=['triage','todo'] for what to start, maxMinutes for quick wins, dueBefore for overdue and this week, activeSince for what changed. Due dates are calendar days with no time zone: pass the customer's own today. By default the list is the board flattened: the columns in the order triage, todo, in_progress, done, dismissed, and inside each column the order the team keeps — in triage that starts as the order an edition delivered its recommendations, most important first, newest edition on top, until somebody moves them. One edition's tickets: origin='briefing' with its runId as briefingRunId (from get_briefing or get_briefing_history). To read neighbours for move_ticket, use sort='board' (the default) and the destination column alone. A ticket's description and every comment are Markdown.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
qNoReturn only the tickets whose title or description contains this text, compared without regard to case. It is matched literally — punctuation is text, not a pattern — and threads are not searched. A match in a description is weaker evidence than one in the title: a briefing's description quotes its grounding, so read the ticket before calling two tickets the same work
pageNoWhich page, from 1 (the default). pagination.hasMore says whether a next one exists
sortNoThe order of the list: 'board', 'priority', 'due', 'activity'. 'board' (the default) is the board as the team sees it and the only order to read move_ticket neighbours from. What to start: status=['triage','todo'], sort='priority'. 'priority' puts the highest impact first; among the same impact, the least effort first, and among the same effort the fewest minutes of the edition's estimate; then the earliest due date, then board order. A missing value sorts last at each step. 'due' puts the earliest due date first, undated last. 'activity' puts the most recently touched first. Any order but 'board' mixes the columns; each ticket carries its status.
limitNoHow many tickets per page, 1 to 100; 50 when omitted. Pass limit=1 when you only need pagination.total and byStatus
effortNoReturn only the tickets sized as one of these — one, or several: ['low','medium']. Tickets nobody sized are left out. This is the ticket's size word, not its minutes: a briefing's estimatedMinutes is the edition's own time estimate, neither is derived from the other, and a 'low' ticket can be an afternoon — when a person asks for something quick, use maxMinutes on list_tickets.
numberNoReturn the one ticket carrying this number on the board — what a person means by #14
originNoWho opened the ticket, never which dimension it is about (that is `dimension`): user — a person in the app; api — an API key, which is what everything you write here carries; briefing — a Strategic Briefing; ai_sources — reserved for a future AI Sources writer, which opens none today, so that value matches none.
statusNoReturn only the tickets in these columns — one, or several: ['todo','in_progress']. Omit it for every column. byStatus ignores this filter, so its counts still cover every column, narrowed by every other filter you passed. What the columns mean: triage — nobody has decided yet, and you cannot know whether anyone looked at it; todo — decided and not started; in_progress — being worked on; done — the team moved it there, never proof the work was good or that a measurement moved because of it: put a ticket beside a number as two facts with their dates, joined by no verb; dismissed — the team decided not to do it. The set is fixed and a project cannot add to it.
dueFromNoReturn only the tickets due on or after this calendar day, YYYY-MM-DD. Tickets with no due date are left out. A due date has no time zone, so pass the customer's own day
includeNoAsk for each ticket's Markdown description in the list. Left out by default: one ticket's description runs to thousands of characters, so a page fetched with them is large enough to be worth asking for on purpose. get_ticket always returns it
labelIdNoReturn only the tickets carrying one label — its ID from list_ticket_labels
assigneeNoReturn only the tickets one person owns — their user ID from list_ticket_assignees, or 'none' for the tickets nobody owns. A ticket whose owner has left the organization reads as unassigned everywhere, but is still found here by their ID
dimensionNoReturn only the tickets a Strategic Briefing opened for one part of its analysis, or 'none' for the tickets no part claims — everything a person or an API key opened, and a briefing's ticket whose edition named none. 'agent-readiness' is the key for Agent Adoption; the key predates the name and does not change
dueBeforeNoReturn only the tickets due strictly before this calendar day, YYYY-MM-DD. Overdue: status=['triage','todo','in_progress'], dueBefore=<today>, sort='due'. Due this week: the same columns, dueFrom=<today>, dueBefore=<the day after the week ends>. Tickets with no due date are left out. A due date has no time zone, so pass the customer's own day
impactMinNoReturn only the tickets whose impact is at least this, 1 to 4 (1 Minor · 2 Moderate · 3 Significant · 4 Critical; 4 matters most). Tickets nobody sized are left out
projectIdYesProject ID (from list_projects)
maxMinutesNoReturn only the tickets a Strategic Briefing opened whose edition estimated at most this many minutes of work. Quick wins: status=['triage','todo'], impactMin=3, maxMinutes=120, sort='priority'. A ticket without an edition's estimate — everything a person or an API key opened, and a briefing's ticket the edition did not size — is left out; for those, effort=['low'] instead
activeSinceNoReturn only the tickets something happened to at or after this moment — an edit, a move, or a new thread entry (lastActivityAt). Changed since yesterday: activeSince=<the start of the customer's yesterday>, sort='activity'. ISO 8601 with its offset; a time without one is read as UTC, and YYYY-MM-DD is the start of that day in UTC. On a changed ticket, a statusChangedAt later than this means it changed column, and a lastActivityAt later than its updatedAt means a thread entry was written or edited after the ticket's own last change. A deleted ticket is gone and does not appear
briefingRunIdNoReturn only the tickets one Strategic Briefing edition opened — its runId, from get_briefing or get_briefing_history. They come back whole, finished and dismissed ones included, so the list matches the count the briefing states

Schema Changelog

Changes observed during successful MCP inspections.

  1. Addedv4.0.1

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations declaring readOnlyHint=true and openWorldHint=false, the description still adds substantial behavior: pagination.total counts across pages and must be quoted over items.length, hasMore signals a next page, byStatus counts per column ignoring the status filter, and descriptions are omitted by default because a page with them is large. These are non-obvious return/behavioral traits not encoded in the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is very long (~300+ words), but for a 19-parameter tool the length is largely earned and the core purpose is front-loaded. Some clauses (e.g. the recap of who opened a ticket, restated in the origin param) sprawl slightly, keeping it from a 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, yet the description spells out the return shape ({ items, pagination: { page, limit, total, totalPages, hasMore }, byStatus }) plus pagination math and Markdown conventions, so an agent knows exactly what comes back. Complete for this tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3, but the description adds meaning beyond field docs by combining parameters into recipes (e.g. limit=1 for the board census, origin='briefing' with briefingRunId, impactMin+maxMinutes+sort='priority' for quick wins) and warns about cross-parameter traps like effort vs maxMinutes.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('List a project's Strategic Tickets, a page at a time') and immediately scopes what a ticket is. It also distinguishes itself from the sibling get_ticket ('get_ticket always has it'), so an agent can tell them apart without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit one-call recipes for common intents: sort='priority' with status=['triage','todo'] for what to start, maxMinutes for quick wins, dueBefore for overdue/this week, activeSince for what changed. It also names the alternative (get_ticket) for the description case and points to get_briefing/get_briefing_history for briefingRunId.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.