MCP for AI agents
TeamUp runs a public Model Context Protocol server. External AI agents get the same tools the in-chat assistant uses — events, sign-ups, team splitting, live scoring, dues — with per-event authorization enforced server-side.
Endpoint
https://team-up.tgmbot.com/mcp
Streamable-HTTP transport, MCP spec 2025-06-18. Tools carry readOnlyHint / destructiveHint annotations and structured output schemas; the server also exposes MCP resources (for example team-up://event/{eventId}/log) with change notifications.
Quick start (Claude, Cursor, any MCP client)
Add the server to your client config and complete the sign-in it opens:
{
"mcpServers": {
"team-up": {
"url": "https://team-up.tgmbot.com/mcp"
}
}
}Authorization is OAuth 2.1 with PKCE and Dynamic Client Registration (RFC 7591) — no manual API keys. Clients discover everything from the standard metadata:
https://team-up.tgmbot.com/.well-known/oauth-protected-resource https://team-up.tgmbot.com/.well-known/oauth-authorization-server
Prefer a personal token for scripting? The MCP setup page can issue one in the browser.
Conventions
Success responses are plain objects (also mirrored as structuredContent); failures return { error: "reason" } with isError: true — tools never throw. Role-gated tools state their requirement in the description and return an error rather than prompting. Listing tools use cursor pagination: {cursor?, limit?} → {items, nextCursor?}.
Tool reference (58)
Generated from the server source on every build — the reference cannot drift from the deployed tools.
account
get_my_accountsread-onlyGet My Accounts
Get all platform accounts linked to the calling user.
No parameters.
Output schema (JSON Schema)
{
"type": "object",
"properties": {
"accounts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"platform": {
"type": "string",
"enum": [
"TELEGRAM",
"VK",
"APPLE"
]
},
"username": {
"type": [
"string",
"null"
]
},
"firstName": {
"type": "string"
},
"lastName": {
"type": [
"string",
"null"
]
},
"canReceiveDm": {
"type": "boolean"
}
},
"required": [
"id",
"platform",
"username",
"firstName",
"lastName",
"canReceiveDm"
],
"additionalProperties": false
}
}
},
"required": [
"accounts"
],
"additionalProperties": false
}chat
bind_target_chatBind Target Chat
Bind the current private DM to a target group chat. After binding, every chat-scoped action (createEvent, registerFor, splitTeams, finishEvent, …) targets the bound group; the event card lives there. Replies still come back to this DM only. Only callable from a private DM. Use unbindTargetChat to clear.
| Parameter | Type | Required | Description |
|---|---|---|---|
query | string | no | Free-text fragment of the target chat name (case-insensitive substring match). Use this when the user names the chat conversationally. |
platform | 'TELEGRAM' | 'VK' | no | Target chat platform |
platformChatId | string | no | Platform-native chat id (use after listManagedChats returned it) |
list_managed_chatsread-onlyList Managed Chats
List group chats the calling user can manage from a private DM: chats where the user has past messages OR has created an event. For each chat returns name, active event (id, title, date) when present, lastSeenAt, and `isCurrentTarget` — true when the chat is the one the current DM is already bound to (so the agent can say "this is the chat you are working with right now").
No parameters.
unbind_target_chatUnbind Target Chat
Clear the target-chat binding on the current DM. Subsequent messages stop being routed to the group; event creation in the DM will be refused again.
No parameters.
dues
claim_duesОтметить перевод взноса
Record that a player transferred the game fee to the organizer (self-report). Marks the dues entries as "claimed" — the organizer later confirms them against their bank app. One call covers everyone the transfer paid for. Without userIds the sender claims for themselves.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | no | Event ID. Defaults to the active event of the current chat. Required via MCP. |
userIds | integer[] | no | Everyone whose fee this transfer covers (uid:N from the snapshot). Absent = just the message sender. If the sender paid for themselves AND others, include the sender too. |
delete_bank_entrydestructiveorganizerУдалить движение по кассе
Delete a bank (treasury) expense/income entry by its id — for correcting a mistake. Get ids from getBudget. Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
entryId | integer | yes | id of the ledger entry (from getBudget) |
get_budgetread-onlyКасса / бюджет чата
Treasury of this chat: the rolling bank balance (collected fees + income − expenses), the per-game collected-fees breakdown, the expense/income ledger, and the current bank holder. Use for "сколько в кассе / банке", "покажи бюджет / расходы".
No parameters.
get_chat_debtsread-onlyДолги по чату
Cross-game debts of this chat: who still owes game fees (unpaid or merely claimed but not confirmed) across finished events, grouped per player with totals. Use for "кто должен?" and for reminding debtors.
No parameters.
get_duesread-onlyОплаты взносов события
Dues state of one event: per-head amount, per-player payment entries with statuses (unpaid | claimed | confirmed | waived), counters, and the chat transfer requisites with provenance (who set them, when).
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | no | Event ID. Defaults to the active event of the current chat. Required via MCP. |
record_bank_entryorganizerЗаписать движение по кассе
Record a movement of the team cash pot (bank) that is NOT a player fee: an expense (pitch rental, bibs, ball) or miscellaneous income (sponsor, carry-over). The rolling bank balance is collected fees + income − expenses. Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
kind | 'expense' | 'income' | yes | expense (money out) or income (money in) |
amount | integer | yes | Amount in whole RUB (always positive) |
label | string | yes | What it was, e.g. "аренда поля", "манишки" |
eventId | integer | no | Optional: the game this expense belongs to. Defaults to none. |
set_bank_holderownerДержатель банка
Designate the member who physically holds the team cash pot (bank/treasury), or clear it. Shown in the budget and on "кто держит банк / кассу". Requires caller to be OWNER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
userId | integer | no | Member who holds the pot (uid:N) |
clear | boolean | no | Set true to remove the current holder |
set_chat_requisitesdestructiveownerРеквизиты для взносов
Set, update, or remove the chat-level payment instructions players follow to pay game fees. This is ONE free-text field: store whatever the organizer wrote, exactly as they wrote it. remove: true wipes it. Requires caller to be OWNER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
details | string | no | The payment instructions in the organizer's own words. Any format: "+79119156634 Тиньков", "наличными Жене на поле", "https://qr.nspk.ru/…", or several lines. |
remove | boolean | no | true = delete the stored requisites entirely |
set_dues_statusorganizerСтатусы оплат взносов
Organizer-side dues transition: confirm received transfers, reset a wrong mark back to unpaid, or waive a fee. Target either explicit userIds OR allExcept (= every confirmed participant except the listed ones). Exactly one of the two must be provided. Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | no | Event ID. Defaults to the active event of the current chat. Required via MCP. |
status | 'confirmed' | 'unpaid' | 'waived' | yes | Target status: confirmed (money received), unpaid (reset), waived (free/forgiven) |
userIds | integer[] | no | Explicit target users. Mutually exclusive with allExcept. |
allExcept | integer[] | no | Apply to every confirmed participant EXCEPT these users. Empty array = everyone. Mutually exclusive with userIds. |
paidAmount | integer | no | Exact RUB received (single user + status confirmed only). Less than the fee records a partial payment; the remainder stays as debt. Omit for a full payment. |
event
apply_previous_setuporganizerApply Previous Setup
Copy all EventFeature settings (event types, max players, deadline, etc.) from the most recent previous event in this chat to the given event. Call this when the organizer confirms they want the same settings as last time. Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | yes | ID of the new event to apply settings to |
archive_eventdestructiveorganizerArchive Event
Archive the event — removes it from the default event list but preserves all data. Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | yes | Event ID |
create_eventCreate Event
Create a new event (game/meeting) owned by the calling user. When called from a chat-bound agent, the event is also linked to the current chat and previous-event suggestions come from that chat. If another event in the same chat is still active (not finished, not archived) the behaviour depends on whether the previous event has any signs of life: • 0 confirmed registrations OR no activity for 24+ hours → it is auto-finished (replacedPreviousEvent in the response with reason=empty|inactivity, plus a system note posted to the chat) and the new event is created. • ≥1 confirmed registration AND fresh activity (registration, log entry, or just-created) → the call returns error=collection_in_progress with the active eventId and registrationsCount so the agent can ask the organizer to confirm before discarding their work. Over MCP, the event is stand-alone and previous-event suggestions come from events the caller has created.
| Parameter | Type | Required | Description |
|---|---|---|---|
date | string | no | Event date/time in ISO 8601 format. |
title | string | no | Optional event title |
finish_eventorganizerFinish Event
Finish the event. Writes an event_finish entry to the event log and marks the event as finished. After this, the event stops being the active one in the chat. Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | yes | Event ID |
get_eventread-onlyGet Event
Get event details (title, date, status, registrations, teams). Accepts eventId; if omitted and called from a chat-bound agent context, falls back to the active event of the current chat. Over MCP, eventId is required.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | no |
get_event_naming_templateread-onlyСхема названий событий
Current chat-level naming scheme for auto-created events (used when createEvent is called without an explicit title), plus a preview of what the next auto-created event would be called. Use for "как называются наши игры", "какая сейчас схема названий".
No parameters.
list_my_eventsread-onlyList My Events
List events the calling user has a relationship with (created or participated in). Supports cursor-based pagination. Pass the `nextCursor` from the previous page to fetch the next one.
| Parameter | Type | Required | Description |
|---|---|---|---|
archived | boolean | no | If true, returns archived events instead of active ones. |
cursor | string | no | Opaque pagination cursor from a previous response. |
limit | integer | no | Page size (default 20, max 100). |
Output schema (JSON Schema)
{
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"title": {
"type": [
"string",
"null"
]
},
"date": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"collecting",
"finished",
"archived"
]
},
"isCreator": {
"type": "boolean"
},
"registrationsCount": {
"type": "integer"
}
},
"required": [
"id",
"title",
"date",
"status",
"isCreator",
"registrationsCount"
],
"additionalProperties": false
}
},
"nextCursor": {
"type": "string"
}
},
"required": [
"items"
],
"additionalProperties": false
}reopen_eventorganizerReopen Event
Undo a previous finishEvent. Cancels the last event_finish log entry and clears finishedAt. If eventId is omitted, reopens the most recent finished event in this chat. Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | no | Event ID. Omit to pick the most recent finished event in the chat. |
set_event_featureorganizerSet Event Feature
Add, update, or remove a generic feature for an event (e.g. payment, maxPlayers, deadline, mvp). Typed features (rollcall, teams) do not need this — they activate automatically. Pass remove: true to deactivate a feature. Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | yes | Event ID |
feature | string | yes | Feature key, e.g. "payment", "max_players", "deadline" |
config | object | no | Feature configuration object |
remove | boolean | no | Set true to remove this feature from the event |
set_event_naming_templateorganizerНазвание событий
Set the chat-level default naming scheme applied to events auto-created without an explicit title. Presets: "sequential" — "{label} #{n}" (e.g. "Игра #14"); "weekday" — "{Weekday} #{n}" (e.g. "Вторник #14"); "date" — "{label}, {day} {month}" (e.g. "Игра, 20 июля"), no number. `label` replaces the default word "Игра" (e.g. "Футбол", "Тренировка") — ignored by "weekday". Only affects FUTURE auto-created events; past titles never change. Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
scheme | 'sequential' | 'weekday' | 'date' | yes | Naming preset to apply |
label | string | no | Word used instead of the default "Игра", e.g. "Футбол". Ignored by "weekday". |
update_eventorganizerUpdate Event
Patch an existing event: rename (`title`), change description, or reschedule (`date`). Pass only the fields you want to change. Other fields stay untouched. Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | yes | Event ID |
title | string | null | no | New title. Null clears the title; omit to keep current. |
description | string | null | no | New description. Null clears it; omit to keep current. |
date | string | no | New date/time in ISO 8601 (e.g. "2026-04-25T18:00:00+03:00"). Omit to keep current. |
event-logger
add_event_typeorganizerAdd Event Type
Add or update one event type for logging at a sports or team event. Call once per type. Multiple calls add multiple types. Event types are universal — usable from Watch, chat, or any other logger. Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | yes | Event ID |
id | string | yes | snake_case identifier, e.g. "goal", "three_pointer" |
label | string | yes | Display label, e.g. "Гол", "Трёхочковый" |
emoji | string | no | Optional emoji, e.g. "⚽" |
color | string | no | Optional hex color, e.g. "#FF3B30" |
scoreDelta | number | no | Score impact: always positive or 0. Direction controlled by scoreTarget |
requiresTeam | boolean | no | Whether team selection is required when logging this event |
requiresPlayer | boolean | no | Whether player selection is required when logging this event |
timeEffect | 'start' | 'pause' | 'reset' | no | Timer effect: start — start/resume, pause — pause, reset — reset to 0 |
scoreTarget | 'self' | 'opponent' | no | Which team receives the score: self (default) or opponent. Use opponent for own_goal |
add_log_entryAdd Log Entry
Record one entry into the live game log from chat: a scoring play (goal, point), a card/foul, match-clock control (a type carrying timeEffect: start/pause/reset), or a phase marker. The entry type must already exist in the event catalog — see getScoringConfig / addEventType. The scorer is resolved server-side by badgeNum or exact roster name; scoreDelta and timer effect come from the type config, not from you. Call once per entry.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | yes | Event ID |
typeId | string | yes | Event type id from the catalog, e.g. "goal", "foul", "timer_pause" |
badgeNum | integer | no | Player badge number (stable per registration) |
playerName | string | no | Player name exactly as in the roster; used when badgeNum is unknown |
teamId | integer | no | Team id; defaults to the resolved player's team |
cancel_log_entrydestructiveCancel Log Entry
Undo a previously logged game entry by writing an amendment — the score recomputes automatically. Without localId, cancels the most recent still-active non-structural entry (a scoring play or card, not a timer/phase marker). Get a specific localId from getEventLog.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | yes | Event ID |
localId | string | no | localId of the entry to cancel (from getEventLog); omit to cancel the latest non-structural entry |
get_event_logread-onlyGet Event Log
Return the chronological match log for an event (or a specific game inside it). Already accounts for cancellations and amendment chains — only entries that are still in effect are returned. Each item carries: type, label, team name, player name, occurredAt (ISO), and matchTime (M:SS — game-clock time at the moment, derived from timer_start/pause/reset events). Use this when the user asks for the match protocol, full list of goals/cards, "кто забил во втором тайме", or any time-on-clock detail. Prefer this over getGameState when scoreboard summary is not enough.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | yes | Event ID |
gameId | integer | no | Optional: limit to a single game inside a multi-game event |
get_game_stateread-onlyGet Game State
Get the live game state for an event: structured score (mode-aware: GOAL_TIMER / SET_POINT / RACE_TO / ROUND_JUDGE), a short `summary` string of the current scoreboard, and `recentEvents` — the full chronological list of non-cancelled log entries (goals, assists, cards, timer marks) with team and player labels. Always call this when the user asks for the score, who scored, who assisted, the match summary, or any per-player breakdown — never answer those from memory or the static event snapshot.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | yes | Event ID |
get_scoring_configread-onlyGet Scoring Config
Return the event's logging catalog and scoring setup: every configured event type with its system attributes (scoreDelta, scoreTarget, timeEffect for clock control, requiresTeam/requiresPlayer), the scoringMode, the timer/set/finish/round configs, and the active game id. Call before addLogEntry when unsure which types exist or what their ids are.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | yes | Event ID |
set_scoring_configorganizerSet Scoring Config
Update scoring configuration of an event without touching event types. Use to tweak an already-applied preset (e.g. change setsToWin, targetScore, participantFormat). Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | yes | |
scoringMode | 'GOAL_TIMER' | 'WEIGHTED_TIMER' | 'SET_POINT' | 'RACE_TO' | 'ROUND_JUDGE' | no | |
participantFormat | 'team_vs_team' | '1v1' | '2v2' | '3v3' | no | |
setConfig | object | no | |
timerConfig | object | no | |
finishCondition | object | no |
memory
recall_memoryread-onlyRecall Player Memory
Semantic search over saved player facts in this chat. Use to answer "что я знаю про X" or to find players by trait ("кто хорошо играет в защите").
| Parameter | Type | Required | Description |
|---|---|---|---|
query | string | yes | What to recall, in natural language. |
userId | integer | no | Narrow to one player (from findChatUsers). |
Output schema (JSON Schema)
{
"type": "object",
"properties": {
"facts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"userId": {
"type": "integer"
},
"text": {
"type": "string"
},
"similarity": {
"type": "number"
}
},
"required": [
"userId",
"text",
"similarity"
],
"additionalProperties": false
}
}
},
"required": [
"facts"
],
"additionalProperties": false
}remember_factRemember Player Fact
Save a long-term fact about a PLAYER (how they play, position/role, reliability, preferences). Requires an explicit userId — resolve the name first via findChatUsers. One concise fact per call.
| Parameter | Type | Required | Description |
|---|---|---|---|
userId | integer | yes | Player the fact is about (from findChatUsers). |
text | string | yes | The fact, one sentence, in Russian. |
notifications
send_test_pushSend Test Push
Send a test notification to the current user through the notification pipeline (delivered as a Telegram bot DM for now). Use to verify push infrastructure. Always targets only the requesting user.
| Parameter | Type | Required | Description |
|---|---|---|---|
text | string | no | Optional custom body for the test notification. |
presets
apply_presetorganizerApply Preset
Apply a sport preset to an event. Atomically replaces event_types config with preset types, scoringMode, setConfig, timerConfig, finishCondition, roundConfig and participantFormat. Optional overrides let you tune a preset without creating a new one (team size, period length, setsToWin, etc). This is the recommended way to configure a new event. Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | yes | Event ID |
presetId | string | yes | Preset id from the catalog (e.g. "football", "volleyball", "table_tennis", "mma"). Legacy ids resolved via aliases. |
setsToWin | integer | no | Override setConfig.setsToWin for SET_POINT presets |
pointsToWinSet | integer | no | Override setConfig.pointsToWinSet for SET_POINT presets |
periodMinutes | number | no | Override timerConfig.periodMinutes for timed presets |
periods | integer | no | Override timerConfig.periods (number of halves/quarters/periods) |
participantFormat | 'team_vs_team' | '1v1' | '2v2' | '3v3' | no | Override participantFormat (e.g. 2v2 for badminton doubles) |
targetScore | integer | no | Override finishCondition.targetScore for RACE_TO presets |
list_presetsread-onlyList Presets
List all sport presets available for applyPreset. Optionally filter by scoringMode (GOAL_TIMER, WEIGHTED_TIMER, SET_POINT, RACE_TO, ROUND_JUDGE).
| Parameter | Type | Required | Description |
|---|---|---|---|
scoringMode | 'GOAL_TIMER' | 'WEIGHTED_TIMER' | 'SET_POINT' | 'RACE_TO' | 'ROUND_JUDGE' | no | Filter by scoring model |
Output schema (JSON Schema)
{
"type": "object",
"properties": {
"presets": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"emoji": {
"type": "string"
},
"scoringMode": {
"type": "string",
"enum": [
"GOAL_TIMER",
"WEIGHTED_TIMER",
"SET_POINT",
"RACE_TO",
"ROUND_JUDGE"
]
},
"participantFormat": {
"type": "string",
"enum": [
"team_vs_team",
"1v1",
"2v2",
"3v3"
]
}
},
"required": [
"id",
"name",
"emoji",
"scoringMode",
"participantFormat"
],
"additionalProperties": false
}
}
},
"required": [
"presets"
],
"additionalProperties": false
}rollcall
find_chat_usersread-onlyFind Chat Users
Get users known to the calling user, sorted by recent activity. Agent (chat-bound): participants of the current chat, by messages and registrations. MCP: users who participated in events created by the caller (registrations or team memberships).
No parameters.
Output schema (JSON Schema)
{
"type": "object",
"properties": {
"users": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"firstName": {
"type": [
"string",
"null"
]
},
"lastName": {
"type": [
"string",
"null"
]
},
"username": {
"type": [
"string",
"null"
]
}
},
"required": [
"id",
"firstName",
"lastName",
"username"
],
"additionalProperties": false
}
}
},
"required": [
"users"
],
"additionalProperties": false
}get_registrationsread-onlyGet Registrations
Get all registrations for an event, ordered by badge number.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | yes |
Output schema (JSON Schema)
{
"type": "object",
"properties": {
"eventId": {
"type": "integer"
},
"registrations": {
"type": "array",
"items": {
"type": "object",
"properties": {
"badgeNum": {
"type": "integer"
},
"userId": {
"type": "integer"
},
"name": {
"type": "string"
},
"status": {
"type": "string"
},
"isVirtual": {
"type": "boolean"
},
"registeredAt": {
"type": "string"
}
},
"required": [
"badgeNum",
"userId",
"name",
"status",
"isVirtual",
"registeredAt"
],
"additionalProperties": false
}
}
},
"required": [
"eventId",
"registrations"
],
"additionalProperties": false
}join_eventJoin Event
Register the calling user for an event. Accepts eventId; if omitted and called from a chat-bound agent context, falls back to the active event of the current chat. If the event has a max players limit, the user may be auto-placed on the waiting list.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | no | Event ID. Required when calling via MCP. |
asReserve | boolean | no | Set true to explicitly join the waiting list as a reserve player |
leave_eventLeave Event
Cancel the calling user's registration for an event. Accepts eventId; if omitted and called from a chat-bound agent context, falls back to the active event of the current chat.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | no | Event ID. Required when calling via MCP. |
note | string | no | Reason for cancellation |
register_forRegister Participant
Register another person for the active event. Use userId (from findChatUsers) for known chat members. Use guestName to search for similar users before creating a new one. Use confirmedNewName only after guestName returned candidates and organizer confirmed this is a new person.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | no | Event ID. Required when calling via MCP. |
userId | integer | no | User ID from findChatUsers result |
guestName | string | no | Name to search among existing users. Returns candidates if similar users found. Agent-only. |
confirmedNewName | string | no | Create virtual user with this name. Only after guestName search was done and organizer confirmed new person. Agent-only. |
asReserve | boolean | no | Set true to register as reserve/waiting list |
rename_guestRename Guest
Rename a guest (a bot-created virtual participant) in place — keeps their badge number and registration. Identify the guest by badgeNum (preferred) or userId. Works ONLY on guests; a real platform user keeps their own name and the tool returns an error.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | no | Event ID. Defaults to the active event of the current chat. Required via MCP. |
badgeNum | integer | no | Badge number of the guest to rename (preferred). |
userId | integer | no | Or the guest userId. |
newName | string | yes | New display name for the guest. |
save_rosterdestructiveSave Roster
Single entry point for a pasted full/"final" lineup. Two shapes: a flat ORDERED list → pass `userIds` (array order = badge order); a lineup grouped under 2+ team names ("Yellow: …, Purple: …") → pass `teams` — registers everyone AND assigns the named teams in one step. Prefer this over per-name registerFor calls. Resolve names to userId first (getRegistrations + findChatUsers); create unknown guests with registerFor(guestName) and pass the returned userId. By default removes nobody and returns `toRemove` (registered people absent from the list) — show them to the user and re-call with removeMissing:true only after they confirm.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | no | Event ID. Defaults to the active event of the current chat. Required via MCP. |
userIds | integer[] | no | Flat ordered lineup: array position = badge order. Existing users/guests only. Mutually exclusive with `teams`. |
teams | object[] | no | Grouped lineup: registers everyone (badge order = concatenation of the groups) and REPLACES the event teams with these named teams. Mutually exclusive with `userIds`. |
removeMissing | boolean | no | Cancel confirmed registrations not in the lineup. Only after the user confirmed the diff. |
set_registration_statusorganizerSet Registration Status
Promote a waiting player to confirmed or move a confirmed player to the waiting list. Accepts either badgeNum or userId to identify the player. Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | no | Event ID. Required when calling via MCP. |
badgeNum | integer | no | Badge number of the player. Provide badgeNum or userId. |
userId | integer | no | User ID (from findChatUsers). Provide badgeNum or userId. |
status | 'confirmed' | 'waiting' | yes | New status |
unregister_forUnregister Participant
Cancel registration of another player (by userId) for an event. Accepts eventId; if omitted and called from a chat-bound agent context, falls back to the active event of the current chat. Use leaveEvent when the caller wants to cancel their own registration.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | no | Event ID. Required when calling via MCP. |
userId | integer | yes | User ID of the player to unregister |
note | string | no | Reason for cancellation |
scheduler
cancel_scheduled_promptCancel Scheduled Prompt
Cancel (deactivate) a scheduled prompt by id. The prompt stops firing. Use listScheduledPrompts first if the id is unknown.
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | yes | ScheduledPrompt id (from listScheduledPrompts). |
list_scheduled_promptsread-onlyList Scheduled Prompts
List scheduled prompts configured for the current chat (active and paused).
No parameters.
Output schema (JSON Schema)
{
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"prompt": {
"type": "string"
},
"runAt": {
"type": "string"
},
"recurring": {
"type": "boolean"
},
"status": {
"type": "string"
},
"enabled": {
"type": "boolean"
}
},
"required": [
"id",
"prompt",
"runAt",
"recurring",
"status",
"enabled"
],
"additionalProperties": false
}
}
},
"required": [
"items"
],
"additionalProperties": false
}schedule_promptSchedule Prompt
Schedule a natural-language instruction to run later in THIS chat — one-shot (absolute `at`) or recurring (`recurrence`). At fire time the instruction is fed to the agent exactly as if the user typed it, so it can create events, remind, split teams, finish events, etc. Provide EITHER `at` (ISO 8601) OR `recurrence`, never both. The tool asks the user to confirm before saving. Each run consumes chat credits.
| Parameter | Type | Required | Description |
|---|---|---|---|
prompt | string | yes | The instruction to run later, phrased as a direct command to the agent. |
at | string | no | One-shot absolute fire time, ISO 8601 (e.g. 2026-05-30T19:00:00+03:00). |
recurrence | object | no | Recurring rule. hour/minute are in the chat timezone. Minimum cadence is HOURLY (sub-hourly is not supported); HOURLY fires every `interval` hours at `minute`. |
sheets
get_sheet_export_linkorganizerGet Spreadsheet Export Link
Get the chat's live CSV export feeds for spreadsheets (Google Sheets / Excel). Returns per-feed URLs (events, attendance, player stats; optionally dues and cash ledger) plus a ready =IMPORTDATA(...) formula. Calling again returns the same link. includeMoney omitted = keep the link's current setting (new links start without money feeds). Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
includeMoney | boolean | no | Expose dues.csv and ledger.csv on the link (requires the viewMoney capability). Omitted: keep the current setting. |
read_spreadsheet_linkread-onlyorganizerRead Spreadsheet Link
Read a PUBLIC Google Sheets link ("anyone with the link") as CSV text. Use it when someone shares their spreadsheet to migrate a roster into the chat. Reads the tab the URL points at (#gid=...), else the first tab. Fails on private sheets — the person must either open link access or paste the table as text. Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
url | string | yes | The Google Sheets URL as pasted by the user |
revoke_sheet_export_linkdestructiveorganizerRevoke Spreadsheet Export Link
Revoke the chat's CSV export link: every copy of the URL stops working immediately, including formulas already pasted into spreadsheets. getSheetExportLink afterwards mints a fresh link. Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
No parameters.
signup-graphql
create_signup_linkorganizerCreate Sign-up Link
Create a public sign-up link for an event — a game card anyone can open in a browser to see the roster and sign themselves up after logging in. Made for teams whose chat has no assistant (WhatsApp and the like): share the URL there and sign-ups still land on this roster. Each call creates a NEW link, so one game can have several with different rules; use listSignupLinks to see the existing ones before making another. Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | yes | Event ID |
label | string | no | Short name so several links on one game stay tellable apart |
maxSignups | integer | no | Anti-abuse ceiling: the link stops accepting after this many sign-ups (default 50). NOT the squad size — the roster limit is a separate event setting (max_players). |
autoApprove | boolean | no | false = every sign-up waits for the organizer to approve it |
guestsPerUser | integer | no | How many guests one person may bring; 0 = none |
showRoster | boolean | no | Publish participant names on the card, or only the headcount |
deadlineAt | string | no | ISO instant after which the link stops accepting; omit for no deadline |
list_signup_linksread-onlyorganizerList Sign-up Links
Lists an event's public sign-up links with their settings and how many sign-ups each has brought in. Use before creating another one. Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | yes | Event ID |
spectator-graphql
get_spectator_linkorganizerGet Spectator Link
Get a public spectator link (live score screen) for an event. Anyone with the link can watch the score and event timeline in a browser without logging in. Enables sharing when it is not enabled yet; calling again returns the same link. Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | yes | Event ID |
teams
move_playerorganizerMove Player
Move a participant to a different team, or remove them from their current team if toTeamId is omitted. If the participant is not yet assigned to any team, they will be added to the target team. Accepts either badgeNum or userId to identify the participant. Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
badgeNum | integer | no | Participant badge number (shown as [#N] in the event snapshot and getRegistrations). Provide badgeNum or userId. |
userId | integer | no | User ID (from findChatUsers or registerFor result). Provide badgeNum or userId. |
eventId | integer | yes | Event ID |
toTeamId | integer | no | Target team ID. Omit to remove the participant from their current team. |
set_team_member_roleorganizerSet Team Member Role
Set or clear a role for a team member (e.g. captain, goalkeeper). Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
teamMemberId | integer | yes | TeamMember ID |
role | string | no | Role to assign. Omit or set null to clear. |
split_teamsdestructiveorganizerРазбить участников на команды
Split registered members into teams by an explicit split ACTION: strategy "random" ("разбей на 2"), or strategy "manual" when the organizer assigns already-known members to teams interactively. For a PASTED full lineup (flat or grouped under team names) use saveRoster instead. Requires caller to be ORGANIZER of the target event. Returns {error} otherwise — do not call speculatively.
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId | integer | yes | Event ID |
teamCount | integer | no | Number of teams for random split (default: 2) |
strategy | 'random' | 'manual' | no | Distribution strategy (default: random) |
teams | object[] | no | Required when strategy is "manual" |
confirm | boolean | no | Required (true) to let a random split overwrite existing teams. When teams already exist and confirm is absent, the tool returns {needsConfirm, currentTeams} instead of executing — relay the question to the organizer and re-call with confirm: true only after they agree. |
user-card
get_user_cardread-onlyGet User Card
A user's track record in THIS chat: participation (events attended/registered, games played, member since, how often they show up), whether they organize or just play, per-event-type tallies (goals / points / aces — whatever this chat logs), and saved notes. Use to answer "что за игрок X", "расскажи про X", "часто ли ходит X". Resolve names to a userId via findChatUsers first.
| Parameter | Type | Required | Description |
|---|---|---|---|
userId | integer | no | A single user (from findChatUsers). |
userIds | integer[] | no | Several users at once. |
include | 'participation' | 'performance' | 'memory'[] | no | Which sections to return. Omit for all; e.g. ["participation"] for a cheap scan. |
Output schema (JSON Schema)
{
"type": "object",
"properties": {
"users": {
"type": "array",
"items": {
"type": "object",
"properties": {
"identity": {
"type": "object",
"properties": {
"userId": {
"type": "integer"
},
"firstName": {
"type": [
"string",
"null"
]
},
"lastName": {
"type": [
"string",
"null"
]
},
"username": {
"type": [
"string",
"null"
]
},
"isVirtual": {
"type": "boolean"
}
},
"required": [
"userId",
"firstName",
"lastName",
"username",
"isVirtual"
],
"additionalProperties": false
},
"participation": {
"type": "object",
"properties": {
"eventsRegistered": {
"type": "integer"
},
"eventsAttended": {
"type": "integer"
},
"gamesPlayed": {
"type": "integer"
},
"organizerCount": {
"type": "integer"
},
"eventsPerMonth": {
"type": [
"number",
"null"
]
},
"firstSeenAt": {
"type": [
"string",
"null"
]
},
"lastSeenAt": {
"type": [
"string",
"null"
]
}
},
"required": [
"eventsRegistered",
"eventsAttended",
"gamesPlayed",
"organizerCount",
"eventsPerMonth",
"firstSeenAt",
"lastSeenAt"
],
"additionalProperties": false
},
"performance": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"count": {
"type": "integer"
},
"label": {
"type": "string"
}
},
"required": [
"count"
],
"additionalProperties": false
}
},
"notes": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"identity"
],
"additionalProperties": false
}
},
"computedAt": {
"type": [
"string",
"null"
]
}
},
"required": [
"users",
"computedAt"
],
"additionalProperties": false
}