The Plain MCP connector routes your AI agent's tool calls to Plain's own MCP server through Scalekit. Each user signs in to Plain once, and Scalekit stores and refreshes their tokens, so your agent never handles credentials. It comes with 427 tools.
- Tools
- 427
- What they doRead · write · destructive
- 27 · 335 · 6527 read335 write65 destructive
- Users sign in with
- OAuth
- OAuth app
- Scalekit's or your own
Setup
Install the SDK
Terminal window npm install @scalekit-sdk/node dotenvTerminal window pip install scalekit-sdk-python python-dotenvSet your credentials
Add your Scalekit credentials to your
.envfile. Find values in app.scalekit.com > Developers > API Credentials..env SCALEKIT_ENVIRONMENT_URL=<your-environment-url>SCALEKIT_CLIENT_ID=<your-client-id>SCALEKIT_CLIENT_SECRET=<your-client-secret>Create the Plain MCP connection
In AgentKit > Connections, create a Plain MCP connection. The name you give it is the
connection_nameyour code passes. See Configure connections.Scalekit credentials are available for Plain MCP server, so you don't need to register an OAuth app.
Authorize a user and make your first call
quickstart.mts import { ScalekitClient } from '@scalekit-sdk/node'import 'dotenv/config'import { createInterface } from 'node:readline/promises'const scalekit = new ScalekitClient(process.env.SCALEKIT_ENVIRONMENT_URL,process.env.SCALEKIT_CLIENT_ID,process.env.SCALEKIT_CLIENT_SECRET,)const actions = scalekit.actionsconst connector = 'plainmcp'const identifier = 'user_123'// Generate an authorization link for the userconst { link } = await actions.getAuthorizationLink({ connectionName: connector, identifier })console.log('Authorize Plain MCP:', link)const rl = createInterface({ input: process.stdin, output: process.stdout })await rl.question('Press Enter after authorizing...')rl.close()// Make your first callconst result = await actions.executeTool({connector,identifier,toolName: 'plainmcp_getcustomers',toolInput: {},})console.log(result)Terminal window npx tsx quickstart.mtsquickstart.py import osfrom scalekit import ScalekitClientfrom dotenv import load_dotenvload_dotenv()scalekit_client = ScalekitClient(env_url=os.getenv("SCALEKIT_ENVIRONMENT_URL"),client_id=os.getenv("SCALEKIT_CLIENT_ID"),client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"),)actions = scalekit_client.actionsconnection_name = "plainmcp"identifier = "user_123"# Generate an authorization link for the userlink_response = actions.get_authorization_link(connection_name=connection_name,identifier=identifier,)print("Authorize Plain MCP:", link_response.link)input("Press Enter after authorizing...")# Make your first callresult = actions.execute_tool(tool_input={},tool_name="plainmcp_getcustomers",connection_name=connection_name,identifier=identifier,)print(result)Terminal window python quickstart.pyEach user signs in once. See Authorize a user for the full flow and statuses.
Tools
Pass the exact name toexecute_toolplainmcp_getcustomerdetailsFetch a customer's full profile including email, assignment, company, and timestamps.Read-onlyGetCustomerDetails
Fetch a customer's full profile including email, assignment, company, and timestamps.
Inputs
customerIdstringrequired- Plain customer ID (starts with c_). Get it from getCustomers or getCustomerDetails.
plainmcp_getcustomersReturn a paginated list of all customers in the workspace.Read-onlyGetCustomers
Return a paginated list of all customers in the workspace.
Inputs
cursorstring- No description.
firststring- No description.default
50 tenantIdentifiersstring- No description.
plainmcp_getcustomerthreadsReturn all threads belonging to a specific customer, with optional status filtering.Read-onlyGetCustomerThreads
Return all threads belonging to a specific customer, with optional status filtering.
Inputs
customerIdstringrequired- No description.
cursorstring- No description.
firststring- No description.default
10 statusDetailsstring- No description.
statusesstring- No description.
plainmcp_gethelpcenterarticleFetch a single Help Center article by its ID.Read-onlyGetHelpCenterArticle
Fetch a single Help Center article by its ID.
Inputs
idstringrequired- Unique identifier of the resource.
plainmcp_gethelpcenterarticlebyslugFetch a Help Center article by its URL slug.Read-onlyGetHelpCenterArticleBySlug
Fetch a Help Center article by its URL slug.
Inputs
helpCenterIdstringrequired- Plain Help Center ID (starts with hc_). Get it from getHelpCenters.
slugstringrequired- URL slug of the Help Center article.
plainmcp_gethelpcenterarticlegroupsReturn all article groups for a Help Center.Read-onlyGetHelpCenterArticleGroups
Return all article groups for a Help Center.
Inputs
helpCenterIdstringrequired- No description.
cursorstring- No description.
firststring- No description.default
50
plainmcp_gethelpcenterarticlesReturn a paginated list of articles in a Help Center.Read-onlyGetHelpCenterArticles
Return a paginated list of articles in a Help Center.
Inputs
helpCenterIdstringrequired- No description.
cursorstring- No description.
firststring- No description.default
50
plainmcp_gethelpcentersReturn all Help Centers in the workspace.Read-onlyGetHelpCenters
Return all Help Centers in the workspace.
Inputs
cursorstring- No description.
firststring- No description.default
50
plainmcp_getlabelsReturn all label types available in the workspace.Read-onlyGetLabels
Return all label types available in the workspace.
Inputs
cursorstring- No description.
firststring- No description.default
50
plainmcp_getmyassignedthreadsReturn threads assigned to the authenticated user, with optional status and priority filters.Read-onlyGetMyAssignedThreads
Return threads assigned to the authenticated user, with optional status and priority filters.
Inputs
userIdstringrequired- No description.
cursorstring- No description.
firststring- No description.default
10 prioritiesstring- No description.
statusDetailsstring- No description.
statusesstring- No description.
plainmcp_getmyuserReturn the profile of the currently authenticated workspace user.Read-onlyGetMyUser
Return the profile of the currently authenticated workspace user.
Inputs
This tool takes no inputs.
plainmcp_getmyworkspaceReturn details about the current workspace including its ID and name.Read-onlyGetMyWorkspace
Return details about the current workspace including its ID and name.
Inputs
This tool takes no inputs.
plainmcp_getsidekicksessionPoll a Sidekick session: read its status, its newest messages, and any approval it is blocked on.Read-onlyGetSidekickSession
Poll a Sidekick session: read its status, its newest messages, and any approval it is blocked on. Call this repeatedly after startSidekickSession or sendSidekickMessage.
Inputs
discussionIdstringrequired- No description.
beforestring- No description.
laststring- No description.default
10
plainmcp_getsnippetFetch a single snippet by ID, including soft-deleted snippets (where isDeleted is true).Read-onlyGetSnippet
Fetch a single snippet by ID, including soft-deleted snippets (where isDeleted is true). Use this when you already have a snippet ID from getSnippets or another tool.
Inputs
snippetIdstringrequired- Snippet ID (starts with sn_), from getSnippets or another tool.
plainmcp_getsnippetsFetch a paginated list of snippets from the workspace.Read-onlyGetSnippets
Fetch a paginated list of snippets from the workspace. Snippets are reusable reply templates that agents insert when composing replies. Soft-deleted snippets are excluded from this list.
Inputs
cursorstring- No description.
firststring- No description.default
50
plainmcp_gettenantdetailsFetch full details for a specific tenant by its ID.Read-onlyGetTenantDetails
Fetch full details for a specific tenant by its ID.
Inputs
tenantIdstringrequired- Plain tenant ID (starts with t_). Get it from getCustomers.
plainmcp_gettenantsReturn a paginated list of all tenants in the workspace.Read-onlyGetTenants
Return a paginated list of all tenants in the workspace.
Inputs
cursorstring- No description.
firststring- No description.default
50
plainmcp_getthreaddetailsFetch a thread's full details and timeline entries by thread ID.Read-onlyGetThreadDetails
Fetch a thread's full details and timeline entries by thread ID.
Inputs
threadIdstringrequired- No description.
timelineCursorstring- No description.
timelineFirststring- No description.default
50
plainmcp_getthreadfieldschemasReturn all custom thread field schemas defined in the workspace.Read-onlyGetThreadFieldSchemas
Return all custom thread field schemas defined in the workspace.
Inputs
cursorstring- No description.
firststring- No description.default
50
plainmcp_getthreadknowledgesourcecitationsFetch the knowledge sources cited by AI agent replies on a thread.Read-onlyGetThreadKnowledgeSourceCitations
Fetch the knowledge sources cited by AI agent replies on a thread. Currently only Ari, Plain's AI support agent, produces citations. Correlate timelineEntryId with the timeline entry id values from getThreadDetails to see which reply cited which source. Returns an empty list when the thread has no citations.
Inputs
threadIdstringrequired- Plain thread ID (starts with th_) to fetch citations for.
plainmcp_getthreadsReturn threads with flexible filtering by status, priority, assignee, customer, labels, or date range.Read-onlyGetThreads
Return threads with flexible filtering by status, priority, assignee, customer, labels, or date range.
Inputs
assignedToUserstring- No description.
createdAtAfterstring- No description.
createdAtBeforestring- No description.
cursorstring- No description.
customerIdsstring- No description.
firststring- No description.default
10 isAssignedstring- No description.
labelTypeIdsstring- No description.
prioritiesstring- No description.
slaStatusesstring- No description.
slaTypesstring- No description.
statusDetailsstring- No description.
statusesstring- No description.
surveyResponsestring- No description.
tenantIdentifiersstring- No description.
threadFieldsstring- No description.
plainmcp_getuserbyemailLook up a workspace user by their email address.Read-onlyGetUserByEmail
Look up a workspace user by their email address.
Inputs
emailstringrequired- Email address of the user.
plainmcp_listsidekicksessionsList Sidekick sessions in the workspace, most recent activity first.Read-onlyListSidekickSessions
List Sidekick sessions in the workspace, most recent activity first. Use this to resume a session from an earlier conversation, check whether a session landed after a timeout, or find sessions that need attention. Pass agentStatuses: [NEEDS_INPUT] for sessions blocked on a human approval decision, or agentStatuses: [IN_PROGRESS] for ones still working. statuses is the session's own lifecycle (OPEN/RESOLVED) and does not overlap with agentStatuses.
Inputs
afterstring- No description.
agentStatusesstring- No description.
createdByUserIdsstring- No description.
firststring- No description.default
20 statusesstring- No description.
plainmcp_searchcustomersSearch customers by name or email and return a paginated list of matches.Read-onlySearchCustomers
Search customers by name or email and return a paginated list of matches.
Inputs
searchstringrequired- No description.
cursorstring- No description.
firststring- No description.default
50 tenantIdentifiersstring- No description.
plainmcp_searchtenantsSearch tenants by name and return matching results.Read-onlySearchTenants
Search tenants by name and return matching results.
Inputs
searchTermstringrequired- No description.
cursorstring- No description.
firststring- No description.default
50
plainmcp_searchthreadlinkcandidatesSearch a connected issue tracker for external entities that can be linked to a thread via createThreadLink.Read-onlySearchThreadLinkCandidates
Search a connected issue tracker for external entities that can be linked to a thread via createThreadLink. Scope the search to one issue tracker with sourceType (e.g. jira_issue, incidentio_incident, shortcut_story, rootly_incident, github_issue) and match against issue titles or identifiers with the free-text searchQuery. Requires a connected issue tracker integration for the given sourceType.
Inputs
filtersstringrequired- No description.
searchQuerystringrequired- Free text matched against titles or identifiers. For `github_issue`, include `repo:owner/repo`.
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_searchthreadsSearch threads by text with optional filters for status, priority, assignee, customer, and labels.Read-onlySearchThreads
Search threads by text with optional filters for status, priority, assignee, customer, and labels.
Inputs
searchQuerystringrequired- No description.
assignedToUserstring- No description.
cursorstring- No description.
customerIdsstring- No description.
firststring- No description.default
50 labelTypeIdsstring- No description.
prioritiesstring- No description.
statusDetailsstring- No description.
statusesstring- No description.
tenantIdentifiersstring- No description.
plainmcp_acceptsuggestedlabeltypesAccepts one or more pending suggested label types, creating a real label type for each and marking the suggestions as ACCEPTED.WriteAccept Suggested Label Types
Accepts one or more pending suggested label types, creating a real label type for each and marking the suggestions as ACCEPTED. All ids must currently be PENDING. Fails the whole batch with error code `label_type_name_already_exists` if a suggestion's name matches an existing label type or another suggestion in the same batch. Requires the `labelType:create` and `labelType:read` permissions. Arguments: - input: AcceptSuggestedLabelTypesInput!
Inputs
inputstringrequired- No description.
plainmcp_accountFetches a single account by its Plain-assigned ID.WriteAccount
Fetches a single account by its Plain-assigned ID. Returns null if no matching account is found. Requires the `tenant:read` permission. Arguments: - accountId: ID!
Inputs
accountIdstringrequired- No description.
plainmcp_accountfieldschemasReturns the list of account field schemas defined in the workspace.WriteAccount Field Schemas
Returns the list of account field schemas defined in the workspace. Use the `source` and `isVisible` filters to narrow results. Supports cursor-based pagination. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - filters: AccountFieldSchemasFilter - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
plainmcp_accountsReturns a paginated list of accounts in the workspace.WriteAccounts
Returns a paginated list of accounts in the workspace. Use the `filters` argument to narrow the results and `sortBy` to order them (by name ascending when omitted). Requires the `tenant:read` permission. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String - filters: AccountsFilter - sortBy: AccountsSort
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
sortBystring- No description.
plainmcp_activethreadclusterReturns the cluster that the given thread currently belongs to, or null if the thread has not been assigned to any cluster.WriteActive Thread Cluster
Returns the cluster that the given thread currently belongs to, or null if the thread has not been assigned to any cluster. Use this to show a customer-support agent which broader topic group a specific thread falls into. This API is in beta and may change without notice. Arguments: - threadId: ID!
Inputs
threadIdstringrequired- No description.
plainmcp_addadditionalassigneesAdd one or more users or machine users as additional (secondary) assignees on a thread.WriteAdd Additional Assignees
Add one or more users or machine users as additional (secondary) assignees on a thread. Additional assignees are looped in but are not the primary person responsible. Requires the `thread:assign` and `thread:read` permissions. Arguments: - input: AddAdditionalAssigneesInput!
Inputs
inputstringrequired- No description.
plainmcp_addcustomertoaccountsAdds a customer to one or more accounts.WriteAdd Customer To Accounts
Adds a customer to one or more accounts. The customer can be identified by their Plain ID, external ID, or email address. If the customer is already a member of a given account the operation is a no-op for that account. Requires the `customer:edit` and `customerTenantMembership:create` permissions. Arguments: - input: AddCustomerToAccountsInput!
Inputs
inputstringrequired- No description.
plainmcp_addcustomertocustomergroupsAdd a customer to one or more customer groups (up to 25 at once), identified by group ID, key, or external ID.WriteAdd Customer To Customer Groups
Add a customer to one or more customer groups (up to 25 at once), identified by group ID, key, or external ID. Memberships that already exist are silently skipped, making this operation safe to call repeatedly. Returns only the newly created memberships. Requires `customerGroupMembership:create` permission. Arguments: - input: AddCustomerToCustomerGroupsInput!
Inputs
inputstringrequired- No description.
plainmcp_addcustomertotenantsAdds a customer to one or more tenants.WriteAdd Customer To Tenants
Adds a customer to one or more tenants. The customer can be identified by their Plain ID, external ID, or email address. If the customer is already a member of a given tenant the operation is a no-op for that tenant. Requires the `customer:edit` and `customerTenantMembership:create` permissions. Deprecated: Use addCustomerToAccounts instead Arguments: - input: AddCustomerToTenantsInput!
Inputs
inputstringrequired- No description.
plainmcp_addlabelstouserAdd one or more team labels to a Plain user (agent).WriteAdd Labels To User
Add one or more team labels to a Plain user (agent). Only label types with type `TEAM` may be applied to users. Label types already present on the user are silently skipped. Requires the `label:create` permission. Arguments: - input: AddLabelsToUserInput!
Inputs
inputstringrequired- No description.
plainmcp_addmemberstotierAdds one or more tenants or companies to a tier (up to 25 per call).WriteAdd Members To Tier
Adds one or more tenants or companies to a tier (up to 25 per call). Because each tenant or company can belong to only one tier at a time, adding a member that already belongs to another tier will move it to this tier. Requires the `tierMembership:read` and `tierMembership:create` permissions. Arguments: - input: AddMembersToTierInput!
Inputs
inputstringrequired- No description.
plainmcp_agentsandboxtoolpoliciesThe Sidekick Agent tool approval policies for the workspace: every catalog tool with its effective approval mode (per-workspace override merged over the factory default).WriteAgent Sandbox Tool Policies
The Sidekick Agent tool approval policies for the workspace: every catalog tool with its effective approval mode (per-workspace override merged over the factory default). Optionally filter to a single service (e.g. "plain"). Arguments: - service: String
Inputs
servicestring- No description.
plainmcp_aifeedbackPaginated list of the feedback your team has submitted on Plain's AI features, such as a thumbs up or down on a Customer Agent reply, newest first.WriteAi Feedback
Paginated list of the feedback your team has submitted on Plain's AI features, such as a thumbs up or down on a Customer Agent reply, newest first. Use the optional `filters` argument to narrow results by feature, sentiment or submission time. Requires the `aiFeatureFeedback:read` permission. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - filters: AiFeedbackFilter - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
plainmcp_aitonerulesReturns the workspace's AI tone rules, which guide how Plain's AI features phrase replies.WriteAi Tone Rules
Returns the workspace's AI tone rules, which guide how Plain's AI features phrase replies. Use the optional `isEnabled` filter to retrieve only active rules. Pagination is supported via standard `first`/`after` and `last`/`before` cursor arguments, though in practice all rules are returned in a single page. Requires the `aiToneRule:read` permission. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String - filters: AiToneRulesFilter
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
plainmcp_autoresponderFetch a single autoresponder by its ID.WriteAutoresponder
Fetch a single autoresponder by its ID. Returns null if no autoresponder with that ID exists. Arguments: - autoresponderId: ID!
Inputs
autoresponderIdstringrequired- No description.
plainmcp_autorespondersList all autoresponders in the workspace, ordered by their configured priority order.WriteAutoresponders
List all autoresponders in the workspace, ordered by their configured priority order. Supports cursor-based pagination. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_billingplansReturns the available billing plans that can be selected for self-serve checkout.WriteBilling Plans
Returns the available billing plans that can be selected for self-serve checkout. Supports standard forward and backward pagination. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_broadcastrecipientunsubscribesReturns a paginated list of Slack channels that have opted out of broadcasts, newest first.WriteBroadcast Recipient Unsubscribes
Returns a paginated list of Slack channels that have opted out of broadcasts, newest first. Requires the `broadcast:read` permission and the broadcasts feature flag. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - searchQuery: String â Narrows to unsubscribes whose connected channel name contains this, or whose Slack workspace name contains this, matched case-insensitively and unanchored. Channel-name matches exclude disconnected channels; a workspace-name match returns every opted-out channel in that Slack workspace, including disconnected ones. - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
searchQuerystring- Narrows to unsubscribes whose connected channel name contains this, or whose Slack workspace name contains this, matched case-insensitively and unanchored. Channel-name matches exclude disconnected channels; a workspace-name match returns every opted-out channel in that Slack workspace, including disconnected ones.
plainmcp_broadcastsReturns a paginated list of the workspace's broadcasts, newest first.WriteBroadcasts
Returns a paginated list of the workspace's broadcasts, newest first. Soft-deleted broadcasts are excluded. Optionally narrow the results with `filters` (status). Supports standard forward and backward cursor pagination. Requires the `broadcast:read` permission. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - filters: BroadcastsFilter - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
plainmcp_bulkjoinslackchannelsInstructs the Plain Slack bot to join public Slack channels for the given workspace Slack channel integration.WriteBulk Join Slack Channels
Instructs the Plain Slack bot to join public Slack channels for the given workspace Slack channel integration. By default it joins every public channel matching an auto-join rule on the integration. Set `rule` to join only the public channels matching one rule, identified by its channel name prefix and suffix. Arguments: - input: BulkJoinSlackChannelsInput!
Inputs
inputstringrequired- No description.
plainmcp_bulkupdateconnectedslackchannelsApplies many connected-slack-channel updates in a single request.WriteBulk Update Connected Slack Channels
Applies many connected-slack-channel updates in a single request. Each update is applied independently with the same semantics as `updateConnectedSlackChannel`; partial failures are reported per-item. Arguments: - input: BulkUpdateConnectedSlackChannelsInput!
Inputs
inputstringrequired- No description.
plainmcp_bulkupdateslackchannelsettingsApplies many Slack per-channel setting writes in a single request.WriteBulk Update Slack Channel Settings
Applies many Slack per-channel setting writes in a single request. Each update targets the `WORKSPACE_SLACK_CONNECTED_CHANNEL` scope and is written with the same semantics as `updateSetting`. The writes are attempted independently; partial failures are reported per-item. Arguments: - input: BulkUpdateSlackChannelSettingsInput!
Inputs
inputstringrequired- No description.
plainmcp_bulkupsertworkflowstepsAtomically replace all steps in a workflow.WriteBulk Upsert Workflow Steps
Atomically replace all steps in a workflow. Steps with a matching `stepId` are updated; steps without an ID (or with a new ID) are created; steps that existed before but are absent from the input are deleted. Optionally updates `startStepId` and the trigger configuration in the same call. Maximum 60 steps per workflow. Read `workflowBuilderGuide` first for the trigger events and every step payload. Arguments: - input: BulkUpsertWorkflowStepsInput!
Inputs
inputstringrequired- No description.
plainmcp_businesshoursoverrideFetches a single business hours override by its ID, or null if no override with that ID exists.WriteBusiness Hours Override
Fetches a single business hours override by its ID, or null if no override with that ID exists. Requires the `businessHours:read` permission. Arguments: - businessHoursOverrideId: ID!
Inputs
businessHoursOverrideIdstringrequired- No description.
plainmcp_businesshoursoverridesReturns a paginated list of business hours overrides across the workspace's schedules, sorted by start date.WriteBusiness Hours Overrides
Returns a paginated list of business hours overrides across the workspace's schedules, sorted by start date. Filter by schedule, start date or end date. Requires the `businessHours:read` permission. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - filters: WorkspaceBusinessHoursOverridesFilter - sortBy: BusinessHoursOverridesSort - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
sortBystring- No description.
plainmcp_businesshoursscheduleFetches a single business hours schedule by its ID, or null if no schedule with that ID exists.WriteBusiness Hours Schedule
Fetches a single business hours schedule by its ID, or null if no schedule with that ID exists. Requires the `businessHours:read` permission. Arguments: - businessHoursScheduleId: ID!
Inputs
businessHoursScheduleIdstringrequired- No description.
plainmcp_businesshoursschedulesReturns a paginated list of the workspace's business hours schedules, sorted by name.WriteBusiness Hours Schedules
Returns a paginated list of the workspace's business hours schedules, sorted by name. Requires the `businessHours:read` permission. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_calculaterolechangecostCalculates the billing cost delta of changing a user's role or seat type, including prorated and full-period amounts.WriteCalculate Role Change Cost
Calculates the billing cost delta of changing a user's role or seat type, including prorated and full-period amounts. Use this before making a role change to show the user an accurate cost preview. Arguments: - input: CalculateRoleChangeCostInput!
Inputs
inputstringrequired- No description.
plainmcp_changethreadcustomerReassign a thread to a different customer.WriteChange Thread Customer
Reassign a thread to a different customer. The original customer retains all their other threads. Requires the `thread:edit` permission. Arguments: - input: ChangeThreadCustomerInput!
Inputs
inputstringrequired- No description.
plainmcp_changethreaddiscussionstatusMoves a discussion between OPEN and RESOLVED.WriteChange Thread Discussion Status
Moves a discussion between OPEN and RESOLVED. Callable by a person, by the custom agent a discussion is bound to, or by the machine user that started a Sidekick Agent discussion. Arguments: - input: ChangeThreadDiscussionStatusInput!
Inputs
inputstringrequired- No description.
plainmcp_chatappFetch a single chat app by its ID.WriteChat App
Fetch a single chat app by its ID. Returns null if no chat app with that ID exists in the workspace. Requires the `chatApp:read` permission. Deleting a chat app is done by the user in the Plain app. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/chat/<chatAppId>` (never the `<workspaceId>` placeholder). Arguments: - chatAppId: ID!
Inputs
chatAppIdstringrequired- No description.
plainmcp_chatappsList all chat apps in the workspace.WriteChat Apps
List all chat apps in the workspace. Supports cursor-based pagination. Requires the `chatApp:read` permission. Deleting a chat app is done by the user in the Plain app. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/chat/<chatAppId>` (never the `<workspaceId>` placeholder). Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_chatappsecretCheck whether a signing secret exists for a chat app.WriteChat App Secret
Check whether a signing secret exists for a chat app. Returns metadata about the secret (creation time, actor) but never the secret value itself â the raw secret is only returned once, at creation time via `createChatAppSecret`. Returns null if no secret has been created for the given chat app. Requires the `chatAppSecret:read` permission. Arguments: - chatAppId: ID!
Inputs
chatAppIdstringrequired- No description.
plainmcp_connecteddiscordchannelsReturns a paginated list of Discord channels synced from a specific guild.WriteConnected Discord Channels
Returns a paginated list of Discord channels synced from a specific guild. Use `refreshConnectedDiscordChannels` to pull the latest channel list from Discord before querying. Not connected yet? Connecting needs the user's approval in the provider. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/install/discord` (never the `<workspaceId>` placeholder), which takes them straight to Discord to approve, then read this again to confirm. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - discordGuildId: String! - first: Int - after: String - last: Int - before: String
Inputs
discordGuildIdstringrequired- No description.
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_connectedmsteamschannelsReturns a paginated list of Microsoft Teams channels that are connected to this workspace.WriteConnected Msteams Channels
Returns a paginated list of Microsoft Teams channels that are connected to this workspace. Supports forward and backward cursor pagination. Not connected yet? Connecting needs the user's approval in the provider. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/install/ms-teams` (never the `<workspaceId>` placeholder), which takes them straight to Microsoft Teams to approve, then read this again to confirm. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_connectedslackchannelReturns a single connected Slack channel by its Plain ID, or null if not found.WriteConnected Slack Channel
Returns a single connected Slack channel by its Plain ID, or null if not found. Arguments: - connectedSlackChannelId: ID!
Inputs
connectedSlackChannelIdstringrequired- No description.
plainmcp_connectedslackchannelsGets all slack channels for this workspace, which match the specified filters.WriteConnected Slack Channels
Gets all slack channels for this workspace, which match the specified filters. To count or list the channels a broadcast would reach, use `broadcastSendTargetRecipients` instead: it leaves out channels that unsubscribed. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - filters: ConnectedSlackChannelsFilter - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
plainmcp_createaccountCreates a new account.WriteCreate Account
Creates a new account. Fails with a validation error if an account already exists with the provided `externalId`. Use `upsertAccount` instead if you want to create or update an account idempotently. Requires the `tenant:create` permission. Arguments: - input: CreateAccountInput!
Inputs
inputstringrequired- No description.
plainmcp_createaifeedbackSubmit feedback on any Plain AI feature result.WriteCreate Ai Feedback
Submit feedback on any Plain AI feature result. Pass a JSON-encoded object in the `feedback` field whose `type` discriminates the feature (`AI_AGENT`, `THREAD_CATCHUP`, `THREAD_CLUSTERS`, `TONE_RULE`, or `KNOWLEDGE_GAP`) and includes the relevant context fields and an optional `sentiment` (`POSITIVE`, `NEGATIVE`, or `NEUTRAL`). Arguments: - input: CreateAiFeedbackInput!
Inputs
inputstringrequired- No description.
plainmcp_createaitoneruleCreates a single AI tone rule with the given category and description.WriteCreate Ai Tone Rule
Creates a single AI tone rule with the given category and description. Rules are enabled by default; pass `isEnabled: false` to create the rule in a disabled state. A workspace may have at most 7 simultaneously enabled rules across all categories. Requires the `aiToneRule:create` permission. Arguments: - input: CreateAiToneRuleInput!
Inputs
inputstringrequired- No description.
plainmcp_createalltestthreadsCreate one test thread per scenario for the signed-in user, so they get a populated inbox in a single call rather than one `createTestThread` per scenario.WriteCreate All Test Threads
Create one test thread per scenario for the signed-in user, so they get a populated inbox in a single call rather than one `createTestThread` per scenario. Each thread comes from that scenario's own test customer, and its opening message is written shortly after this returns. Scenarios the caller already has a test thread for are skipped, so calling this again tops the set up rather than duplicating it, and a scenario that fails does not stop the rest. Use `testThreads` for the caller's full set. Requires the `thread:create` permission.
Inputs
This tool takes no inputs.
plainmcp_createattachmentuploadurlGenerate a presigned upload URL for an attachment.WriteCreate Attachment Upload Url
Generate a presigned upload URL for an attachment. Use the returned `uploadFormUrl` and `uploadFormData` fields to POST the file as multipart/form-data directly to storage. The upload URL expires after 2 hours; the resulting `attachment.id` can then be referenced in mutations such as `createThread`, `replyToEmail`, or `createNote`. Requires the `attachment:create` permission. Attachments that are never referenced in a message are automatically deleted after 24 hours. Arguments: - input: CreateAttachmentUploadUrlInput!
Inputs
inputstringrequired- No description.
plainmcp_createautoresponderCreate a new autoresponder that automatically sends a reply when a thread is created from a matching message source and satisfies all specified conditions.WriteCreate Autoresponder
Create a new autoresponder that automatically sends a reply when a thread is created from a matching message source and satisfies all specified conditions. A workspace can have at most 25 autoresponders. Requires the `autoresponder:create` permission. Arguments: - input: CreateAutoresponderInput!
Inputs
inputstringrequired- No description.
plainmcp_createbroadcastCreate a new broadcast: a message authored once and posted to many Slack channels at once.WriteCreate Broadcast
Create a new broadcast: a message authored once and posted to many Slack channels at once. Creating one never sends it â a new broadcast is a DRAFT, and scheduling the real send is done by a human in the Plain app. Required input fields: `name`, `content`, `contentFormat`, `type`. - `name` identifies the broadcast internally and is never shown to recipients. It is what `searchBroadcasts` matches on. - `notificationTitle` is what recipients see in the notification the broadcast arrives as. It does leave Plain. Optional here, but the broadcast cannot be sent or tested until it is set. - `type` must be `SLACK`. It is fixed at creation: content is written against a channel's rendering rules, so a broadcast cannot be moved to another channel later. - `contentFormat` and `content` go together. From MCP, send `SLACK_BLOCK_KIT` and a JSON array of Slack blocks, as `chat.postMessage` would take. A one-paragraph body looks like this, passed as a string: "[{\"type\":\"section\",\"text\":{\"type\":\"mrkdwn\",\"text\":\"Hello\"}}]" Buttons need a `url` â interactive elements do nothing in a broadcast. Images must be publicly reachable. This format cannot be edited in the Plain app. `TIPTAP` is still accepted (a serialised Tiptap document) and is what the app composer writes; do not use it unless you are copying content already stored that way. - `isLinkUnfurlingEnabled` controls whether Slack expands links and media. Defaults to true, which is Slack's own behaviour. - `appendUnsubscribeLink` controls whether Plain appends an unsubscribe footer when this broadcast is delivered. Omit to inherit the workspace default from `getBroadcastUnsubscribeLinkSetting`; pass true or false to override that default for this broadcast only. It controls footer emission, not whether unsubscribes are honoured. - `senderType` is who the broadcast is sent as: `PLAIN_WORKSPACE` posts under the workspace's own name and logo and takes no `senderUserId`; `PLAIN_USER` posts as a Plain user and requires `senderUserId`. Get user IDs from `getMyUser` or `getUserByEmail`. Leave `senderEmailAddress` unset: it belongs to a future email channel, not to a Slack broadcast. - `sendTarget` is who the broadcast reaches, resolved to concrete channels at send time. `scope: ALL_RECIPIENTS` means every connected, enabled customer channel and rejects `filters`; `scope: MATCHING` requires `filters`. Omit `scope` to target only the channels named in `recipients`. Inside `filters`, dimensions AND together and values within a dimension OR, and it must constrain something â reaching everyone is `ALL_RECIPIENTS`, not an empty filter. `audienceIds` reference saved audiences (`getBroadcastAudiences`), which must be of the same type as the broadcast. Preview the live resolved set with `getBroadcastSendTargetRecipients`. Both the sender and the target can be left unset here and filled in later with `updateBroadcast`. Use `sendTestBroadcast` to post a test copy to channels you name before a human schedules the real send.
Inputs
inputstringrequired- No description.
plainmcp_createbroadcastaudienceCreate a reusable broadcast audience: a named set of broadcast recipients, resolved to concrete Slack channels at send time rather than when saved.WriteCreate Broadcast Audience
Create a reusable broadcast audience: a named set of broadcast recipients, resolved to concrete Slack channels at send time rather than when saved. Required input fields: `name`, `type`, `filters`. - `name` identifies the audience internally and is never shown to recipients. - `type` must be `SLACK`. It is fixed at creation, and an audience can only be attached to a broadcast of the same type. - `filters` is what the audience selects. Dimensions on one node AND together and values within a dimension OR: `tierIds: [a, b]` means either tier, while `tierIds: [a]` plus `slackChannelNameContains: ["eng"]` means both must hold. An empty dimension cannot be written â omit it instead. - `tenantIds` / `tierIds` â get IDs from `getTenants` or `searchTenants`. - `tenantFields` â filter on a tenant field by its `externalFieldId`, supplying the value field matching the field's type. - `slackChannels` â channels pinned by ID, nothing re-resolves these, so an audience holding only these is a saved channel list. - `slackChannelNameContains` â unanchored, case-insensitive name substrings, ORed with each other and resolved at send time, so channels created or renamed later are picked up. - `and` / `or` / `not` hold further filters. `and` and `or` nest at most two levels deep. `not` may name a single dimension and nothing else. - `audienceIds` is rejected here: an audience cannot be defined in terms of another audience. It is only valid on a broadcast's own send target. - `filters: {}` â no rows at all â means every tenant, and is the only way to say so. Every nested node must constrain something. `filters` is validated against `type`, so a filter naming a dimension this type cannot resolve is rejected here rather than silently resolving to nobody at send time. Editing an audience later changes who every broadcast using it will reach on its next send.
Inputs
inputstringrequired- No description.
plainmcp_createbusinesshoursoverrideCreate an override that replaces a schedule's weekly hours from `startsOn` to `endsOn`, e.g.WriteCreate Business Hours Override
Create an override that replaces a schedule's weekly hours from `startsOn` to `endsOn`, e.g. a holiday. Can't overlap another override on the same schedule. Requires the `businessHours:create` permission. Arguments: - input: CreateBusinessHoursOverrideInput!
Inputs
inputstringrequired- No description.
plainmcp_createbusinesshoursscheduleCreate a new named business hours schedule, optionally with its opening slots.WriteCreate Business Hours Schedule
Create a new named business hours schedule, optionally with its opening slots. Overlapping and adjacent slots are merged on write. Requires the `businessHours:create` permission. Arguments: - input: CreateBusinessHoursScheduleInput!
Inputs
inputstringrequired- No description.
plainmcp_createchatappCreate a new chat app, which represents a source of chat messages (e.g.WriteCreate Chat App
Create a new chat app, which represents a source of chat messages (e.g. a specific in-product widget or integration). Optionally supply a `logo` using a previously uploaded workspace file ID. The logo must be a public, image-type workspace file. Requires the `chatApp:create` permission and the live-chat billing entitlement. Arguments: - input: CreateChatAppInput!
Inputs
inputstringrequired- No description.
plainmcp_createcustomercardconfigCreates a new customer card config.WriteCreate Customer Card Config
Creates a new customer card config. New configs are placed at the bottom of the list (order 100000) by default. A maximum of 25 card configs can be created per workspace. Returns a `too_many_customer_card_configs` error if the limit is reached. The `key` must be unique within the workspace and is used in the request payload sent to your API URL. Arguments: - input: CreateCustomerCardConfigInput!
Inputs
inputstringrequired- No description.
plainmcp_createcustomereventCreates a customer event that appears in the timeline of every thread belonging to the customer.WriteCreate Customer Event
Creates a customer event that appears in the timeline of every thread belonging to the customer. Use this to surface important product activity (e.g. a failed payment, a deleted API key) so your team has full context when helping the customer. The event layout is defined using Plain UI components. Requires the `customerEvent:create` permission. Arguments: - input: CreateCustomerEventInput!
Inputs
inputstringrequired- No description.
plainmcp_createcustomergroupCreate a new customer group with a unique key, display name, and color.WriteCreate Customer Group
Create a new customer group with a unique key, display name, and color. Use `upsertCustomerGroup` instead if you need idempotent create-or-update behaviour. Requires `customerGroup:create` permission. Arguments: - input: CreateCustomerGroupInput!
Inputs
inputstringrequired- No description.
plainmcp_createcustomersurveyCreates a new customer survey (e.g.WriteCreate Customer Survey
Creates a new customer survey (e.g. a CSAT survey) in the workspace. A survey is sent to the customer when a thread they're on is marked done and matches the survey's conditions, after `responseDelayMinutes`. Requires the `customerSurvey:create` permission and a billing entitlement for customer surveys. You must supply a template (currently only `csatTemplate` is supported) and can optionally specify targeting conditions, an enabled state, a send delay, and a per-customer cooldown interval. Arguments: - input: CreateCustomerSurveyInput!
Inputs
inputstringrequired- No description.
plainmcp_createcustomroleCreates a new custom role in the workspace.WriteCreate Custom Role
Creates a new custom role in the workspace. Custom roles inherit the Support permissions by default; set `permissionsPreset` to `VIEWER` for a view-only role that takes a viewer seat rather than a member seat. Thread visibility can be further limited using `upsertRoleScopes`. Requires the `roles:create` permission and the `custom_roles` billing entitlement. Arguments: - input: CreateCustomRoleInput!
Inputs
inputstringrequired- No description.
plainmcp_createemailpreviewurlGenerates a short-lived URL that can be used to preview the rendered HTML of an email.WriteCreate Email Preview Url
Generates a short-lived URL that can be used to preview the rendered HTML of an email. Useful for displaying email content in external tools or dashboards. Arguments: - input: CreateEmailPreviewUrlInput!
Inputs
inputstringrequired- No description.
plainmcp_createescalationpathCreates a new escalation path with the given name, optional description, and an ordered list of steps (up to 20).WriteCreate Escalation Path
Creates a new escalation path with the given name, optional description, and an ordered list of steps (up to 20). Each step routes the thread to either a specific user or the owners of a label type. Steps must not contain duplicates. Requires the `escalationPath:create` permission and the escalation paths feature entitlement. Arguments: - input: CreateEscalationPathInput!
Inputs
inputstringrequired- No description.
plainmcp_createhelpcenterCreate a help center with its names, description, type, subdomain, colour and logo.WriteCreate Help Center
Create a help center with its names, description, type, subdomain, colour and logo. Requires the `helpCenter:edit` permission. Pass each field as its own argument, not wrapped in an `input` object. Custom JavaScript and sign-in can't be set here, because they run code on every public page or take a secret. The user sets them in the Plain app: call `getMyWorkspace` for this workspace's ID and give them the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/help-center/<helpCenterId>` (never the `<workspaceId>` placeholder).
Inputs
descriptionstringrequired- No description.
internalNamestringrequired- No description.
publicNamestringrequired- No description.
subdomainstringrequired- No description.
typestringrequired- No description.
colorstring- No description.
logostring- No description.
plainmcp_createhelpcenterarticlegroupCreate a new article group (folder) within a help center.WriteCreate Help Center Article Group
Create a new article group (folder) within a help center. Pass parentHelpCenterArticleGroupId to nest the group inside an existing group. Requires the helpCenter:edit permission. Arguments: - input: CreateHelpCenterArticleGroupInput!
Inputs
inputstringrequired- No description.
plainmcp_createindexeddocumentManually add a single URL as an indexed document within an existing knowledge source.WriteCreate Indexed Document
Manually add a single URL as an indexed document within an existing knowledge source. The document is fetched and queued for indexing asynchronously. Requires Plain AI to be enabled on the workspace; turn it on with `updateSetting` (code `plain_ai`, WORKSPACE scope, boolean `true`). Arguments: - input: CreateIndexedDocumentInput!
Inputs
inputstringrequired- No description.
plainmcp_createissuetrackerissueCreate a new issue in a connected issue tracker (Shortcut, Rootly, incident.io, or GitHub) and return a `ThreadLinkCandidate` that can immediately be used with `createThreadLink` to link it to a thread.WriteCreate Issue Tracker Issue
Create a new issue in a connected issue tracker (Shortcut, Rootly, incident.io, or GitHub) and return a `ThreadLinkCandidate` that can immediately be used with `createThreadLink` to link it to a thread. The `fields` array must include all required fields for the chosen tracker (use `issueTrackerFields` to discover which fields are required and their allowed values). For GitHub, the acting user must have a personal GitHub user auth integration set up via `createGithubUserAuthIntegration`; the issue is created on their behalf. Requires the `threadLink:create` permission. Arguments: - input: CreateIssueTrackerIssueInput!
Inputs
inputstringrequired- No description.
plainmcp_createknowledgesourceCreate a new knowledge source that Plain AI will index and use when generating replies.WriteCreate Knowledge Source
Create a new knowledge source that Plain AI will index and use when generating replies. Use type `SITEMAP` to crawl all URLs listed in a sitemap XML file, or type `URL` to index a single page. Requires Plain AI to be enabled on the workspace; turn it on with `updateSetting` (code `plain_ai`, WORKSPACE scope, boolean `true`). Arguments: - input: CreateKnowledgeSourceInput!
Inputs
inputstringrequired- No description.
plainmcp_createmachineuserCreates a new machine user in the workspace.WriteCreate Machine User
Creates a new machine user in the workspace. Each machine user can hold multiple API keys and optionally has a public-facing name shown to customers. Only one machine user of type AI_AGENT is allowed per workspace. Requires the `machineUser:create` permission. Arguments: - input: CreateMachineUserInput!
Inputs
inputstringrequired- No description.
plainmcp_createmcpfeedbackReport a problem or an idea about Plain's MCP tools to the Plain team.WriteCreate Mcp Feedback
Report a problem or an idea about Plain's MCP tools to the Plain team. Call this when a tool fails unexpectedly, when you cannot do what the user asked with the available tools, or when you have a concrete idea that would make the tools more useful. Describe the problem in `comment` and name the tool in `toolName` if one was involved. Do not include customer data, personal information, or message content in `comment`. Requires the `aiFeatureFeedback:create` permission. Arguments: - input: CreateMcpFeedbackInput!
Inputs
inputstringrequired- No description.
plainmcp_createmyfavoritepageSaves a page as a favorite for the currently authenticated user.WriteCreate My Favorite Page
Saves a page as a favorite for the currently authenticated user. If the caller has already favorited a page with the same key, the existing record is returned unchanged (idempotent). Requires the `favoritePage:create` permission. Arguments: - input: CreateMyFavoritePageInput!
Inputs
inputstringrequired- No description.
plainmcp_createsavedthreadsviewCreates a new saved threads view in the workspace.WriteCreate Saved Threads View
Creates a new saved threads view in the workspace. The view stores a named filter configuration (including sort order, grouping, layout, and display options) that can be applied when querying threads. Requires the savedThreadsView:create permission; depending on workspace settings, only admins or all members may be allowed to create views. Arguments: - input: CreateSavedThreadsViewInput!
Inputs
inputstringrequired- No description.
plainmcp_createservicelevelagreementCreate a service level agreement (SLA) for a tier.WriteCreate Service Level Agreement
Create a service level agreement (SLA) for a tier. Each SLA commits your team to a time target and can be scoped by thread priority and/or label type. Provide exactly one of `firstResponseTimeMinutes` (time from thread creation to first reply), `nextResponseTimeMinutes` (time from each customer message to the next reply), `firstResolutionTimeMinutes` (time from thread creation to first Done), or `totalResolutionTimeMinutes` (time from thread creation to Done, including after reopen). A `nextResponseTimeMinutes` SLA can only be created if a `firstResponseTimeMinutes` SLA already exists on the same tier. Requires the `serviceLevelAgreement:create` permission. Arguments: - input: CreateServiceLevelAgreementInput!
Inputs
inputstringrequired- No description.
plainmcp_createservicelevelagreementpolicyCreate an SLA policy together with its targets.WriteCreate Service Level Agreement Policy
Create an SLA policy together with its targets. A policy holds at most one target per type, and any combination of types is valid. Business hours schedules are chosen once per policy: every target that uses business hours must reference the same schedules, and a target with none is tracked 24/7. A policy only starts tracking once it is applied to a thread. Requires the `serviceLevelAgreement:create` permission. Arguments: - input: CreateServiceLevelAgreementPolicyInput!
Inputs
inputstringrequired- No description.
plainmcp_createtaskCreate a new task in Plain.WriteCreate Task
Create a new task in Plain. Only `title` is required. Optional fields: - `description`: longer context or instructions for the task. - `status`: TODO (default), IN_PROGRESS, DONE, or CANCELLED. - `priority`: 0 (urgent), 1 (high), 2 (normal, default), or 3 (low). - `accountId`: the account this task relates to. - `assignedTo`: provide either `userId` or `machineUserId`, not both. To link the new task to a thread, pass the returned task `id` to `createThreadLink` as `plainTask: { plainTaskId }`.
Inputs
inputstringrequired- No description.
plainmcp_createtenantCreates a new tenant.WriteCreate Tenant
Creates a new tenant. Fails with a validation error if a tenant already exists with the provided `externalId`. Use `upsertTenant` instead if you want to create or update a tenant idempotently. Requires the `tenant:create` permission. Deprecated: Use createAccount instead Arguments: - input: CreateTenantInput!
Inputs
inputstringrequired- No description.
plainmcp_createtestthreadCreate a test thread for the signed-in user.WriteCreate Test Thread
Create a test thread for the signed-in user. Test threads come from a test customer rather than a real one. The scenario is picked for you and fixes the thread's title; its opening message is written shortly after this returns. They are listed by `testThreads` rather than `threads`, and only for the user who created them. Pass `channel: SLACK` to have the conversation happen in the workspace's Slack test channel instead of chat, so the caller sees a thread arrive the way a customer's Slack message does. Requires the `thread:create` permission. Arguments: - input: CreateTestThreadInput
Inputs
inputstring- No description.
plainmcp_createthreaddiscussionStart a new discussion on a Plain thread.WriteCreate Thread Discussion
Start a new discussion on a Plain thread. Supports Slack (posts a new thread in a connected Slack channel), Email (sends an outbound email chain), and Cursor workspace background agent discussions. The markdownContent field is sent as the opening message; for Slack discussions you may also supply slackBlocks (JSON-encoded Block Kit array) for rich Slack formatting while markdownContent serves as the Plain UI fallback. Prefer createDiscussion for new integrations. Arguments: - input: CreateThreadDiscussionInput!
Inputs
inputstringrequired- No description.
plainmcp_createthreadeventCreates a thread event that appears only in the timeline of the specified thread.WriteCreate Thread Event
Creates a thread event that appears only in the timeline of the specified thread. Use this when an activity is specific to a single conversation rather than the customer as a whole. The event layout is defined using Plain UI components. Thread events are visible only to your team and are never shown to the customer. Requires the `threadEvent:create` and `threadEvent:read` permissions. Arguments: - input: CreateThreadEventInput!
Inputs
inputstringrequired- No description.
plainmcp_createthreadfrommsteamsmessageCreates a thread from a message in a Microsoft Teams channel or chat that the Plain bot is a member of.WriteCreate Thread From Msteams Message
Creates a thread from a message in a Microsoft Teams channel or chat that the Plain bot is a member of. This is the trigger for the `API_ONLY` value of the `ms_teams/ingestion_mode` workspace setting, and works in `AUTOMATIC` mode too. In a channel, the whole post the message belongs to becomes the thread. In a chat, the thread also includes the messages before and after this one, taken from the chat's 50 most recent messages. Thread creation runs asynchronously, so `thread` is only returned when the message was already on a thread. Requires the `thread:create` permission. Arguments: - input: CreateThreadFromMSTeamsMessageInput!
Inputs
inputstringrequired- No description.
plainmcp_createthreadfromslackmessageCreates a thread from a top-level message in a connected customer Slack channel, along with the replies Plain has already received for it.WriteCreate Thread From Slack Message
Creates a thread from a top-level message in a connected customer Slack channel, along with the replies Plain has already received for it. This is the trigger for the `API_ONLY` ingestion mode, and works in every other mode too. Ingestion runs asynchronously, so `thread` is returned only when the message had already been ingested. Requires the `thread:create` permission. This is not a way to import historic conversations: only replies Plain saw over the Slack events API are included, so a message from before the Plain bot joined the channel becomes a thread missing everything that was said before then. Arguments: - input: CreateThreadFromSlackMessageInput!
Inputs
inputstringrequired- No description.
plainmcp_createtierCreates a new tier.WriteCreate Tier
Creates a new tier. You can optionally add tenant and company members at creation time. Requires the `tier:create` permission. Arguments: - input: CreateTierInput!
Inputs
inputstringrequired- No description.
plainmcp_createworkflowCreate a new workflow.WriteCreate Workflow
Create a new workflow. The workflow starts unpublished with no steps; use `bulkUpsertWorkflowSteps` to add steps and `updateWorkflow` to publish it. The `trigger` field must be a valid JSON-encoded trigger configuration. Read `workflowBuilderGuide` first for the trigger events and every step payload. Arguments: - input: CreateWorkflowInput!
Inputs
inputstringrequired- No description.
plainmcp_createworkflowstepAdd a single step to a workflow.WriteCreate Workflow Step
Add a single step to a workflow. For bulk changes to a workflow's step graph, prefer `bulkUpsertWorkflowSteps`. `workflowBuilderGuide` lists every step payload. Arguments: - input: CreateWorkflowStepInput!
Inputs
inputstringrequired- No description.
plainmcp_createworkspacefiledownloadurlGenerate a fresh download URL for a workspace file.WriteCreate Workspace File Download Url
Generate a fresh download URL for a workspace file. For PRIVATE files, returns a short-lived pre-signed URL (valid for 3 minutes); for PUBLIC files, returns a permanent CDN URL with no expiry. Call this whenever you need to give a user access to a file rather than caching URLs, as private URLs expire quickly. Arguments: - input: CreateWorkspaceFileDownloadUrlInput!
Inputs
inputstringrequired- No description.
plainmcp_createworkspacefileuploadurlBegin a two-step file upload.WriteCreate Workspace File Upload Url
Begin a two-step file upload. Returns a pre-signed S3 form URL and form data fields that you POST the raw file bytes to directly from the client. The upload URL expires in 2 hours. Files must be 50 MB or smaller; certain executable file extensions (e.g. .exe, .bat) are rejected. Requires the `workspaceFile:create` permission. Arguments: - input: CreateWorkspaceFileUploadUrlInput!
Inputs
inputstringrequired- No description.
plainmcp_createworkspaceslackintegrationfromauthConnect workspace Slack notifications using a Slack connection the workspace already has.WriteCreate Workspace Slack Integration From Auth
Connect workspace Slack notifications using a Slack connection the workspace already has. There is no second OAuth install. Pass the id of an existing workspace Slack channel integration (`workspaceSlackChannelIntegrations`). Requires `workspaceSlackIntegration:create`. This does not choose the channel notifications post to, and it does not start posting. After it succeeds, set the `notification/slack/channel_id` setting on the new integration. Until that setting is present, Plain drops workspace Slack notifications for it.
Inputs
inputstringrequired- No description.
plainmcp_cursorrepositoriesReturns the list of GitHub repositories accessible via the given Cursor integration.WriteCursor Repositories
Returns the list of GitHub repositories accessible via the given Cursor integration. Results are fetched live from the Cursor API and cached for up to 5 minutes. Requires the `workspaceCursorIntegration:read` permission. Arguments: - integrationId: ID!
Inputs
integrationIdstringrequired- No description.
plainmcp_customerbyemailFetch a customer by their email address.WriteCustomer By Email
Fetch a customer by their email address. Returns null if no customer with that email exists. Requires the `customer:read` permission. Arguments: - email: String!
Inputs
emailstringrequired- No description.
plainmcp_customerbyexternalidGet a customer by its external ID.WriteCustomer By External Id
Get a customer by its external ID. A customer's external ID is unique within a workspace. Arguments: - externalId: ID!
Inputs
externalIdstringrequired- No description.
plainmcp_customercardconfigReturns a single customer card config by ID.WriteCustomer Card Config
Returns a single customer card config by ID. Returns null if no config with the given ID exists. Deleting a card is done by the user in the Plain app. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/customer-cards/<customerCardConfigId>` (never the `<workspaceId>` placeholder). Arguments: - customerCardConfigId: ID!
Inputs
customerCardConfigIdstringrequired- No description.
plainmcp_customercardconfigsReturns all customer card configs for the workspace, ordered by their `order` field.WriteCustomer Card Configs
Returns all customer card configs for the workspace, ordered by their `order` field. Deleting a card is done by the user in the Plain app. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/customer-cards/<customerCardConfigId>` (never the `<workspaceId>` placeholder).
Inputs
This tool takes no inputs.
plainmcp_customercardinstancesReturns the current customer card instances for a customer, triggering a fresh load for any cards that are expired or in an error state.WriteCustomer Card Instances
Returns the current customer card instances for a customer, triggering a fresh load for any cards that are expired or in an error state. Cards that are cached and within their TTL are returned immediately as `CustomerCardInstanceLoaded`. Cards that need to be fetched are returned as `CustomerCardInstanceLoading`; subscribe to `customerCardInstanceChanges` to receive the result when loading completes. Pass `threadId` to provide thread context to your card API endpoint. A maximum of 25 card instances will be returned, due to only allowing 25 customer card configs. Arguments: - customerId: ID! - threadId: ID
Inputs
customerIdstringrequired- No description.
threadIdstring- No description.
plainmcp_customergroupFetch a single customer group by its ID.WriteCustomer Group
Fetch a single customer group by its ID. Returns null if no group with the given ID exists in the workspace. Arguments: - customerGroupId: ID!
Inputs
customerGroupIdstringrequired- No description.
plainmcp_customergroupsFetch a paginated list of all customer groups in the workspace.WriteCustomer Groups
Fetch a paginated list of all customer groups in the workspace. Optionally filter by external IDs using the `filters` argument. Uses cursor-based pagination. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - filters: CustomerGroupsFilter - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
plainmcp_customersFetch a paginated list of all customers in the workspace.WriteCustomers
Fetch a paginated list of all customers in the workspace. Supports filtering by group membership, company, spam status and more via `filters`, and ordering via `sortBy`. Use cursor-based pagination (`first`/`after` or `last`/`before`) to page through large result sets. Requires the `customer:read` permission. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - filters: CustomersFilter - sortBy: CustomersSort - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
sortBystring- No description.
plainmcp_customersurveyFetches a single customer survey by its ID.WriteCustomer Survey
Fetches a single customer survey by its ID. Returns null if no survey with that ID exists. Arguments: - id: ID!
Inputs
idstringrequired- No description.
plainmcp_customersurveysReturns a paginated list of all customer surveys configured in the workspace, ordered by their display order.WriteCustomer Surveys
Returns a paginated list of all customer surveys configured in the workspace, ordered by their display order. Use this to build management UIs or sync survey configurations. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_customroleReturns a single custom role by its ID, or null if not found.WriteCustom Role
Returns a single custom role by its ID, or null if not found. Requires the `roles:read` permission. Changing a role's permissions or which threads it can see is done by the user in the Plain app. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/roles/<customRoleId>` (never the `<workspaceId>` placeholder). Arguments: - customRoleId: ID!
Inputs
customRoleIdstringrequired- No description.
plainmcp_customrolesReturns all custom roles defined in the workspace.WriteCustom Roles
Returns all custom roles defined in the workspace. Use this to list the custom roles you have created and inspect their scope definitions. Supports cursor-based pagination. Requires the `roles:read` permission. Changing a role's permissions or which threads it can see is done by the user in the Plain app. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/roles/<customRoleId>` (never the `<workspaceId>` placeholder). Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_dismisssuggestedlabeltypesDismisses one or more pending suggested label types without creating label types.WriteDismiss Suggested Label Types
Dismisses one or more pending suggested label types without creating label types. All ids must currently be PENDING. Requires the `labelType:create` permission. Arguments: - input: DismissSuggestedLabelTypesInput!
Inputs
inputstringrequired- No description.
plainmcp_duplicatebroadcastCopy an existing broadcast into a new DRAFT.WriteDuplicate Broadcast
Copy an existing broadcast into a new DRAFT. Authoring fields (name prefixed with "Copy of", content, audience, sender, notification title, and related settings) are copied. Send history, schedule, recipients, and delivery stats are not â the copy is never scheduled or sent by this mutation. Returns the new draft's identity only. Call `getBroadcastDetails` with the returned id to read the copied content, sender, and audience. Requires `broadcast:create` and `broadcast:read`. Use `updateBroadcast` and `scheduleBroadcast` on the returned id if the draft should go out.
Inputs
inputstringrequired- No description.
plainmcp_editqueuedagentsessionmessageEdits the text of a user message that is waiting in a Sidekick Agent AGENT_SESSION queue.WriteEdit Queued Agent Session Message
Edits the text of a user message that is waiting in a Sidekick Agent AGENT_SESSION queue. Attachments are not editable in this flow â delete and re-send to change them. Rejects with `queued_agent_session_message_already_dispatched` if the agent has already picked the message up. Arguments: - input: EditQueuedAgentSessionMessageInput!
Inputs
inputstringrequired- No description.
plainmcp_emailsuppressionReturns the suppression for a specific email address, or null when the address is not suppressed.WriteEmail Suppression
Returns the suppression for a specific email address, or null when the address is not suppressed. Arguments: - emailAddress: String!
Inputs
emailAddressstringrequired- No description.
plainmcp_enabledaitonerulestextReturns all currently enabled AI tone rules serialised as a plain-text instruction string that is suitable for injecting into AI prompts.WriteEnabled Ai Tone Rules Text
Returns all currently enabled AI tone rules serialised as a plain-text instruction string that is suitable for injecting into AI prompts. Returns `null` when no rules are enabled or the feature flag is off. Requires the `aiToneRule:read` permission.
Inputs
This tool takes no inputs.
plainmcp_escalatethreadAdvance a thread to the next step in its escalation path.WriteEscalate Thread
Advance a thread to the next step in its escalation path. The thread must already have an escalation path attached (via `updateThreadEscalationPath`) â if not, this call returns an error. Requires the `thread:edit` permission. Arguments: - input: EscalateThreadInput!
Inputs
inputstringrequired- No description.
plainmcp_escalationpathFetches a single escalation path by its ID.WriteEscalation Path
Fetches a single escalation path by its ID. Returns null if no escalation path with the given ID exists. Requires the `escalationPath:read` permission. Arguments: - id: ID!
Inputs
idstringrequired- No description.
plainmcp_escalationpathsReturns a paginated list of all escalation paths configured in the workspace.WriteEscalation Paths
Returns a paginated list of all escalation paths configured in the workspace. Requires the `escalationPath:read` permission. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_exportworkflowtemplateBuild the files for publishing a workflow as a template; writes nothing.WriteExport Workflow Template
Build the files for publishing a workflow as a template; writes nothing. Requires the `workflowRule:create` permission. Arguments: - input: ExportWorkflowTemplateInput!
Inputs
inputstringrequired- No description.
plainmcp_forkthreadCreate a new thread by forking from a specific timeline entry in an existing thread.WriteFork Thread
Create a new thread by forking from a specific timeline entry in an existing thread. The forked thread starts at the chosen message, allowing you to split a conversation into a separate support case. Requires the `thread:create` permission. Arguments: - input: ForkThreadInput!
Inputs
inputstringrequired- No description.
plainmcp_generateaitonerulesfromdescriptionUses AI to generate a set of tone rules from a free-text description of the desired communication style (up to 5000 characters).WriteGenerate Ai Tone Rules From Description
Uses AI to generate a set of tone rules from a free-text description of the desired communication style (up to 5000 characters). The generated rules are saved to the workspace in a disabled state so you can review and selectively enable them. Returns the newly created rules. Requires the `aiToneRule:create` permission. Arguments: - input: GenerateAiToneRulesFromDescriptionInput!
Inputs
inputstringrequired- No description.
plainmcp_generatedrepliesThis API is in beta and may change without notice.WriteGenerated Replies
This API is in beta and may change without notice. Returns the current suggested reply candidates for a thread, scoped to the most recent inbound message from the customer or from a machine user. Suggestions submitted via `addGeneratedReply` are always included. Suggestions generated by Plain AI are excluded when suggested responses are disabled or not available for the workspace, or when an externally submitted suggestion exists for the same message. Returns an empty list if the thread has no such message or no suggestion is available. Requires the `generatedReply:read` permission. Arguments: - threadId: ID! - options: [GenerateReplyOption!]
Inputs
threadIdstringrequired- No description.
optionsstring- No description.
plainmcp_generatehelpcenterarticleUse AI to generate one or more draft help center articles from the content of a support thread.WriteGenerate Help Center Article
Use AI to generate one or more draft help center articles from the content of a support thread. Returns the generated articles in DRAFT status for review before publishing. Requires the helpCenter:edit permission. Arguments: - input: GenerateHelpCenterArticleInput!
Inputs
inputstringrequired- No description.
plainmcp_getbroadcastaudiencedetailsFetch a single broadcast audience by its ID, or null if no audience with that ID exists.WriteGet Broadcast Audience Details
Fetch a single broadcast audience by its ID, or null if no audience with that ID exists. Returns soft-deleted audiences (where `isDeleted` is true), so the record of what a past broadcast was sent to survives. In `filters`, dimensions on one node AND together and values within a dimension OR. `slackChannels` are channels pinned by ID; the `slackChannelNameContains` substrings are re-resolved at send time. An audience with no filters at all means every tenant. `type` is fixed at creation and must match the type of any broadcast the audience is attached to. Audience IDs start with `ba_`. Do not invent IDs â only use values returned by the MCP tools.
Inputs
broadcastAudienceIdstringrequired- No description.
plainmcp_getbroadcastaudiencesFetch a paginated list of the workspace's broadcast audiences, newest first.WriteGet Broadcast Audiences
Fetch a paginated list of the workspace's broadcast audiences, newest first. An audience is a named, reusable set of broadcast recipients, resolved to concrete Slack channels at send time rather than when it was saved. Soft-deleted audiences are excluded. Pass `searchQuery` to narrow to audiences whose name contains it, matched case-insensitively and unanchored. The match happens in the database, so it finds audiences that are not on the current page. Use the `cursor` variable with the endCursor from the previous response's pageInfo to fetch the next page. The cursor is an opaque token: pass it back unchanged and do not construct, modify, or alter it. Set `first` to control page size (default 50). In `filters`, dimensions on one node AND together and values within a dimension OR: `tierIds: [a, b]` means either tier, while `tierIds: [a]` plus `slackChannelNameContains: ["eng"]` means both must hold. `slackChannels` are channels pinned by ID, so an audience holding only those is a saved channel list. `slackChannelNameContains` is re-resolved at send time, so it picks up channels created or renamed since. An audience with no filters at all means every tenant. An audience's own filters never contain `audienceIds` â an audience cannot be defined in terms of another one. Audience IDs start with `ba_`. Do not invent IDs â only use values returned by the MCP tools.
Inputs
cursorstring- No description.
firststring- No description.default
50 searchQuerystring- Narrows to audiences whose name contains this, matched case-insensitively and unanchored. Searched in the database rather than on the page, so it finds audiences a client has not loaded.
plainmcp_getbroadcastdetailsFetch a single broadcast by its ID, including its authored content and who it is targeted at.WriteGet Broadcast Details
Fetch a single broadcast by its ID, including its authored content and who it is targeted at. Returns null if no broadcast with that ID exists, and returns soft-deleted broadcasts (where `isDeleted` is true). `content` is encoded as `contentFormat` says: `TIPTAP` is a serialised Tiptap JSON document (what the Plain app writes); `SLACK_BLOCK_KIT` is a JSON array of Slack blocks. Neither is plain text or markdown. `sendTarget` is who the broadcast reaches, resolved to concrete channels at send time rather than now. `scope: ALL_RECIPIENTS` means every connected, enabled customer channel and carries no `filters`; `scope: MATCHING` means only what `filters` selects. `recipients` are channels named outright and added to whatever `filters` resolves to; `excludeRecipients` are subtracted last. Inside `filters`, dimensions on one node AND together and values within a dimension OR. `audienceIds` reference saved audiences â read them with `getBroadcastAudienceDetails`. Preview the live resolved set with `getBroadcastSendTargetRecipients`. `appendUnsubscribeLink` is the per-broadcast override for whether Plain appends an unsubscribe footer when this broadcast is delivered. Null inherits the workspace default from `getBroadcastUnsubscribeLinkSetting`; true or false overrides that default for this broadcast only. It controls footer emission, not whether unsubscribes are honoured. `latestSend` is the most recent non-test send, and where progress lives. Use `getBroadcastSends` for the full send history, and `getBroadcastSendDeliveries` for the recipients of one send. Broadcast IDs start with `bc_`, audience IDs with `ba_`. Broadcast URL format: https://app.plain.com/workspace/{workspaceId}/broadcasts/{broadcastId} where {workspaceId} is fetched via `getMyWorkspace` (starts with `w_`). Do not invent IDs â only use values returned by the MCP tools.
Inputs
broadcastIdstringrequired- No description.
plainmcp_getbroadcastrecipientunsubscribesFetch a paginated list of Slack channels that have opted out of broadcasts, newest first.WriteGet Broadcast Recipient Unsubscribes
Fetch a paginated list of Slack channels that have opted out of broadcasts, newest first. Use this to answer "is this channel unsubscribed?" or to audit who will be skipped on the next send. An unsubscribe is global per channel: the channel is excluded from every broadcast audience until someone resubscribes it. That is a different reason for missing a send than "the filter never matched" â check this list (or `getBroadcastSendTargetRecipients` / `SKIPPED_UNSUBSCRIBED` deliveries) before concluding a filter is wrong. Optionally narrow with `searchQuery`: matched case-insensitively and unanchored against the connected channel's current name or the Slack workspace (team) name. A channel-name hit only includes currently connected channels. A workspace-name hit returns every opted-out channel in that Slack workspace, including disconnected ones (`connectedSlackChannel` null). Disconnected channels also appear when listing without a query. Omit `searchQuery` rather than passing an empty string. A search hit is not proof the named channel is unsubscribed. Inspect each row: treat it as that channel only when `connectedSlackChannel.name` matches (after stripping a leading `#`) or `slackChannelId` matches. Other rows are siblings from a workspace whose name contained the query â do not report those as the channel the user asked about. Use the `cursor` variable with the endCursor from the previous response's pageInfo to fetch the next page. The cursor is an opaque token: pass it back unchanged and do not construct, modify, or alter it. Set `first` to control page size (default 50). To remove an unsubscribe, call `resubscribeBroadcastRecipient` with the same `slackTeamId` + `slackChannelId`. To add one, call `unsubscribeBroadcastRecipient`. Unsubscribe IDs start with `bru_`. Do not invent IDs â only use values returned by the MCP tools.
Inputs
cursorstring- No description.
firststring- No description.default
50 searchQuerystring- Narrows to unsubscribes whose connected channel name contains this, or whose Slack workspace name contains this, matched case-insensitively and unanchored. Channel-name matches exclude disconnected channels; a workspace-name match returns every opted-out channel in that Slack workspace, including disconnected ones.
plainmcp_getbroadcastsFetch a paginated list of the workspace's broadcasts, newest first.WriteGet Broadcasts
Fetch a paginated list of the workspace's broadcasts, newest first. A broadcast is a message authored once and posted to many Slack channels at once. Soft-deleted broadcasts are excluded from this list. Optionally narrow the list with `statuses`, e.g. ["DRAFT"] for broadcasts still being written or ["SENT"] for ones already delivered. A broadcast's status comes from its latest real send, so no status reflects a test send. Omit `statuses` to list every status â an empty list is rejected. Use the `cursor` variable with the endCursor from the previous response's pageInfo to fetch the next page. The cursor is an opaque token: pass it back unchanged and do not construct, modify, or alter it. Set `first` to control page size (default 50). `appendUnsubscribeLink` is the per-broadcast override for the unsubscribe footer (null inherits `getBroadcastUnsubscribeLinkSetting`). `latestSend` is the most recent non-test send and is where progress lives â read `deliveryCounts` from it rather than counting deliveries. `skippedUnsubscribed` is channels matched at resolve time but not posted because they opted out; it is not part of `total`. Use `getBroadcastSends` for a broadcast's full send history, and `getBroadcastSendDeliveries` for the recipients of one send. Broadcast IDs start with `bc_`. Broadcast URL format: https://app.plain.com/workspace/{workspaceId}/broadcasts/{broadcastId} where {workspaceId} is fetched via `getMyWorkspace` (starts with `w_`). Do not invent IDs â only use values returned by the MCP tools.
Inputs
cursorstring- No description.
firststring- No description.default
50 statusesstring- No description.
plainmcp_getbroadcastsenddeliveriesFetch the individual recipients of one broadcast send â which channel got the message, which did not, and why.WriteGet Broadcast Send Deliveries
Fetch the individual recipients of one broadcast send â which channel got the message, which did not, and why. Use this to answer "who missed it" or "did this channel get it". A delivery is one recipient's copy of the broadcast within one send. Narrow with `deliveryStatuses`, e.g. ["FAILED"], ["SENT"], or ["SKIPPED_UNSUBSCRIBED"]. `SKIPPED_UNSUBSCRIBED` means the channel matched the audience at send time but was not posted because it had opted out â that is a different reason for missing the message than a filter that never matched, or a `FAILED` delivery with a `failureReason`. Read `failureReason` for why a `FAILED` delivery did not land. Combine with `searchQuery` to find one recipient: matched case-insensitively and unanchored against the recorded Slack channel name, the Slack channel id, and the email address, so a delivery is found by whichever of those identifies it. The match happens in the database, so it finds deliveries that are not on the current page. Omit `searchQuery` rather than passing an empty string. `slackChannelName` is the name recorded when the send resolved, so it still names a channel that was later renamed or disconnected; it is null for deliveries from before the name was recorded. This reads the send named by `broadcastSendId`. Get the id from `getBroadcastSends`; use `isTest` to distinguish test from real sends there. An id belonging to another broadcast matches nothing. `cursor` and `first` page that send's deliveries. Use the endCursor from the previous response's `deliveries.pageInfo`; it stays valid because every page selects the same send. The cursor is an opaque token: pass it back unchanged and do not construct, modify, or alter it. `deliveryCounts` on the send is the unfiltered summary of the whole send. `skippedUnsubscribed` is not part of `total`. `deliveries.totalCount` is how many rows match `deliveryStatuses` and `searchQuery`. A broadcast with hundreds of recipients has hundreds of deliveries, so prefer the counts plus a `deliveryStatuses: ["FAILED"]` or `["SKIPPED_UNSUBSCRIBED"]` query over paging the whole list. `edges` is empty when the broadcast has no send with that id. For the full send history use `getBroadcastSends`. For the live opted-out list independent of any send, use `getBroadcastRecipientUnsubscribes`. Broadcast IDs start with `bc_`, send IDs with `bcs_`, delivery IDs with `bcsd_`. Do not invent IDs â only use values returned by the MCP tools.
Inputs
broadcastIdstringrequired- No description.
broadcastSendIdstringrequired- No description.
cursorstring- No description.
deliveryStatusesstring- No description.
firststring- No description.default
50 searchQuerystring- No description.
plainmcp_getbroadcastsendsFetch the send history of one broadcast, newest first.WriteGet Broadcast Sends
Fetch the send history of one broadcast, newest first. Use this to answer "has this broadcast gone out, and how far did each run get". One send is one run of the broadcast. A broadcast that has been sent once and tested twice has three sends. Test sends post real messages and collect real deliveries, so check `isTest` before presenting an entry as a real send, or pass `isTest: false` to exclude them. `statuses` narrows to sends in particular states; `DRAFT` is not one of them, since it describes a broadcast with no send rather than a send. Omit a filter to leave that dimension unconstrained â an empty list is rejected. `deliveryCounts` is how far a send got, summarised across its recipients. It is one query per send regardless of how many recipients there are, so read it rather than counting recipients. `skippedUnsubscribed` is channels matched at resolve time but not posted because they opted out; it is recorded separately and is not part of `total`. For the individual recipients of one send â which channel got it, which failed and why, which were skipped as unsubscribed â use `getBroadcastSendDeliveries`. Use the `cursor` variable with the endCursor from the previous response's pageInfo to fetch the next page. The cursor is an opaque token: pass it back unchanged and do not construct, modify, or alter it. Set `first` to control page size (default 20). Broadcast IDs start with `bc_`, send IDs with `bcs_`. Do not invent IDs â only use values returned by the MCP tools.
Inputs
broadcastIdstringrequired- No description.
cursorstring- No description.
firststring- No description.default
20 isTeststring- No description.
statusesstring- No description.
plainmcp_getbroadcastsendtargetrecipientsPreview who a broadcast send target resolves to right now â the live filter-to-recipient count, not a past send.WriteGet Broadcast Send Target Recipients
Preview who a broadcast send target resolves to right now â the live filter-to-recipient count, not a past send. Use this to answer "how many channels would get this?" and "why is the count zero?" before a human schedules the real send. Point-in-time: the number moves as tenants, tiers, tenant fields and connected channels change. Resolved through the same path a send uses, so it is what would actually be delivered to rather than an estimate assembled another way. Unsubscribed channels are excluded from `count` the same way a real send excludes them. Required input: `type` (must be `SLACK`) and `sendTarget`. - `sendTarget.scope: ALL_RECIPIENTS` means every connected, enabled customer channel and rejects `filters`. `scope: MATCHING` requires `filters`. Omit `scope` to target only channels named in `recipients`. - Inside `filters`, dimensions on one node AND together and values within a dimension OR. `audienceIds` reference saved audiences (`getBroadcastAudiences`). - `recipients` are channels named outright and added to whatever `filters` resolves to; `excludeRecipients` are subtracted last. When `count` is zero, read `emptyReason` before guessing â and treat an opt-out as a real possibility even when the reason is not `ALL_RECIPIENTS_UNSUBSCRIBED`: - `NO_TENANTS_MATCHED` â the filter itself matched no tenants. - `NO_RECIPIENTS_RESOLVED` â nothing reachable remained. That includes disabled / disconnected channels, and also every pin-by-id match (`filters.slackChannels` or named `recipients`) having opted out. Name / tenant filters usually surface the same opt-out as `ALL_RECIPIENTS_UNSUBSCRIBED` instead. Before telling the user a named channel is unreachable, call `getBroadcastRecipientUnsubscribes` (or resubscribe and re-preview) â an opt-out is not a broken connection. - `EXCLUDED_BY_AUDIENCE` â something matched, then the target's own exclusions removed all of it. - `ALL_RECIPIENTS_UNSUBSCRIBED` â something matched, and every channel it would have reached has opted out. That is not a broken filter; list the opted-out channels with `getBroadcastRecipientUnsubscribes` and restore one with `resubscribeBroadcastRecipient` if appropriate. `recipients` pages the channels that remain after unsubscribes are excluded. Use `searchQuery` to find one by name without changing `count`. Use the `cursor` variable with the endCursor from the previous response's pageInfo to fetch the next page. The cursor is an opaque token: pass it back unchanged and do not construct, modify, or alter it. For a broadcast that has already sent, prefer `getBroadcastSendDeliveries` with `deliveryStatuses: ["SKIPPED_UNSUBSCRIBED"]` and the send's `deliveryCounts.skippedUnsubscribed` â those record what happened at send time rather than a live preview.
Inputs
inputstringrequired- No description.
cursorstring- No description.
firststring- No description.default
50 searchQuerystring- No description.
plainmcp_getbroadcastunsubscribelinksettingRead whether this workspace appends an unsubscribe link to outgoing broadcasts by default.WriteGet Broadcast Unsubscribe Link Setting
Read whether this workspace appends an unsubscribe link to outgoing broadcasts by default. This is emission-only: it controls whether the footer link is rendered on delivered messages. It does not enable or disable unsubscribes themselves â channels can still be opted out via `unsubscribeBroadcastRecipient` or the public link, and audience resolution always honours existing unsubscribes regardless of this setting. Precedence when a broadcast is delivered: 1. If the broadcast has an explicit `appendUnsubscribeLink` override, that value wins for that broadcast only. 2. Otherwise this workspace default applies. Null on the broadcast means "inherit this setting". The default for a new workspace is false (no footer). Read a broadcast's own override with `getBroadcastDetails`.
Inputs
This tool takes no inputs.
plainmcp_getknowledgegapdetailsFetch a specific knowledge gap by its ID, including its task and the threads where customers hit it.WriteGet Knowledge Gap Details
Fetch a specific knowledge gap by its ID, including its task and the threads where customers hit it. Each signal's `threadId` is a thread where Ari could not answer the customer; pass it to `getThreadDetails` to read the question. Use `signalsCursor` with the endCursor from the previous response's signals pageInfo to fetch more signals. The cursor is an opaque token: pass it back unchanged and do not construct, modify, or alter it. To close a gap: check `searchKnowledgeSources` for existing content, draft or improve it (e.g. via `upsertHelpCenterArticle`), then set the gap's task to DONE with `updateTask`. If the gap is not worth addressing, set the task to CANCELLED instead.
Inputs
knowledgeGapIdstringrequired- No description.
signalsCursorstring- No description.
signalsFirststring- No description.default
25
plainmcp_getknowledgegapsFetch knowledge gaps: questions customers ask that Ari, Plain's AI agent, could not answer from the workspace's knowledge sources.WriteGet Knowledge Gaps
Fetch knowledge gaps: questions customers ask that Ari, Plain's AI agent, could not answer from the workspace's knowledge sources. Each gap is detected from Ari replies and has a task raised for it; the gap's status follows that task's status. By default, returns only open gaps (TODO, which includes IN_PROGRESS tasks), most frequently hit first. To include all gaps, pass statuses: null. To see the most recently hit gaps, pass sortBy: { field: LAST_SEEN_AT, direction: DESC }. To scope to a time window, pass `lastSeenAt` with ISO 8601 bounds, e.g. { after: "2026-10-12T00:00:00Z" } for gaps hit at least once since then. `signals.totalCount` is how many times customers have hit the gap, all time, even when `lastSeenAt` is set. Use the `cursor` variable with the endCursor from the previous response's pageInfo to fetch the next page. The cursor is an opaque token: pass it back unchanged and do not construct, modify, or alter it. Set `first` to control page size (default 25). Pass a gap's `id` to `getKnowledgeGapDetails` for the threads that hit it.
Inputs
cursorstring- No description.
firststring- No description.default
25 lastSeenAtstring- No description.
sortBystring- No description.
statusesstring- No description.
plainmcp_getknowledgesourcesFetch the workspace's knowledge sources: the sitemaps and single URLs that Plain indexes for Ari and other AI features.WriteGet Knowledge Sources
Fetch the workspace's knowledge sources: the sitemaps and single URLs that Plain indexes for Ari and other AI features. Each source's `status` shows whether it is pending, indexed (with `indexedAt`), or failed (with a `reason`). Sitemaps also include counts of their crawled pages by status, so a sitemap can be indexed overall while some pages failed. Use the `cursor` variable with the endCursor from the previous response's pageInfo to fetch the next page. The cursor is an opaque token: pass it back unchanged and do not construct, modify, or alter it. Set `first` to control page size (default 25). To pick up changes to a source's content without waiting for the automatic weekly reindex, pass its `id` to `reindexKnowledgeSource`.
Inputs
cursorstring- No description.
firststring- No description.default
25
plainmcp_getmsteamsmembersforchannelFetches the current members of a Microsoft Teams channel directly from the Teams API.WriteGet Msteams Members For Channel
Fetches the current members of a Microsoft Teams channel directly from the Teams API. Requires a workspace MS Teams integration and calls Microsoft Graph; use this to populate member lists when resolving customers for a channel. Arguments: - msTeamsChannelId: ID! - msTeamsTeamId: ID!
Inputs
msTeamsChannelIdstringrequired- No description.
msTeamsTeamIdstringrequired- No description.
plainmcp_getmyassignedtasksFetch tasks assigned to a specific user in Plain.WriteGet My Assigned Tasks
Fetch tasks assigned to a specific user in Plain. Pass the authenticated user's ID (from `getMyUser`, starts with `u_`) as `userId`. By default, returns only open tasks (TODO and IN_PROGRESS), highest priority first. To include all tasks 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. The cursor is an opaque token: pass it back unchanged and do not construct, modify, or alter it. Set `first` to control page size (default 25). Task URL format: https://app.plain.com/workspace/{workspaceId}/tasks/{ref}/ where {ref} is the task `ref` field on each result (e.g. `T-123`) and {workspaceId} is fetched via `getMyWorkspace` (starts with `w_`). Do not invent IDs. Only use values returned by the MCP tools.
Inputs
userIdstringrequired- No description.
cursorstring- No description.
firststring- No description.default
25 statusesstring- No description.
plainmcp_gettaskdetailsFetch detailed information about a specific task by its ID.WriteGet Task Details
Fetch detailed information about a specific task by its ID. If you only have the human-readable ref shown in the Plain app (e.g. `T-123`), use `getTaskDetailsByRef` instead. Returns the task's status, priority, account, assignee, the threads linked to it, and the entities that raised it (e.g. a knowledge gap). Use `threadLinksCursor` with the endCursor from the previous response's threadLinks pageInfo to fetch more linked threads. The cursor is an opaque token: pass it back unchanged and do not construct, modify, or alter it. Linked threads only carry a `threadId`; pass it to `getThreadDetails` for the thread's title, status, and context. Thread URL format: https://app.plain.com/workspace/{workspaceId}/thread/{threadId}/ where {workspaceId} is fetched via `getMyWorkspace` (starts with `w_`).
Inputs
taskIdstringrequired- No description.
threadLinksCursorstring- No description.
threadLinksFirststring- No description.default
25
plainmcp_gettaskdetailsbyrefFetch detailed information about a specific task by its human-readable ref, as displayed in the Plain app (e.g.WriteGet Task Details By Ref
Fetch detailed information about a specific task by its human-readable ref, as displayed in the Plain app (e.g. `T-123`). Returns the task's status, priority, account, assignee, the threads linked to it, and the entities that raised it (e.g. a knowledge gap). Use `threadLinksCursor` with the endCursor from the previous response's threadLinks pageInfo to fetch more linked threads. The cursor is an opaque token: pass it back unchanged and do not construct, modify, or alter it. Linked threads only carry a `threadId`; pass it to `getThreadDetails` for the thread's title, status, and context. Thread URL format: https://app.plain.com/workspace/{workspaceId}/thread/{threadId}/ where {workspaceId} is fetched via `getMyWorkspace` (starts with `w_`).
Inputs
refstringrequired- No description.
threadLinksCursorstring- No description.
threadLinksFirststring- No description.default
25
plainmcp_gettasksFetch a paginated list of tasks in the workspace.WriteGet Tasks
Fetch a paginated list of tasks in the workspace. By default, returns only open tasks (TODO and IN_PROGRESS), most recently updated first. To include all tasks regardless of status, pass statuses: null. Narrow results with `assignedToUserIds` (user IDs, starting with `u_`), `isAssigned`, or `accountIds`. Change ordering with `sortBy`, e.g. { field: PRIORITY, direction: ASC } (lower priority numbers are more urgent). For tasks assigned to the authenticated user, prefer `getMyAssignedTasks`. Use the `cursor` variable with the endCursor from the previous response's pageInfo to fetch the next page. The cursor is an opaque token: pass it back unchanged and do not construct, modify, or alter it. Set `first` to control page size (default 25). Task URL format: https://app.plain.com/workspace/{workspaceId}/tasks/{ref}/ where {ref} is the task `ref` field on each result (e.g. `T-123`) and {workspaceId} is fetched via `getMyWorkspace` (starts with `w_`). Do not invent IDs. Only use values returned by the MCP tools.
Inputs
accountIdsstring- No description.
assignedToUserIdsstring- No description.
cursorstring- No description.
firststring- No description.default
25 isAssignedstring- No description.
sortBystring- No description.
statusesstring- No description.
plainmcp_githubuserauthintegrationReturns the GitHub user authentication integration for the currently authenticated user, or null if no integration exists.WriteGithub User Auth Integration
Returns the GitHub user authentication integration for the currently authenticated user, or null if no integration exists.
Inputs
This tool takes no inputs.
plainmcp_helpcenterFetch a single help center by ID.WriteHelp Center
Fetch a single help center by ID. Returns null if not found. Arguments: - id: ID!
Inputs
idstringrequired- No description.
plainmcp_helpcenterarticleFetch a single help center article by ID.WriteHelp Center Article
Fetch a single help center article by ID. Returns null if not found. Deleting an article is done by the user in the Plain app. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/help-center/<helpCenterId>/articles/<articleId>` (never the `<workspaceId>` placeholder). Arguments: - id: ID!
Inputs
idstringrequired- No description.
plainmcp_helpcenterarticlebyslugFetch an article by its URL slug within a specific help center.WriteHelp Center Article By Slug
Fetch an article by its URL slug within a specific help center. Slugs are unique per help center. Returns null if no article matches. Arguments: - helpCenterId: ID! - slug: String!
Inputs
helpCenterIdstringrequired- No description.
slugstringrequired- No description.
plainmcp_helpcenterarticlegroupFetch a single article group by ID.WriteHelp Center Article Group
Fetch a single article group by ID. Returns null if not found. Arguments: - id: ID!
Inputs
idstringrequired- No description.
plainmcp_helpcenterarticlegroupbyslugFetch an article group by its URL slug within a specific help center.WriteHelp Center Article Group By Slug
Fetch an article group by its URL slug within a specific help center. Returns null if no group matches. Arguments: - helpCenterId: ID! - slug: String!
Inputs
helpCenterIdstringrequired- No description.
slugstringrequired- No description.
plainmcp_helpcenterindexFetch the navigation index for a help center by its ID: every heading, article group and article in sidebar order, with its type, id, parent and title.WriteHelp Center Index
Fetch the navigation index for a help center by its ID: every heading, article group and article in sidebar order, with its type, id, parent and title. Returns null if not found. A large help center's index is returned in one response, so this keeps to what an index needs. Read an article's slug, description or content with `helpCenterArticle`. To change the index, pass the returned `hash` to `updateHelpCenterIndex` with every item as `{ type, entityId: id, parentId, title }`. The call fails if the index changed since you read it; read it again and reapply your change.
Inputs
idstringrequired- No description.
plainmcp_helpcentersList all help centers in the workspace.WriteHelp Centers
List all help centers in the workspace. Supports cursor-based pagination and optional filtering. Custom JavaScript, sign-in, access, the type and the subdomain of an existing help center are set by the user in the Plain app. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/help-center/<helpCenterId>` (never the `<workspaceId>` placeholder), or `â¦/help-center/create` for a new help center that needs them. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String - filters: HelpCentersFilter
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
plainmcp_importjobdefinitionFetch the import job definition for a connected service integration.WriteImport Job Definition
Fetch the import job definition for a connected service integration. Pass isEnabled: true to return only the currently active definition, or isEnabled: false to return any definition regardless of enabled state. Returns null if no matching definition exists. Arguments: - serviceIntegrationKey: String! - isEnabled: Boolean
Inputs
serviceIntegrationKeystringrequired- No description.
isEnabledstring- No description.
plainmcp_importjobsList import jobs, optionally filtered by service integration key or import job definition ID.WriteImport Jobs
List import jobs, optionally filtered by service integration key or import job definition ID. Each job is a single sync run of an import job definition, with a run per entity type showing its progress, status and timing. Each job carries its whole run history, so a page holds 10 jobs unless you pass a different `first`. Page on with `after`.
Inputs
afterstring- No description.
filtersstring- No description.
firststring- No description.default
10
plainmcp_indexeddocumentsList indexed documents across your workspace, newest first.WriteIndexed Documents
List indexed documents across your workspace, newest first. Use the `knowledgeSourceId` filter to retrieve only the documents belonging to a specific knowledge source, and the `statuses` filter to retrieve only documents with a given ingestion status. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String - filters: IndexedDocumentsFilter
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
plainmcp_interpolationvariablesList the static variables that can be interpolated with `{{ key }}` in snippets, auto-responses, bulk replies and workflow actions, with a label and group for building a picker.WriteInterpolation Variables
List the static variables that can be interpolated with `{{ key }}` in snippets, auto-responses, bulk replies and workflow actions, with a label and group for building a picker. Thread field variables are not included; derive them from the thread field schemas as `threadField.<key>`. Requires the `workspace:read` permission.
Inputs
This tool takes no inputs.
plainmcp_issuetrackerfieldsFetch the configurable fields for a connected issue tracker (e.g.WriteIssue Tracker Fields
Fetch the configurable fields for a connected issue tracker (e.g. Shortcut, Rootly, incident.io, GitHub). Pass previously selected field values in `selectedFields` so that dependent fields (such as labels that depend on a chosen repository) are populated correctly. Returns the list of fields the caller must or may provide when calling `createIssueTrackerIssue`. Requires the `threadLinkCandidate:search` permission. Arguments: - issueTrackerType: String! â One of `github_issue`, `shortcut_issue`, `incidentio_incident` or `rootly_incident`. - selectedFields: [SelectedIssueTrackerField!]!
Inputs
issueTrackerTypestringrequired- One of `github_issue`, `shortcut_issue`, `incidentio_incident` or `rootly_incident`.
selectedFieldsarrayrequired- No description.
plainmcp_knowledgesourceFetch a single knowledge source by its ID.WriteKnowledge Source
Fetch a single knowledge source by its ID. Returns null if no knowledge source with the given ID exists. Arguments: - knowledgeSourceId: ID!
Inputs
knowledgeSourceIdstringrequired- No description.
plainmcp_knowledgesourcecitationsbythreadReturns the knowledge sources cited by AI agent replies across a thread, each linked to the timeline entry it was cited in and carrying a snapshot title (and best-effort url) plus the live cited document when it still exists.WriteKnowledge Source Citations By Thread
Returns the knowledge sources cited by AI agent replies across a thread, each linked to the timeline entry it was cited in and carrying a snapshot title (and best-effort url) plus the live cited document when it still exists. Returns an empty list when the thread has no citations or is not visible to the caller. Requires the `thread:read` and `timeline:read` permissions. Arguments: - threadId: ID!
Inputs
threadIdstringrequired- No description.
plainmcp_knowledgesourcesList all knowledge sources in the workspace.WriteKnowledge Sources
List all knowledge sources in the workspace. Use the `type` filter to retrieve only sitemap or single-URL sources. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String - filters: KnowledgeSourcesFilter
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
plainmcp_labeltypeReturns a single label type by its ID.WriteLabel Type
Returns a single label type by its ID. Returns null if no label type with that ID exists. Requires the `labelType:read` permission. A team's assignment settings, such as its round-robin capacity, come from `teamSettings`. Arguments: - labelTypeId: ID!
Inputs
labelTypeIdstringrequired- No description.
plainmcp_labeltypebyexternalidReturns a label type by its external ID.WriteLabel Type By External Id
Returns a label type by its external ID. Returns null if no match is found. External IDs are unique within a workspace and are set when creating or updating a label type. Requires the `labelType:read` permission. Arguments: - externalId: ID!
Inputs
externalIdstringrequired- No description.
plainmcp_linearappintegrationThe workspace-level Linear app integration, if one has been authorised.WriteLinear App Integration
The workspace-level Linear app integration, if one has been authorised. Not connected yet? Connecting needs the user's approval in the provider. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/install/linear` (never the `<workspaceId>` placeholder), which takes them straight to Linear to approve, then read this again to confirm.
Inputs
This tool takes no inputs.
plainmcp_lockthreadLock a thread to prevent further replies or changes by non-admin users.WriteLock Thread
Lock a thread to prevent further replies or changes by non-admin users. Use this when a resolution is final and you want to freeze the conversation. Requires the `thread:edit` permission. Arguments: - input: LockThreadInput!
Inputs
inputstringrequired- No description.
plainmcp_machineuserFetches a single machine user by ID.WriteMachine User
Fetches a single machine user by ID. Returns null if no machine user with the given ID exists in the workspace. Its API keys and their permissions come from `machineUserApiKeys`, which needs the `apiKey:read` permission. Deleting a machine user, and creating, changing or deleting its API keys, are done by the user in the Plain app, so a key's secret never passes through an agent. Call `getMyWorkspace` for this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/machine-users/<machineUserId>`, or `â¦/api-keys/add` and `â¦/api-keys/<apiKeyId>` under it for keys (never the `<workspaceId>` placeholder).
Inputs
machineUserIdstringrequired- No description.
plainmcp_machineuserapikeysLists a machine user's API keys with each key's permissions.WriteMachine User Api Keys
Lists a machine user's API keys with each key's permissions. Requires the `apiKey:read` permission. Creating, changing and deleting API keys are done by the user in the Plain app, so a key's secret never passes through an agent. Call `getMyWorkspace` for this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/machine-users/<machineUserId>/api-keys/add`, or `â¦/api-keys/<apiKeyId>` for an existing key (never the `<workspaceId>` placeholder), then read this again to confirm.
Inputs
machineUserIdstringrequired- No description.
afterstring- No description.
firststring- No description.default
50
plainmcp_machineusersReturns a paginated list of all machine users in the workspace.WriteMachine Users
Returns a paginated list of all machine users in the workspace. Use the optional `filters.type` argument to restrict results to a specific machine user type (e.g. API_USER or AI_AGENT). Deleting a machine user, and creating, changing or deleting its API keys, are done by the user in the Plain app, so a key's secret never passes through an agent. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/machine-users/<machineUserId>` (never the `<workspaceId>` placeholder), or `â¦/api-keys/add` and `â¦/api-keys/<apiKeyId>` under it for keys. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - filters: MachineUsersFilter - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
plainmcp_markcustomerasspamFlag a customer as spam.WriteMark Customer As Spam
Flag a customer as spam. This hides their threads from the inbox and excludes them from metrics. Marking a customer that is already marked as spam returns a `customer_already_marked_as_spam` error. Pass the customer `id` (starts with `c_`) as `customerId`. Use `getCustomers`, `searchCustomers`, or `getCustomerDetails` to discover it.
Inputs
inputstringrequired- No description.
plainmcp_markthreaddiscussionreadClear the unread flag on a discussion.WriteMark Thread Discussion Read
Clear the unread flag on a discussion. Use this when the user has viewed a discussion so that the isUnread indicator is reset. Returns the updated discussion. Arguments: - input: MarkThreadDiscussionReadInput!
Inputs
inputstringrequired- No description.
plainmcp_moveworkflowMove a workflow so it sits directly after another, or to the front of the list when `afterWorkflowId` is null.WriteMove Workflow
Move a workflow so it sits directly after another, or to the front of the list when `afterWorkflowId` is null. Only the moved workflow changes. Arguments: - input: MoveWorkflowInput!
Inputs
inputstringrequired- No description.
plainmcp_mybillingrotaReturns the current billing rota for the workspace, listing which users are actively on-rota and which are off-rota.WriteMy Billing Rota
Returns the current billing rota for the workspace, listing which users are actively on-rota and which are off-rota. The rota is used to track which users currently consume an active eng-rota seat.
Inputs
This tool takes no inputs.
plainmcp_mybillingsubscriptionReturns the current workspace billing subscription, including plan, status, trial info, feature entitlements, and credit balances.WriteMy Billing Subscription
Returns the current workspace billing subscription, including plan, status, trial info, feature entitlements, and credit balances. Returns null if the workspace has no billing account.
Inputs
This tool takes no inputs.
plainmcp_myemailsignatureReturns the email signature configured for the currently authenticated user, or null if none has been set.WriteMy Email Signature
Returns the email signature configured for the currently authenticated user, or null if none has been set.
Inputs
This tool takes no inputs.
plainmcp_myfavoritepagesReturns the favorite pages saved by the currently authenticated user, ordered by most recently created first.WriteMy Favorite Pages
Returns the favorite pages saved by the currently authenticated user, ordered by most recently created first. Each user's favorites are independent â this query only returns pages belonging to the caller. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_myinternalnotificationsReturns a paginated list of internal notifications for the currently authenticated user.WriteMy Internal Notifications
Returns a paginated list of internal notifications for the currently authenticated user. Use the optional `filters` argument to narrow results by read status or creation time. Supports forward and backward cursor-based pagination via `first`/`after` and `last`/`before`. Only available to human users â machine users will receive a forbidden error. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - filters: InternalNotificationsFilter - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
plainmcp_mylinearintegrationReturns the current user's Linear integration, or null if no integration has been set up.WriteMy Linear Integration
Returns the current user's Linear integration, or null if no integration has been set up.
Inputs
This tool takes no inputs.
plainmcp_mymsteamsintegrationReturns the Microsoft Teams integration for the currently authenticated user, or null if the user has not connected their account.WriteMy Msteams Integration
Returns the Microsoft Teams integration for the currently authenticated user, or null if the user has not connected their account.
Inputs
This tool takes no inputs.
plainmcp_mypermissionsReturns the full list of permission strings granted to the currently authenticated user or machine user in this workspace.WriteMy Permissions
Returns the full list of permission strings granted to the currently authenticated user or machine user in this workspace. Useful for inspecting what actions the caller is authorized to perform.
Inputs
This tool takes no inputs.
plainmcp_myslackintegrationReturns the current user's personal Slack notifications integration, or null if none is connected.WriteMy Slack Integration
Returns the current user's personal Slack notifications integration, or null if none is connected.
Inputs
This tool takes no inputs.
plainmcp_myuseraccountReturns the UserAccount for the currently authenticated user, or null if no account has been created yet.WriteMy User Account
Returns the UserAccount for the currently authenticated user, or null if no account has been created yet. Useful during onboarding to check whether account setup is complete.
Inputs
This tool takes no inputs.
plainmcp_myworkspaceinvitesReturns all pending workspace invites sent to the currently authenticated user's email address.WriteMy Workspace Invites
Returns all pending workspace invites sent to the currently authenticated user's email address. Use this to let a user see and act on workspaces they have been invited to join. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_myworkspacesReturns all workspaces the currently authenticated human user belongs to, paginated.WriteMy Workspaces
Returns all workspaces the currently authenticated human user belongs to, paginated. Not available to machine users. Use this to let users switch between workspaces. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_permissionsReturns the complete list of all permission strings defined in Plain, sorted alphabetically.WritePermissions
Returns the complete list of all permission strings defined in Plain, sorted alphabetically. Use this to discover valid permission values when building role or API key management UIs. Requires the `permission:read` permission.
Inputs
This tool takes no inputs.
plainmcp_refreshconnecteddiscordchannelsSyncs the list of Discord channels for a guild from the Discord API into Plain.WriteRefresh Connected Discord Channels
Syncs the list of Discord channels for a guild from the Discord API into Plain. Call this after channels are added or renamed in Discord so that `connectedDiscordChannels` reflects the latest state. Arguments: - input: RefreshConnectedDiscordChannelsInput!
Inputs
inputstringrequired- No description.
plainmcp_reindexknowledgesourceReindex a knowledge source now instead of waiting for the automatic weekly reindex, e.g.WriteReindex Knowledge Source
Reindex a knowledge source now instead of waiting for the automatic weekly reindex, e.g. after its pages were updated to fill a knowledge gap or after a failed index. Pass the source's `id` from `getKnowledgeSources`, or a search result's `knowledgeSourceId` from `searchKnowledgeSources`. Indexing runs in the background: the source returns as pending, and `getKnowledgeSources` shows when it is indexed or failed. For sitemaps, only new or changed pages are reprocessed, and pages no longer in the sitemap are removed. Requires Plain AI to be enabled on the workspace.
Inputs
inputstringrequired- No description.
plainmcp_reloadcustomercardinstanceForces a fresh load of a customer card instance, bypassing the cache.WriteReload Customer Card Instance
Forces a fresh load of a customer card instance, bypassing the cache. Use this when you know your external data has changed and you want to immediately fetch updated card content from your API URL. The response will be a `CustomerCardInstanceLoading`; subscribe to `customerCardInstanceChanges` to receive the loaded or errored result. Arguments: - input: ReloadCustomerCardInstanceInput!
Inputs
inputstringrequired- No description.
plainmcp_reorderautorespondersSet new order values for one or more autoresponders.WriteReorder Autoresponders
Set new order values for one or more autoresponders. You must pass a unique `order` integer and a unique autoresponder ID for each entry; duplicate IDs or duplicate order values are rejected. Only the autoresponders included in the input are repositioned â others are left unchanged. Requires the `autoresponder:edit` permission. Arguments: - input: ReorderAutorespondersInput!
Inputs
inputstringrequired- No description.
plainmcp_reordercustomercardconfigsUpdates the display order of one or more customer card configs.WriteReorder Customer Card Configs
Updates the display order of one or more customer card configs. Only the configs listed in the input are updated; other configs keep their current order. This allows you to swap two configs or move a single card without specifying the full list. Duplicate order values are permitted and ties are broken by ID. Arguments: - input: ReorderCustomerCardConfigsInput!
Inputs
inputstringrequired- No description.
plainmcp_reordercustomersurveysUpdates the display order of one or more customer surveys in a single call.WriteReorder Customer Surveys
Updates the display order of one or more customer surveys in a single call. Pass an array of survey ID / order-index pairs; only surveys whose order actually changes are updated. Duplicate survey IDs in the input are rejected. Requires the `customerSurvey:edit` permission. Arguments: - input: ReorderCustomerSurveysInput!
Inputs
inputstringrequired- No description.
plainmcp_replytoemailReplies to an existing email in a thread, threading the response correctly in email clients.WriteReply To Email
Replies to an existing email in a thread, threading the response correctly in email clients. Use inReplyToEmailId to identify the email being replied to. Supports CC and BCC recipients (up to 49 combined) and file attachments. Requires the email:create and email:read permissions. Arguments: - input: ReplyToEmailInput!
Inputs
inputstringrequired- No description.
plainmcp_resolvecustomerformsteamschannelFinds or creates a Plain customer associated with the Microsoft Teams users in the given channel, using the workspace's connected MS Teams integration.WriteResolve Customer For Msteams Channel
Finds or creates a Plain customer associated with the Microsoft Teams users in the given channel, using the workspace's connected MS Teams integration. Useful for bootstrapping a support thread from a Teams channel conversation. Arguments: - input: ResolveCustomerForMSTeamsChannelInput!
Inputs
inputstringrequired- No description.
plainmcp_resolvecustomerforslackchannelFinds or creates a Plain customer associated with a Slack channel, using the Slack users in that channel to identify the customer.WriteResolve Customer For Slack Channel
Finds or creates a Plain customer associated with a Slack channel, using the Slack users in that channel to identify the customer. Useful for bootstrapping threads from Slack channels. Arguments: - input: ResolveCustomerForSlackChannelInput!
Inputs
inputstringrequired- No description.
plainmcp_resubscribebroadcastrecipientRemove an unsubscribe so a Slack channel can receive broadcasts again.WriteResubscribe Broadcast Recipient
Remove an unsubscribe so a Slack channel can receive broadcasts again. Idempotent: resubscribing a channel that was never unsubscribed is a no-op and returns `unsubscribe: null` with no error. Required input fields: `type`, `slackTeamId`, `slackChannelId`. - `type` must be `SLACK`. A channel id is only unique within its Slack team, so both `slackTeamId` and `slackChannelId` are required together. - When an unsubscribe existed, the response's `unsubscribe` field is the record that was removed (for confirmation). When nothing was opted out, `unsubscribe` is null and `error` is also null. After a successful resubscribe, the channel returns to normal audience resolution: if a filter or named recipient would have included it, it will again. Confirm with `getBroadcastSendTargetRecipients` or `getBroadcastRecipientUnsubscribes` rather than assuming. Prefer confirming the channel identity with the user before calling this.
Inputs
inputstringrequired- No description.
plainmcp_rolesReturns the roles available in the workspace: the built-in roles (Owner, Admin, Support, Viewer, None) and any custom roles.WriteRoles
Returns the roles available in the workspace: the built-in roles (Owner, Admin, Support, Viewer, None) and any custom roles. Requires the `roles:read` permission. Each role's permission list, often hundreds of entries, is left out so every role fits on one page. A custom role's preset and thread scopes come from `customRole`.
Inputs
afterstring- No description.
filtersstring- No description.
firststring- No description.default
50
plainmcp_savedthreadsviewFetches a single saved threads view by its ID.WriteSaved Threads View
Fetches a single saved threads view by its ID. Returns null if no view with the given ID exists in the workspace. Arguments: - savedThreadsViewId: ID!
Inputs
savedThreadsViewIdstringrequired- No description.
plainmcp_savedthreadsviewsReturns all saved threads views for the workspace, ordered by creation time.WriteSaved Threads Views
Returns all saved threads views for the workspace, ordered by creation time. Use this to list the views available in your workspace. Supports forward and backward cursor pagination. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_schedulebroadcastQueues a broadcast to be sent, moving it from `DRAFT` to `SCHEDULED`.WriteSchedule Broadcast
Queues a broadcast to be sent, moving it from `DRAFT` to `SCHEDULED`. Calling this again on a broadcast that has not started sending changes when it will go out; once the send has started it is rejected. The broadcast must have a sender and at least one channel. A null `scheduledAt` clears the schedule instead, returning the broadcast to `DRAFT`. Requires the `broadcast:send` and `broadcast:read` permissions. Arguments: - input: ScheduleBroadcastInput!
Inputs
inputstringrequired- No description.
plainmcp_searchaccountsSearches accounts by name or domain (case-insensitive partial match), or by external ID (exact match).WriteSearch Accounts
Searches accounts by name or domain (case-insensitive partial match), or by external ID (exact match). The search term must be at least 2 characters long. Returns a paginated list of results. Requires the `tenant:read` permission. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - searchQuery: AccountsSearchQuery! - filters: AccountsFilter - first: Int - after: String - last: Int - before: String
Inputs
searchQuerystringrequired- No description.
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
plainmcp_searchbroadcastsSearch broadcasts by name.WriteSearch Broadcasts
Search broadcasts by name. The search is case-insensitive, matches on any part of the name, ignores accents, and requires at least 2 characters. A broadcast's `name` is internal only â it is never shown to recipients, so it is safe to search on and to show back to the user. Soft-deleted broadcasts are excluded. Optionally narrow the results with `statuses`, applied on top of the name match. Omit it to search every status â an empty list is rejected. Use the `cursor` variable with the endCursor from the previous response's pageInfo to fetch the next page. The cursor is an opaque token: pass it back unchanged and do not construct, modify, or alter it. Set `first` to control page size (default 50). Broadcast IDs start with `bc_`. Broadcast URL format: https://app.plain.com/workspace/{workspaceId}/broadcasts/{broadcastId} where {workspaceId} is fetched via `getMyWorkspace` (starts with `w_`). Do not invent IDs â only use values returned by the MCP tools.
Inputs
searchQuerystringrequired- No description.
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
plainmcp_searchknowledgesourcesSemantic search across the workspace's knowledge: indexed documents (URLs and sitemaps added as knowledge sources) and help center articles that Plain's AI is allowed to use.WriteSearch Knowledge Sources
Semantic search across the workspace's knowledge: indexed documents (URLs and sitemaps added as knowledge sources) and help center articles that Plain's AI is allowed to use. This is the same knowledge Ari draws from, but not Ari's exact retrieval, so a result here does not guarantee Ari would have found it. Searches up to `pageSize` matching chunks (default 3, max 50), then returns one result per source, ordered by its most relevant chunk. Each result contains all indexed text from that source, so fewer than `pageSize` results may return and responses grow quickly; only raise `pageSize` if the first results miss. Narrow results with `types` (INDEXED_DOCUMENT, HELP_CENTER_ARTICLE) or `labelTypeIds` (unlabelled content may also be included). When working a knowledge gap, search its title and description before writing new content: no relevant result means the content is missing; a relevant result means it exists but Ari missed it or it is out of date, so improve the existing source rather than creating a duplicate. After updating an indexed document's page, pass its `knowledgeSourceId` to `reindexKnowledgeSource` so Ari picks up the change.
Inputs
searchQuerystringrequired- No description.
optionsstring- No description.
pageSizestring- No description.
plainmcp_searchplainhelpcenterPerform a semantic (vector) search across Plain's own public help center (help.plain.com).WriteSearch Plain Help Center
Perform a semantic (vector) search across Plain's own public help center (help.plain.com). Available to every workspace's Sidekick Agent so it can answer questions about how Plain itself works. Read-only and hard-restricted to Plain's public product documentation; it never returns the caller's own data or any other workspace's content. Returns up to `pageSize` results (default 10, max 50) ranked by relevance. Arguments: - searchQuery: String! - pageSize: Int
Inputs
searchQuerystringrequired- No description.
pageSizestring- No description.
plainmcp_searchslackusersSearches for slack users in a slack channel based on a search term.WriteSearch Slack Users
Searches for slack users in a slack channel based on a search term. The search term can be part of either the slack's handle or full name. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - slackTeamId: String! - slackChannelId: String! - searchQuery: String! - first: Int - after: String - last: Int - before: String
Inputs
searchQuerystringrequired- No description.
slackChannelIdstringrequired- No description.
slackTeamIdstringrequired- No description.
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_searchthreadslackusersSearches for slack users in a thread based on a search term.WriteSearch Thread Slack Users
Searches for slack users in a thread based on a search term. The search term can be part of either the slack's handle or full name. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - threadId: ID! - searchQuery: String! - first: Int - after: String - last: Int - before: String
Inputs
searchQuerystringrequired- No description.
threadIdstringrequired- No description.
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_sendbulkemailSends the same email body to multiple threads at once (up to 100 thread IDs per call).WriteSend Bulk Email
Sends the same email body to multiple threads at once (up to 100 thread IDs per call). Useful for broadcasting updates to a set of customers, for example notifying affected users of an incident. Arguments: - input: SendBulkEmailInput!
Inputs
inputstringrequired- No description.
plainmcp_sendchatSend a chat message from a support agent (or machine user) to a customer on a CHAT-channel thread.WriteSend Chat
Send a chat message from a support agent (or machine user) to a customer on a CHAT-channel thread. Either `text` or at least one `attachmentIds` entry must be provided. If `threadId` is omitted a new thread is created; if supplied the message is appended to the existing thread. An optional `timestamp` (ISO 8601, must be in the past) allows backdating messages when backfilling historical data. Requires the `chat:create` permission and the live-chat billing entitlement. Arguments: - input: SendChatInput!
Inputs
inputstringrequired- No description.
plainmcp_senddiscordmessageSends an outbound Discord message on a thread.WriteSend Discord Message
Sends an outbound Discord message on a thread. Requires both a workspace-level Discord channel integration and a personal user auth integration for the sending user. The message is posted into the Discord thread associated with the Plain thread. Arguments: - input: SendDiscordMessageInput!
Inputs
inputstringrequired- No description.
plainmcp_sendmsteamsmessageSends a Microsoft Teams message on a thread.WriteSend Msteams Message
Sends a Microsoft Teams message on a thread. The thread must be associated with a connected MS Teams channel and the workspace must have an active MS Teams integration. Arguments: - input: SendMSTeamsMessageInput!
Inputs
inputstringrequired- No description.
plainmcp_sendnewemailSends a new outbound email to a customer, creating a new thread by default.WriteSend New Email
Sends a new outbound email to a customer, creating a new thread by default. Use threadId to attach the email to an existing thread instead. Supports CC and BCC recipients (up to 49 combined), file attachments, and an optional alternate from address. Requires the email:create and email:read permissions. Arguments: - input: SendNewEmailInput!
Inputs
inputstringrequired- No description.
plainmcp_sendslackmessageSends a Slack message on a thread.WriteSend Slack Message
Sends a Slack message on a thread. The message appears in the thread's associated Slack channel as a reply or new message. Arguments: - input: SendSlackMessageInput!
Inputs
inputstringrequired- No description.
plainmcp_sendtestbroadcastSend a test copy of a broadcast to Slack channels you name, so you can see what recipients will get before the real audience does.WriteSend Test Broadcast
Send a test copy of a broadcast to Slack channels you name, so you can see what recipients will get before the real audience does. This posts real messages into real channels. Everyone in the channels you name will see it. It carries a notice at the top marking it as a test, and it goes out through the same pipeline and under the broadcast's own sender, so what arrives is what any channel would have received. Confirm the channel list with the user before calling this. - `channels` takes between 1 and 10 `{ slackTeamId, slackChannelId }` pairs. A channel ID is only unique within its Slack team, so both are needed. Every channel must already be connected to this workspace, and naming the same channel twice posts to it once. - The channels are independent of the broadcast's own audience, which is left untouched. The broadcast needs a sender and a notification title, but it does not need any channels of its own â testing is what you do before choosing them. - A test send never changes the broadcast's `status`, and never locks or unlocks editing. Only available while the broadcast can still be edited: once its real send has started, it can no longer be tested. The response includes the test send's id. Pass it to `getBroadcastSendDeliveries` to see whether each channel got it. This does not schedule the real send. Queuing a broadcast to its actual audience is done by a human in the Plain app.
Inputs
inputstringrequired- No description.
plainmcp_sendthreaddiscussionmessageSend a reply to an existing Slack or email discussion.WriteSend Thread Discussion Message
Send a reply to an existing Slack or email discussion. The message is posted in the original channel (as a Slack thread reply or email reply) and recorded in Plain. For Slack discussions you may optionally provide slackBlocks, set unfurlLinks, or broadcast the reply into the parent channel via replyBroadcast (replyBroadcast cannot be combined with attachmentIds). Prefer sendDiscussionMessage for new integrations. Arguments: - input: SendThreadDiscussionMessageInput!
Inputs
inputstringrequired- No description.
plainmcp_servicelevelagreementpoliciesReturns the SLA policies in the workspace, sorted by name.WriteService Level Agreement Policies
Returns the SLA policies in the workspace, sorted by name. Pass `filters` to narrow by name or by the target types a policy holds. Supports cursor-based pagination. Requires the `serviceLevelAgreement:read` permission. Deleting a policy is done by the user in the Plain app. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/slas/<policy id>` (never the `<workspaceId>` placeholder). Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - filters: ServiceLevelAgreementPoliciesFilter - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
plainmcp_servicelevelagreementpolicyReturns a single SLA policy by its Plain ID.WriteService Level Agreement Policy
Returns a single SLA policy by its Plain ID. Returns null if no policy with that ID exists. Requires the `serviceLevelAgreement:read` permission. Deleting a policy is done by the user in the Plain app. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/slas/<policy id>` (never the `<workspaceId>` placeholder). Arguments: - serviceLevelAgreementPolicyId: ID!
Inputs
serviceLevelAgreementPolicyIdstringrequired- No description.
plainmcp_setcustomeraccountsReplaces the full set of account memberships for a customer in a single call.WriteSet Customer Accounts
Replaces the full set of account memberships for a customer in a single call. Any accounts not included in the input are removed; any new ones are added. Use this when syncing account membership from your own system rather than tracking individual add/remove changes. Requires the `customer:edit`, `customerTenantMembership:create`, and `customerTenantMembership:delete` permissions. Arguments: - input: SetCustomerAccountsInput!
Inputs
inputstringrequired- No description.
plainmcp_setcustomertenantsReplaces the full set of tenant memberships for a customer in a single call.WriteSet Customer Tenants
Replaces the full set of tenant memberships for a customer in a single call. Any tenants not included in the input are removed; any new ones are added. Use this when syncing tenant membership from your own system rather than tracking individual add/remove changes. Requires the `customer:edit`, `customerTenantMembership:create`, and `customerTenantMembership:delete` permissions. Deprecated: Use setCustomerAccounts instead Arguments: - input: SetCustomerTenantsInput!
Inputs
inputstringrequired- No description.
plainmcp_setslackautojoinrulesReplaces all auto-join rules for a workspace slack channel integration.WriteSet Slack Auto Join Rules
Replaces all auto-join rules for a workspace slack channel integration. The provided rules become the complete set of rules for the integration. Arguments: - input: SetSlackAutoJoinRulesInput!
Inputs
inputstringrequired- No description.
plainmcp_setupaccountfieldschemamappingMaps an account field schema to a built-in Plain concept such as `TIER`, enabling automatic tier assignment based on the field's value.WriteSetup Account Field Schema Mapping
Maps an account field schema to a built-in Plain concept such as `TIER`, enabling automatic tier assignment based on the field's value. Only one schema can be mapped to a given concept at a time. Arguments: - input: SetupAccountFieldSchemaMappingInput!
Inputs
inputstringrequired- No description.
plainmcp_setuptenantfieldschemamappingMaps a tenant field schema to a built-in Plain concept such as `TIER`, enabling automatic tier assignment based on the field's value.WriteSetup Tenant Field Schema Mapping
Maps a tenant field schema to a built-in Plain concept such as `TIER`, enabling automatic tier assignment based on the field's value. Only one schema can be mapped to a given concept at a time. Deprecated: Use setupAccountFieldSchemaMapping instead Arguments: - input: SetupTenantFieldSchemaMappingInput!
Inputs
inputstringrequired- No description.
plainmcp_sidekickcreditbalanceThe workspace's current Sidekick (Plain) credit balance: the monthly allowance grant/used/remaining and when it resets, plus any purchased top-up remaining.WriteSidekick Credit Balance
The workspace's current Sidekick (Plain) credit balance: the monthly allowance grant/used/remaining and when it resets, plus any purchased top-up remaining. Use it to answer how many credits are left. Requires the `billing:read` permission.
Inputs
This tool takes no inputs.
plainmcp_sidekickcreditusagebydayCredit usage for the workspace, bucketed by the UTC day each billable item resolved, over the given date range.WriteSidekick Credit Usage By Day
Credit usage for the workspace, bucketed by the UTC day each billable item resolved, over the given date range. Covers Sidekick sessions and work done by the workspace's own agents. Use it to show a per-day breakdown of credit consumption. Requires the `billing:read` permission. Arguments: - input: SidekickCreditUsageByDayInput!
Inputs
inputstringrequired- No description.
plainmcp_sidekickcustomskillA single workspace custom skill, including its instructions, for editing.WriteSidekick Custom Skill
A single workspace custom skill, including its instructions, for editing. Arguments: - id: ID!
Inputs
idstringrequired- No description.
plainmcp_sidekickgithubaccessiblereposReturns every GitHub repository the Sidekick Agent integration (identified by serviceAuthorizationId) can currently see via its OAuth token.WriteSidekick Github Accessible Repos
Returns every GitHub repository the Sidekick Agent integration (identified by serviceAuthorizationId) can currently see via its OAuth token. Use this list to let users pick which repos Sidekick Agent should focus on before calling updateSidekickGithubConfig. Arguments: - serviceAuthorizationId: ID!
Inputs
serviceAuthorizationIdstringrequired- No description.
plainmcp_sidekickgithubserviceconfigReturns the Sidekick Agent GitHub configuration for a workspace: which repositories are selected for Sidekick Agent to use and any workspace-level or per-repo operating instructions.WriteSidekick Github Service Config
Returns the Sidekick Agent GitHub configuration for a workspace: which repositories are selected for Sidekick Agent to use and any workspace-level or per-repo operating instructions. Returns null when no configuration has been saved yet. Arguments: - serviceAuthorizationId: ID!
Inputs
serviceAuthorizationIdstringrequired- No description.
plainmcp_sidekickposthogserviceconfigReturns the Sidekick Agent PostHog configuration for a workspace, including any operating instructions and the default project the agent queries.WriteSidekick Posthog Service Config
Returns the Sidekick Agent PostHog configuration for a workspace, including any operating instructions and the default project the agent queries. Returns null when no configuration has been saved yet. Arguments: - serviceAuthorizationId: ID!
Inputs
serviceAuthorizationIdstringrequired- No description.
plainmcp_sidekickserviceconfigReturns the Sidekick Agent configuration for a connected service (Datadog, Sentry, Grafana, Linear, Notion, incident.io, Attio, HubSpot, Jira, Granola, LaunchDarkly, Grain or Cursor), identified by its serviceAuthorizationId.WriteSidekick Service Config
Returns the Sidekick Agent configuration for a connected service (Datadog, Sentry, Grafana, Linear, Notion, incident.io, Attio, HubSpot, Jira, Granola, LaunchDarkly, Grain or Cursor), identified by its serviceAuthorizationId. Includes any operating instructions that guide how Sidekick Agent uses the integration. Returns null when no configuration has been saved yet. GitHub and PostHog have their own configuration shapes â use sidekickGithubServiceConfig / sidekickPosthogServiceConfig instead. Arguments: - serviceAuthorizationId: ID!
Inputs
serviceAuthorizationIdstringrequired- No description.
plainmcp_sidekicksettingsReturns workspace-level Sidekick Agent settings, including the custom prompt that is appended to every Sidekick Agent session's system prompt and the tools selected during onboarding.WriteSidekick Settings
Returns workspace-level Sidekick Agent settings, including the custom prompt that is appended to every Sidekick Agent session's system prompt and the tools selected during onboarding. Always returns an object. customPrompt is null when not configured. preferredIntegrations is empty when none are selected.
Inputs
This tool takes no inputs.
plainmcp_sidekickskillsEvery skill available to Sidekick Agent in this workspace: Plain's system skills plus the workspace's custom skills, each with its effective enabled state.WriteSidekick Skills
Every skill available to Sidekick Agent in this workspace: Plain's system skills plus the workspace's custom skills, each with its effective enabled state.
Inputs
This tool takes no inputs.
plainmcp_slackautojoinrulesGets the auto-join rules for a workspace slack channel integration.WriteSlack Auto Join Rules
Gets the auto-join rules for a workspace slack channel integration. Rules that have not yet been saved through `setSlackAutoJoinRules` are read from the legacy prefix/suffix settings and have a null id. Arguments: - integrationId: ID!
Inputs
integrationIdstringrequired- No description.
plainmcp_slackuserReturns a Slack user within a specific channel, looked up by their Slack user ID.WriteSlack User
Returns a Slack user within a specific channel, looked up by their Slack user ID. Returns null if the user is not found in that channel. Arguments: - slackTeamId: String! - slackChannelId: String! - slackUserId: ID!
Inputs
slackChannelIdstringrequired- No description.
slackTeamIdstringrequired- No description.
slackUserIdstringrequired- No description.
plainmcp_snippetFetches a single snippet by its ID, or null if no snippet with that ID exists.WriteSnippet
Fetches a single snippet by its ID, or null if no snippet with that ID exists. Returns soft-deleted snippets (where `isDeleted` is true). Requires the `snippet:read` permission. Arguments: - snippetId: ID!
Inputs
snippetIdstringrequired- No description.
plainmcp_subscriptioneventtypesList every event type that can be subscribed to on a webhook target.WriteSubscription Event Types
List every event type that can be subscribed to on a webhook target. Each entry includes the event type identifier and a human-readable description. Use this to discover valid values for `eventSubscriptions` when creating or updating a webhook target. Requires the `subscriptionEventTypes:read` permission.
Inputs
This tool takes no inputs.
plainmcp_suggestedlabeltypesReturns the PENDING AI-suggested label types awaiting review, most recently created first.WriteSuggested Label Types
Returns the PENDING AI-suggested label types awaiting review, most recently created first. Requires the `suggestedLabelType:read` permission.
Inputs
This tool takes no inputs.
plainmcp_suggestedslackteammatesSuggests teammates to invite to Plain, sourced from the members of the workspace's connected Slack discussion channels.WriteSuggested Slack Teammates
Suggests teammates to invite to Plain, sourced from the members of the workspace's connected Slack discussion channels. Only members of the workspace's own Slack team are included (Slack Connect guests are excluded), and anyone (matched by email, case-insensitive) who is already a member of this workspace or has a pending invite to it is excluded. Returns an empty list when there are no connected, enabled discussion channels for the given slackTeamId (e.g. a Slack Connect channel integration). Arguments: - slackTeamId: String!
Inputs
slackTeamIdstringrequired- No description.
plainmcp_syncuserworkinghoursReplace a user's working hours schedule in full.WriteSync User Working Hours
Replace a user's working hours schedule in full. When `isEnabled` is true, the user's status is automatically switched to ONLINE at the start of each slot and to OFFLINE or AWAY (depending on workspace settings) at the end. Omit `userId` to configure the currently authenticated user's own schedule. Arguments: - input: SyncUserWorkingHoursInput!
Inputs
inputstringrequired- No description.
plainmcp_tasksFetch a paginated list of tasks in the workspace.WriteTasks
Fetch a paginated list of tasks in the workspace. Use `filters` to narrow results by status, assignee, company, or tenant. Use `sortBy` to order by priority, status, or creation/update time. Requires the `task:read` permission. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String - filters: TasksFilter - sortBy: TasksSort
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
sortBystring- No description.
plainmcp_teamsettingsFetch the settings for a team (label type of kind TEAM) identified by its label type ID.WriteTeam Settings
Fetch the settings for a team (label type of kind TEAM) identified by its label type ID. Returns null if no settings have been configured yet for the team. Arguments: - labelTypeId: ID!
Inputs
labelTypeIdstringrequired- No description.
plainmcp_tenantFetches a single tenant by its Plain-assigned ID.WriteTenant
Fetches a single tenant by its Plain-assigned ID. Returns null if no matching tenant is found. Requires the `tenant:read` permission. Deprecated: Use account instead Arguments: - tenantId: ID!
Inputs
tenantIdstringrequired- No description.
plainmcp_tenantfieldschemasReturns the list of tenant field schemas defined in the workspace.WriteTenant Field Schemas
Returns the list of tenant field schemas defined in the workspace. Use the `source` and `isVisible` filters to narrow results. Supports cursor-based pagination. Deprecated: Use accountFieldSchemas instead Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - filters: TenantFieldSchemasFilter - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
plainmcp_tenantsReturns a paginated list of tenants in the workspace.WriteTenants
Returns a paginated list of tenants in the workspace. Use the `filters` argument to narrow the results and `sortBy` to order them (by name ascending when omitted). Requires the `tenant:read` permission. Deprecated: Use accounts instead Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String - filters: TenantsFilter - sortBy: TenantsSort
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
sortBystring- No description.
plainmcp_testthreadsThe signed-in user's own test threads, oldest first.WriteTest Threads
The signed-in user's own test threads, oldest first. They are excluded from `threads`, so this is the only query that lists them. Requires the `thread:read` permission.
Inputs
This tool takes no inputs.
plainmcp_threadbyexternalidFetch a thread by the external ID you assigned it, scoped to a specific customer.WriteThread By External Id
Fetch a thread by the external ID you assigned it, scoped to a specific customer. Because `externalId` is only unique per-customer, both `customerId` and `externalId` are required. Returns null if no match. Requires the `thread:read` permission. Arguments: - customerId: ID! - externalId: ID!
Inputs
customerIdstringrequired- No description.
externalIdstringrequired- No description.
plainmcp_threadbymsteamsmessageResolves a Microsoft Teams message to the Plain thread its conversation is on.WriteThread By Msteams Message
Resolves a Microsoft Teams message to the Plain thread its conversation is on. If the message's thread was closed and the conversation continued in a successor thread, returns the open successor; if there is no open successor, returns the closed thread, which has `lockedAt` set. Returns null if Plain has not ingested the message. For a channel post, pass the root post's ID. After `createThreadFromMSTeamsMessage` returns no thread, poll this query until it returns a thread whose `lockedAt` is null. While the first thread is being created it returns null; while a successor to a closed thread is being created it returns the closed thread. Requires the `thread:read` permission. Arguments: - msTeamsMessageId: ID! â The Teams message ID, as provided by Teams in the activity's `id`.
Inputs
msTeamsMessageIdstringrequired- The Teams message ID, as provided by Teams in the activity's `id`.
plainmcp_threadbyrefFetch a thread by its human-readable ref (e.g.WriteThread By Ref
Fetch a thread by its human-readable ref (e.g. `T-1234`). Useful when the ref is more convenient to store than the internal ID. Returns null if no match. Requires the `thread:read` permission. Arguments: - ref: String!
Inputs
refstringrequired- No description.
plainmcp_threadbyslackmessageResolves a Slack message to the Plain thread it belongs to, using the same channel ID and message timestamp as `createThreadFromSlackMessage`.WriteThread By Slack Message
Resolves a Slack message to the Plain thread it belongs to, using the same channel ID and message timestamp as `createThreadFromSlackMessage`. Returns null if no thread is associated with the given Slack message. Requires the `thread:read` permission. Arguments: - slackChannelId: String! â The Slack channel the message is in, as provided by Slack (e.g. C0123ABCD). - slackMessageTimestamp: String! â The Slack `ts` of the message.
Inputs
slackChannelIdstringrequired- The Slack channel the message is in, as provided by Slack (e.g. C0123ABCD).
slackMessageTimestampstringrequired- The Slack `ts` of the message.
plainmcp_threadbyslackpermalinkResolves a Slack message permalink to the Plain thread it belongs to.WriteThread By Slack Permalink
Resolves a Slack message permalink to the Plain thread it belongs to. Returns null if no thread is associated with the given Slack message. Arguments: - slackPermalink: String!
Inputs
slackPermalinkstringrequired- No description.
plainmcp_threadclusterFetches a single thread cluster by its ID.WriteThread Cluster
Fetches a single thread cluster by its ID. Returns null if no cluster with that ID exists in the current workspace. This API is in beta and may change without notice. Arguments: - id: ID!
Inputs
idstringrequired- No description.
plainmcp_threadclustersReturns all AI-generated thread clusters for the current workspace, sorted by thread count descending.WriteThread Clusters
Returns all AI-generated thread clusters for the current workspace, sorted by thread count descending. Clusters group semantically similar threads together so you can spot trends and recurring issues at a glance. The optional `variant` argument selects which clustering model run to return; omit it to receive the default variant. This API is in beta and may change without notice. Arguments: - variant: String
Inputs
variantstring- No description.
plainmcp_threadclusterspaginatedReturns a paginated list of AI-generated thread clusters for the current workspace.WriteThread Clusters Paginated
Returns a paginated list of AI-generated thread clusters for the current workspace. Use `filters` to narrow results by company, tenant, or clustering variant. Supports standard cursor-based pagination via `first`/`after` and `last`/`before`. Requires the `thread:read` permission. This API is in beta and may change without notice. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String - filters: ThreadClustersFilter
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
plainmcp_threaddiscussionFetch a single discussion by its ID.WriteThread Discussion
Fetch a single discussion by its ID. Returns null if no discussion with the given ID exists. Arguments: - threadDiscussionId: ID!
Inputs
threadDiscussionIdstringrequired- No description.
plainmcp_threadfieldschemaFetches a single thread field schema by its ID.WriteThread Field Schema
Fetches a single thread field schema by its ID. Returns null if no schema with the given ID exists. Selecting the `createdBy`/`updatedBy` actor down to its `user` additionally requires the `user:read` permission. Arguments: - threadFieldSchemaId: ID!
Inputs
threadFieldSchemaIdstringrequired- No description.
plainmcp_threadheatmapmetricFetch a heatmap metric for threads with filter support, distributing thread activity across a 7-day à 24-hour grid.WriteThread Heatmap Metric
Fetch a heatmap metric for threads with filter support, distributing thread activity across a 7-day à 24-hour grid. Unlike the legacy `heatmapMetric`, this query uses the unified `ThreadMetricFilters` input for consistent filtering by label, tier, assignee, and more. Requires `metrics:read`; filtering `assignedToUser` to anyone other than the caller additionally requires `metricsAgent:read`. Arguments: - input: ThreadHeatmapMetricInput!
Inputs
inputstringrequired- No description.
plainmcp_threadlinkgroupsReturns a paginated list of thread link groups, each representing a distinct external entity (e.g.WriteThread Link Groups
Returns a paginated list of thread link groups, each representing a distinct external entity (e.g. a Linear issue or Jira ticket) that is linked to one or more threads. Use this to build views that aggregate threads by a shared linked issue. Supports filtering by status, specific group IDs, company, or tier. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String - filters: ThreadLinkGroupFilter
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
plainmcp_threadsbyexternalidFetch all threads that share the given external ID, returned as a paginated connection.WriteThreads By External Id
Fetch all threads that share the given external ID, returned as a paginated connection. Unlike `threadByExternalId`, this is not scoped to a customer: because `externalId` is only unique per-customer, the same external ID can appear on threads belonging to different customers, and this query returns all of them. Returns an empty connection if there are no matches. Requires the `thread:read` permission. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - externalId: ID! - first: Int - after: String - last: Int - before: String
Inputs
externalIdstringrequired- No description.
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_threadsinglevaluemetricFetch an aggregate (single-value) metric for threads with rich filter and group-by support.WriteThread Single Value Metric
Fetch an aggregate (single-value) metric for threads with rich filter and group-by support. Returns one value per group bucket for the specified date range and `SingleValueMetricName`, making it suitable for summary dashboards or leaderboard-style breakdowns by assignee, tier, or label type. Requires `metrics:read`; grouping by assignee or filtering `assignedToUser` to anyone other than the caller additionally requires `metricsAgent:read`. Arguments: - input: ThreadSingleValueMetricInput!
Inputs
inputstringrequired- No description.
plainmcp_threadslackuserReturns a Slack user associated with the given thread, looked up by their Slack user ID.WriteThread Slack User
Returns a Slack user associated with the given thread, looked up by their Slack user ID. Returns null if the user is not found in that thread's Slack context. Arguments: - threadId: ID! - slackUserId: ID!
Inputs
slackUserIdstringrequired- No description.
threadIdstringrequired- No description.
plainmcp_threadtimeseriesmetricFetch a time-series metric for threads with rich filter and group-by support.WriteThread Time Series Metric
Fetch a time-series metric for threads with rich filter and group-by support. Choose a `TimeSeriesMetricName` (e.g. `threads_created_count`, `threads_first_response_time__p50`), specify a mandatory date range and bucketing interval, and optionally group results by assignee, company, tier, label type, and more. This is the preferred reporting query when you need server-side filtering across thread attributes. Requires `metrics:read`; grouping by assignee or filtering `assignedToUser` to anyone other than the caller additionally requires `metricsAgent:read`. Arguments: - input: ThreadTimeSeriesMetricInput!
Inputs
inputstringrequired- No description.
plainmcp_tierReturns a single tier by its Plain ID.WriteTier
Returns a single tier by its Plain ID. Returns null if no tier with that ID exists. Requires the `tier:read` permission. Deleting a tier is done by the user in the Plain app. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/tiers/<tierId>` (never the `<workspaceId>` placeholder). Arguments: - tierId: ID!
Inputs
tierIdstringrequired- No description.
plainmcp_tiersReturns all tiers in the workspace, sorted by creation date.WriteTiers
Returns all tiers in the workspace, sorted by creation date. Supports cursor-based pagination. Requires the `tier:read` permission. Deleting a tier is done by the user in the Plain app. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/tiers/<tierId>` (never the `<workspaceId>` placeholder). Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_timelineentriesReturns a paginated list of all timeline entries for a customer, ordered from oldest to newest.WriteTimeline Entries
Returns a paginated list of all timeline entries for a customer, ordered from oldest to newest. Timeline entries include every event, message, note, and automated activity that has occurred across all of the customer's threads. Supports cursor-based pagination via `first`/`after` and `last`/`before` arguments. Trimmed copy of the generated tool: the full selection is over 130k characters, so this selects the same timeline entry fields as getThreadDetails.
Inputs
customerIdstringrequired- No description.
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_timelineentryFetches a single timeline entry by its ID within a customer's timeline.WriteTimeline Entry
Fetches a single timeline entry by its ID within a customer's timeline. Returns null if the entry does not exist. Trimmed copy of the generated tool: the full selection is over 130k characters, so this selects the same timeline entry fields as getThreadDetails.
Inputs
customerIdstringrequired- No description.
timelineEntryIdstringrequired- No description.
plainmcp_toggleslackmessagereactionAdds or removes a reaction from a slack message timeline entry.WriteToggle Slack Message Reaction
Adds or removes a reaction from a slack message timeline entry. Arguments: - input: ToggleSlackMessageReactionInput!
Inputs
inputstringrequired- No description.
plainmcp_triggerworkflowManually trigger a workflow against a specific thread.WriteTrigger Workflow
Manually trigger a workflow against a specific thread. Returns the resulting WorkflowExecution so you can track the run's status and step results. Arguments: - input: TriggerWorkflowInput!
Inputs
inputstringrequired- No description.
plainmcp_unmarkcustomerasspamClear the spam flag from a customer, restoring their threads to the inbox and metrics.WriteUnmark Customer As Spam
Clear the spam flag from a customer, restoring their threads to the inbox and metrics. The `markedAsSpamAt` timestamp is cleared. Pass the customer `id` (starts with `c_`) as `customerId`. Use `getCustomers`, `searchCustomers`, or `getCustomerDetails` to discover it.
Inputs
inputstringrequired- No description.
plainmcp_unsubscribebroadcastrecipientRecord that a Slack channel should not receive further broadcasts.WriteUnsubscribe Broadcast Recipient
Record that a Slack channel should not receive further broadcasts. Idempotent: unsubscribing a channel that is already unsubscribed is a no-op and returns the existing record. Required input fields: `type`, `slackTeamId`, `slackChannelId`. - `type` must be `SLACK`. A channel id is only unique within its Slack team, so both `slackTeamId` and `slackChannelId` are required together. - The channel does not need to still be connected to this workspace. An unsubscribe for a disconnected channel is still recorded and will apply if the channel is connected again later. - This does not recall messages already posted. It only affects future audience resolution and future sends. An unsubscribe is global per channel â there are no per-broadcast or per-category unsubscribes. After this call, the channel is excluded from every broadcast until `resubscribeBroadcastRecipient` removes the record. Prefer confirming the channel identity with the user before calling this. To list who is already opted out, use `getBroadcastRecipientUnsubscribes`.
Inputs
inputstringrequired- No description.
plainmcp_updateaccounttierSets the tier for a single account, identified by its Plain ID or external ID.WriteUpdate Account Tier
Sets the tier for a single account, identified by its Plain ID or external ID. Pass a null `tierIdentifier` to remove the account from its current tier. Use `addMembersToTier` when you need to move multiple accounts at once. Requires the `tierMembership:read` and `tierMembership:create` permissions. Arguments: - input: UpdateAccountTierInput!
Inputs
inputstringrequired- No description.
plainmcp_updateaitonerulesUpdates up to 10 AI tone rules in a single call.WriteUpdate Ai Tone Rules
Updates up to 10 AI tone rules in a single call. Each update item must include the rule ID and at least one field to change (`description` or `isEnabled`). Enabling a rule that would push the total number of enabled rules above 7 returns an error. Returns the full updated rule objects. Requires the `aiToneRule:edit` permission. Arguments: - input: UpdateAiToneRulesInput!
Inputs
inputstringrequired- No description.
plainmcp_updateautoresponderUpdate one or more fields on an existing autoresponder.WriteUpdate Autoresponder
Update one or more fields on an existing autoresponder. Only fields provided in the input are changed; omitted fields retain their current values. Requires the `autoresponder:edit` permission. Arguments: - input: UpdateAutoresponderInput!
Inputs
inputstringrequired- No description.
plainmcp_updatebroadcastUpdate one or more fields of an existing broadcast.WriteUpdate Broadcast
Update one or more fields of an existing broadcast. Only `broadcastId` is required; every other field is optional and omitting it leaves that field unchanged. `type` cannot be changed. Most fields use a wrapper input: pass `{ value: ... }` to set it, or omit the field entirely to leave it alone. `notificationTitle`, `senderUserId` and `senderEmailAddress` accept `{ value: null }` to clear them. - `content` is encoded as `contentFormat` says, so set `contentFormat` alongside it whenever the encoding of the new body differs from the stored one. From MCP, send `SLACK_BLOCK_KIT` and a JSON array of Slack blocks. A one-paragraph body looks like this, passed as a string: "[{\"type\":\"section\",\"text\":{\"type\":\"mrkdwn\",\"text\":\"Hello\"}}]" Buttons need a `url`; images must be publicly reachable; this format cannot be edited in the Plain app. Switching format without matching `content` is rejected. If the stored body is `TIPTAP` and you are only tweaking it, read it with `getBroadcastDetails` and send `TIPTAP` again â replacing it with Block Kit is a wholesale rewrite. - `notificationTitle` is what recipients see in the notification. Clearing it leaves a broadcast that cannot be sent. - `senderType` is `PLAIN_WORKSPACE` (posts as the workspace, no `senderUserId`) or `PLAIN_USER` (requires `senderUserId`). Either half can be set on its own as long as the resulting pair is coherent. Leave `senderEmailAddress` unset: it belongs to a future email channel, not to a Slack broadcast. - `appendUnsubscribeLink` uses `{ value: true }`, `{ value: false }`, or `{ value: null }` to clear the override so the broadcast inherits the workspace default from `getBroadcastUnsubscribeLinkSetting` again. Omit the field to leave the override unchanged. It controls footer emission, not whether unsubscribes are honoured. - `sendTarget` replaces the current target wholesale rather than merging into it, so read the existing one with `getBroadcastDetails` and send the full shape you want. `scope: ALL_RECIPIENTS` rejects `filters`; `scope: MATCHING` requires them. Preview the live resolved set with `getBroadcastSendTargetRecipients`. A broadcast that is already scheduled has to stay sendable, so clearing its sender or its target is rejected. Once its send has started it cannot be edited at all.
Inputs
inputstringrequired- No description.
plainmcp_updatebroadcastaudienceUpdate a broadcast audience's name, filters, or both.WriteUpdate Broadcast Audience
Update a broadcast audience's name, filters, or both. Only `broadcastAudienceId` is required; omitting a field leaves it unchanged. - `name` uses a wrapper input: pass `{ value: "..." }` to set it. - `filters` replaces the stored filters wholesale rather than merging into them, so read the current ones with `getBroadcastAudienceDetails` and send the full shape you want. They are validated against the audience's existing `type`, which cannot be changed. Editing an audience changes who every broadcast using it will reach on its next send, including broadcasts someone else wrote â check `getBroadcastDetails` on the broadcasts that reference it before widening or narrowing an audience.
Inputs
inputstringrequired- No description.
plainmcp_updatebusinesshoursoverrideUpdate an override's name, dates or slots.WriteUpdate Business Hours Override
Update an override's name, dates or slots. Omitted fields are left unchanged. Requires the `businessHours:edit` permission. Arguments: - input: UpdateBusinessHoursOverrideInput!
Inputs
inputstringrequired- No description.
plainmcp_updatebusinesshoursscheduleUpdate a business hours schedule's name, its slots, or both.WriteUpdate Business Hours Schedule
Update a business hours schedule's name, its slots, or both. Omitted fields are left unchanged; passing an empty `slots` array clears the schedule's business hours. Overlapping and adjacent slots are merged on write. Requires the `businessHours:edit` permission. Arguments: - input: UpdateBusinessHoursScheduleInput!
Inputs
inputstringrequired- No description.
plainmcp_updatechatappUpdate the name or logo of an existing chat app.WriteUpdate Chat App
Update the name or logo of an existing chat app. Only the fields provided in the input are changed. Requires the `chatApp:edit` permission. Arguments: - input: UpdateChatAppInput!
Inputs
inputstringrequired- No description.
plainmcp_updateconnecteddiscordchannelUpdates settings for a connected Discord channel, such as enabling or disabling it.WriteUpdate Connected Discord Channel
Updates settings for a connected Discord channel, such as enabling or disabling it. Disabled channels will not receive new messages from Plain. Arguments: - input: UpdateConnectedDiscordChannelInput!
Inputs
inputstringrequired- No description.
plainmcp_updateconnectedslackchannelUpdates the settings of a connected Slack channel, such as its channel type (customer or discussion) or whether it is enabled.WriteUpdate Connected Slack Channel
Updates the settings of a connected Slack channel, such as its channel type (customer or discussion) or whether it is enabled. Arguments: - input: UpdateConnectedSlackChannelInput!
Inputs
inputstringrequired- No description.
plainmcp_updatecustomercardconfigPartially updates a customer card config.WriteUpdate Customer Card Config
Partially updates a customer card config. Only fields that are provided in the input will be changed; omitted fields are left unchanged. Updating `apiUrl` or `apiHeaders` requires the `customerCardConfigApiDetails:edit` permission. Changing the `key` must still result in a unique key within the workspace. Arguments: - input: UpdateCustomerCardConfigInput!
Inputs
inputstringrequired- No description.
plainmcp_updatecustomergroupUpdate the name, key, color, or external ID of an existing customer group.WriteUpdate Customer Group
Update the name, key, color, or external ID of an existing customer group. At least one field must be provided in the input. Requires `customerGroup:edit` permission. Arguments: - input: UpdateCustomerGroupInput!
Inputs
inputstringrequired- No description.
plainmcp_updatecustomersurveyUpdates an existing customer survey.WriteUpdate Customer Survey
Updates an existing customer survey. At least one field must be provided. Partial updates are supported â only the fields you include are changed. Requires the `customerSurvey:edit` permission. Arguments: - input: UpdateCustomerSurveyInput!
Inputs
inputstringrequired- No description.
plainmcp_updateescalationpathUpdates an existing escalation path.WriteUpdate Escalation Path
Updates an existing escalation path. All fields are optional â only the fields provided will be changed. If `steps` is provided, it replaces the full list of steps; omit it to leave the current steps unchanged. Returns an error if the escalation path does not exist. Requires the `escalationPath:edit` permission. Arguments: - input: UpdateEscalationPathInput!
Inputs
inputstringrequired- No description.
plainmcp_updategeneratedreplyRecord teammate feedback (thumbs up / thumbs down and an optional comment) on a generated reply.WriteUpdate Generated Reply
Record teammate feedback (thumbs up / thumbs down and an optional comment) on a generated reply. Use this to signal whether a suggestion was helpful so Plain can improve future suggestions. Requires the `generatedReply:edit` permission. Arguments: - input: UpdateGeneratedReplyInput!
Inputs
inputstringrequired- No description.
plainmcp_updatehelpcenterUpdate a help center's names, description, colour, logo or whether chat is on.WriteUpdate Help Center
Update a help center's names, description, colour, logo or whether chat is on. Only the arguments you pass are changed. Requires the `helpCenter:edit` permission. Pass each field as its own argument, not wrapped in an `input` object. Custom JavaScript, sign-in, access, the type and the subdomain can't be changed here, because they run code on every public page, take a secret, or change who can see the help center and where. The user changes them in the Plain app: call `getMyWorkspace` for this workspace's ID and give them the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/help-center/<helpCenterId>` (never the `<workspaceId>` placeholder).
Inputs
helpCenterIdstringrequired- No description.
colorstring- No description.
descriptionstring- No description.
internalNamestring- No description.
isChatEnabledstring- No description.
logostring- No description.
publicNamestring- No description.
plainmcp_updatehelpcenterarticlegroupUpdate the name of an existing article group.WriteUpdate Help Center Article Group
Update the name of an existing article group. Requires the helpCenter:edit permission. Arguments: - input: UpdateHelpCenterArticleGroupInput!
Inputs
inputstringrequired- No description.
plainmcp_updatehelpcentercustomdomainnameSet or clear the custom domain name for a help center.WriteUpdate Help Center Custom Domain Name
Set or clear the custom domain name for a help center. After setting, use verifyHelpCenterCustomDomainName to confirm DNS propagation. Requires the helpCenter:edit permission. Arguments: - input: UpdateHelpCenterCustomDomainNameInput!
Inputs
inputstringrequired- No description.
plainmcp_updatehelpcenterindexReplace the navigation index (sidebar order and hierarchy) of a help center in a single call.WriteUpdate Help Center Index
Replace the navigation index (sidebar order and hierarchy) of a help center in a single call. You must supply the hash returned by the helpCenterIndex query â if the index has changed since you read it, the call will fail so you can re-fetch and re-apply your changes. Requires the helpCenter:edit permission. Arguments: - input: UpdateHelpCenterIndexInput!
Inputs
inputstringrequired- No description.
plainmcp_updateimportjobdefinitionDisable the active import job definition for a service integration.WriteUpdate Import Job Definition
Disable the active import job definition for a service integration. This is the only supported update â pass isEnabled: false to stop future sync runs. Returns an error if no enabled definition exists for the given service. Arguments: - input: UpdateImportJobDefinitionInput!
Inputs
inputstringrequired- No description.
plainmcp_updateinternalnotificationsMarks one or more internal notifications as read, unread, or archived.WriteUpdate Internal Notifications
Marks one or more internal notifications as read, unread, or archived. Pass the notification IDs to update along with the desired `readAt` and/or `archivedAt` timestamps. Set `readAt` to null to mark a notification as unread; set `archivedAt` to a timestamp to archive it. Returns the updated notifications. Requires the `user:read` permission. Arguments: - input: UpdateInternalNotificationsInput!
Inputs
inputstringrequired- No description.
plainmcp_updatemachineuserUpdates the name, description, or avatar of an existing machine user.WriteUpdate Machine User
Updates the name, description, or avatar of an existing machine user. At least one of `fullName`, `publicName`, `description`, or `avatar` must be provided. Requires the `machineUser:edit` permission. Arguments: - input: UpdateMachineUserInput!
Inputs
inputstringrequired- No description.
plainmcp_updatemyuserUpdates profile fields (display name, short name, or avatar) for the currently authenticated human user.WriteUpdate My User
Updates profile fields (display name, short name, or avatar) for the currently authenticated human user. Only the fields provided are changed; omitted fields are left unchanged. Not available to machine users. Arguments: - input: UpdateMyUserInput!
Inputs
inputstringrequired- No description.
plainmcp_updatenoteUpdates the text, markdown, or attachments of an existing note.WriteUpdate Note
Updates the text, markdown, or attachments of an existing note. Requires the `note:edit` permission. Arguments: - input: UpdateNoteInput!
Inputs
inputstringrequired- No description.
plainmcp_updaterolepriorityorderSets the order in which roles win when a user is given more than one through SSO or directory sync.WriteUpdate Role Priority Order
Sets the order in which roles win when a user is given more than one through SSO or directory sync. Custom roles can be placed anywhere below the admin role and above the none role. Requires the `roles:edit` permission. Arguments: - input: UpdateRolePriorityOrderInput!
Inputs
inputstringrequired- No description.
plainmcp_updatesavedthreadsviewUpdates an existing saved threads view.WriteUpdate Saved Threads View
Updates an existing saved threads view. All fields in the input are optional; only the fields you provide will be changed. Depending on workspace settings, only the view's creator or workspace admins may be allowed to edit a view they did not create. Arguments: - input: UpdateSavedThreadsViewInput!
Inputs
inputstringrequired- No description.
plainmcp_updateservicelevelagreementUpdate an existing SLA's time target, priority or label filter, business-hours setting, or breach actions.WriteUpdate Service Level Agreement
Update an existing SLA's time target, priority or label filter, business-hours setting, or breach actions. An SLA belongs to a tier or to an SLA policy: read a tier's SLAs with `tier` and a policy's with `serviceLevelAgreementPolicy`, though the SLA's ID alone is enough to update it. You cannot change an SLA's type after creation. Use the field-level wrapper inputs (e.g. `{ "value": 60 }`) for the fields you want to change and omit the rest. Requires the `serviceLevelAgreement:edit` permission. Arguments: - input: UpdateServiceLevelAgreementInput!
Inputs
inputstringrequired- No description.
plainmcp_updateservicelevelagreementpolicyUpdate an SLA policy and its targets.WriteUpdate Service Level Agreement Policy
Update an SLA policy and its targets. Pass the full set of targets you want the policy to have: a target of an existing type is updated in place, so live SLA trackers are unaffected, a new type is added, and a type you leave out is removed along with its trackers. Requires the `serviceLevelAgreement:edit` permission. Arguments: - input: UpdateServiceLevelAgreementPolicyInput!
Inputs
inputstringrequired- No description.
plainmcp_updatesettingCreate or overwrite a named setting at the given scope.WriteUpdate Setting
Create or overwrite a named setting at the given scope. Provide exactly one value field in `SettingValueInput` (boolean, string, number, or stringArray) that matches the expected type for the setting code. Returns the stored setting on success. To clear a value and revert to the scope hierarchy default, use `deleteSetting` instead. Arguments: - input: UpdateSettingInput!
Inputs
inputstringrequired- No description.
plainmcp_updatesnippetUpdates one or more fields of an existing snippet.WriteUpdate Snippet
Updates one or more fields of an existing snippet. Each field uses a wrapper input â pass `{ value: "..." }` to set it or omit it entirely to leave it unchanged. To remove the snippet's `path` (un-group it) pass `{ value: null }`. Requires the `snippet:edit` permission. Arguments: - input: UpdateSnippetInput!
Inputs
inputstringrequired- No description.
plainmcp_updatetaskUpdate an existing task in Plain.WriteUpdate Task
Update an existing task in Plain. Only the fields you include are changed; omitted fields are left as is. - `status`: TODO, IN_PROGRESS, DONE, or CANCELLED. - `priority`: 0 (urgent), 1 (high), 2 (normal), or 3 (low). - `accountId`: the account this task relates to. - `assignedTo`: provide either `userId` or `machineUserId`, not both. Pass `assignedTo: null` to unassign the task.
Inputs
inputstringrequired- No description.
plainmcp_updatetenanttierSets the tier for a single tenant, identified by its Plain ID or external ID.WriteUpdate Tenant Tier
Sets the tier for a single tenant, identified by its Plain ID or external ID. Pass a null `tierIdentifier` to remove the tenant from its current tier. Use `addMembersToTier` when you need to move multiple tenants at once. Requires the `tierMembership:read` and `tierMembership:create` permissions. Deprecated: Use updateAccountTier instead Arguments: - input: UpdateTenantTierInput!
Inputs
inputstringrequired- No description.
plainmcp_updatethreadaccountMove a thread to a different account, or pass `accountIdentifier: null` to detach it from its current account.WriteUpdate Thread Account
Move a thread to a different account, or pass `accountIdentifier: null` to detach it from its current account. Requires the `thread:edit` permission. Arguments: - input: UpdateThreadAccountInput!
Inputs
inputstringrequired- No description.
plainmcp_updatethreadagentstatusUpdate the AI agent status of a thread (`IN_PROGRESS`, `HANDED_OFF`, or `HANDLED`).WriteUpdate Thread Agent Status
Update the AI agent status of a thread (`IN_PROGRESS`, `HANDED_OFF`, or `HANDLED`). Use this to signal that an AI agent has taken over, handed off to a human, or fully resolved the thread. Requires the `thread:edit` permission. Arguments: - input: UpdateThreadAgentStatusInput!
Inputs
inputstringrequired- No description.
plainmcp_updatethreadchannelassociationaccountmembershippolicyChanges how accounts are assigned for an existing thread channel association.WriteUpdate Thread Channel Association Account Membership Policy
Changes how accounts are assigned for an existing thread channel association. Requires the `threadChannelAssociation:edit` permission. Arguments: - input: UpdateThreadChannelAssociationAccountMembershipPolicyInput!
Inputs
inputstringrequired- No description.
plainmcp_updatethreadchannelassociationtenantmembershippolicyChanges how tenants are assigned for an existing thread channel association.WriteUpdate Thread Channel Association Tenant Membership Policy
Changes how tenants are assigned for an existing thread channel association. Requires the `threadChannelAssociation:edit` permission. Deprecated: Use updateThreadChannelAssociationAccountMembershipPolicy instead Arguments: - input: UpdateThreadChannelAssociationTenantMembershipPolicyInput!
Inputs
inputstringrequired- No description.
plainmcp_updatethreadescalationpathAttach a thread to a specific escalation path, or pass `escalationPathId: null` to detach it.WriteUpdate Thread Escalation Path
Attach a thread to a specific escalation path, or pass `escalationPathId: null` to detach it. An escalation path defines the sequence of users or teams the thread escalates through if nobody responds in time. Requires the `thread:edit` permission. Arguments: - input: UpdateThreadEscalationPathInput!
Inputs
inputstringrequired- No description.
plainmcp_updatethreadexternalidUpdate the external ID of a thread.WriteUpdate Thread External Id
Update the external ID of a thread. Pass `externalId: null` to clear it. Requires the `thread:edit` permission. Arguments: - input: UpdateThreadExternalIdInput!
Inputs
inputstringrequired- No description.
plainmcp_updatethreadservicelevelagreementpolicyAssign an SLA policy to a thread.WriteUpdate Thread Service Level Agreement Policy
Assign an SLA policy to a thread. A policy takes precedence over the thread's tier when selecting SLAs. Pass `serviceLevelAgreementPolicyId: null` to detach the policy and fall back to the tier's SLAs. Requires the `thread:edit` permission. Arguments: - input: UpdateThreadServiceLevelAgreementPolicyInput!
Inputs
inputstringrequired- No description.
plainmcp_updatethreadsuggestedactionstatusAccept or dismiss a specific AI-suggested action on a thread's catchup summary.WriteUpdate Thread Suggested Action Status
Accept or dismiss a specific AI-suggested action on a thread's catchup summary. Pass the `suggestedActionId` from the thread's `catchupDetail` and the new `status`. Requires the `thread:edit` permission. Arguments: - input: UpdateThreadSuggestedActionStatusInput!
Inputs
inputstringrequired- No description.
plainmcp_updatethreadtenantMove a thread to a different tenant, or pass `tenantIdentifier: null` to detach it from its current tenant.WriteUpdate Thread Tenant
Move a thread to a different tenant, or pass `tenantIdentifier: null` to detach it from its current tenant. Requires the `thread:edit` permission. Deprecated: Use updateThreadAccount instead Arguments: - input: UpdateThreadTenantInput!
Inputs
inputstringrequired- No description.
plainmcp_updatethreadtierAssign a thread to a tier, which governs the SLAs applied to it.WriteUpdate Thread Tier
Assign a thread to a tier, which governs the SLAs applied to it. Pass `tierIdentifier: null` to detach the thread from its current tier. Requires the `thread:edit` permission. Arguments: - input: UpdateThreadTierInput!
Inputs
inputstringrequired- No description.
plainmcp_updatetierUpdates the name, color, external ID, default priority, or default flag of an existing tier.WriteUpdate Tier
Updates the name, color, external ID, default priority, or default flag of an existing tier. Only the fields you provide are changed. Requires the `tier:update` permission. Arguments: - input: UpdateTierInput!
Inputs
inputstringrequired- No description.
plainmcp_updateuserdefaultsavedthreadsviewSets or clears the default saved threads view for a specific user.WriteUpdate User Default Saved Threads View
Sets or clears the default saved threads view for a specific user. Pass null for savedViewId to remove the default. This controls which thread view the user sees when they first open the inbox. Arguments: - input: UpdateUserDefaultSavedThreadsViewInput!
Inputs
inputstringrequired- No description.
plainmcp_updateworkflowUpdate a workflow's name, trigger configuration, entry step, or published status.WriteUpdate Workflow
Update a workflow's name, trigger configuration, entry step, or published status. To change where a workflow sits in the list, use `moveWorkflow`. Read `workflowBuilderGuide` first for the trigger events and every step payload. Arguments: - input: UpdateWorkflowInput!
Inputs
inputstringrequired- No description.
plainmcp_updateworkflowstepUpdate a single workflow step's configuration, transitions, or canvas position.WriteUpdate Workflow Step
Update a single workflow step's configuration, transitions, or canvas position. Replacing `transitions` is a full replacement of the array. `workflowBuilderGuide` lists every step payload. Arguments: - input: UpdateWorkflowStepInput!
Inputs
inputstringrequired- No description.
plainmcp_upsertaccountCreates a new account or updates an existing one identified by `externalId` or `accountId`.WriteUpsert Account
Creates a new account or updates an existing one identified by `externalId` or `accountId`. Use this to keep Plain's account records in sync with the groups or organisations in your own product. The `result` field on the output indicates whether a record was created or updated. Requires the `tenant:create` and `tenant:edit` permissions. Arguments: - input: UpsertAccountInput!
Inputs
inputstringrequired- No description.
plainmcp_upsertaccountfieldSets or updates a field value for a specific account.WriteUpsert Account Field
Sets or updates a field value for a specific account. Identify the target field using `accountFieldIdentifier` (account ID + external field ID) and pass exactly one value argument matching the schema's `type` (e.g. `stringValue`, `numberValue`, `booleanValue`, `arrayValue`, `dateValue`, `userReferenceValues`, or `accountReferenceValues`). Requires the `tenantField:create`, `tenantField:update`, and `tenantFieldSchema:read` permissions. Identifying the account by `externalId` also requires the `tenant:read` permission. Arguments: - input: UpsertAccountFieldInput!
Inputs
inputstringrequired- No description.
plainmcp_upsertaccountfieldschemaCreates or updates one or more account field schemas in a single call.WriteUpsert Account Field Schema
Creates or updates one or more account field schemas in a single call. Each schema is identified by the combination of `source` and `externalFieldId` â if a schema with that pair already exists it is updated, otherwise a new one is created. Requires the `tenantFieldSchema:create`, `tenantFieldSchema:update`, and `tenantFieldSchema:delete` permissions. Arguments: - input: UpsertAccountFieldSchemaInput!
Inputs
inputstringrequired- No description.
plainmcp_upsertcustomergroupCreate or update a customer group identified by `customerGroupId`, `customerGroupKey`, or `externalId`.WriteUpsert Customer Group
Create or update a customer group identified by `customerGroupId`, `customerGroupKey`, or `externalId`. If a matching group is found it is updated and the result is `UPDATED`; if data is unchanged the result is `NOOP`; otherwise a new group is created and the result is `CREATED`. Note: using `customerGroupId` as the identifier returns an error if the group does not exist. Requires `customerGroup:create` and `customerGroup:edit` permissions. Arguments: - input: UpsertCustomerGroupInput!
Inputs
inputstringrequired- No description.
plainmcp_upsertmyemailsignatureCreates or updates the email signature for the currently authenticated user.WriteUpsert My Email Signature
Creates or updates the email signature for the currently authenticated user. The signature is appended automatically to outbound emails sent by that user. Arguments: - input: UpsertMyEmailSignatureInput!
Inputs
inputstringrequired- No description.
plainmcp_upsertteamsettingsCreate or update the settings for a team (label type of kind TEAM).WriteUpsert Team Settings
Create or update the settings for a team (label type of kind TEAM). If settings do not yet exist for the given team, they are created with defaults (round-robin disabled, max capacity 5); otherwise the existing settings are updated with the supplied values. The labelTypeId must refer to a label type of type TEAM â passing any other label type ID returns a validation error. Requires the `labelType:edit` permission. Arguments: - input: UpsertTeamSettingsInput!
Inputs
inputstringrequired- No description.
plainmcp_upserttenantfieldschemaCreates or updates one or more tenant field schemas in a single call.WriteUpsert Tenant Field Schema
Creates or updates one or more tenant field schemas in a single call. Each schema is identified by the combination of `source` and `externalFieldId` â if a schema with that pair already exists it is updated, otherwise a new one is created. Requires `tenantFieldSchema:create` or `tenantFieldSchema:edit` permission. Deprecated: Use upsertAccountFieldSchema instead Arguments: - input: UpsertTenantFieldSchemaInput!
Inputs
inputstringrequired- No description.
plainmcp_userFetch a single workspace member by their ID.WriteUser
Fetch a single workspace member by their ID. Returns null if no user with that ID exists. Requires the `user:read` permission. Changing a member's role is done by the user in the Plain app. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/members/<userId>` (never the `<workspaceId>` placeholder). Arguments: - userId: ID!
Inputs
userIdstringrequired- No description.
plainmcp_userauthdiscordchannelintegrationReturns the current user's personal Discord authentication for a specific guild, or null if the user has not connected their Discord account to that guild.WriteUser Auth Discord Channel Integration
Returns the current user's personal Discord authentication for a specific guild, or null if the user has not connected their Discord account to that guild. Arguments: - discordGuildId: String!
Inputs
discordGuildIdstringrequired- No description.
plainmcp_userauthdiscordchannelintegrationsReturns a paginated list of all personal Discord authentication integrations for the current user across all guilds.WriteUser Auth Discord Channel Integrations
Returns a paginated list of all personal Discord authentication integrations for the current user across all guilds. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_userauthslackintegrationReturns the current user's user-auth Slack integration for the given Slack workspace, or null if not connected.WriteUser Auth Slack Integration
Returns the current user's user-auth Slack integration for the given Slack workspace, or null if not connected. Used for integrations that send messages as the user rather than as a bot. Arguments: - slackTeamId: String!
Inputs
slackTeamIdstringrequired- No description.
plainmcp_userauthslackintegrationbythreadidReturns the current user's user-auth Slack integration for the Slack workspace associated with the given thread, or null if not connected.WriteUser Auth Slack Integration By Thread Id
Returns the current user's user-auth Slack integration for the Slack workspace associated with the given thread, or null if not connected. Arguments: - threadId: ID!
Inputs
threadIdstringrequired- No description.
plainmcp_userbyemailFetch a workspace member by their email address.WriteUser By Email
Fetch a workspace member by their email address. Returns null if no match is found. Deleted users are also returned â check the `isDeleted`, `deletedAt`, and `deletedBy` fields to determine whether the user has been removed. Requires the `user:read` permission. Arguments: - email: String!
Inputs
emailstringrequired- No description.
plainmcp_usersList all human members of the workspace, with optional filters to narrow results by role assignability.WriteUsers
List all human members of the workspace, with optional filters to narrow results by role assignability. Supports cursor-based pagination. Requires the `user:read` permission. Inviting people and changing their roles are done by the user in the Plain app. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/members/add` (never the `<workspaceId>` placeholder), or `â¦/settings/members/<userId>` to change a member's role. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - filters: UsersFilter - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
plainmcp_userslackchannelmembershipsReturns the Slack channels the current user belongs to within the given Slack workspace.WriteUser Slack Channel Memberships
Returns the Slack channels the current user belongs to within the given Slack workspace. Useful for populating channel pickers in UI integrations. Arguments: - slackTeamId: String!
Inputs
slackTeamIdstringrequired- No description.
plainmcp_verifyhelpcentercustomdomainnameTrigger a DNS verification check for the custom domain configured on the help center.WriteVerify Help Center Custom Domain Name
Trigger a DNS verification check for the custom domain configured on the help center. Returns an error if the expected TXT record is not yet visible. Requires the helpCenter:edit permission. Arguments: - input: VerifyHelpCenterCustomDomainNameInput!
Inputs
inputstringrequired- No description.
plainmcp_webhooktargetFetch a single webhook target by its ID.WriteWebhook Target
Fetch a single webhook target by its ID. Returns null if no target with that ID exists in the workspace. Requires the `webhookTarget:read` permission. Creating, changing and deleting webhook targets are done by the user in the Plain app, because a webhook sends workspace events to an outside URL. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/webhooks/<webhookTargetId>` (never the `<workspaceId>` placeholder), or `â¦/settings/webhooks/add` for a new one. Arguments: - webhookTargetId: ID!
Inputs
webhookTargetIdstringrequired- No description.
plainmcp_webhooktargetsList all webhook targets registered in the workspace, paginated.WriteWebhook Targets
List all webhook targets registered in the workspace, paginated. Returns every endpoint Plain is configured to deliver events to. Requires the `webhookTarget:read` permission. Creating, changing and deleting webhook targets are done by the user in the Plain app, because a webhook sends workspace events to an outside URL. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/webhooks/add` (never the `<workspaceId>` placeholder), or `â¦/settings/webhooks/<webhookTargetId>` for an existing one. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_webhookversionsList all available webhook schema versions.WriteWebhook Versions
List all available webhook schema versions. Use this to discover which versions you can pin a webhook target to, and to check whether a version you are already using has been deprecated. Requires the `webhookTarget:read` permission. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_workflowGet a workflow by id.WriteWorkflow
Get a workflow by id. Returns null if no workflow with the given ID exists. Workflows are the step-based automation model that supports conditions, actions, and wait steps connected in a graph. Arguments: - workflowId: ID!
Inputs
workflowIdstringrequired- No description.
plainmcp_workflowbuilderguideHow to build or edit a workflow with these tools, as markdown: the trigger events, every condition and action payload with its fields, how steps connect, and how to publish and link to the result.WriteWorkflow Builder Guide
How to build or edit a workflow with these tools, as markdown: the trigger events, every condition and action payload with its fields, how steps connect, and how to publish and link to the result. Read it before creating or changing a workflow. Requires the `workflowRule:read` permission.
Inputs
This tool takes no inputs.
plainmcp_workflowcapabilitiesReturns which blocks (condition/action/wait steps) are available for a workflow of the given trigger type.WriteWorkflow Capabilities
Returns which blocks (condition/action/wait steps) are available for a workflow of the given trigger type. The builder UI sources its palette from this so the allow-list lives in the backend, not hardcoded in the UI. E.g. SCHEDULE workflows have no thread, so they allow no conditions/waits and only a restricted set of action types. Read `workflowBuilderGuide` first for the trigger events and every step payload. Arguments: - triggerType: WorkflowTriggerType!
Inputs
triggerTypestringrequired- No description.
plainmcp_workflowexecutionGet a single workflow execution by id.WriteWorkflow Execution
Get a single workflow execution by id. Returns null if no execution with the given ID exists. Use this to inspect the status, timing, and per-step results of a specific run. Arguments: - workflowExecutionId: ID!
Inputs
workflowExecutionIdstringrequired- No description.
plainmcp_workflowexecutionsList executions for a specific workflow, paginated.WriteWorkflow Executions
List executions for a specific workflow, paginated. Use this to audit the run history of a workflow and check for failures. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - workflowId: ID! - first: Int - after: String - last: Int - before: String
Inputs
workflowIdstringrequired- No description.
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_workflowexecutionsbyentityList workflow executions filtered by the entity they ran against (e.g.WriteWorkflow Executions By Entity
List workflow executions filtered by the entity they ran against (e.g. a specific thread), paginated. Useful for showing all automation that has fired on a given thread. Optionally narrow further by workflow ID or execution status. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - filters: WorkflowExecutionByEntityFilter! - first: Int - after: String - last: Int - before: String
Inputs
filtersstringrequired- No description.
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_workflowexecutionsforworkspaceList executions across every workflow in the workspace, newest first, paginated.WriteWorkflow Executions For Workspace
List executions across every workflow in the workspace, newest first, paginated. Use this for a workspace-wide view of what automation has been doing, or narrow it with `filters` â by workflow, by the entity a run fired against, or by state. Executions that have not started yet sort to the top. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - filters: WorkflowExecutionsFilter - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
plainmcp_workflowsList workflows in the workspace, paginated.WriteWorkflows
List workflows in the workspace, paginated. Use `filters` to narrow results by trigger type (MANUAL, EVENTS or SCHEDULE), published status, the events an `events` trigger listens for, or the entities their steps reference (e.g. every workflow applying a given SLA policy). Ordered by `position` ascending unless `sortBy` says otherwise. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String - filters: WorkflowsFilter - sortBy: WorkflowsSort
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
sortBystring- No description.
plainmcp_workflowtemplateNull if no template with that ID is published.WriteWorkflow Template
Null if no template with that ID is published. Deprecated templates still resolve here, which is what keeps existing install links working. Needs an authenticated caller and nothing more. Arguments: - templateId: ID!
Inputs
templateIdstringrequired- No description.
plainmcp_workflowtemplategalleryPublished templates for the gallery, metadata only â deprecated ones are already absent because the templates repo omits them.WriteWorkflow Template Gallery
Published templates for the gallery, metadata only â deprecated ones are already absent because the templates repo omits them. Use `workflowTemplate` for one with its workflows. Needs an authenticated caller and nothing more: templates are one published document, identical for every workspace, so there is nothing to scope by permission.
Inputs
This tool takes no inputs.
plainmcp_workspaceFetch a workspace by its ID.WriteWorkspace
Fetch a workspace by its ID. Returns null if the workspace does not exist or the caller does not have access to it. Arguments: - workspaceId: ID!
Inputs
workspaceIdstringrequired- No description.
plainmcp_workspacechatsettingsReturns the workspace-level chat settings, including whether the live-chat channel is enabled for this workspace.WriteWorkspace Chat Settings
Returns the workspace-level chat settings, including whether the live-chat channel is enabled for this workspace.
Inputs
This tool takes no inputs.
plainmcp_workspacediscordchannelintegrationFetches a single workspace Discord channel integration by its ID.WriteWorkspace Discord Channel Integration
Fetches a single workspace Discord channel integration by its ID. Returns null if no integration with that ID exists. Not connected yet? Connecting needs the user's approval in the provider. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/install/discord` (never the `<workspaceId>` placeholder), which takes them straight to Discord to approve, then read this again to confirm. Arguments: - integrationId: ID!
Inputs
integrationIdstringrequired- No description.
plainmcp_workspacediscordchannelintegrationsReturns a paginated list of all Discord server (guild) channel integrations connected to this workspace.WriteWorkspace Discord Channel Integrations
Returns a paginated list of all Discord server (guild) channel integrations connected to this workspace. Not connected yet? Connecting needs the user's approval in the provider. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/install/discord` (never the `<workspaceId>` placeholder), which takes them straight to Discord to approve, then read this again to confirm. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_workspaceemailsettingsReturns the workspace's email settings, including whether email is enabled, any custom domain configuration, and BCC addresses.WriteWorkspace Email Settings
Returns the workspace's email settings, including whether email is enabled, any custom domain configuration, and BCC addresses. Changing these settings, including the support email domain, its forwarding and alternate addresses, is done by the user in the Plain app, because they decide where mail is sent from and to. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/email` (never the `<workspaceId>` placeholder).
Inputs
This tool takes no inputs.
plainmcp_workspaceinvitesReturns all pending invites for the current workspace.WriteWorkspace Invites
Returns all pending invites for the current workspace. Use this to view outstanding invitations and their status from an admin perspective. Inviting someone is done by the user in the Plain app. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/members/add` (never the `<workspaceId>` placeholder). Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_workspacemsteamsintegrationReturns the workspace-level Microsoft Teams integration, or null if none has been created yet.WriteWorkspace Msteams Integration
Returns the workspace-level Microsoft Teams integration, or null if none has been created yet. Not connected yet? Connecting needs the user's approval in the provider. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/install/ms-teams` (never the `<workspaceId>` placeholder), which takes them straight to Microsoft Teams to approve, then read this again to confirm.
Inputs
This tool takes no inputs.
plainmcp_workspacesetupReturns how far this workspace has progressed through setup: channels, teammates, label types, tiers, automation and Sidekick Agent tools.WriteWorkspace Setup
Returns how far this workspace has progressed through setup: channels, teammates, label types, tiers, automation and Sidekick Agent tools. These are the same steps as the Onboarding checklist the user sees in the Plain app. Connecting the email channel and inviting teammates are done by the user in the Plain app. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/email` or `https://app.plain.com/workspace/w_â¦/settings/members/add` (never the `<workspaceId>` placeholder).
Inputs
This tool takes no inputs.
plainmcp_workspaceslackchannelintegrationReturns a single workspace Slack channel integration by ID, or null if not found.WriteWorkspace Slack Channel Integration
Returns a single workspace Slack channel integration by ID, or null if not found. Not connected yet? Connecting needs the user's approval in the provider. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/install/slack` (never the `<workspaceId>` placeholder), which takes them straight to Slack to approve, then read this again to confirm. Arguments: - integrationId: ID!
Inputs
integrationIdstringrequired- No description.
plainmcp_workspaceslackchannelintegrationsReturns a paginated list of all workspace Slack channel integrations for this workspace.WriteWorkspace Slack Channel Integrations
Returns a paginated list of all workspace Slack channel integrations for this workspace. Not connected yet? Connecting needs the user's approval in the provider. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/install/slack` (never the `<workspaceId>` placeholder), which takes them straight to Slack to approve, then read this again to confirm. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_workspaceslackintegrationReturns a single workspace-level Slack notifications integration by ID, or null if not found.WriteWorkspace Slack Integration
Returns a single workspace-level Slack notifications integration by ID, or null if not found. A Slack channel integration's ID (from `workspaceSlackChannelIntegrations`) returns null here; to connect notifications through one, use `createWorkspaceSlackIntegrationFromAuth`. Not connected yet? Connecting needs the user's approval in the provider. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/slack` (never the `<workspaceId>` placeholder), then read this again to confirm. Arguments: - integrationId: ID!
Inputs
integrationIdstringrequired- No description.
plainmcp_workspaceslackintegrationsReturns a paginated list of all workspace-level Slack notifications integrations for this workspace.WriteWorkspace Slack Integrations
Returns a paginated list of all workspace-level Slack notifications integrations for this workspace. For the Slack teams connected for support channels, use `workspaceSlackChannelIntegrations`. To connect notifications through a Slack channel integration the workspace already has, use `createWorkspaceSlackIntegrationFromAuth`. Not connected yet? Connecting needs the user's approval in the provider. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/slack` (never the `<workspaceId>` placeholder), then read this again to confirm. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
firststring- No description.
laststring- No description.
plainmcp_workspaceslacksidekickintegrationReturns the current workspace's Slack Sidekick Agent integration, or null if Sidekick Agent has not been installed.WriteWorkspace Slack Sidekick Integration
Returns the current workspace's Slack Sidekick Agent integration, or null if Sidekick Agent has not been installed. Requires the workspaceSlackSidekickIntegration:read permission. Not connected yet? Connecting needs the user's approval in the provider. Get this workspace's ID and give the user the full link with that ID in it, `https://app.plain.com/workspace/w_â¦/settings/slack` (never the `<workspaceId>` placeholder), then read this again to confirm.
Inputs
This tool takes no inputs.
plainmcp_addgeneratedreplyAdd an AI-generated reply to a thread in Plain.DestructiveAddGeneratedReply
Add an AI-generated reply to a thread in Plain.
Inputs
inputstringrequired- No description.
plainmcp_addlabelsAdd one or more labels to a thread.DestructiveAddLabels
Add one or more labels to a thread.
Inputs
inputstringrequired- No description.
plainmcp_archivelabeltypeArchive a label type so it can no longer be applied to threads.DestructiveArchiveLabelType
Archive a label type so it can no longer be applied to threads.
Inputs
inputstringrequired- No description.
plainmcp_assignthreadAssign a thread to a user or machine user.DestructiveAssignThread
Assign a thread to a user or machine user.
Inputs
inputstringrequired- No description.
plainmcp_bulkupsertthreadfieldsCreate or update multiple thread field values in a single call.DestructiveBulkUpsertThreadFields
Create or update multiple thread field values in a single call.
Inputs
inputstringrequired- No description.
plainmcp_changethreadpriorityUpdate the priority of a thread.DestructiveChangeThreadPriority
Update the priority of a thread. Valid priorities are 0 (urgent) through 3 (low).
Inputs
inputstringrequired- No description.
plainmcp_createlabeltypeCreate a new label type that can be applied to threads.DestructiveCreateLabelType
Create a new label type that can be applied to threads.
Inputs
inputstringrequired- No description.
plainmcp_createnoteAdd an internal note to a thread, visible only to workspace members.DestructiveCreateNote
Add an internal note to a thread, visible only to workspace members.
Inputs
inputstringrequired- No description.
plainmcp_createsnippetCreate a new snippet (reusable reply template) in the workspace.DestructiveCreateSnippet
Create a new snippet (reusable reply template) in the workspace. name is what agents search for when inserting the snippet; text is the plain-text body (required). Optionally provide markdown for rich-text channels, and path (alphanumeric only) to place the snippet in a folder in the Plain app. Snippet bodies may include template variables such as {{ customer.email }}, {{ customer.fullName }}, {{ user.publicName }}, {{ thread.ref }}.
Inputs
inputstringrequired- No description.
plainmcp_createthreadOpen a new support thread for an existing customer.DestructiveCreateThread
Open a new support thread for an existing customer. Does not send a message — follow up with replyToThread if needed.
Inputs
inputstringrequired- No description.
plainmcp_createthreadfieldschemaCreate a new custom thread field schema for the workspace.DestructiveCreateThreadFieldSchema
Create a new custom thread field schema for the workspace.
Inputs
inputstringrequired- No description.
plainmcp_createthreadlinkLink a thread to an external entity (e.g.DestructiveCreateThreadLink
Link a thread to an external entity (e.g. a Linear issue, Jira issue, incident.io incident, or another Plain thread/task). Provide threadId plus exactly one way to identify the link target: linearIssue, jiraIssue, plainThread, plainTask, or sourceId+sourceType (use searchThreadLinkCandidates to discover sourceId for a given sourceType).
Inputs
inputstringrequired- No description.
plainmcp_deleteaitonerulesPermanently deletes one or more AI tone rules by ID.DestructiveDelete Ai Tone Rules
Permanently deletes one or more AI tone rules by ID. If any supplied ID does not exist the entire operation fails and no rules are deleted. Requires the `aiToneRule:delete` permission. Arguments: - input: DeleteAiToneRulesInput!
Inputs
inputstringrequired- No description.
plainmcp_deletealltestthreadsPermanently delete every test thread belonging to the signed-in user.DestructiveDelete All Test Threads
Permanently delete every test thread belonging to the signed-in user.
Inputs
This tool takes no inputs.
plainmcp_deleteautoresponderPermanently delete an autoresponder.DestructiveDelete Autoresponder
Permanently delete an autoresponder. The deleted autoresponder is returned in the response. Requires the `autoresponder:delete` permission. Arguments: - input: DeleteAutoresponderInput!
Inputs
inputstringrequired- No description.
plainmcp_deletebroadcastSoft-delete a broadcast.DestructiveDelete Broadcast
Soft-delete a broadcast. Deleted broadcasts are excluded from `getBroadcasts` and `searchBroadcasts` but remain fetchable by ID with `getBroadcastDetails`, where `isDeleted` is true â so the record of what was sent survives. Deleting a broadcast whose send is already underway does not recall the messages it has already posted.
Inputs
inputstringrequired- No description.
plainmcp_deletebroadcastaudienceSoft-delete a broadcast audience.DestructiveDelete Broadcast Audience
Soft-delete a broadcast audience. Deleted audiences are excluded from `getBroadcastAudiences` but stay fetchable by ID with `getBroadcastAudienceDetails`, so the record of what a past broadcast was sent to survives. Rejected with `cannot_delete_broadcast_audience` while a broadcast targeting the audience is scheduled or being sent, because past `SCHEDULED` its author can no longer edit the reference away.
Inputs
inputstringrequired- No description.
plainmcp_deletebusinesshoursoverrideDelete an override.DestructiveDelete Business Hours Override
Delete an override. The schedule's weekly hours apply to its dates again. Requires the `businessHours:delete` permission. Arguments: - input: DeleteBusinessHoursOverrideInput!
Inputs
inputstringrequired- No description.
plainmcp_deletebusinesshoursscheduleDelete a business hours schedule and the slots belonging to it.DestructiveDelete Business Hours Schedule
Delete a business hours schedule and the slots belonging to it. Requires the `businessHours:delete` permission. Arguments: - input: DeleteBusinessHoursScheduleInput!
Inputs
inputstringrequired- No description.
plainmcp_deletecustomergroupPermanently delete a customer group by ID.DestructiveDelete Customer Group
Permanently delete a customer group by ID. This will fail if the group still has members â remove all customers from the group first. Requires `customerGroup:delete` permission. Arguments: - input: DeleteCustomerGroupInput!
Inputs
inputstringrequired- No description.
plainmcp_deletecustomersurveyPermanently deletes a customer survey.DestructiveDelete Customer Survey
Permanently deletes a customer survey. Returns an error if the survey does not exist. Requires the `customerSurvey:delete` permission. Arguments: - input: DeleteCustomerSurveyInput!
Inputs
inputstringrequired- No description.
plainmcp_deletedthreadsPaginated list of threads that have been deleted.DestructiveDeleted Threads
Paginated list of threads that have been deleted. Only threads deleted after the deletion audit log was enabled for your workspace are included. Useful for auditing or syncing deletions to an external system. Requires the `thread:read` permission. Pages of 100 can be too big to read: ask for 50 at a time with `first`, then page on with `after`. Arguments: - filters: DeletedThreadsFilter - first: Int - after: String - last: Int - before: String
Inputs
afterstring- No description.
beforestring- No description.
filtersstring- No description.
firststring- No description.
laststring- No description.
plainmcp_deleteescalationpathPermanently deletes an escalation path by ID.DestructiveDelete Escalation Path
Permanently deletes an escalation path by ID. Returns an error if the escalation path does not exist. Threads that were attached to this escalation path will lose their escalation path association. Requires the `escalationPath:delete` permission. Arguments: - input: DeleteEscalationPathInput!
Inputs
inputstringrequired- No description.
plainmcp_deletehelpcenterarticlegroupDelete an article group.DestructiveDelete Help Center Article Group
Delete an article group. Articles that belonged to the group are not deleted â they become ungrouped. To remove articles entirely, use deleteHelpCenterArticle. Requires the helpCenter:edit permission. Arguments: - input: DeleteHelpCenterArticleGroupInput!
Inputs
inputstringrequired- No description.
plainmcp_deleteknowledgesourceDelete a knowledge source and remove it from Plain AI's index.DestructiveDelete Knowledge Source
Delete a knowledge source and remove it from Plain AI's index. This is idempotent â deleting a knowledge source that does not exist returns no error. Arguments: - input: DeleteKnowledgeSourceInput!
Inputs
inputstringrequired- No description.
plainmcp_deletemyfavoritepageRemoves a favorite page for the currently authenticated user.DestructiveDelete My Favorite Page
Removes a favorite page for the currently authenticated user. If the specified favorite page does not exist or belongs to a different user, the mutation succeeds silently with no error. Requires the `favoritePage:delete` permission. Arguments: - input: DeleteMyFavoritePageInput!
Inputs
inputstringrequired- No description.
plainmcp_deletesavedthreadsviewPermanently deletes a saved threads view.DestructiveDelete Saved Threads View
Permanently deletes a saved threads view. Returns an error if the view does not exist. Depending on workspace settings, only the view's creator or workspace admins may be allowed to delete a view they did not create. Arguments: - input: DeleteSavedThreadsViewInput!
Inputs
inputstringrequired- No description.
plainmcp_deleteservicelevelagreementDelete an SLA from a tier.DestructiveDelete Service Level Agreement
Delete an SLA from a tier. A first-response-time SLA cannot be deleted while a next-response-time SLA still exists on the same tier â delete the next-response SLA first. Returns the deleted SLA on success. Requires the `serviceLevelAgreement:delete` permission. Arguments: - input: DeleteServiceLevelAgreementInput!
Inputs
inputstringrequired- No description.
plainmcp_deletesnippetSoft-deletes a snippet.DestructiveDelete Snippet
Soft-deletes a snippet. Deleted snippets are hidden from the snippet picker but remain fetchable by ID with `isDeleted: true`, preserving the history of replies that referenced them. Requires the `snippet:delete` permission. Arguments: - input: DeleteSnippetInput!
Inputs
inputstringrequired- No description.
plainmcp_deletetestthreadPermanently delete one of the signed-in user's own test threads.DestructiveDelete Test Thread
Permanently delete one of the signed-in user's own test threads. Other threads are reported as not found. Arguments: - input: DeleteTestThreadInput!
Inputs
inputstringrequired- No description.
plainmcp_deletethreadfieldRemoves a stored thread field value from a thread, identified by thread ID and field key.DestructiveDelete Thread Field
Removes a stored thread field value from a thread, identified by thread ID and field key. Has no effect if the field has no value. Requires the `threadField:delete` permission. Arguments: - input: DeleteThreadFieldInput!
Inputs
inputstringrequired- No description.
plainmcp_deletethreadfieldschemaPermanently delete a custom thread field schema by key.DestructiveDeleteThreadFieldSchema
Permanently delete a custom thread field schema by key.
Inputs
inputstringrequired- No description.
plainmcp_deletethreadlinkRemove a link between a thread and an external entity.DestructiveDeleteThreadLink
Remove a link between a thread and an external entity. Pass the threadLinkId of the link to delete (the id returned by createThreadLink or listed under a thread's links in getThreadDetails).
Inputs
inputstringrequired- No description.
plainmcp_deleteworkflowPermanently delete a workflow and all its steps.DestructiveDelete Workflow
Permanently delete a workflow and all its steps. Existing executions are retained for audit purposes. Arguments: - input: DeleteWorkflowInput!
Inputs
inputstringrequired- No description.
plainmcp_deleteworkflowstepDelete a single step from a workflow.DestructiveDelete Workflow Step
Delete a single step from a workflow. You are responsible for updating any steps that reference this step in their transitions. Arguments: - input: DeleteWorkflowStepInput!
Inputs
inputstringrequired- No description.
plainmcp_getattachmentdownloadurlGenerate a short-lived download URL for an attachment on a thread.DestructiveGetAttachmentDownloadUrl
Generate a short-lived download URL for an attachment on a thread. Use attachment IDs returned by getThreadDetails. The returned downloadUrl expires after 3 minutes. Requires the attachment:download permission.
Inputs
attachmentIdstringrequired- Attachment ID from a thread's timeline entries (e.g. NoteEntry, ChatEntry, EmailEntry), returned by getThreadDetails.
plainmcp_markthreadasdoneMark a thread as done, moving it out of the active queue.DestructiveMarkThreadAsDone
Mark a thread as done, moving it out of the active queue.
Inputs
inputstringrequired- No description.
plainmcp_markthreadastodoMark a thread as todo, returning it to the active queue.DestructiveMarkThreadAsTodo
Mark a thread as todo, returning it to the active queue.
Inputs
inputstringrequired- No description.
plainmcp_mergethreadMerge one Plain thread into another (a MERGED_INTO native thread link).DestructiveMergeThread
Merge one Plain thread into another (a MERGED_INTO native thread link). The child thread is merged into the parent thread; on success the child thread is marked as done. For a non-merging association between threads or to an external entity, use createThreadLink instead.
Inputs
childThreadIdstringrequired- Thread ID (starts with th_) of the thread to merge in. This thread will be marked as done.
parentThreadIdstringrequired- Thread ID (starts with th_) of the thread to merge into.
plainmcp_movelabeltypeReorder a label type within the workspace label list.DestructiveMoveLabelType
Reorder a label type within the workspace label list.
Inputs
inputstringrequired- No description.
plainmcp_removeaccountfieldschemamappingRemoves the mapping between an account field schema and a built-in Plain concept, disabling any automatic behaviour (such as tier assignment) driven by that field.DestructiveRemove Account Field Schema Mapping
Removes the mapping between an account field schema and a built-in Plain concept, disabling any automatic behaviour (such as tier assignment) driven by that field. Arguments: - input: RemoveAccountFieldSchemaMappingInput!
Inputs
inputstringrequired- No description.
plainmcp_removeadditionalassigneesRemove one or more additional assignees from a thread.DestructiveRemove Additional Assignees
Remove one or more additional assignees from a thread. Does not affect the primary assignee. Requires the `thread:unassign` and `thread:read` permissions. Arguments: - input: RemoveAdditionalAssigneesInput!
Inputs
inputstringrequired- No description.
plainmcp_removecustomerfromaccountsRemoves a customer from one or more accounts.DestructiveRemove Customer From Accounts
Removes a customer from one or more accounts. The customer can be identified by their Plain ID, external ID, or email address. If the customer is not currently a member of a specified account the operation is a no-op for that account. Requires the `customer:edit` and `customerTenantMembership:delete` permissions. Arguments: - input: RemoveCustomerFromAccountsInput!
Inputs
inputstringrequired- No description.
plainmcp_removecustomerfromcustomergroupsRemove a customer from one or more customer groups (up to 25 at once), identified by group ID, key, or external ID.DestructiveRemove Customer From Customer Groups
Remove a customer from one or more customer groups (up to 25 at once), identified by group ID, key, or external ID. Returns an error if the customer is not currently a member of any of the specified groups. Requires `customerGroupMembership:delete` permission. Arguments: - input: RemoveCustomerFromCustomerGroupsInput!
Inputs
inputstringrequired- No description.
plainmcp_removecustomerfromtenantsRemoves a customer from one or more tenants.DestructiveRemove Customer From Tenants
Removes a customer from one or more tenants. The customer can be identified by their Plain ID, external ID, or email address. If the customer is not currently a member of a specified tenant the operation is a no-op for that tenant. Requires the `customer:edit` and `customerTenantMembership:delete` permissions. Deprecated: Use removeCustomerFromAccounts instead Arguments: - input: RemoveCustomerFromTenantsInput!
Inputs
inputstringrequired- No description.
plainmcp_removelabelsRemove one or more labels from a thread.DestructiveRemoveLabels
Remove one or more labels from a thread.
Inputs
inputstringrequired- No description.
plainmcp_removelabelsfromuserRemove one or more labels from a Plain user (agent) by label ID.DestructiveRemove Labels From User
Remove one or more labels from a Plain user (agent) by label ID. Returns the remaining labels still applied to the user after the removal. Requires the `label:delete` permission. Arguments: - input: RemoveLabelsFromUserInput!
Inputs
inputstringrequired- No description.
plainmcp_removemembersfromtierRemoves one or more tenants or companies from their current tier (up to 25 per call).DestructiveRemove Members From Tier
Removes one or more tenants or companies from their current tier (up to 25 per call). After removal the member has no tier. Requires the `tierMembership:read` and `tierMembership:delete` permissions. Arguments: - input: RemoveMembersFromTierInput!
Inputs
inputstringrequired- No description.
plainmcp_removetenantfieldschemamappingRemoves the mapping between a tenant field schema and a built-in Plain concept, disabling any automatic behaviour (such as tier assignment) driven by that field.DestructiveRemove Tenant Field Schema Mapping
Removes the mapping between a tenant field schema and a built-in Plain concept, disabling any automatic behaviour (such as tier assignment) driven by that field. Deprecated: Use removeAccountFieldSchemaMapping instead Arguments: - input: RemoveTenantFieldSchemaMappingInput!
Inputs
inputstringrequired- No description.
plainmcp_reorderthreadfieldschemasChange the display order of custom thread field schemas.DestructiveReorderThreadFieldSchemas
Change the display order of custom thread field schemas.
Inputs
inputstringrequired- No description.
plainmcp_replytothreadSend a reply to the last message in a thread via email, Slack, or chat.DestructiveReplyToThread
Send a reply to the last message in a thread via email, Slack, or chat.
Inputs
inputstringrequired- No description.
plainmcp_resolvesidekickapprovalApprove or deny a Sidekick tool-call approval request.DestructiveResolveSidekickApproval
Approve or deny a Sidekick tool-call approval request. ASK THE USER BEFORE CALLING THIS - show them the justification and every requested call from getSidekickSession's approval-request entry, and wait for an explicit instruction. Approving authorises Sidekick's own credentials (usually broader than the user's), not the user's own action. Denying is always safe and only reduces what Sidekick may do.
Inputs
decisionstringrequired- No description.
leaseIdstringrequired- No description.
reviewerNotestring- No description.
plainmcp_sendsidekickmessageSend a follow-up message into an existing Sidekick session.DestructiveSendSidekickMessage
Send a follow-up message into an existing Sidekick session. Use this to answer a question from Sidekick, redirect it, or give it the next task in the same session. This tool returns as soon as the message is accepted - poll getSidekickSession for the reply.
Inputs
discussionIdstringrequired- Sidekick session handle (starts with thdis_) returned by startSidekickSession.
markdownContentstringrequired- The follow-up message to send into the session.
plainmcp_snoozethreadSnooze a thread until a specified date and time.DestructiveSnoozeThread
Snooze a thread until a specified date and time.
Inputs
inputstringrequired- No description.
plainmcp_startsidekicksessionStart a new Sidekick (Plain's AI agent) session and return the handle used by every other Sidekick tool.DestructiveStartSidekickSession
Start a new Sidekick (Plain's AI agent) session and return the handle used by every other Sidekick tool. Runs asynchronously; poll getSidekickSession with the returned discussion id to follow progress and collect the reply. On a timeout do NOT retry blindly - call listSidekickSessions first to check whether the first attempt landed.
Inputs
markdownContentstringrequired- No description.
additionalContextstring- No description.
threadIdstring- No description.
plainmcp_unarchivelabeltypeRestore an archived label type so it can be applied to threads again.DestructiveUnarchiveLabelType
Restore an archived label type so it can be applied to threads again.
Inputs
inputstringrequired- No description.
plainmcp_unassignthreadRemove the current assignee from a thread.DestructiveUnassignThread
Remove the current assignee from a thread.
Inputs
inputstringrequired- No description.
plainmcp_updatelabeltypeUpdate the name or color of an existing label type.DestructiveUpdateLabelType
Update the name or color of an existing label type.
Inputs
inputstringrequired- No description.
plainmcp_updatethreadfieldschemaUpdate the label or options of an existing thread field schema.DestructiveUpdateThreadFieldSchema
Update the label or options of an existing thread field schema.
Inputs
inputstringrequired- No description.
plainmcp_updatethreadtitleUpdate the title of an existing thread.DestructiveUpdateThreadTitle
Update the title of an existing thread.
Inputs
inputstringrequired- No description.
plainmcp_upsertcustomerCreate or update a customer by external ID, email, or customer ID.DestructiveUpsertCustomer
Create or update a customer by external ID, email, or customer ID.
Inputs
inputstringrequired- No description.
plainmcp_upserthelpcenterarticleCreate or update a Help Center article by slug.DestructiveUpsertHelpCenterArticle
Create or update a Help Center article by slug.
Inputs
inputstringrequired- No description.
plainmcp_upserttenantCreate or update a tenant by external ID or tenant ID.DestructiveUpsertTenant
Create or update a tenant by external ID or tenant ID.
Inputs
inputstringrequired- No description.
plainmcp_upserttenantfieldSet or update a custom field value on a tenant.DestructiveUpsertTenantField
Set or update a custom field value on a tenant.
Inputs
inputstringrequired- No description.
plainmcp_upsertthreadfieldSet or update a custom field value on a thread.DestructiveUpsertThreadField
Set or update a custom field value on a thread.
Inputs
inputstringrequired- No description.
No tools match.