Skip to content

MCP tool reference ​

Connect using the MCP setup guide. Tool names and argument names below are case-sensitive. Optional arguments can be omitted. Cancellation tokens in the .NET implementation are supplied by the server, not sent as tool arguments. The server registers 70 tools for regular accounts:

GroupToolsCount
Account and avatarsget_me, list_avatars, create_avatar, update_avatar, set_default_avatar5
Discover places and chatslist_places, list_place_chats, list_group_chats, list_peer_chats4
Manage chatsget_chat, create_chat, update_chat, list_members, add_members, remove_member, join_chat, leave_chat8
Chat invite linkscreate_invite_link, list_invite_links, revoke_invite_link3
Placesget_place, create_place, update_place, list_place_members, add_place_members, remove_place_member, create_place_invite_link, list_place_invite_links8
Read messagesget_id_range, list_messages, list_pinned_messages, list_reactions4
Post and stream messagespost_message, edit_message, remove_message, start_message_stream, append_message_stream, finish_message_stream, start_voice_stream, append_voice_stream, finish_voice_stream9
Pins, reactions and notifying memberspin_message, unpin_message, react, notify_members, notify_mentioned5
Uploadsbegin_upload, append_upload, finish_upload, upload_from_url, abort_upload5
Import historyget_import, start_import, consent_to_import, end_import, begin_import_upload, finish_import_upload, import_upload_from_url, import_messages8
Chat contentlist_media, list_files, list_links3
Conversationslist_conversations, get_conversation2
Searchsearch_messages, search_contacts2
Notificationslist_notifications, wait_for_notifications, dismiss_notification, dismiss_all_notifications4

Every tool uses structured content. Each tool acts as the authenticated account and is subject to that account's chat and place permissions.

Account and avatars ​

ToolRequired argumentsOptional argumentsResult
get_meNoneNoneMcpAccount: your user ID, name and default avatar.
list_avatarsNoneNoneMcpAvatar[]; isDefault marks the one used in new chats.
create_avatarname: stringbio: string; pictureMediaId: stringMcpAvatar
update_avataravatarId: stringname, bio, pictureMediaId: stringsMcpAvatar; omitted fields keep their value.
set_default_avataravatarId: stringNoneNo application result value.

pictureMediaId comes from finish_upload with purpose avatar_picture.

Discover places and chats ​

ToolRequired argumentsOptional argumentsResult
list_placesNoneafterId: string or null; limit: integerMcpListPlacesResult
list_place_chatsplaceId: stringafterId: string or null; limit: integerMcpListChatsResult
list_group_chatsNoneafterId: string or null; limit: integerMcpListChatsResult
list_peer_chatsNoneafterId: string or null; limit: integerMcpListChatsResult

list_places returns places in the account's place list. list_place_chats returns its listed chats within one place. list_group_chats returns standalone group chats, excluding peer and place chats. list_peer_chats returns direct chats; if a chat has no explicit title, its title falls back to the other person's avatar name. These are account-list operations, not a search of every public chat on the server; use search_contacts to look for other public chats and places.

All four default to afterId: null and limit: 256. The server clamps limit to 1–1024. For a following page, supply the final returned place/chat ID as afterId. The cursor is exclusive.

Treat this cursor as an opaque position in the current list. The implementation finds the matching ID and starts after it; it does not compare IDs numerically or lexicographically. An unknown cursor restarts from the beginning. Avoid repeated pages if the underlying list changes or a cursor disappears. Items that cannot be resolved are omitted, so a short page is not a guaranteed total count.

Manage chats and members ​

ToolRequired argumentsOptional argumentsResult
get_chatchatIdNoneMcpChatDetails
create_chattitle: string; isPublic: booleandescription: string; placeId: string; pictureMediaId: stringMcpChatDetails
update_chatchatIdtitle, description: strings; isPublic: boolean; pictureMediaId: stringMcpChatDetails
list_memberschatIdafterId: string; limit: integerMcpListMembersResult
add_memberschatId; userIds: string[]NoneNo application result value.
remove_memberchatId; authorId: stringNoneNo application result value.
join_chatchatIdNoneNo application result value.
leave_chatchatIdNoneNo application result value.
  • get_chat returns kind, title, description, picture, place, member count and the caller's permissions (names of the permission flags).
  • create_chat creates a group chat, or a chat inside a place when placeId is given. The caller becomes its owner. Update omitted fields keep their value in update_chat.
  • list_members is paged by author ID (default limit 256, clamped to 1–1024); the cursor is exclusive and the list is sorted by author ID. Members who have left are omitted.
  • add_members needs the Invite permission; user IDs come from get_me, list_members or list_peer_chats. remove_member needs the EditMembers permission and the author ID must belong to the given chat.
  • join_chat joins a public chat or one the caller was invited to.
ToolRequired argumentsResult
create_invite_linkchatIdMcpInviteLink: the current link; one is generated if none is active. Needs the Invite permission.
list_invite_linkschatIdMcpInviteLink[]: active links only (revoked and exhausted are omitted).
revoke_invite_linkinviteId: stringNo application result value. Works for chat and place links.

Treat an invite URL as a secret: anyone holding it can use it.

Places ​

ToolRequired argumentsOptional argumentsResult
get_placeplaceIdNoneMcpPlaceDetails
create_placetitle: string; isPublic: booleandescription; pictureMediaId; backgroundMediaIdMcpPlaceDetails; the caller becomes owner.
update_placeplaceIdtitle, description: strings; isPublic: boolean; pictureMediaId; backgroundMediaIdMcpPlaceDetails; omitted fields keep their value.
list_place_membersplaceIdafterId: string; limit: integerMcpListMembersResult
add_place_membersplaceId; userIds: string[]NoneNo application result value. Needs the Invite permission.
remove_place_memberplaceId; authorId: stringNoneNo application result value. Needs the EditMembers permission.
create_place_invite_linkplaceIdNoneMcpInviteLink (generated if none is active).
list_place_invite_linksplaceIdNoneMcpInviteLink[]; revoke with revoke_invite_link.

Place pictures and backgrounds come from finish_upload with purpose chat_picture. list_place_members pages like list_members. The author ID passed to remove_place_member must belong to the place.

Read messages ​

get_id_range ​

Required argument: chatId (string). Returns McpIdRange<long>: the chat's inclusive firstId and lastId. An empty range has lastId < firstId. Gaps are possible; subtracting the bounds does not count messages.

list_messages ​

ArgumentTypeMeaning
chatIdstring, requiredChat to read.
afterIdinteger or null, optionalReturn local message IDs greater than this; null starts at the beginning.
limitinteger, optionalDefaults to 256; clamped to 1–1024.

Returns McpListMessagesResult, containing messages (ExternalMessage), their inclusive range, and the chat's fullRange. Messages are read in ascending local-ID order. Continue with the last returned message's id; stop when no messages are returned.

Removed messages are omitted. System and currently streaming entries are included. A streaming entry has no text (null) until its content is ready. If you need its final content, read that region again later: advancing a cursor past it will not return later changes to the same ID. Pagination is not a change feed; edits and removals of older messages require rereading the relevant range.

Each message includes attachment metadata, mentions, a reply reference and an origin. Reading metadata does not upload or modify files.

The following is a tools/call request body for an initialized MCP connection. Replace the example ID with one returned by a discovery tool; let your MCP client handle initialization, headers and transport negotiation.

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "list_messages",
    "arguments": {
      "chatId": "<returned-chat-id>",
      "afterId": null,
      "limit": 50
    }
  }
}

list_pinned_messages and list_reactions ​

ToolRequired argumentsResult
list_pinned_messageschatIdExternalMessage[]: the chat's pinned messages.
list_reactionschatId; entryId: integerMcpReactionSummary[]: emoji, count and the first reacting author IDs.

Post and stream messages ​

The server sends usage instructions to every client at initialization. They describe four ways to post a message, in increasing order of what the client must supply:

  1. post_message: ordinary text, all at once.
  2. start_message_stream, append_message_stream, finish_message_stream: text that arrives over time, for example while a model generates it. The message appears immediately and fills in live, as a transcript does while someone speaks. A person listening to the chat hears it in a synthesized voice.
  3. start_voice_stream with audio only: you supply the sound. Nothing transcribes it, so the message has no text.
  4. start_voice_stream with audio and text: you supply both; neither speech recognition nor synthesis runs. The message has your own voice and an exact transcript.

Single messages ​

ToolRequired argumentsOptional argumentsResult
post_messagechatId: string; text: stringreplyToId: integer (local ID of the message being replied to); attachmentMediaIds: string[] (from finish_upload, kept in order)The new message's local ID (64-bit integer).
edit_messagechatId: string; entryId: integer; text: stringNoneNo application result value.
remove_messagechatId: string; entryId: integerNoneSoft-removes the message. No application result value.

entryId is the numeric message ID within chatId, not a composite entry ID or an author ID. Writing uses the account's normal permissions. Treat a tool error as a failed operation rather than assuming the message was changed. To mention a person, write @u:<userId> in the text (see notify_mentioned).

Example tools/call parameters for posting:

json
{
  "name": "post_message",
  "arguments": {
    "chatId": "<returned-chat-id>",
    "text": "The meeting notes are ready for review."
  }
}

Posting has no client-supplied idempotency key: if a connection fails after sending, inspect the chat before retrying to avoid duplicate posts.

Streamed text ​

ToolRequired argumentsOptional argumentsResult
start_message_streamchatIdentryId: integer (stream into one of your own recent messages instead of posting a new one); language: string such as "en-US" (default: your own language)McpMessageStream
append_message_streamstreamId: string; offset: integer; text: stringNoneMcpMessageStream
finish_message_streamstreamId: stringNoneMcpMessageStream

Lifecycle:

  1. Call start_message_stream. The message exists in the chat at once. Keep the returned streamId and entryId.
  2. Call append_message_stream for each piece. offset is the number of characters the server already has; use the offset returned by the previous call (or by start_message_stream). If it does not match, nothing is written and the reply carries the real offset, so a call you retried or whose reply you lost can resume without duplicating text.
  3. Call finish_message_stream once. It settles the message on the text received so far; calling it again within 90 seconds returns the same result. To discard the message, finish the stream and then call remove_message.

A stream with no append for 90 seconds is finished for you with what arrived. To start over, append a line holding only <!--reset-->: it and everything above it are dropped from what readers see, and the text after it becomes the message.

speechBacklog in each reply is the number of seconds of speech a listener still has to hear before reaching what you just wrote. Slow down while it grows. It is null when nobody is listening. Without a backlog value, write at speaking pace for the language: roughly 15 characters per second for English, 17 for Russian, 6 for Japanese and 4 for Mandarin; the backlog is the better signal because voice speed depends on language, voice and provider.

Voice messages ​

ToolRequired argumentsOptional argumentsResult
start_voice_streamchatIdreplyToId: integer; language: string (decides what listeners can translate the message from)McpVoiceStream
append_voice_streamstreamId: string; textOffset: integertext: string; audioBase64: string (Ogg Opus, at most 1 MB decoded); audioOffset: number (seconds)McpVoiceStream
finish_voice_streamstreamId: stringNoneMcpVoiceStream

Lifecycle: call start_voice_stream, then append_voice_stream as often as needed with audio, text or both, then finish_voice_stream. The message is heard live and settles into an ordinary playable message. entryId is null in the start reply and in append replies until finish_voice_stream returns it; it stays null if neither audio nor words arrived (nothing is posted). Calling finish_voice_stream again within 90 seconds returns the same result, and a stream with no append for 90 seconds is finished for you.

Audio rules:

  • Format: Ogg Opus, with every packet holding exactly one 20 ms frame. Encoders: ffmpeg -c:a libopus -frame_duration 20 or opusenc --framesize 20. A 40 ms or 60 ms packet is rejected and ends the stream.
  • Send audio in order, chunked anywhere (a chunk may split an Ogg page), in chunks of at most 1 MB decoded. Audio is append-only and has no offset check: a chunk sent twice is heard twice.
  • Deliver at least as fast as the audio plays. A listener hears the stream live, and audio that arrives slower than real time is a gap in the middle of a sentence. Faster is fine.
  • audioDuration in the reply is what the server decoded. If it stops growing while audioBytes grows, the audio is not being read; check the packet size first.

Text rules:

  • textOffset works like offset in text streams: pass the characters the server already has; on mismatch no text is written and the reply carries the real offset.
  • Send a clause of text when the audio carrying it is going out, not on a fixed cadence. A listener reads text as it arrives and hears audio when playback reaches it.
  • audioOffset is the number of seconds into your own audio at the end of this text. It writes the time map used for seeking in the finished message, not live display. Omit it and the server uses the audio it has received. Send audio before the text it corresponds to, or pass audioOffset, so transcript and sound line up.

Pins, reactions and pings ​

ToolRequired argumentsResult
pin_messagechatId; entryId: integerNo application result value.
unpin_messagechatId; entryId: integerNo application result value.
reactchatId; entryId: integer; emoji: string (the emoji character)No application result value. Toggles: sets the reaction, or removes it if the same emoji is already set.
notify_memberschatIdNo application result value.
notify_mentionedchatId; entryId: integerNo application result value.

notify_members rings all chat members, bypassing mute. It is accepted only for private chats with at most 10 members. Use it sparingly. notify_mentioned rings the members mentioned in one of your own messages, also bypassing mute; mention members in the message text as @u:<userId>.

Uploads ​

Attachments and pictures are uploaded first, then referenced by media ID. The chunked flow is resumable:

  1. begin_upload
  2. append_upload repeatedly
  3. finish_upload
ToolRequired argumentsOptional argumentsResult
begin_uploadfileName: string; contentType: string; length: integer (total bytes)purpose: attachment (default), chat_picture or avatar_picture; chatId: string (required for attachment)McpUploadStatus
append_uploaduploadId: string; offset: integer; dataBase64: string (at most 1 MB decoded)NoneMcpUploadStatus
finish_uploaduploadId: stringNoneMcpUploadStatus
upload_from_urlurl: string (public http or https URL)purpose; chatId; fileNameMcpUploadStatus
abort_uploaduploadId: stringNoneDiscards an unfinished upload. No application result value.
  • append_upload writes at offset, which must equal the server's current offset. If it does not, nothing is written and the status returns the current offset, so you can resume. Chunks larger than 1 MB are rejected.
  • finish_upload starts server-side processing (image normalization or video transcoding) and waits up to 2 minutes. When stage is Ready, media is set and its mediaId can be passed to post_message, create_chat, update_chat, create_place, update_place, create_avatar or update_avatar. If processing is still running, the current stage is returned: call finish_upload again. A failed processing step is returned as a tool error.
  • upload_from_url downloads the file on the server, then uploads it as the chunked flow would, and waits for processing like finish_upload. The file name defaults to the URL's last segment. The download is subject to the server's attachment size limit.
  • Only the account that began an upload can append to, finish or abort it.
  • append_upload and abort_upload also work on uploads begun with begin_import_upload (see Import history).
  • Purposes: attachment for message attachments, chat_picture for chat or place pictures and backgrounds, avatar_picture for avatar pictures.

Import history ​

Owners of a group chat or a place can import history from another service, such as a Telegram, WhatsApp or Slack export, with the original authors and dates. The tools wrap the import service of the RPC API (IChatImports); the process as members and owners see it is described in Import and export.

Every author must consent first, and starting an import stops posting for every member, the owner included, until it ends. A place-wide import (started on the place's root chat) stops every chat of the place. The order:

  1. get_import: check that no import runs yet.
  2. start_import with confirm: true.
  3. Remind the members listed in pending with post_message into their peerChatId (direct chats stay open during an import), and poll get_import until enough of them have consented. The owner consents with consent_to_import like everyone else.
  4. Upload attachments: begin_import_upload, append_upload, finish_import_upload, or import_upload_from_url.
  5. import_messages in batches, oldest first.
  6. end_import.
ToolRequired argumentsOptional argumentsResult
get_importchatIdoffset: integer (default 0); limit: integer (default 50, clamped to 1–100)McpImportStatus
start_importchatIdconfirm: boolean; requestId: stringMcpImportSession
consent_to_importchatId; importId: stringNoneNo application result value.
end_importchatId; importIdNoneMcpImportEndResult
begin_import_uploadchatId; importId; authorUserId: string; fileName; contentType; length: integerNoneMcpUploadStatus
finish_import_uploadchatId; importId; uploadId: stringNoneMcpUploadStatus
import_upload_from_urlurl: string; chatId; importId; authorUserIdfileNameMcpUploadStatus
import_messageschatId; importId; batchId: string; messages: arrayNoneMcpImportMessagesResult

get_import ​

chatId is a group chat, a place chat or a place's root chat. The result's active is false when nothing runs. Otherwise it carries the import's importId, who started it and when, how many members have consented, the consented share in percent, and whether you have consented. A place-wide import is reported for every chat of the place, with scope set to place and placeId.

Owners also get pending: a page of the members who have not consented, each with a name and peerChatId, your direct chat with that member (null if you have none). Page through it with offset and limit. Other readers get the counts only. Poll this tool while you wait for consent.

start_import ​

Owners only. chatId is a group chat or a single place chat (scope chat), or a place's root chat for a place-wide import (scope place). Confirm with the user first: nothing starts unless confirm is true, and the tool returns an error that explains why. The call takes about 10 seconds and fails if someone posts in the meantime.

Pass the same requestId to retry a call whose answer you did not get; it returns the same session. Use a new requestId for each new import.

consent_to_import gives your own consent only. It cannot be revoked for that import, and owners must consent too if their own messages are to be imported.

end_import is owners only and allowed at any time; members can post again afterwards. Members who never consented simply have no messages imported. The result reports how many had not consented.

Attachments ​

begin_import_upload starts a chunked upload for an imported message by authorUserId, who must have consented. chatId must be the chat you pass to import_messages; for a place-wide import that is a place chat, not the root. Its status has no mediaId yet. Send the bytes with append_upload, then call finish_import_upload, which returns the status in stage Ready. import_upload_from_url does all three from a public http or https URL. Pass the upload ID in uploadIds of import_messages. Each upload attaches to one message only.

import_messages ​

Owners only. Imports 1 to 100 messages in one call.

Message fieldMeaning
authorUserIdUser ID of the member who wrote it.
sentAtUnix time in milliseconds, like createdAt in list_messages.
textVoxt markup, up to 64 KB.
replyToIdOptional. Local ID of a message that is already in the chat.
uploadIdsOptional. Up to 10 upload IDs from begin_import_upload or import_upload_from_url.

batchId is your ID for the batch, up to 100 characters. Resending a batchId with the same messages returns its earlier result instead of importing again.

Rules for the dates and the order:

  • A message must be dated in the past.
  • It must be later than the chat's newest message. System messages count, such as members joining, so in a group chat the dates must be later than when its members joined.
  • It must be later than the messages imported by earlier calls, so send batches forward in time. Within a batch the order does not matter, but no two messages may share a date.
  • A reply target must already be in the chat. To reply to a message of the same batch, import the target in an earlier batch and use the id it returned.

chatId is a group chat or a place chat, never a root chat. A message whose author left, is not a member or has not consented is rejected on its own: the call still succeeds, and the rejection is reported in that message's error. Imported messages notify no one. post_message is not an import: it posts as you, dated now.

ToolRequired argumentsOptional argumentsResult
list_mediachatIdperiodKey: string; pageIndex: integer (0-based)McpContentPage<McpMediaItem>
list_fileschatIdperiodKey; pageIndexMcpContentPage<McpFileItem>
list_linkschatIdperiodKey; pageIndexMcpContentPage<McpLinkItem>

These list photos and videos, files and links posted in a chat, grouped into monthly periods, newest period first. Omit periodKey for the newest period. Page within a period by increasing pageIndex while it is less than pageCount. Continue to older content by passing the returned nextPeriodKey as periodKey (with pageIndex 0). nextPeriodKey is null when there is no older period. A periodKey that does not exist returns an empty page.

Conversations ​

A conversation is a summarized stretch of messages, such as a voice session.

ToolRequired argumentsOptional argumentsResult
list_conversationschatIdbeforeId: string; limit: integer (default 64, clamped to 1–1024)McpListConversationsResult
get_conversationconversationId: string (from list_conversations)NoneMcpConversation

list_conversations returns conversations newest first. Pass the result's nextBeforeId as beforeId to go older. nextBeforeId is null when fewer than limit conversations were found, meaning there are no older ones.

ToolRequired argumentsOptional argumentsResult
search_messagesquery: stringchatId: string; placeId: string; limit: integer (default 20, max 100)McpFoundMessage[]
search_contactsquery: stringscope: people, groups (default) or places; own: boolean (default true); placeId: string; limit: integer (default 20, max 100)McpFoundContact[]

search_messages is a full-text search over messages the account can read, optionally limited to one chat or place. search_contacts searches people, group chats or places by name. With own true it searches the account's own contacts, joined chats and places; with own false it searches other public ones. An invalid scope is a tool error. Search depends on the server's search feature being enabled; if it is not, these two tools fail while the others work.

Notifications ​

The notification tools work on the account's active notifications: the ones currently pending on its devices, such as mentions, replies, reactions, attention pings, thread and conversation pings, invitations and incoming calls. Reading a chat clears its mentions, so consume them as they arrive. The notification history log is not exposed through MCP.

ToolRequired argumentsOptional argumentsResult
list_notificationsNonechatId: string; placeId: stringMcpListNotificationsResult
wait_for_notificationsNoneversion: string; chatId: string; placeId: string; timeoutSeconds: integer (default 30, clamped to 1–55)McpListNotificationsResult
dismiss_notificationid: stringNoneNo application result value.
dismiss_all_notificationsNoneNoneNo application result value.

Without chatId and placeId everything is returned. chatId limits the result to one chat (a group chat, a place chat or a peer chat; a contact is its peer chat, so pass the peer chat ID), and placeId to the chats of one place. An invalid ID is a tool error.

McpListNotificationsResult has the items and a version, a short identifier of that exact set. To follow notifications as they arrive, call wait_for_notifications with the version you last processed: it returns as soon as the set differs (including when an existing notification is merged and its text or time changes), or returns the unchanged set after the timeout, in which case call it again with the same version. An empty or stale version returns the current set at once. Persist the last version you processed to resume after a broken connection. Each item carries its related message (ExternalMessage) when the message exists and the chat is still accessible. Dismiss a notification by the id of an item.

Reading tool results ​

Read the MCP result's structuredContent and check isError first. Object results use the models in the data reference. A scalar return such as post_message may be wrapped as { "result": 123 } by the MCP SDK. Tools described above as returning no application result value have no payload; use the success/error result rather than expecting an object.

Tool errors state their reason when the cause is invalid input, a missing object, a rejected value or a permission failure. Other failures are reported with a generic message.

Source ​

Source files at d2eee636e0f13804421d2864a9575fa21ab6c940: message tools, chat tools, place tools, account tools, media tools, conversation tools, search tools, notification tools and server instructions.