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:
| Group | Tools | Count |
|---|---|---|
| Account and avatars | get_me, list_avatars, create_avatar, update_avatar, set_default_avatar | 5 |
| Discover places and chats | list_places, list_place_chats, list_group_chats, list_peer_chats | 4 |
| Manage chats | get_chat, create_chat, update_chat, list_members, add_members, remove_member, join_chat, leave_chat | 8 |
| Chat invite links | create_invite_link, list_invite_links, revoke_invite_link | 3 |
| Places | get_place, create_place, update_place, list_place_members, add_place_members, remove_place_member, create_place_invite_link, list_place_invite_links | 8 |
| Read messages | get_id_range, list_messages, list_pinned_messages, list_reactions | 4 |
| Post and stream messages | post_message, edit_message, remove_message, start_message_stream, append_message_stream, finish_message_stream, start_voice_stream, append_voice_stream, finish_voice_stream | 9 |
| Pins, reactions and notifying members | pin_message, unpin_message, react, notify_members, notify_mentioned | 5 |
| Uploads | begin_upload, append_upload, finish_upload, upload_from_url, abort_upload | 5 |
| Import history | get_import, start_import, consent_to_import, end_import, begin_import_upload, finish_import_upload, import_upload_from_url, import_messages | 8 |
| Chat content | list_media, list_files, list_links | 3 |
| Conversations | list_conversations, get_conversation | 2 |
| Search | search_messages, search_contacts | 2 |
| Notifications | list_notifications, wait_for_notifications, dismiss_notification, dismiss_all_notifications | 4 |
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 ​
| Tool | Required arguments | Optional arguments | Result |
|---|---|---|---|
get_me | None | None | McpAccount: your user ID, name and default avatar. |
list_avatars | None | None | McpAvatar[]; isDefault marks the one used in new chats. |
create_avatar | name: string | bio: string; pictureMediaId: string | McpAvatar |
update_avatar | avatarId: string | name, bio, pictureMediaId: strings | McpAvatar; omitted fields keep their value. |
set_default_avatar | avatarId: string | None | No application result value. |
pictureMediaId comes from finish_upload with purpose avatar_picture.
Discover places and chats ​
| Tool | Required arguments | Optional arguments | Result |
|---|---|---|---|
list_places | None | afterId: string or null; limit: integer | McpListPlacesResult |
list_place_chats | placeId: string | afterId: string or null; limit: integer | McpListChatsResult |
list_group_chats | None | afterId: string or null; limit: integer | McpListChatsResult |
list_peer_chats | None | afterId: string or null; limit: integer | McpListChatsResult |
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 ​
| Tool | Required arguments | Optional arguments | Result |
|---|---|---|---|
get_chat | chatId | None | McpChatDetails |
create_chat | title: string; isPublic: boolean | description: string; placeId: string; pictureMediaId: string | McpChatDetails |
update_chat | chatId | title, description: strings; isPublic: boolean; pictureMediaId: string | McpChatDetails |
list_members | chatId | afterId: string; limit: integer | McpListMembersResult |
add_members | chatId; userIds: string[] | None | No application result value. |
remove_member | chatId; authorId: string | None | No application result value. |
join_chat | chatId | None | No application result value. |
leave_chat | chatId | None | No application result value. |
get_chatreturns kind, title, description, picture, place, member count and the caller's permissions (names of the permission flags).create_chatcreates a group chat, or a chat inside a place whenplaceIdis given. The caller becomes its owner. Update omitted fields keep their value inupdate_chat.list_membersis 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_membersneeds the Invite permission; user IDs come fromget_me,list_membersorlist_peer_chats.remove_memberneeds the EditMembers permission and the author ID must belong to the given chat.join_chatjoins a public chat or one the caller was invited to.
Invite links ​
| Tool | Required arguments | Result |
|---|---|---|
create_invite_link | chatId | McpInviteLink: the current link; one is generated if none is active. Needs the Invite permission. |
list_invite_links | chatId | McpInviteLink[]: active links only (revoked and exhausted are omitted). |
revoke_invite_link | inviteId: string | No application result value. Works for chat and place links. |
Treat an invite URL as a secret: anyone holding it can use it.
Places ​
| Tool | Required arguments | Optional arguments | Result |
|---|---|---|---|
get_place | placeId | None | McpPlaceDetails |
create_place | title: string; isPublic: boolean | description; pictureMediaId; backgroundMediaId | McpPlaceDetails; the caller becomes owner. |
update_place | placeId | title, description: strings; isPublic: boolean; pictureMediaId; backgroundMediaId | McpPlaceDetails; omitted fields keep their value. |
list_place_members | placeId | afterId: string; limit: integer | McpListMembersResult |
add_place_members | placeId; userIds: string[] | None | No application result value. Needs the Invite permission. |
remove_place_member | placeId; authorId: string | None | No application result value. Needs the EditMembers permission. |
create_place_invite_link | placeId | None | McpInviteLink (generated if none is active). |
list_place_invite_links | placeId | None | McpInviteLink[]; 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 ​
| Argument | Type | Meaning |
|---|---|---|
chatId | string, required | Chat to read. |
afterId | integer or null, optional | Return local message IDs greater than this; null starts at the beginning. |
limit | integer, optional | Defaults 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.
{
"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 ​
| Tool | Required arguments | Result |
|---|---|---|
list_pinned_messages | chatId | ExternalMessage[]: the chat's pinned messages. |
list_reactions | chatId; entryId: integer | McpReactionSummary[]: 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:
post_message: ordinary text, all at once.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.start_voice_streamwith audio only: you supply the sound. Nothing transcribes it, so the message has no text.start_voice_streamwith audio and text: you supply both; neither speech recognition nor synthesis runs. The message has your own voice and an exact transcript.
Single messages ​
| Tool | Required arguments | Optional arguments | Result |
|---|---|---|---|
post_message | chatId: string; text: string | replyToId: 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_message | chatId: string; entryId: integer; text: string | None | No application result value. |
remove_message | chatId: string; entryId: integer | None | Soft-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:
{
"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 ​
| Tool | Required arguments | Optional arguments | Result |
|---|---|---|---|
start_message_stream | chatId | entryId: 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_stream | streamId: string; offset: integer; text: string | None | McpMessageStream |
finish_message_stream | streamId: string | None | McpMessageStream |
Lifecycle:
- Call
start_message_stream. The message exists in the chat at once. Keep the returnedstreamIdandentryId. - Call
append_message_streamfor each piece.offsetis the number of characters the server already has; use theoffsetreturned by the previous call (or bystart_message_stream). If it does not match, nothing is written and the reply carries the realoffset, so a call you retried or whose reply you lost can resume without duplicating text. - Call
finish_message_streamonce. 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 callremove_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 ​
| Tool | Required arguments | Optional arguments | Result |
|---|---|---|---|
start_voice_stream | chatId | replyToId: integer; language: string (decides what listeners can translate the message from) | McpVoiceStream |
append_voice_stream | streamId: string; textOffset: integer | text: string; audioBase64: string (Ogg Opus, at most 1 MB decoded); audioOffset: number (seconds) | McpVoiceStream |
finish_voice_stream | streamId: string | None | McpVoiceStream |
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 20oropusenc --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.
audioDurationin the reply is what the server decoded. If it stops growing whileaudioBytesgrows, the audio is not being read; check the packet size first.
Text rules:
textOffsetworks likeoffsetin 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.
audioOffsetis 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 passaudioOffset, so transcript and sound line up.
Pins, reactions and pings ​
| Tool | Required arguments | Result |
|---|---|---|
pin_message | chatId; entryId: integer | No application result value. |
unpin_message | chatId; entryId: integer | No application result value. |
react | chatId; 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_members | chatId | No application result value. |
notify_mentioned | chatId; entryId: integer | No 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:
begin_uploadappend_uploadrepeatedlyfinish_upload
| Tool | Required arguments | Optional arguments | Result |
|---|---|---|---|
begin_upload | fileName: string; contentType: string; length: integer (total bytes) | purpose: attachment (default), chat_picture or avatar_picture; chatId: string (required for attachment) | McpUploadStatus |
append_upload | uploadId: string; offset: integer; dataBase64: string (at most 1 MB decoded) | None | McpUploadStatus |
finish_upload | uploadId: string | None | McpUploadStatus |
upload_from_url | url: string (public http or https URL) | purpose; chatId; fileName | McpUploadStatus |
abort_upload | uploadId: string | None | Discards an unfinished upload. No application result value. |
append_uploadwrites atoffset, 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_uploadstarts server-side processing (image normalization or video transcoding) and waits up to 2 minutes. WhenstageisReady,mediais set and itsmediaIdcan be passed topost_message,create_chat,update_chat,create_place,update_place,create_avatarorupdate_avatar. If processing is still running, the current stage is returned: callfinish_uploadagain. A failed processing step is returned as a tool error.upload_from_urldownloads the file on the server, then uploads it as the chunked flow would, and waits for processing likefinish_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_uploadandabort_uploadalso work on uploads begun withbegin_import_upload(see Import history).- Purposes:
attachmentfor message attachments,chat_picturefor chat or place pictures and backgrounds,avatar_picturefor 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:
get_import: check that no import runs yet.start_importwithconfirm: true.- Remind the members listed in
pendingwithpost_messageinto theirpeerChatId(direct chats stay open during an import), and pollget_importuntil enough of them have consented. The owner consents withconsent_to_importlike everyone else. - Upload attachments:
begin_import_upload,append_upload,finish_import_upload, orimport_upload_from_url. import_messagesin batches, oldest first.end_import.
| Tool | Required arguments | Optional arguments | Result |
|---|---|---|---|
get_import | chatId | offset: integer (default 0); limit: integer (default 50, clamped to 1–100) | McpImportStatus |
start_import | chatId | confirm: boolean; requestId: string | McpImportSession |
consent_to_import | chatId; importId: string | None | No application result value. |
end_import | chatId; importId | None | McpImportEndResult |
begin_import_upload | chatId; importId; authorUserId: string; fileName; contentType; length: integer | None | McpUploadStatus |
finish_import_upload | chatId; importId; uploadId: string | None | McpUploadStatus |
import_upload_from_url | url: string; chatId; importId; authorUserId | fileName | McpUploadStatus |
import_messages | chatId; importId; batchId: string; messages: array | None | McpImportMessagesResult |
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 and end_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 field | Meaning |
|---|---|
authorUserId | User ID of the member who wrote it. |
sentAt | Unix time in milliseconds, like createdAt in list_messages. |
text | Voxt markup, up to 64 KB. |
replyToId | Optional. Local ID of a message that is already in the chat. |
uploadIds | Optional. 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
idit 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.
Media, files and links ​
| Tool | Required arguments | Optional arguments | Result |
|---|---|---|---|
list_media | chatId | periodKey: string; pageIndex: integer (0-based) | McpContentPage<McpMediaItem> |
list_files | chatId | periodKey; pageIndex | McpContentPage<McpFileItem> |
list_links | chatId | periodKey; pageIndex | McpContentPage<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.
| Tool | Required arguments | Optional arguments | Result |
|---|---|---|---|
list_conversations | chatId | beforeId: string; limit: integer (default 64, clamped to 1–1024) | McpListConversationsResult |
get_conversation | conversationId: string (from list_conversations) | None | McpConversation |
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.
Search ​
| Tool | Required arguments | Optional arguments | Result |
|---|---|---|---|
search_messages | query: string | chatId: string; placeId: string; limit: integer (default 20, max 100) | McpFoundMessage[] |
search_contacts | query: string | scope: 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.
| Tool | Required arguments | Optional arguments | Result |
|---|---|---|---|
list_notifications | None | chatId: string; placeId: string | McpListNotificationsResult |
wait_for_notifications | None | version: string; chatId: string; placeId: string; timeoutSeconds: integer (default 30, clamped to 1–55) | McpListNotificationsResult |
dismiss_notification | id: string | None | No application result value. |
dismiss_all_notifications | None | None | No 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.