Skip to the documentation
MCP server

Organising

Labels and read state.

Organising tools

ToolWhat it does
markThreadsReadMark one or more threads read.
markThreadsUnreadMark one or more threads unread.
modifyLabelsAdd or remove labels on threads, each named by its id or its name. A label that does not exist is refused, not created.
getUserLabelsEvery label, sorted by name, with its id, its colour and how many conversations carry it, a page at a time.
getLabelOne label by id or name, with its colour, its conversation count and when it was created and last changed.
createLabelCreate a label, coloured with a hex value or a gradient token.
updateLabelRename or recolour a label. Its id stays, so every conversation keeps it.
deleteLabelDelete a label and take it off every conversation. There is no undo.
trashThreadsMove threads to the Bin, out of the inbox, spam, snoozed and archive at once. Nothing is deleted.
restoreThreadsTake threads back out of the Bin or Spam and put them in the inbox.
deleteThreadsForeverDelete threads for good, every message and attachment in them. There is no undo.
snoozeThreadsHide threads until wakeAt, a future ISO 8601 instant, when they come back to the inbox.
unsnoozeThreadsBring snoozed threads back to the inbox now and cancel their wake time.
muteThreadsMute threads: each leaves the inbox for the archive, and new mail in it arrives archived, unread and silent.
unmuteThreadsTake the mute off, so the next message arrives in the inbox again.
listFollowUpsThe reminders set on mail you sent: waiting, answered, due or cancelled.
setFollowUpAsk to be reminded about a thread if nobody replies by remindAt, a future ISO 8601 instant.
cancelFollowUpCancel a waiting reminder by its id.
listSenderCategoriesThe senders whose mail always goes to one inbox tab.
setSenderCategoryAlways sort one sender into primary, promotions, updates, social or forums.
clearSenderCategoryRemove a sender’s tab, so the rules sort their mail again.
testLabelTry a label’s AI instructions on recent inbox mail without labelling anything. It spends one AI action.

Labelling a conversation with modifyLabels needs “Label, read and archive threads” (threads:write), as it does in the app. Creating, renaming, recolouring and deleting need “Create and edit labels” (labels:write), and someone limited to particular addresses also needs “Change mailbox settings and the signature” (settings:write) to rename, recolour or delete, because those change the label for everybody.

A colour is a hex value such as #3B82F6 or one of the seven gradient tokens, gradient:sunset to gradient:midnight. GET /labels/colors on the REST API lists the whole palette.

A label’s id comes from the name it was created with, so Big Clients is USER_BIG_CLIENTS, and it survives a rename. createLabel refuses a name another label already has rather than overwriting that label.

An MCP client decides for itself whether to ask you before a tool runs. deleteLabel cannot be undone, so its description tells the model to check with you first.

Moving, restoring, snoozing and deleting threads need “Label, read and archive threads” (threads:write), and a client limited to some addresses reaches only the threads that arrived at them. In the app’s chat, deleteThreadsForever always asks first, and the other four ask unless you asked for them.

Muting, reminders and sender tabs need “Label, read and archive threads” (threads:write) too. A mute applies to everyone on the workspace. sendEmail and replyToEmail take followUpAt to set a reminder as the mail goes out, and listThreads takes category to read one inbox tab.

createLabel and updateLabel take aiInstructions and aiEnabled: with both, AI applies the label to arriving mail that fits what you wrote. It needs a paid plan, a workspace may have ten such labels, and it only ever adds the label.

Reference

modifyLabels

Scopesthreads:writeThe app's assistant asks first unless you asked for itToolkitcore

Add or remove labels on email threads. Name each label by its id (USER_RECEIPTS) or by its name as getUserLabels lists it. The system labels STARRED, IMPORTANT, UNREAD, INBOX and ARCHIVE are accepted too, so archiving is adding ARCHIVE and removing INBOX. A label that does not exist is refused rather than created: call createLabel first.

Inputs

threadIdsstring[]Required
Up to 1000 items
addLabelIdsstring[]Required

Labels to put on, by id or by name.

removeLabelIdsstring[]Required

Labels to take off, by id or by name.

Also available in

API
PATCH /threads/{id}POST /threads/{id}/restore
TypeScript
nextmail.threads.update()nextmail.threads.restore()
Python
threads.update()threads.restore()
Ruby
threads.updatethreads.restore
PHP
threads->updatethreads->restore
Go
Threads.UpdateThreads.Restore
Java
threads().updatethreads().restore
C#
Threads.UpdateAsyncThreads.RestoreAsync

getUserLabels

Scopeslabels:readThe app's assistant runs it without askingToolkitcore

The labels in this workspace, sorted by name. Each line gives the name, the id that modifyLabels, updateLabel and deleteLabel take, the colour (a hex value or a gradient token such as gradient:sunset) and how many conversations carry the label. An id comes from the name the label was created with and never changes, even after a rename. One page at a time: when more follow, the last line gives a cursor to pass back for the next page.

Inputs

limitinteger
At least 1At most 100
cursorstring

Also available in

API
GET /labelsGET /labels/{id}
TypeScript
nextmail.labels.list()nextmail.labels.listAll()nextmail.labels.iterate()nextmail.labels.get()
Python
labels.list()labels.list_all()labels.iterate()labels.get()
Ruby
labels.listlabels.list_alllabels.iteratelabels.get
PHP
labels->listlabels->listAlllabels->iteratelabels->get
Go
Labels.ListLabels.ListAllLabels.IterateLabels.Get
Java
labels().listlabels().listAlllabels().iteratelabels().get
C#
Labels.ListAsyncLabels.ListAllAsyncLabels.IterateAsyncLabels.GetAsync

getLabel

Scopeslabels:readThe app's assistant runs it without askingToolkitworkspace

createLabel

Scopeslabels:writeThe app's assistant asks first unless you asked for itToolkitcore

Create a new email label. A workspace holds at most 50 of them. The id comes from the name (Big Clients becomes USER_BIG_CLIENTS), so a name another label already has, or whose id another label holds, is refused. Leave backgroundColor out for a label with no colour. A label colour is a hex colour such as #3B82F6, or one of the gradient tokens gradient:sunset, gradient:ember, gradient:meadow, gradient:lagoon, gradient:aurora, gradient:berry, gradient:midnight. The app offers #EF4444, #F97316, #EA9602, #DCB30B, #79BB19, #2EB45C, #00AD9B, #09A9CA, #3B82F6, #6366F1, #8B5CF6, #D946EF, #EC4899, #64748B as its solid swatches, and any other hex is kept as it is. With aiInstructions and aiEnabled, AI applies the label to arriving mail that fits what you wrote, and testLabel tries it on recent mail first.

Inputs

namestringRequired
Not empty
backgroundColorstring

A label colour is a hex colour such as #3B82F6, or one of the gradient tokens gradient:sunset, gradient:ember, gradient:meadow, gradient:lagoon, gradient:aurora, gradient:berry, gradient:midnight. The app offers #EF4444, #F97316, #EA9602, #DCB30B, #79BB19, #2EB45C, #00AD9B, #09A9CA, #3B82F6, #6366F1, #8B5CF6, #D946EF, #EC4899, #64748B as its solid swatches, and any other hex is kept as it is.

aiInstructionsstring

What the label is for, in plain words, such as "invoices and receipts" or "anything from investors". With aiEnabled on, AI reads each arriving message against it and adds the label when it fits. An empty string clears it.

Up to 500 characters
aiEnabledboolean

true has AI apply the label to arriving mail that fits aiInstructions. It only ever adds the label and never archives or moves mail. It needs instructions and a paid plan, and a workspace may have ten such labels.

Also available in

API
POST /labels
TypeScript
nextmail.labels.create()
Python
labels.create()
Ruby
labels.create
PHP
labels->create
Go
Labels.Create
Java
labels().create
C#
Labels.CreateAsync

updateLabel

Scopeslabels:writeThe app's assistant asks first unless you asked for itToolkitcore

Rename or recolour a label, or change what AI does with it. Name it by its id or its current name, and give any of name, backgroundColor, aiInstructions and aiEnabled: a field left out stays as it is, and an empty backgroundColor clears the colour. The id never changes, so every conversation keeps the label through a rename. A label colour is a hex colour such as #3B82F6, or one of the gradient tokens gradient:sunset, gradient:ember, gradient:meadow, gradient:lagoon, gradient:aurora, gradient:berry, gradient:midnight. The app offers #EF4444, #F97316, #EA9602, #DCB30B, #79BB19, #2EB45C, #00AD9B, #09A9CA, #3B82F6, #6366F1, #8B5CF6, #D946EF, #EC4899, #64748B as its solid swatches, and any other hex is kept as it is.

Inputs

idstringRequired

The label id, or its current name.

Not empty
namestring

The new name.

Not empty
backgroundColorstring

The new colour. An empty string clears it.

aiInstructionsstring

What the label is for, in plain words, such as "invoices and receipts" or "anything from investors". With aiEnabled on, AI reads each arriving message against it and adds the label when it fits. An empty string clears it.

Up to 500 characters
aiEnabledboolean

true has AI apply the label to arriving mail that fits aiInstructions. It only ever adds the label and never archives or moves mail. It needs instructions and a paid plan, and a workspace may have ten such labels.

Also available in

API
PATCH /labels/{id}
TypeScript
nextmail.labels.update()
Python
labels.update()
Ruby
labels.update
PHP
labels->update
Go
Labels.Update
Java
labels().update
C#
Labels.UpdateAsync

deleteLabel

Scopeslabels:writeThe app's assistant always asks firstToolkitcore

Delete a label for good and take it off every conversation that carries it. The conversations stay where they are. There is no undo: creating the same name again gives the same id, but the conversations do not get the label back. Name the label by its id or its name, and check with the person you are working for first.

Inputs

idstringRequired

The label id, or its name.

Not empty

Also available in

API
DELETE /labels/{id}
TypeScript
nextmail.labels.delete()
Python
labels.delete()
Ruby
labels.delete
PHP
labels->delete
Go
Labels.Delete
Java
labels().delete
C#
Labels.DeleteAsync

trashThreads

Scopesthreads:writeThe app's assistant asks first unless you asked for itToolkitcore

Move email threads to the Bin, as the delete button of the app does: each one leaves the inbox, spam, snoozed and archive at once, and a snoozed one no longer wakes. Nothing is deleted, and restoreThreads takes them back out.

Inputs

threadIdsstring[]Required
1 to 1000 items

Also available in

API
POST /threads/{id}/trash
TypeScript
nextmail.threads.trash()
Python
threads.trash()
Ruby
threads.trash
PHP
threads->trash
Go
Threads.Trash
Java
threads().trash
C#
Threads.TrashAsync

restoreThreads

Scopesthreads:writeThe app's assistant asks first unless you asked for itToolkitcore

Take email threads out of the Bin or Spam and put them back in the inbox, as Restore from Bin does. A thread that is already in the inbox stays there.

Inputs

threadIdsstring[]Required
1 to 1000 items

Also available in

API
PATCH /threads/{id}POST /threads/{id}/restore
TypeScript
nextmail.threads.update()nextmail.threads.restore()
Python
threads.update()threads.restore()
Ruby
threads.updatethreads.restore
PHP
threads->updatethreads->restore
Go
Threads.UpdateThreads.Restore
Java
threads().updatethreads().restore
C#
Threads.UpdateAsyncThreads.RestoreAsync

deleteThreadsForever

Scopesthreads:writeThe app's assistant always asks firstToolkitcore

Delete email threads for good, every message and attachment in them, as Delete from Bin does in the app. This cannot be undone. To throw mail away without losing it, use trashThreads instead.

Inputs

threadIdsstring[]Required
1 to 1000 items

Also available in

API
DELETE /threads/{id}
TypeScript
nextmail.threads.delete()
Python
threads.delete()
Ruby
threads.delete
PHP
threads->delete
Go
Threads.Delete
Java
threads().delete
C#
Threads.DeleteAsync

snoozeThreads

Scopesthreads:writeThe app's assistant asks first unless you asked for itToolkitcore

Hide email threads until a set time, as Snooze does: each leaves the inbox and comes back to it at wakeAt, an ISO 8601 instant in the future such as 2026-10-05T09:00:00Z. Threads wake at an hourly sweep, so up to an hour late. Snoozing a snoozed thread again replaces its wake time. getCurrentDate gives the time now.

Inputs

threadIdsstring[]Required
1 to 1000 items
wakeAtstringRequired
Formatdate-time

Also available in

API
POST /threads/{id}/snooze
TypeScript
nextmail.threads.snooze()
Python
threads.snooze()
Ruby
threads.snooze
PHP
threads->snooze
Go
Threads.Snooze
Java
threads().snooze
C#
Threads.SnoozeAsync

muteThreads

Scopesthreads:writeThe app's assistant asks first unless you asked for itToolkitcore

Mute email threads, as Mute does: a thread in the inbox moves to the archive, and from then on new mail in it goes straight to the archive, unread, with no push, sound or desktop notice. It mutes the thread for everyone on the workspace, and mail addressed only to one person does not bring it back. unmuteThreads undoes it.

Inputs

threadIdsstring[]Required
1 to 1000 items

Also available in

API
POST /threads/{id}/mute
TypeScript
nextmail.threads.mute()
Python
threads.mute()
Ruby
threads.mute
PHP
threads->mute
Go
Threads.Mute
Java
threads().mute
C#
Threads.MuteAsync

unmuteThreads

Scopesthreads:writeThe app's assistant asks first unless you asked for itToolkitcore

Take the mute off email threads, so the next message in each arrives in the inbox and alerts people again. The threads stay where they are: move one back to the inbox with modifyLabels if it should be there now. A thread that is not muted is left as it is.

Inputs

threadIdsstring[]Required
1 to 1000 items

Also available in

API
POST /threads/{id}/unmute
TypeScript
nextmail.threads.unmute()
Python
threads.unmute()
Ruby
threads.unmute
PHP
threads->unmute
Go
Threads.Unmute
Java
threads().unmute
C#
Threads.UnmuteAsync

listFollowUps

Scopesthreads:readThe app's assistant runs it without askingToolkitcore

The reminders set on mail you sent, newest first: waiting for a reply, answered, due (the time came with no reply and the thread is back in the inbox) or cancelled. status keeps one state and threadId the reminders of one thread.

Inputs

statusstring
One of"waiting""answered""due""cancelled"
threadIdstring
1 to 256 characters
limitinteger
At least 1At most 200

Also available in

API
GET /follow-ups
TypeScript
nextmail.followUps.list()
Python
follow_ups.list()
Ruby
follow_ups.list
PHP
followUps->list
Go
FollowUps.List
Java
followUps().list
C#
FollowUps.ListAsync

setFollowUp

Scopesthreads:writeThe app's assistant asks first unless you asked for itToolkitcore

Ask to be reminded about a thread if nobody replies by remindAt, an ISO 8601 time in the future, at most a year ahead. If a real reply arrives first the reminder closes by itself. Otherwise the thread returns to the top of the inbox, unread, with a push. Automatic replies, delivery reports and your own sending address do not count as a reply. A thread holds one waiting reminder per person, so setting another moves the time. To set one while sending, pass followUpAt to sendEmail or replyToEmail. getCurrentDate gives the time now.

Inputs

threadIdstringRequired
1 to 256 characters
remindAtstringRequired
Formatdate-time

Also available in

API
POST /follow-ups
TypeScript
nextmail.followUps.set()
Python
follow_ups.set()
Ruby
follow_ups.set
PHP
followUps->set
Go
FollowUps.Set
Java
followUps().set
C#
FollowUps.SetAsync

cancelFollowUp

Scopesthreads:writeThe app's assistant asks first unless you asked for itToolkitcore

Cancel a waiting reminder by its id from listFollowUps, so the thread stays where it is when the time comes. A reminder that already ended is reported as it is.

Inputs

idstringRequired
1 to 128 characters

Also available in

API
DELETE /follow-ups/{id}
TypeScript
nextmail.followUps.cancel()
Python
follow_ups.cancel()
Ruby
follow_ups.cancel
PHP
followUps->cancel
Go
FollowUps.Cancel
Java
followUps().cancel
C#
FollowUps.CancelAsync

listSenderCategories

Scopesthreads:readThe app's assistant runs it without askingToolkitcore

The senders whose mail always goes to one inbox tab. New mail is sorted into primary, promotions, updates, social or forums by plain rules, and a choice listed here wins over them.

Inputs

Takes no input.

Also available in

API
GET /sender-categories
TypeScript
nextmail.threads.listSenderCategories()
Python
threads.list_sender_categories()
Ruby
threads.list_sender_categories
PHP
threads->listSenderCategories
Go
Threads.ListSenderCategories
Java
threads().listSenderCategories
C#
Threads.ListSenderCategoriesAsync

setSenderCategory

Scopesthreads:writeThe app's assistant asks first unless you asked for itToolkitcore

Always sort mail from one sender into one inbox tab: primary, promotions, updates, social or forums. It also moves the inbox threads whose newest message is from them into that tab. Saving again replaces the choice.

Inputs

senderstringRequired
3 to 320 characters
categorystringRequired
One of"primary""promotions""updates""social""forums"

Also available in

API
PUT /sender-categories/{email}
TypeScript
nextmail.threads.setSenderCategory()
Python
threads.set_sender_category()
Ruby
threads.set_sender_category
PHP
threads->setSenderCategory
Go
Threads.SetSenderCategory
Java
threads().setSenderCategory
C#
Threads.SetSenderCategoryAsync

clearSenderCategory

Scopesthreads:writeThe app's assistant asks first unless you asked for itToolkitcore

Remove the tab choice of one sender, so new mail from them is sorted by the rules again. Threads already sorted stay where they are.

Inputs

senderstringRequired
3 to 320 characters

Also available in

API
DELETE /sender-categories/{email}
TypeScript
nextmail.threads.clearSenderCategory()
Python
threads.clear_sender_category()
Ruby
threads.clear_sender_category
PHP
threads->clearSenderCategory
Go
Threads.ClearSenderCategory
Java
threads().clearSenderCategory
C#
Threads.ClearSenderCategoryAsync

testLabel

Scopeslabels:writethreads:readThe app's assistant runs it without askingToolkitcore

Try a label on recent mail: runs the AI over the newest inbox threads and says which ones the label would catch, without labelling anything. Pass aiInstructions to try wording that is not saved yet, or leave it out to try what the label holds. It spends one AI action, which the labelling of arriving mail never does.

Inputs

idstringRequired

The label id, as getUserLabels lists it.

Not empty
aiInstructionsstring
1 to 500 characters

Also available in

API
POST /labels/{id}/test
TypeScript
nextmail.labels.test()
Python
labels.test()
Ruby
labels.test
PHP
labels->test
Go
Labels.Test
Java
labels().test
C#
Labels.TestAsync