From 61c0b39e0669e1c16ceda59796822b56d4510f25 Mon Sep 17 00:00:00 2001 From: spencerm Date: Tue, 16 Jun 2026 21:28:36 -0600 Subject: [PATCH] Improve ticket-filter guidance: agent_id lookup, status OR, workspace_id list_tickets struggled to express 'assigned to me and not resolved/closed'. Document that assignee filtering uses the numeric agent_id (resolve from email via list_agents first) and that open statuses must be enumerated as (status:2 OR status:3) since there's no negation. Add workspace_id passthrough for multi-workspace accounts. Mirror the guidance in the skill reference. Co-Authored-By: Claude Opus 4.8 --- mcp-server/server.py | 32 +++++++++++++++++++++++++++----- reference.md | 11 +++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/mcp-server/server.py b/mcp-server/server.py index 6e20195..c2d9251 100644 --- a/mcp-server/server.py +++ b/mcp-server/server.py @@ -124,15 +124,37 @@ def _coerce_priority(v: Any) -> Any: @mcp.tool() def list_tickets(query: str | None = None, updated_since: str | None = None, order_by: str | None = None, order_type: str | None = None, + workspace_id: int | None = None, page: int = 1, per_page: int = 30) -> str: - """List or filter tickets. With `query`, uses /tickets/filter, e.g. - "status:2 AND priority:3". Status 2=Open 3=Pending 4=Resolved 5=Closed; - priority 1=Low 2=Medium 3=High 4=Urgent.""" + """List or filter tickets. With `query`, uses the /tickets/filter endpoint. + + Status codes: 2=Open 3=Pending 4=Resolved 5=Closed. + Priority codes: 1=Low 2=Medium 3=High 4=Urgent. + + Building a filter `query`: + * Filter by ASSIGNEE with the numeric `agent_id`, NOT an email. To go from + an email to the id, call list_agents(email=...) first and read `id`. + * "Open / unresolved / not closed" has no negation operator — enumerate the + statuses instead: `(status:2 OR status:3)`. Wrap an OR group in + parentheses when combining with AND. + * Quote string values: `tag:'vip'`. Dates: `created_at:>'2026-01-01'`. + + Examples: + * Tickets assigned to agent 21000816864 that are still open: + "agent_id:21000816864 AND (status:2 OR status:3)" + * Open high-priority: "status:2 AND priority:3" + * Unassigned & open: "agent_id:0 AND status:2" + + `workspace_id`: accounts with multiple workspaces only search one workspace by + default. Pass a workspace id to target another (see an agent's workspace_ids). + """ if query: - params = {"query": f'"{query}"', "page": page, "per_page": min(per_page, 100)} + params = {"query": f'"{query}"', "workspace_id": workspace_id, + "page": page, "per_page": min(per_page, 100)} return _out(_request("GET", "/tickets/filter", params=params)) params = {"updated_since": updated_since, "order_by": order_by, - "order_type": order_type, "page": page, "per_page": min(per_page, 100)} + "order_type": order_type, "workspace_id": workspace_id, + "page": page, "per_page": min(per_page, 100)} return _out(_request("GET", "/tickets", params=params)) diff --git a/reference.md b/reference.md index c864ffc..555b9eb 100644 --- a/reference.md +++ b/reference.md @@ -55,11 +55,22 @@ requester is emailed; a note with `"private": true` is internal-only. - The whole expression must be URL-double-quoted; `scripts/fs.py` does this when you pass `--param query=...` / `--param filter=...`. +Two common gotchas: +- **Assignee is `agent_id` (numeric), not an email.** Resolve an email to an id + first: `GET /agents?email=person@co.com` → read `id`, then filter on it. +- **No "not" operator for status.** "Open / unresolved / not closed" must be + enumerated: `(status:2 OR status:3)`. Parenthesize the OR group when AND-ing it. + Examples: - `status:2 AND priority:3` - `agent_id:0 AND status:2` — unassigned open tickets +- `agent_id:21000816864 AND (status:2 OR status:3)` — assigned to an agent, still open - `type:'Incident' AND created_at:>'2026-06-01'` +Multi-workspace accounts: `/tickets/filter` searches one workspace by default. +Pass `--param workspace_id=` to target another (an agent's `workspace_ids` +lists which ones they're in). + ## Listing vs. filtering - `GET /tickets` supports `filter` presets (`new_and_my_open`, `watching`,