api-patterns
3CX's native PBX MCP server: the per-PBX endpoint shape (every PBX is its own FQDN and its own OAuth authorization server — there is no shared mcp.3cx.com),…
Priority scoring and assignment for an unassigned PSA ticket queue: the scoring factors (SLA proximity, client tier, ticket age, technician load, skill/category match), how to combine them into an explainable ranked order rather than a black-box formula, and the tool-discovery
$ npx -y skills add wyre-technology/msp-claude-plugins --skill dispatch-prioritization --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/dispatch-prioritizationContext preview
The summary Claude sees to decide when to auto-load this skill.
Priority scoring and assignment for an unassigned PSA ticket queue: the scoring factors (SLA proximity, client tier, ticket age, technician load, skill/category match), how to combine them into an explainable ranked order rather than a black-box formula, and the tool-discovery
name: "Dispatch Prioritization" description: > Priority scoring and assignment for an unassigned PSA ticket queue: the scoring factors (SLA proximity, client tier, ticket age, technician load, skill/category match), how to combine them into an explainable ranked order rather than a black-box formula, and the tool-discovery pattern for finding which PSA and RMM connectors are actually live before calling any vendor's tools. when_to_use: >- When triaging or assigning an unassigned ticket queue and deciding what order tickets should be worked in or who should take them. Use when: dispatch, triage the queue, assign tickets, who should take this ticket, unassigned queue, balance technician load, prioritize tickets.
An unassigned queue is a prioritization problem, not a first-in-first-out list. This skill scores each unassigned ticket on a small set of factors and turns that score into a defensible assignment order — the same judgment a good dispatcher applies, made explicit and repeatable.
category, owner, and first response is `shared-skills-ticket-triage`; this skill orders and staffs a whole unassigned queue.
`halopsa-tickets`, or `connectwise-psa-tickets` for the PSA's own ticket surface.
Because this pack is cross-vendor, never assume which PSA or RMM is connected, or what its tools are literally named. Before pulling any ticket data:
1. Call `conduit__search_tools` with a query like `"list tickets"` or `"unassigned tickets"` to discover which PSA connector(s) are actually live for this org, and the exact tool names it exposes (they follow `<vendor-slug>__<tool_name>`, e.g. `autotask__search_tickets`, `halopsa__tickets_list`). 2. If an RMM is also useful for scoring (e.g., to weight a ticket tied to a device that's also alerting), repeat the discovery for RMM tools (`datto-rmm__list_devices`, etc.) rather than assuming one is connected. 3. Only after discovery, call the concrete tools that came back. If the discovery call returns no PSA connector at all, stop and say so — there is no queue to dispatch without a PSA.
Never fall back to guessing a tool name (e.g., calling `connectwise__search_tickets` speculatively) — an unrecognized tool call is a worse failure mode than asking the user which PSA they use.
Score each unassigned ticket on these factors, then combine into a single ranked order. Exact weights are a judgment call for the org, but in the absence of a documented local policy, use this relative ordering (highest-impact first):
1. **SLA proximity** — how close the ticket is to breaching (see the `sla-escalation-playbooks` skill for how to read this per PSA family). A ticket at "breached" or "at risk" outranks everything else below. 2. **Client tier** — a Premium/Platinum client's ticket is worked ahead of an otherwise-identical Bronze ticket at the same SLA state, because tier-appropriate response time is itself part of the SLA in most contracts. 3. **Ticket age** — how long the ticket has sat unassigned, independent of formal SLA. A ticket that's been sitting three days with no SLA clock (e.g., a low-priority Syncro ticket with no formal SLA engine) still deserves to move up the queue as age accumulates, or it becomes a `board-hygiene` stale-ticket problem instead. 4. **Technician load** — don't stack the queue onto whoever is already buried. Pull current open-ticket counts per technician where the PSA exposes them (e.g., via a resource/agent search filtered by open tickets) and prefer assigning to technicians with lower current load, subject to skill match. 5. **Skill/category match** — if the PSA carries category, ticket type, or a technician skill/queue mapping, prefer routing to a technician whose queue matches the ticket's category over pure load-balancing. A generalist queue can ignore this factor.
A simple, explainable approach that avoids over-engineering a scoring formula:
1. Bucket tickets by SLA state first (breached-resolution, breached-response, at risk, healthy) — this is the primary sort key. 2. Within a bucket, sort by client tier, then by age. 3. When proposing an assignee, filter by skill/category match (if available), then pick the lowest-load matching technician.
State the ranking logic used in the output so a dispatcher can sanity-check or override it — this skill produces a proposal, not an automatic assignment, unless the operator has explicitly asked for tickets to actually be assigned.
1. Discover PSA tools via `conduit__search_tools` (see above). 2. Pull the unassigned ticket list, scoped to the board/queue in question. 3. For each ticket, resolve priority/status/SLA fields via the PSA's own list tools. 4. Bucket and sort per the ordering above. 5. Return a ranked list with the scoring rationale visible per ticket.
1. Run the ranking workflow above. 2. Pull technician roster and current open-ticket counts (resource/agent search, filtered by open assigned tickets) if the PSA exposes it. If it doesn't, say so and skip load-balancing rather than guessing at technician capacity. 3. Propose one assignee per ticket, in ranked order, with a one-line rationale ("breached response SLA, matches Networking queue, lowest current load among matching technicians"). 4. Do not write the assignment back to the PSA unless the operator explicitly asks for it — default to a proposal.
Say so explicitly: "No PSA connector is available through the gateway, so there's no unassigned queue to
One command to supercharge Claude Code for MSP workflows. Then restart Claude Code. That's it. Documentation: mcp.wyre.ai
Repo: wyre-technology/msp-claude-plugins
3CX's native PBX MCP server: the per-PBX endpoint shape (every PBX is its own FQDN and its own OAuth authorization server — there is no shared mcp.3cx.com),…
3CX's live-operations surface: read-only visibility into active calls, recordings, voicemail, department and queue membership, and forwarding/presence…
3CX's read-only directory surface: resolving a caller by email or by exact extension, searching the PBX's own phonebooks, searching contacts synced from an…
3CX's system-and-configuration surface: server time, PBX event log and application log search, service status, database schema and the read-only SELECT-only…
Abnormal Security abuse mailbox cases: user-reported email submissions, case statuses and judgments, the case lifecycle, bulk and remediation actions, and…
Abnormal Security message analysis: message retrieval, email header inspection, attachments, sender reputation, delivery context, and SPF/DKIM/DMARC…