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.

ParameterTypeRequiredDescription
querystringnoFree-text fragment of the target chat name (case-insensitive substring match). Use this when the user names the chat conversationally.
platform'TELEGRAM' | 'VK'noTarget chat platform
platformChatIdstringnoPlatform-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.

ParameterTypeRequiredDescription
eventIdintegernoEvent ID. Defaults to the active event of the current chat. Required via MCP.
userIdsinteger[]noEveryone 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.

ParameterTypeRequiredDescription
entryIdintegeryesid 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).

ParameterTypeRequiredDescription
eventIdintegernoEvent 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.

ParameterTypeRequiredDescription
kind'expense' | 'income'yesexpense (money out) or income (money in)
amountintegeryesAmount in whole RUB (always positive)
labelstringyesWhat it was, e.g. "аренда поля", "манишки"
eventIdintegernoOptional: 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.

ParameterTypeRequiredDescription
userIdintegernoMember who holds the pot (uid:N)
clearbooleannoSet 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.

ParameterTypeRequiredDescription
detailsstringnoThe payment instructions in the organizer's own words. Any format: "+79119156634 Тиньков", "наличными Жене на поле", "https://qr.nspk.ru/…", or several lines.
removebooleannotrue = 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.

ParameterTypeRequiredDescription
eventIdintegernoEvent ID. Defaults to the active event of the current chat. Required via MCP.
status'confirmed' | 'unpaid' | 'waived'yesTarget status: confirmed (money received), unpaid (reset), waived (free/forgiven)
userIdsinteger[]noExplicit target users. Mutually exclusive with allExcept.
allExceptinteger[]noApply to every confirmed participant EXCEPT these users. Empty array = everyone. Mutually exclusive with userIds.
paidAmountintegernoExact 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.

ParameterTypeRequiredDescription
eventIdintegeryesID 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.

ParameterTypeRequiredDescription
eventIdintegeryesEvent 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.

ParameterTypeRequiredDescription
datestringnoEvent date/time in ISO 8601 format.
titlestringnoOptional 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.

ParameterTypeRequiredDescription
eventIdintegeryesEvent 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.

ParameterTypeRequiredDescription
eventIdintegerno
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.

ParameterTypeRequiredDescription
archivedbooleannoIf true, returns archived events instead of active ones.
cursorstringnoOpaque pagination cursor from a previous response.
limitintegernoPage 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.

ParameterTypeRequiredDescription
eventIdintegernoEvent 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.

ParameterTypeRequiredDescription
eventIdintegeryesEvent ID
featurestringyesFeature key, e.g. "payment", "max_players", "deadline"
configobjectnoFeature configuration object
removebooleannoSet 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.

ParameterTypeRequiredDescription
scheme'sequential' | 'weekday' | 'date'yesNaming preset to apply
labelstringnoWord 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.

ParameterTypeRequiredDescription
eventIdintegeryesEvent ID
titlestring | nullnoNew title. Null clears the title; omit to keep current.
descriptionstring | nullnoNew description. Null clears it; omit to keep current.
datestringnoNew 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.

ParameterTypeRequiredDescription
eventIdintegeryesEvent ID
idstringyessnake_case identifier, e.g. "goal", "three_pointer"
labelstringyesDisplay label, e.g. "Гол", "Трёхочковый"
emojistringnoOptional emoji, e.g. "⚽"
colorstringnoOptional hex color, e.g. "#FF3B30"
scoreDeltanumbernoScore impact: always positive or 0. Direction controlled by scoreTarget
requiresTeambooleannoWhether team selection is required when logging this event
requiresPlayerbooleannoWhether player selection is required when logging this event
timeEffect'start' | 'pause' | 'reset'noTimer effect: start — start/resume, pause — pause, reset — reset to 0
scoreTarget'self' | 'opponent'noWhich 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.

ParameterTypeRequiredDescription
eventIdintegeryesEvent ID
typeIdstringyesEvent type id from the catalog, e.g. "goal", "foul", "timer_pause"
badgeNumintegernoPlayer badge number (stable per registration)
playerNamestringnoPlayer name exactly as in the roster; used when badgeNum is unknown
teamIdintegernoTeam 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.

ParameterTypeRequiredDescription
eventIdintegeryesEvent ID
localIdstringnolocalId 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.

ParameterTypeRequiredDescription
eventIdintegeryesEvent ID
gameIdintegernoOptional: 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.

ParameterTypeRequiredDescription
eventIdintegeryesEvent 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.

ParameterTypeRequiredDescription
eventIdintegeryesEvent 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.

ParameterTypeRequiredDescription
eventIdintegeryes
scoringMode'GOAL_TIMER' | 'WEIGHTED_TIMER' | 'SET_POINT' | 'RACE_TO' | 'ROUND_JUDGE'no
participantFormat'team_vs_team' | '1v1' | '2v2' | '3v3'no
setConfigobjectno
timerConfigobjectno
finishConditionobjectno

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 ("кто хорошо играет в защите").

ParameterTypeRequiredDescription
querystringyesWhat to recall, in natural language.
userIdintegernoNarrow 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.

ParameterTypeRequiredDescription
userIdintegeryesPlayer the fact is about (from findChatUsers).
textstringyesThe 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.

ParameterTypeRequiredDescription
textstringnoOptional 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.

ParameterTypeRequiredDescription
eventIdintegeryesEvent ID
presetIdstringyesPreset id from the catalog (e.g. "football", "volleyball", "table_tennis", "mma"). Legacy ids resolved via aliases.
setsToWinintegernoOverride setConfig.setsToWin for SET_POINT presets
pointsToWinSetintegernoOverride setConfig.pointsToWinSet for SET_POINT presets
periodMinutesnumbernoOverride timerConfig.periodMinutes for timed presets
periodsintegernoOverride timerConfig.periods (number of halves/quarters/periods)
participantFormat'team_vs_team' | '1v1' | '2v2' | '3v3'noOverride participantFormat (e.g. 2v2 for badminton doubles)
targetScoreintegernoOverride 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).

ParameterTypeRequiredDescription
scoringMode'GOAL_TIMER' | 'WEIGHTED_TIMER' | 'SET_POINT' | 'RACE_TO' | 'ROUND_JUDGE'noFilter 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.

ParameterTypeRequiredDescription
eventIdintegeryes
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.

ParameterTypeRequiredDescription
eventIdintegernoEvent ID. Required when calling via MCP.
asReservebooleannoSet 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.

ParameterTypeRequiredDescription
eventIdintegernoEvent ID. Required when calling via MCP.
notestringnoReason 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.

ParameterTypeRequiredDescription
eventIdintegernoEvent ID. Required when calling via MCP.
userIdintegernoUser ID from findChatUsers result
guestNamestringnoName to search among existing users. Returns candidates if similar users found. Agent-only.
confirmedNewNamestringnoCreate virtual user with this name. Only after guestName search was done and organizer confirmed new person. Agent-only.
asReservebooleannoSet 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.

ParameterTypeRequiredDescription
eventIdintegernoEvent ID. Defaults to the active event of the current chat. Required via MCP.
badgeNumintegernoBadge number of the guest to rename (preferred).
userIdintegernoOr the guest userId.
newNamestringyesNew 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.

ParameterTypeRequiredDescription
eventIdintegernoEvent ID. Defaults to the active event of the current chat. Required via MCP.
userIdsinteger[]noFlat ordered lineup: array position = badge order. Existing users/guests only. Mutually exclusive with `teams`.
teamsobject[]noGrouped lineup: registers everyone (badge order = concatenation of the groups) and REPLACES the event teams with these named teams. Mutually exclusive with `userIds`.
removeMissingbooleannoCancel 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.

ParameterTypeRequiredDescription
eventIdintegernoEvent ID. Required when calling via MCP.
badgeNumintegernoBadge number of the player. Provide badgeNum or userId.
userIdintegernoUser ID (from findChatUsers). Provide badgeNum or userId.
status'confirmed' | 'waiting'yesNew 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.

ParameterTypeRequiredDescription
eventIdintegernoEvent ID. Required when calling via MCP.
userIdintegeryesUser ID of the player to unregister
notestringnoReason 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.

ParameterTypeRequiredDescription
idintegeryesScheduledPrompt 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.

ParameterTypeRequiredDescription
promptstringyesThe instruction to run later, phrased as a direct command to the agent.
atstringnoOne-shot absolute fire time, ISO 8601 (e.g. 2026-05-30T19:00:00+03:00).
recurrenceobjectnoRecurring 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.

ParameterTypeRequiredDescription
includeMoneybooleannoExpose 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.

ParameterTypeRequiredDescription
urlstringyesThe 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.

ParameterTypeRequiredDescription
eventIdintegeryesEvent ID
labelstringnoShort name so several links on one game stay tellable apart
maxSignupsintegernoAnti-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).
autoApprovebooleannofalse = every sign-up waits for the organizer to approve it
guestsPerUserintegernoHow many guests one person may bring; 0 = none
showRosterbooleannoPublish participant names on the card, or only the headcount
deadlineAtstringnoISO 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.

ParameterTypeRequiredDescription
eventIdintegeryesEvent 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.

ParameterTypeRequiredDescription
eventIdintegeryesEvent 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.

ParameterTypeRequiredDescription
badgeNumintegernoParticipant badge number (shown as [#N] in the event snapshot and getRegistrations). Provide badgeNum or userId.
userIdintegernoUser ID (from findChatUsers or registerFor result). Provide badgeNum or userId.
eventIdintegeryesEvent ID
toTeamIdintegernoTarget 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.

ParameterTypeRequiredDescription
teamMemberIdintegeryesTeamMember ID
rolestringnoRole 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.

ParameterTypeRequiredDescription
eventIdintegeryesEvent ID
teamCountintegernoNumber of teams for random split (default: 2)
strategy'random' | 'manual'noDistribution strategy (default: random)
teamsobject[]noRequired when strategy is "manual"
confirmbooleannoRequired (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.

ParameterTypeRequiredDescription
userIdintegernoA single user (from findChatUsers).
userIdsinteger[]noSeveral users at once.
include'participation' | 'performance' | 'memory'[]noWhich 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
}