getTenants
Fetch a paginated list of tenants from Plain.
Results include tenant name, external ID, source, and associated tier.
Use the `cursor` variable with the endCursor from the previous
response's pageInfo to fetch the next page. Set `first` to
control page size (default 50).
bulkUpsertThreadFields
Bulk upsert (create or update) multiple thread field values in a single operation.
Provide an array of thread field inputs, each with thread ID, field key, field type, and value.
Use this to efficiently set multiple custom fields on one or more threads.
changeThreadPriority
Change the priority of a thread.
Priority is an integer: 0 = urgent, 1 = high, 2 = normal, 3 = low.
getThreads
Fetch threads with flexible filtering options.
Use this to find first 10 threads by status, status details, assignee, customer, labels, priority, or date ranges.
Set isAssigned: false to get unassigned threads.
Set isAssigned: true to get assigned threads.
Pass null for isAssigned to get all threads regardless of assignment.
statusDetails filters by specific status detail types like CREATED, IN_PROGRESS, NEW_REPLY, WAITING_FOR_CUSTOMER, etc.
Use the `cursor` variable with the endCursor from the previous
response's pageInfo to fetch the next page. Set `first` to
control page size (default 10).
Thread URL format: https://app.plain.com/workspace/{workspaceId}/thread/{threadId}/
where {threadId} is the thread `id` field on each result (starts with `th_`)
and {workspaceId} is fetched via `getMyWorkspace` (starts with `w_`). Do not
invent IDs — only use values returned by the MCP tools.
createThread
Create a new thread for a customer.
A thread is the unit of conversation in Plain. Use this when you need to open a
new ticket on behalf of a customer (for example, capturing an internal report or
a back-channel conversation). To send a message to the customer after creation,
use `replyToThread`. To attach an internal note, use `createNote`.
Required fields on `input`:
- customerIdentifier: One of `customerId` (e.g. `c_...`), `externalId`, or
`emailAddress`. The customer must already exist — call `upsertCustomer`
first if it doesn't.
Common optional fields:
- title: Short summary of the thread. Defaults to `Support request` if omitted.
- description: Preview text shown in thread lists. Inferred from message
content when omitted (which only happens if you also send a first message).
- priority: Integer 0–3, where 0 is most urgent and 3 is least urgent.
Defaults to 2 (normal). Anything outside 0–3 is rejected.
- assignedTo: Provide exactly one of `userId` or `machineUserId`.
- labelTypeIds: Array of label type IDs (e.g. `lt_...`). Look these up via
`getLabels` first; unknown IDs return a validation error.
- threadFields: Each entry needs a `key` and `type` that match an existing
thread field schema (see `getThreadFieldSchemas`). The schema must exist
before you can attach a value.
- tenantIdentifier: Provide either `tenantId` or `externalId` for an existing
tenant. Unknown tenants return a validation error.
- externalId: Your own unique identifier for this thread. Must be unique per
workspace.
- channel: One of `API` (default), `EMAIL`, `CHAT`, `INTERNAL`, `SLACK`, or
`MS_TEAMS`. The schema also exposes `DISCORD` and `IMPORT`, but they are
not accepted here — don't use them.
- channelDetails: REQUIRED when `channel` is `SLACK` (provide
`channelDetails.slack.{slackChannelId, slackTeamId}`) or `MS_TEAMS`
(provide `channelDetails.msTeams.{msTeamsChannelId, msTeamsTeamId}`).
MUST be omitted for any other channel — passing it returns a validation
error.
Gotchas:
- This mutation only creates the thread shell. It does NOT send a message to
the customer. Follow up with `replyToThread` if a customer-visible message
is needed.
- The legacy `components` and `attachmentIds` input fields are deprecated and
should not be set — use `replyToThread` (or chat mutations) afterwards
instead.
- SLACK threads created this way are linked to a Slack channel/team but no
Slack message is posted until you reply.
- `customerIdentifier.emailAddress` will not auto-create a customer; the
mutation fails if no customer matches.
Thread URL format:
https://app.plain.com/workspace/{workspaceId}/thread/{threadId}/
where `{threadId}` is the `id` returned below (starts with `th_`) and
`{workspaceId}` comes from `getMyWorkspace` (starts with `w_`). Do not invent
IDs — only use values returned by the MCP tools.
getCustomers
Fetch a paginated list of customers from Plain.
Results are sorted by full name and exclude customers marked as spam.
Use the `cursor` variable with the endCursor from the previous
response's pageInfo to fetch the next page. Set `first` to
control page size (default 50).
removeLabels
Remove labels from a thread by label IDs.
Labels are used to categorize and organize threads.
markThreadAsTodo
Mark a thread as todo (reopen or set as active).
Optionally provide a statusDetail for the reason:
CREATED, IN_PROGRESS, NEW_REPLY, THREAD_LINK_UPDATED, or THREAD_DISCUSSION_RESOLVED.
getLabels
Fetch a paginated list of label types from Plain. Useful for fetching
the label type ID's necessary for mutations like 'addLabels'.
Results exclude archived labels by default.
Use the `cursor` variable with the endCursor from the previous
response's pageInfo to fetch the next page. Set `first` to
control page size (default 50).
moveLabelType
Move a label type to a different position in the label hierarchy.
You can move it before/after another label type, or change its parent.
Provide afterLabelTypeId, beforeLabelTypeId, or parentLabelTypeId to reposition the label type.
getThreadDetails
Fetch complete details for a specific thread including first 50 timeline entries.
Timeline entries include notes, chats, emails, status changes, assignments, and more.
Use the `timelineCursor` variable with the endCursor from the previous
response's pageInfo to fetch the next page of timelineEntries. Set `timelineFirst` to
control page size (default 50).
Thread URL format: https://app.plain.com/workspace/{workspaceId}/thread/{threadId}/
where {threadId} is the thread `id` returned by this query (starts with `th_`)
and {workspaceId} is fetched via `getMyWorkspace` (starts with `w_`). Do not
invent IDs — only use values returned by the MCP tools.
getCustomerDetails
Fetch detailed information about a specific customer by their ID.
Returns the customer's profile including email, avatar, assignment, company, and timestamps.
upsertTenantField
Create or update a tenant field.
To create or update: provide tenantFieldIdentifier (with tenantId and externalFieldId), type, and the appropriate value field.
Exactly one value field must be provided based on the type:
- STRING_TYPE: stringValue
- NUMBER_TYPE: numberValue
- BOOLEAN_TYPE: booleanValue
- STRING_ARRAY: arrayValue
- DATETIME_TYPE: dateValue
searchCustomers
Search for customers by name, email, short name, or external ID.
The search is case-insensitive and matches partial strings, returns first 50 results.
All fields are searched simultaneously with the same search term (OR logic).
Use the `cursor` variable with the endCursor from the previous
response's pageInfo to fetch the next page. Set `first` to
control page size (default 50).
getTenantDetails
Fetch detailed information about a specific tenant by their ID.
Returns the tenant's profile including name, external ID, source, tier, and tenant fields.
getMyAssignedThreads
Fetch first 10 threads assigned to a specific user in Plain.
By default, returns only active threads (TODO and SNOOZED), excluding DONE threads.
To include all threads regardless of status, pass statuses: null.
To filter by specific statuses, pass an array like statuses: [TODO, DONE].
Use the `cursor` variable with the endCursor from the previous
response's pageInfo to fetch the next page. Set `first` to
control page size (default 10).
Thread URL format: https://app.plain.com/workspace/{workspaceId}/thread/{threadId}/
where {threadId} is the thread `id` field on each result (starts with `th_`)
and {workspaceId} is fetched via `getMyWorkspace` (starts with `w_`). Do not
invent IDs — only use values returned by the MCP tools.
getHelpCenterArticleBySlug
Fetch detailed information for a specific help-center article by slug.
Help-center article URL format (Plain dashboard):
https://app.plain.com/workspace/{workspaceId}/help-center/{helpCenterId}/articles/{helpCenterArticleId}/
where {helpCenterId} is the `$helpCenterId` argument passed to this query
(starts with `hc_`), {helpCenterArticleId} is the article `id` returned by
this query (starts with `hca_`), and {workspaceId} is fetched via
`getMyWorkspace` (starts with `w_`). Do not invent IDs — only use values
returned by the MCP tools.
assignThread
Assign a thread to a user or machine user.
Provide either userId or machineUserId, not both.
If neither is provided, the thread will be assigned to the authenticated user.
upsertThreadField
Upsert (create or update) a thread field value on a thread.
Provide the thread ID, field key, field type, and the value.
Use this to set custom field data on individual threads.
getHelpCenterArticle
Fetch detailed information for a specific help-center article by ID.
Help-center article URL format (Plain dashboard):
https://app.plain.com/workspace/{workspaceId}/help-center/{helpCenterId}/articles/{helpCenterArticleId}/
where {helpCenterArticleId} is the article `id` returned by this query
(starts with `hca_`). This query does not return the parent help center, so
{helpCenterId} (starts with `hc_`) must come from the caller's prior context
or from `getHelpCenters`. {workspaceId} (starts with `w_`) is fetched via
`getMyWorkspace`. Do not invent IDs — only use values returned by the MCP tools.
createThreadFieldSchema
Create a new thread field schema to capture structured data on threads.
Thread field schemas define custom fields that can be added to threads (e.g., priority score, department, due date).
Supports text, number, boolean, date, and enum field types with optional defaults and AI auto-fill.
reorderThreadFieldSchemas
Reorder multiple thread field schemas in a single operation.
Provide a list of thread field schema IDs with their new order values.
This is useful for organizing how thread fields appear in the UI.
searchTenants
Search for tenants by name or external ID.
The search is case-insensitive: partial match on name, exact match on external ID.
The search term must be at least 2 characters long.
Use the `cursor` variable with the endCursor from the previous
response's pageInfo to fetch the next page. Set `first` to
control page size (default 50).
getThreadFieldSchemas
Fetch a paginated list of thread field schemas from Plain.
Thread field schemas define the custom fields available for threads in your workspace.
Use the `cursor` variable with the endCursor from the previous
response's pageInfo to fetch the next page. Set `first` to
control page size (default 50).
getUserByEmail
Look up a Plain user by their email address.
Returns user details including ID, name, role, and status.
addGeneratedReply
Add an AI-generated reply suggestion to a thread.
Required fields:
- threadId: The ID of the thread to add the generated reply to.
- timelineEntryId: The ID of the timeline entry to associate the reply with.
- markdown: The markdown content of the generated reply.
updateThreadFieldSchema
Update an existing thread field schema's properties.
Use this to modify the label, description, order, enum values, default values, or other field settings.
Note: You cannot change the key or type of an existing thread field schema.
replyToThread
Reply to the last message in a thread.
Supports replying to threads where the last message is a Slack message,
an email, or a form submission. If the thread is empty, it will send
an email to the customer.
Required fields:
- threadId: The ID of the thread to reply to.
- textContent: The plain text content of the reply.
Optional fields:
- markdownContent: Markdown formatted version of the reply.
- attachmentIds: IDs of previously uploaded attachments to include.
- channelSpecificOptions: Channel-specific options (e.g. additional email recipients).
getHelpCenterArticles
Fetch a paginated list of articles for a specific help center.
Use the `cursor` variable with the endCursor from the previous
response's pageInfo to fetch the next page. Set `first` to
control page size (default 50).
Help-center article URL format (Plain dashboard):
https://app.plain.com/workspace/{workspaceId}/help-center/{helpCenterId}/articles/{helpCenterArticleId}/
where {helpCenterId} is the `$helpCenterId` argument passed to this query
(starts with `hc_`), {helpCenterArticleId} is the article `id` on each result
(starts with `hca_`), and {workspaceId} is fetched via `getMyWorkspace`
(starts with `w_`). Do not invent IDs — only use values returned by the MCP tools.
createNote
Create an internal note on a thread.
Notes are visible to support agents only, not to customers.
Requires a customerId and text content. Optionally provide a threadId
to attach the note to a specific thread, and markdown for rich formatting.
unassignThread
Unassign a thread, removing the current assignee.
getHelpCenters
Fetch a paginated list of help centers.
Use the `cursor` variable with the endCursor from the previous
response's pageInfo to fetch the next page. Set `first` to
control page size (default 50).
The returned `id` on each help center (starts with `hc_`) is the
{helpCenterId} used in dashboard article URLs:
https://app.plain.com/workspace/{workspaceId}/help-center/{helpCenterId}/articles/{helpCenterArticleId}/
Fetch {workspaceId} via `getMyWorkspace` (starts with `w_`). Do not invent IDs —
only use values returned by the MCP tools.
getMyUser
Get the currently authenticated user's details.
This query uses implicit authentication - no parameters are needed.
Returns the user associated with the current session.
createLabelType
Create a new label type for organizing threads.
Label types can be single-select or multi-select, and can be hierarchical with parent label types.
Use this to add new labels to your workspace's label taxonomy.
getMyWorkspace
Get the currently authenticated user's workspace details.
This query uses implicit authentication - no parameters are needed.
Returns the workspace associated with the current session.
The returned `id` (e.g. `w_01G0EZ1XTM37C5X11SQTDNCTM1`) is the workspace ID
required to construct Plain dashboard URLs, e.g.:
- Thread: https://app.plain.com/workspace/{workspaceId}/thread/{threadId}/
- Help-center article:
https://app.plain.com/workspace/{workspaceId}/help-center/{helpCenterId}/articles/{helpCenterArticleId}/
upsertHelpCenterArticle
Create or update a help-center article.
To create: provide helpCenterId, title, contentHtml, and status.
To update: provide helpCenterArticleId with any fields to change.
Slug is optional and will be normalized to lowercase.
Help-center article URL format (Plain dashboard):
https://app.plain.com/workspace/{workspaceId}/help-center/{helpCenterId}/articles/{helpCenterArticleId}/
where {helpCenterId} is the `helpCenterId` from the input (starts with `hc_`),
{helpCenterArticleId} is the article `id` returned in the result (starts with
`hca_`), and {workspaceId} is fetched via `getMyWorkspace` (starts with `w_`).
Do not invent IDs — only use values returned by the MCP tools.
snoozeThread
Snooze a thread for a specified duration.
The thread will return to TODO status after the snooze period expires.
durationSeconds: how long to snooze (e.g. 3600 = 1 hour, 86400 = 1 day).
statusDetail: WAITING_FOR_CUSTOMER or WAITING_FOR_DURATION.
getHelpCenterArticleGroups
Fetch a paginated list of article groups for a specific help center.
Use the `cursor` variable with the endCursor from the previous
response's pageInfo to fetch the next page. Set `first` to
control page size (default 50).
searchThreads
Search threads by text content in title, description, or messages.
Returns the first 50 results
Optionally filter results by status, priority, customer, assignee, or labels.
Use the `cursor` variable with the endCursor from the previous
response's pageInfo to fetch the next page. Set `first` to
control page size (default 50).
Thread URL format: https://app.plain.com/workspace/{workspaceId}/thread/{threadId}/
where {threadId} is the thread `id` field on each result (starts with `th_`)
and {workspaceId} is fetched via `getMyWorkspace` (starts with `w_`). Do not
invent IDs — only use values returned by the MCP tools.
deleteThreadFieldSchema
Delete a thread field schema from the workspace.
This will remove the field schema and all associated thread field values from threads.
Use this carefully as it permanently removes data.
unarchiveLabelType
Unarchive a previously archived label type to make it available again.
This restores the label type to the active label list so it can be used on threads.
getCustomerThreads
Fetch first 10 threads for a specific customer.
Use this to see a customer's full support history.
Optionally filter by status or sort by different criteria.
Use the `cursor` variable with the endCursor from the previous
response's pageInfo to fetch the next page. Set `first` to
control page size (default 10).
Thread URL format: https://app.plain.com/workspace/{workspaceId}/thread/{threadId}/
where {threadId} is the thread `id` field on each result (starts with `th_`)
and {workspaceId} is fetched via `getMyWorkspace` (starts with `w_`). Do not
invent IDs — only use values returned by the MCP tools.