Skip to main content
The server has 44 tools in seven toolsets. When an assistant connects, it sees every tool. There are no meta-tools that find or run other tools. To load fewer tools, add ?toolsets= to the MCP URL. Every tool acts as the connected employee, in the connection’s company. It returns only what that employee can see in Workchats, and it can do only what that employee can do there.

Conventions

Ids. Tools take and return prefixed ids, so an assistant can pass an id from one tool to another: Comment, subtask and recording ids are plain UUIDs. A conversation is a dm_, grp_ or chn_ id. Results. Each tool returns structuredContent that matches its output schema, and the same object as JSON text, for clients that read only text. Pages. List tools take limit (default 20, at most 50 unless the tool says otherwise) and cursor, and return next_cursor. next_cursor is null on the last page. list_events and list_announcements take limit but no cursor. Effect. Each tool row says what the tool does to Workchats. Each tool declares matching MCP annotations, so a client knows when to ask you first: openWorldHint is false on every tool. send_draft is marked destructive on purpose: a sent message cannot be taken back, so clients ask before they call it. update_task is marked destructive because it overwrites a task others already see. pin_message is marked destructive because a pin is shared: everyone in the conversation sees it, and any member can remove it. Errors. A tool that fails returns isError: true and {"error": {"code", "message"}}: A write tool called with a token that can only read gets an HTTP 403 with insufficient_scope, not a tool error. See OAuth for client developers.

Read-only URL and toolsets

  • /mcp/readonly lists and runs read tools only. A connection made through this URL can only read.
  • ?toolsets= picks toolsets by URL, for example https://mcp.workchats.com/mcp?toolsets=tasks,meetings. Every tool of the named toolsets is listed, plus search and fetch. A tool of a toolset you did not name is not listed, and a call to it answers “Tool not found”. An unknown toolset name gets HTTP 400.
Toolset names: core, messaging, people, tasks, meetings, files, events. A call to discover_tools or execute answers “Tool not found”, as for any unknown name.

Search and fetch

search and fetch have the exact shapes that ChatGPT’s Deep Research and company knowledge expect.
  • search and fetch never return a direct message, or a file whose newest message you can read is in a direct message.
  • search lists no meeting more than 30 days ahead, and one result per meeting series.
  • People, events and polls are not in search.
  • A result title is plain text from a fixed pattern, such as Task: … or File: …, because ChatGPT shows it as a label. Text that other people wrote is cut to 80 characters, with line breaks, < and > removed. A message body is never in a title. fetch wraps the item’s text as usual.
  • A message link opens its conversation in Workchats Web, not the message itself.

Messaging

Notes:
  • Direct messages need their own tool. search_messages searches groups and channels by default. Searching direct messages needs search_dms, or type with dm or all. So you can see in the assistant when it reads your direct messages.
  • Results name their conversation. A message from a channel names the channel and its group. A direct message names the other person. A message that an assistant sent for its author carries via_client.
  • Reading never marks read. catch_up, read_conversation and the search tools leave your unread counts as they are. Only mark_read changes them, and it marks the whole conversation.
  • search_messages and search_dms take a query of 3 to 200 characters. The query is optional when in, with or from is given.
  • draft_message takes a body of 1 to 4,000 characters. To mention a person, write @ and their full name in the body, and give their usr_ id in mentions. See Drafts and the “via” label.

People

  • search_users returns no email address or phone number.
  • get_user_profile returns null for a contact detail, job title or department that the person hides from you, and for the text of a status they hide. The assistant sees what a regular employee sees, also when you are an admin.

Tasks

  • update_task needs the lock_version from the last read. If the task changed since, the answer is conflict. assignee_ids and tags replace the whole list.
  • Assignees must be members of the task’s group.
  • There is no overdue scope. For overdue tasks, use status: open with due_before.
  • A mention in a comment needs @ and the person’s full name in body. add_task_comment returns a warning for each mention it could not store.
  • convert_message_to_task works only on group and channel messages, not direct messages.

Meetings and calls

  • list_meetings leaves out cancelled occurrences.
  • A recurring meeting keeps one transcript, summary and recording, its latest. Every occurrence of the series reports that one.
  • create_meeting ends 30 minutes after start by default, uses your own timezone by default, and has a Workchats video link unless video is false.
  • An answer to the current occurrence of a series also answers the later occurrences, as in the app.

Files

  • A search_files page can hold fewer files than limit, or none, while next_cursor is set. Keep paging until next_cursor is null.
  • ask_filing_cabinet can take up to 45 seconds. It answers with unavailable when your company has the Filing Cabinet off, and it keeps no Filing Cabinet conversation.
  • read_file reads files up to 10 MB. text_status says whether text was extracted, or why not: unsupported, too_large or unavailable.

Events, polls and notifications

  • Reading announcements or notifications here does not mark them seen, read or acknowledged.
  • list_polls leaves out polls of a chat you locked, and polls of a channel you are not in. A poll names its group, not its channel.

Limits

Each employee has these limits, shared by all their connected assistants: A tool over its limit returns the rate_limited tool error with retry_after_seconds. An initialize over its limit gets HTTP 429 with Retry-After.