create_meeting_template
ChatGPTCreates a new meeting template (also creates its first editable draft version). Add sections to the draft with upsert_template_section, then publish it with publish_template_version — only published versions are used for summaries. Scope "directory" (organization-wide) requires admin/owner; "personal" (default) or "team" otherwise. Requires mcp:write.
delete_task
ChatGPTDeletes one of the authenticated user's own tasks by id (soft delete). Rejected if the task is not the user's own. Requires mcp:write.
delete_vocabulary
ChatGPTDeletes a vocabulary term by id. Organization-wide terms can only be deleted by admins/owners; personal terms only by their owner. Requires the mcp:write scope.
draft_template_version
ChatGPTCreates a new editable draft version of an existing template, based on a published version (get the template + its versions via get_meeting_template first). Edit its sections, then publish. Requires mcp:write.
get_appointment
ChatGPTGet one appointment by its Sally appointment id, including whether the signed-in user may change it (canModify) and, if not, the reason (e.g. not the organizer, or the calendar type is not yet supported for changes). Use this before attempting a reschedule/cancel so you can explain up front what is possible.
get_document_settings
ChatGPTReturns the organization's EFFECTIVE document/export settings for the signed-in user, so you can build a document (protocol, summary export, etc.) that matches the account style. Values already merge the org defaults with the user's personal overrides (the same result a real download would use). Content-relevant: detailLevel (how verbose to write summary/tasks), attendeeDisplay (how to render attendees), downloadRestrictions (true = that output must NOT be offered as a download). Rendering-relevant (apply when you build the file yourself): font (name + CSS family/fallback), colors (headerText/bodyText hex), logo (position + image URLs; rightMode none/sally-default/custom), footer (sectionCount + section texts), pageNumbers. Image URLs are ready-to-fetch (/api/v1/File/{id}/File). Read-only, no mcp:write required.
get_folder
ChatGPTReturns ONE recording folder by its id — name, description, owner, number of recordings and how it is shared. Use this whenever you were given a folder id instead of scanning list_folders. The recordings INSIDE the folder come from list_folder_recordings. Returns a not-found error if the token holder has no access.
get_meeting_template
ChatGPTReturns a meeting template with its versions and sections (the editable detail). Pass an optional versionId to inspect a specific version; otherwise the draft/current version is returned. Read the section type/output/detail codes here to reuse them in upsert_template_section.
get_recording
ChatGPTReturns ONE recording by its id — title, creation time, duration, the linked appointment, the pipeline state (sallyStatus) and every language version of its summary. Use this whenever you were given a recording id (for example because the user has that recording open). Do NOT load get_recordings and search the list for it, and never match by name. From here, get_summary(recordingId) gives the summary and get_transcription(recordingId) the transcript. Returns a not-found error if the token holder has no access.
get_recordings
ChatGPTLists recordings the authenticated user can see — i.e. recordings they own, recordings of appointments where they are the technical owner, and recordings in RecordingFolders shared with them (directly or via team membership). User and organization are derived from the Personal Access Token; no parameters are required. For each recording the response returns — if available — the appointment ID and its time window as well as all available summaries with their language codes. Paginated via page/pageSize (max 100), sorted by creation date descending.
get_summary
ChatGPTReturns a summary identified by its recordingSummaryId. With includeDetails=false (default) only the summary text is returned. With includeDetails=true the response additionally contains key facts, decisions, items, AI suggestions for follow-up tasks (taskSuggestions), real tracked tasks (tasks) and custom insights (all language-specific, matching the summary's language). Two task-like arrays are returned and they are NOT the same: taskSuggestions are Sally's AI-extracted proposals from the meeting — they are not tracked work until the user accepts them. tasks are real, user-tracked tasks attached to the meeting (either created from a suggestion or directly) and carry status flags isDone/doneOn/isCanceled/canceledOn. A suggestion that the user already turned into a task has referencedTaskId set, and the corresponding entry in tasks carries taskSuggestionId pointing back to the suggestion. To answer 'what are my open tasks?': use tasks filtered by isDone=false && isCanceled=false; suggestions without referencedTaskId can be surfaced separately as proposals the user hasn't acted on yet. Returns a not-found error if the token holder has no access.
get_task
ChatGPTReturns one of the authenticated user's own tasks by id. Returns a not-found error if the task does not exist or does not belong to the user.
get_transcription
ChatGPTReturns the full transcript of a recording as plain text in the format '[mm:ss] Speaker: ...\n\n[mm:ss] Speaker: ...' — each speaker segment starts with its offset from the beginning of the recording. With includeDetails=true an additional 'segments' array is returned containing per-segment speakerName, text, startTimeInSeconds, endTimeInSeconds and the formatted timestamp. Returns a not-found error if the token holder has no access.
list_folder_recordings
ChatGPTLists the recordings contained in one recording folder, identified by its folderId (get it from list_folders). For each recording it returns the title, duration, whether it is a manual upload, the linked appointment (if the user has an own copy) and all available summaries with their recordingSummaryId + language code — pass a recordingSummaryId to get_summary or the recordingId to get_transcription. Returns a not-found error if the folder does not exist or the user has no access to it. Recording folders are a Pro/Enterprise feature. Read-only, no mcp:write required.
list_folders
ChatGPTLists the recording folders the authenticated user can access — their own folders plus folders shared with them directly or through a team. Folders group recordings; each entry carries its recordingsCount, owner and parent (folders form a tree via parentFolderId). Optional search filters by folder name (case-insensitive substring). Take a folderId from a result and pass it to list_folder_recordings to see the recordings inside. Recording folders are a Pro/Enterprise feature — the tool returns an error if the account has no access. Read-only, no mcp:write required.
list_languages
ChatGPTLists the languages Sally supports, each with its languageId (UUID), iso6391 ("es"), ietfTag ("es-ES") and English name. Use it to resolve a language to the languageId for upsert_vocabulary or transcribe_audio_from_url. (You can also pass languageCode directly to those tools instead of resolving here.) Read-only, no mcp:write required.
list_meeting_templates
ChatGPTLists the meeting templates available to the user (their personal, team and organization templates). Use get_meeting_template for the full detail including versions and sections.
list_tasks
ChatGPTLists the authenticated user's OWN tasks (tasks where they are the responsible person or the owner). Never returns other users' tasks. Filter with status: "open" (default), "overdue", "completed", or "all". Optional search matches the subject (case-insensitive).
list_vocabulary
ChatGPTLists the vocabulary (custom terms that improve transcription accuracy) available to the user: their own personal terms plus all organization-wide terms. Organization-wide terms are visible to everyone but editable only by admins/owners.
publish_template_version
ChatGPTPublishes a draft template version. Only after publishing does Sally use the version for meeting summaries. Requires mcp:write.
schedule_sally_for_meeting
ChatGPTSchedules Sally to join and record an online meeting, given its join link and a start time. Creates a calendar appointment for the authenticated user with recording enabled so the meeting bot joins at the start time. Supported providers: Microsoft Teams, Zoom, Google Meet, Webex. Returns a clear error if the link is not a supported meeting URL, if end is before start, or if the user has no active recording license/trial. Requires the mcp:write scope.
search_appointments
ChatGPTSearches appointments in the current Sally organization. At least one of subject, participant, startDate or endDate must be provided. Filters combine with AND. TEXT MATCHING (subject, participant.name): - Full-text search with automatic prefix expansion (case-insensitive). Each word you pass is matched as 'word*', so 'mark' finds 'Marketing', 'kick' finds 'Kickoff'. - Stemming + synonyms are applied via SQL Server FREETEXT, so 'meetings' also matches 'meeting'. - Multiple words combine with AND: 'kickoff marketing' matches appointments whose subject contains BOTH a word starting with 'kickoff' AND a word starting with 'marketing'. - Pass only content words, skip filler like 'my', 'last', 'the'. The LLM should extract the essential tokens from the user's natural-language question and pass them here. TIME SEMANTICS — CRITICAL: - Results are sorted by StartTime DESC (newest first). The sort includes FUTURE-dated appointments — without a date filter, calendar entries scheduled for tomorrow rank higher than yesterday's completed meeting. - For 'last', 'previous', 'recent', 'most recent' or any other question about a meeting that has ALREADY HAPPENED: pass endDate=<current UTC timestamp> so future-dated calendar entries are excluded. Without this, the tool returns the next upcoming meeting instead of the most recent past one. - For 'next', 'upcoming' or 'on my calendar' (about a meeting that is STILL AHEAD): pass startDate=<current UTC timestamp> and pageSize larger than 1, then pick the entry with the smallest StartTime from the returned list (the sort is DESC, so the upcoming one closest to now is at the END of the page). HOW TO MAP NATURAL-LANGUAGE QUERIES: - 'my last meeting with Mario' → participant='Mario', endDate=<now>, pageSize=1. - 'my next meeting with Mario' → participant='Mario', startDate=<now>, pageSize=50, then take the meeting with the smallest StartTime. - 'kickoff meetings in the last 30 days' → subject='kickoff', startDate=<today-30d>, endDate=<now>. - 'appointments with someone from @acme.com' → participant='@acme.com' (email uses LIKE match, so substrings work here). - 'all of Mario's marketing calls' → subject='marketing', participant='Mario'. LIMITS: - subject: min 3 characters. participant: min 2 characters. - Results sorted by StartTime DESC (newest first; includes future). See TIME SEMANTICS above for past-vs-future handling. Use pageSize=1 for 'latest/last' WITH endDate set. - Returns only appointments the token holder has access to (own appointments as technical owner, or through recording-folder sharing). Each result includes participants (name, email, invitation and attendance status) and all associated recordings with their RecordingSummary IDs and language codes.
search_people
ChatGPTResolve a person by name (or partial name, or email) to their email address, so you can add them as an attendee in create_appointment. Searches the signed-in user's colleagues (members of their organization) and people they have had appointments with. Returns candidates with name, email and source ("colleague" or "participant"). ALWAYS use this when the user names an attendee without giving an email (e.g. "schedule a meeting with Yanick"): call search_people first, then pass the matching candidate's email in attendees. If there are several matches, ask the user which one; if there are none, tell the user you could not find that person and ask for their email address.
search_summaries
ChatGPTFull-text search across meeting summary texts. Use this when the user asks which meetings discussed a topic, e.g. 'which calls mentioned pricing Q1?' or 'when did we talk about the supplier change?'. Returns summary hits with a short snippet, the linked appointment (subject + startTime) and language. Pass the essential content words from the user's question as query. Words are matched with prefix-expansion (so 'pric' finds 'pricing') and stemming (so 'plans' finds 'planning'). Multiple words combine with AND. Typical follow-up: take recordingSummaryId from a promising hit and call get_summary (optionally with includeDetails=true) for the full content. Filters: languageCode (ISO-639-1 like 'en', 'de') restricts to summaries in that language — prefer this to match the user's own language. startDate/endDate filter by summary creation date (UTC, ISO-8601, inclusive). Results are sorted by creation date descending.
search_transcripts
ChatGPTSearches the verbatim transcripts of the recordings the user can see. Use this when the user asks whether or when something was SAID, needs an exact quote, or when search_summaries found nothing: a summary condenses the meeting, so a term that was only mentioned in passing is often only in the transcript. Returns one hit per recording with the number of matching lines and the first five of them (timestamp, speaker, excerpt). How matching works (identical in the Public API summary search): the query is split into words, filler words are dropped, and a hit needs ANY of the remaining words (OR). Words of four or more characters also match inside longer words and in their inflected forms (e.g. 'Festgeldkonten' finds 'Festgeldkonto', 'Konto' finds 'Festgeldkonto'); words of up to three characters must stand as a whole word ('KI' does not match 'Kinder'). Umlaut spellings are interchangeable ('Müller' = 'Mueller'). Case is ignored. Searches the 2,000 most recent recordings in the date range (the 2,000 oldest with orderDirection=asc). For older meetings set startDate/endDate, which filter by recording creation date (UTC, ISO-8601, inclusive). Recordings are sorted by creation date (default newest first). Typical follow-up: call get_transcription with the recordingId for the full context around a match, or get_summary for the condensed result.
set_task_done
ChatGPTMarks one of the authenticated user's own tasks as done (isDone=true) or reopens it (isDone=false). Rejected if the task is not the user's own. Requires mcp:write.
transcribe_audio_from_url
ChatGPTDownloads an audio or video file from an https URL, stores it as a recording and transcribes it (transcription + summary run asynchronously afterwards). Only https URLs to a public host are accepted — internal/loopback/metadata addresses, URLs with credentials and redirects are rejected for security. Supported types: mp4/mkv/avi/mov/webm and mp3/wav/flac/ogg/amr/m4a/opus/aac. Returns a clear error if the user has no active recording license/trial or the transcription quota is exhausted. Requires mcp:write.
upsert_task
ChatGPTCreates a new task (omit id) or edits an existing OWN task (pass its id). The task is always assigned to the authenticated user as the responsible person — you CANNOT create or assign a task for another user through this tool. Editing another user's task is rejected. Requires the mcp:write scope.
upsert_template_section
ChatGPTCreates (omit id) or edits (pass id) a section of a template DRAFT version. The section type, output-format and detail-level are numeric platform codes — the simplest way to get valid values is to copy them from an existing template via get_meeting_template. Requires mcp:write.
upsert_vocabulary
ChatGPTCreates a new vocabulary term (omit id) or edits an existing one (pass id). A term is a word or name Sally should recognize better when transcribing. Set isOrganizationWide=true to apply it to the whole organization — that requires admin/owner rights; personal terms (the default) can be created and edited by any user. Requires the mcp:write scope.