Skip to main content
Thirteen tools. Nine read, four write. Clients discover them through the standard tools/list, so nothing here needs a custom integration. Every summary carries as_of. A queue changes while an agent is reading a recap of it, and a figure with no timestamp is a figure someone quotes in a meeting an hour later.

get_support_summary

How the queue looks right now. Input: none.
open_conversations counts new, open, and pending together. resolved and closed have left the queue, so they appear in by_status but not in the total. first_reply is the median time between a conversation opening and its first public reply, over conversations opened in the last 30 days. It is the same figure behind the widget’s “usually replies in” line. Two things to know when you quote it:
  • The AI’s automatic replies count as first replies. A workspace that sends them reads as fast here even if people answer slowly.
  • median_minutes is null when fewer than five conversations in the window got a reply. One slow night would otherwise set the number.

list_oldest_unanswered

Conversations with no reply since the customer’s last message, oldest first. Input: limit, 1 to 50, default 10.
“Unanswered” is not the same as status = "new". A ticket someone opened, read, and left is unanswered in every sense a customer cares about, and its status is open. This checks whether there has been a public reply since the requester’s last message.

search_tickets

Find conversations by what was written in them, by when they were opened, or both. Everything that matched is counted beside the rows. Use it to find one ticket (“the customer who mentioned order 4512”) or to look at a period (“what customers have been reporting this month”, “how August compared with July”). Input: all optional. Give days on its own for a rolling window, or from and to for a fixed one. If either date is present it wins over days. from on its own runs up to today; to on its own counts days back from that date. With a query and no dates, the window is the last year rather than the last 30 days. A search is usually after one particular conversation, and that one is rarely from this month.
total, by_status, and by_topic describe everything that matched. tickets is one page of it. Read the counts for the shape of the period and the rows for the wording customers used, and do not treat a page as the period.
A topic of null in by_topic is the untriaged bucket: conversations the classifier had no confident label for. It is counted rather than dropped, so the topics add up to total. The window selects on when the conversation was opened. The rows come back in the queue’s own order, most recently active first, which is not the same thing: a conversation from the first of the month that someone replied to this morning sorts near the top. Every row carries its own created_at. There is no status filter, because by_status is the status breakdown. Ask for the window and read the split. Internal notes play no part. A query only matches text the customer could see, and preview is the latest public message. Otherwise a search for a word in a note would tell your agent the note exists, and what it is about. Possible errors:

get_agent_workload

How many open conversations each active member is assigned. Input: none.
Active members only. A deactivated colleague keeps their message history but does not count as capacity.

get_ticket

One conversation and its public messages. Input: ticket_id, required.
Internal notes are not filtered out of the result; they are never fetched in the first place. An MCP client is an AI agent whose output a person may paste anywhere, and an internal note reaching one is the same leak as it reaching a customer, one step removed. An unknown or cross-workspace id returns { "error": "not_found" }.

get_customer

One customer: who they are, how long they have been writing in, and their ten most recent conversations. Input: one of email or ticket_id. With a ticket_id, you get the customer who opened that conversation.
external_id is the id your own app knows them by, when your widget or API sent one. preview is the first public message of each conversation, which is usually what it was about. Your team’s private note on the customer is never included, for the same reason get_ticket leaves out internal notes. Neither are their browser and device details. A customer who asked to be erased comes back with "erased": true and no name or email. A customer merged into another one returns the customer they were merged into. An unknown email, or a ticket from another workspace, returns { "error": "not_found" }.

list_pending_drafts

AI drafts waiting for a person to review, oldest first. Only conversations that are still open: a resolved ticket’s leftover draft is not waiting on anyone. Input: limit, 1 to 25, default 10.
total counts every pending draft, so you can tell a page from the whole list. This includes drafts made with create_draft_reply.

search_knowledge

Find the workspace’s own reference documents by topic. Input: query (an empty query lists everything), limit 1 to 25, default 10.
Titles and sizes only, not the text. A search that returned full documents would spend the context window on the four the model did not want. tokens is there so it can tell a one-line rule from a handbook before asking for it.

read_document

The full text of one reference document. Input: document_id, required. Get it from search_knowledge first.
Documents are read whole, up to 80,000 characters. Past that, complete is false and a note says how much was returned:
The cut is announced rather than silent, because a silent cut reads as the complete text and the reply then states a policy that the unread half qualifies. Passing something that is not a document id returns a message telling the model to search first, rather than a database error. Models otherwise tend to guess a filename from a title.

create_draft_reply

Ask miniDesk’s own model to compose a reply from your documents, for a person to review. Use reply_ticket below when you want to send your own words. Input: ticket_id, required.
delivered: false and the note are returned every single time, on purpose, so a connected agent cannot tell its user that a reply was sent. The draft is stored for review in the dashboard, with the calling model recorded and an audit log row written in the same transaction. It replaces any draft already waiting on that conversation, which is why clients are told this tool is destructive. Possible errors:

reply_ticket

Send your own text to the customer.
This reaches a real person and cannot be unsent. Show the wording to whoever you are working for and get their agreement before calling it.
Input: ticket_id and body, both required. body is the text the customer reads, up to 10,000 characters.
delivered is false when the reply was written but did not reach the customer. Their channel refused it, like Instagram after its 24-hour window, or your workspace hit its sending limits. The reply stays on the conversation, and an internal note there says why.
One message, one conversation. There is no way to send to a list of tickets, and that is deliberate: the reasoning is here. The message is attributed to the credential that sent it, not to a person, so the thread records which integration wrote it. For the same reason these replies are excluded from the pool of past answers our drafting model learns from: nobody on your team put their name to them. Possible errors:

write_knowledge

Propose a reference document: a policy, a rule, a product note. Input: title and content, both required. content is the document text, up to 80,000 characters.
This does not add anything to your knowledge base. The document is stored switched off and appears on the knowledge screen as Waiting for you. Until an Owner approves it, no query in the product will hand its text to a model.
The text goes through the same redaction as every other document, so a card number an agent copied out of a ticket thread does not get stored. Possible errors:

add_internal_note

Leave a note on one conversation for your team. Input: ticket_id and body, both required. body is up to 10,000 characters.
The customer never sees it. It sends no email, does not change the conversation’s status, and does not count toward your plan. miniDesk’s AI does not read it either. The drafting model only reads public messages, so a note cannot change what it writes to a customer. The note is attributed to the credential that wrote it, not to a person, so your team can tell an integration’s notes from a colleague’s. Possible errors:

Tools that do not exist

There is no update_ticket, assign_ticket, or resolve_ticket, and nothing takes a list of tickets. Their absence is the security model, not an oversight. The reasoning is here.