---
name: gsk-microsoft-teams
version: 1.0.0
description: 'Microsoft Teams operations. Actions: send, list_channels, list_chats,
  read_chat, list_channel_messages, list_channel_replies, list_teams, list_members,
  search, search_users, create_chat, create_team, react, delete_message, update_message,
  download_attachment, mark_chat_read, api, upload.'
metadata:
  category: general
  requires:
    bins:
    - gsk
  cliHelp: gsk teams --help
---

# gsk-microsoft-teams

**PREREQUISITE:** Read `../gsk-shared/SKILL.md` for auth, global flags, and security rules.

> **Note:** a unified `gsk connector` flow is rolling out (see `../gsk-connector/SKILL.md`: `gsk connector tools <id>` / `gsk connector call <id> -t <tool>`) and may not be enabled for every account yet. THIS command remains fully supported — use it directly, and it stays the fallback whenever `gsk connector` is unavailable.

Microsoft Teams operations. Actions: send, list_channels, list_chats, read_chat, list_channel_messages, list_channel_replies, list_teams, list_members, search, search_users, create_chat, create_team, react, delete_message, update_message, download_attachment, mark_chat_read, api, upload.

## Usage

```bash
gsk teams [options]
```

**Aliases:** `teams`

## Flags

| Flag | Required | Description |
|------|----------|-------------|
| `<action>` (positional) | Yes | Action to perform. 'send': Send a message in Teams (reply_to_message_id replies in a channel thread or quotes a chat message). Confirmation-gated: on a CLI with client-side confirmation the command runs as a single call after the [y/N] prompt (or --yes).; 'list_channels': List hosted and shared channels for an associated team; 'list_chats': List recent chats; 'read_chat': Read a chat's recent messages by chat_id; 'list_channel_messages': List root messages in a channel; one traversal is not a deletion snapshot; 'list_channel_replies': List replies to a channel message; one traversal is not a deletion snapshot; 'download_attachment': Download one attachment or inline hosted image from a message; returns a file URL; 'mark_chat_read': Mark a chat as read for the connected user (clears its unread badge; own read state only); 'api': Raw Graph call with the connected account, for resources the typed actions do not cover; GET immediate, writes held for confirmation. Confirmation-gated: on a CLI with client-side confirmation the command runs as a single call after the [y/N] prompt (or --yes). Not confirmation-gated when method is GET (also the default when method is omitted): those values run immediately (no prompt, no pending_confirmation step).; 'list_teams': List direct teams and shared-channel host teams; 'search': Search messages; 'search_users': Search for users; 'create_chat': Create a new chat; 'react': Emoji-react to a chat or channel message (or remove your reaction). Confirmation-gated: on a CLI with client-side confirmation the command runs as a single call after the [y/N] prompt (or --yes).; 'upload': Share a file into a chat (uploads to the sender's OneDrive Teams folder, posts a file card). Confirmation-gated: on a CLI with client-side confirmation the command runs as a single call after the [y/N] prompt (or --yes).; 'list_members': List ALL members of a team with roles and emails (full roster, internally paginated); 'create_team': Create a new team (you become owner) and optionally add members by email; 'delete_message': Soft-delete one of your own messages (chat, channel, or threaded reply). Confirmation-gated: on a CLI with client-side confirmation the command runs as a single call after the [y/N] prompt (or --yes).; 'update_message': Edit the body of one of your own messages (chat, channel, or threaded reply). Confirmation-gated: on a CLI with client-side confirmation the command runs as a single call after the [y/N] prompt (or --yes). (string, one of: send, list_channels, list_chats, read_chat, list_channel_messages, list_channel_replies, download_attachment, mark_chat_read, api, list_teams, search, search_users, create_chat, react, upload, list_members, create_team, delete_message, update_message) |
| `--content` | No | [send] The message content to send. Accepts either Markdown or HTML. Markdown (e.g. '## Heading', '**bold**', '- item', tables) is automatically rendered to formatted HTML. You may also pass raw HTML directly: <a href='URL'>text</a> for links, <b>text</b> for bold, <i>text</i> for italic, <br> for line breaks, and other standard HTML tags. INLINE IMAGES are supported: embed <img src="data:image/png;base64,..."> (any image/* data URI) and the bytes are automatically relocated into Microsoft Graph hostedContents so the image renders in the message — no manual Graph calls needed. 'message' is accepted as an alias for this parameter. How this text is rendered is governed by content_format; declare it explicitly when the text could be mistaken for markup (code, '#'-prefixed lines, '**'). \| [upload] Text content to upload as a file (UTF-8). Provide exactly one of 'content' or 'file_path'. \| [update_message] New message body that REPLACES the current one. Accepts Markdown, plain text, or HTML; rendering is governed by content_format. Inline data-URI images are not supported on edit; use send for new images. 'message' is accepted as an alias for this parameter. (string) |
| `--content_format` | No | [send] Declares how 'content' should be rendered — the server cannot reliably guess (a Python comment and a Markdown heading are byte-identical). 'plain': send the text literally, nothing is interpreted as markup — use this for code snippets or any text containing '#', '**', '\|' etc. that must appear verbatim. 'markdown': always render Markdown to formatted HTML. 'html': send the content as authored HTML unchanged. 'auto' (default): legacy guessing — HTML-looking content passes through, anything else renders as Markdown. \| [update_message] Declares how 'content' should be rendered -- the server cannot reliably guess. 'plain': render the text literally, nothing is interpreted as markup. 'markdown': always render Markdown to formatted HTML. 'html': send the content as authored HTML unchanged. 'auto' (default): HTML-looking content passes through, anything else renders as Markdown. (string, one of: auto, plain, markdown, html, default: `auto`) |
| `--chat_id` | No | [send] Optional chat ID to send the message to. If not specified or set to 'self', sends to yourself as a DM. Use chat IDs from microsoft_teams_search_messages results. \| [read_chat] The Teams chat ID (e.g. '19:...@thread.v2'). Required. \| [download_attachment] Chat ID ('19:…@thread.v2') for a chat message. Mutually exclusive with team_id/channel_id. \| [mark_chat_read] Chat ID ('19:…@thread.v2') to mark as read, from microsoft_teams_list_chats. \| [react] ID of the chat containing the message. Provide either chat_id, or team_id + channel_id for a channel message. \| [upload] Target chat ID (e.g. '19:…@thread.v2', from list_chats/search_users). \| [list_members] Chat ID ('19:…@thread.v2') to list a group chat's or DM's members instead of a team's. \| [delete_message] ID of the chat containing the message. Provide either chat_id, or team_id + channel_id for a channel message. \| [update_message] ID of the chat containing the message. Provide either chat_id, or team_id + channel_id for a channel message. (string) |
| `--channel_type` | No | [send] Type of channel: 'teams_chat' for 1:1 or group chats, 'teams_channel' for team channels. Default: 'teams_chat' (string, one of: teams_chat, teams_channel) |
| `--team_id` | No | [send] Required if channel_type is 'teams_channel'. The team ID where the channel belongs. \| [list_channels] Associated team ID from list_teams. \| [list_channel_messages] Host team ID from the selected list_channels result (host_team_id). \| [list_channel_replies] Host team ID from the selected list_channels result (host_team_id). \| [download_attachment] Team ID (GUID) for a channel message; requires channel_id. \| [react] Team ID, for reacting to a channel message (together with channel_id). \| [list_members] ID of the team to list members of. Mutually exclusive with chat_id. \| [delete_message] Team ID, for deleting a channel message (together with channel_id). \| [update_message] Team ID, for editing a channel message (together with channel_id). (string) |
| `--channel_id` | No | [send] Required if channel_type is 'teams_channel'. The channel ID within the team. \| [list_channel_messages] Channel ID from the same selected list_channels result. \| [list_channel_replies] Channel ID from the same selected list_channels result. \| [download_attachment] Channel ID ('19:…@thread.tacv2') for a channel message; requires team_id. \| [react] Channel ID, for reacting to a channel message (together with team_id). \| [delete_message] Channel ID, for deleting a channel message (together with team_id). \| [update_message] Channel ID, for editing a channel message (together with team_id). (string) |
| `--importance` | No | [send] Message importance level that controls notification behavior. 'normal': Regular message, no special notification (default). 'high': Triggers notification without special emphasis. 'urgent': Triggers immediate notification with sound and alert. Default: 'normal' (string, one of: normal, high, urgent) |
| `--notify` | No | [send] Whether to force notification by @mentioning yourself in the message. When true, adds a self-mention to ensure notification is triggered. Useful when sending reminders to yourself. Default: true (boolean) |
| `--mention_user_ids` | No | [send] List of user IDs (GUIDs) to @mention in the message. Use search_users to find user IDs first. The message content should include {mention_N} placeholders where N is the index (0-based), e.g., '{mention_0} thank you' will @mention the first user in the list. (array) |
| `--mention_user_names` | No | [send] Display names for mentioned users, in same order as mention_user_ids. If not provided, will use user IDs as display names. (array) |
| `--reply_to_message_id` | No | [send] Optional ID of an existing message to reply to. For team channels: posts this message as a threaded reply under that root message. For chats: renders a quoted block of the referenced message above your text (like the Teams client's Reply action). Message IDs come from microsoft_teams_read_chat / microsoft_teams_list_channel_messages. \| [download_attachment] For a channel reply: the ROOT message ID the reply belongs to. (string) |
| `--cursor` | No | [list_channels] Opaque next_cursor from the previous page. \| [list_chats] Pagination cursor returned in a previous response's ``next_cursor`` field. Pass it back verbatim to fetch the next page; omit on the first call. \| [read_chat] Pagination cursor from a previous response's ``next_cursor``; omit on the first call. \| [list_channel_messages] Opaque next_cursor from the previous page. \| [list_channel_replies] Opaque next_cursor from the previous page. \| [list_teams] Opaque next_cursor from the previous page. \| [search] Pagination cursor returned in a previous response's ``next_cursor`` field. Pass it back verbatim to fetch the next page; omit on the first call. Stop paging as soon as the returned hits satisfy your need. (string) |
| `--topic` | No | [list_chats] Search for chats by topic/name (case-insensitive partial match). Use this to find a specific group chat by its name. Example: 'WorkflowTest' to find a chat with that topic. Filter is applied per-page; if no match on the current page, use ``next_cursor`` to keep searching. \| [create_chat] Topic/name for the group chat. Required for group chats (2+ members), ignored for 1:1 chats. (string) |
| `--chat_type` | No | [list_chats] Filter by chat type. 'oneOnOne' for 1:1 chats, 'group' for group chats, 'meeting' for meeting chats, 'all' for all types. Default: 'all' (string, one of: oneOnOne, group, meeting, all) |
| `--count` | No | [list_chats] Maximum number of chats to return on this call (page size, clamped to [1, 50]). Default: 50. To fetch beyond a single page, use the ``cursor`` argument with the previous response's ``next_cursor``. \| [search] The maximum number of messages to return on this call (page size, clamped to [1, 25]). Default: 25. To fetch beyond a single page, use the ``cursor`` argument with the previous response's ``next_cursor``. \| [search_users] Maximum number of users to return. Default: 10 (integer) |
| `--limit` | No | [read_chat] Maximum messages to return on this call (clamped to [1, 50]). Default: 30. To fetch beyond a page, pass the previous response's ``next_cursor`` as ``cursor``. \| [list_channel_messages] Messages in this page, clamped to 1-50. Default: 30. \| [list_channel_replies] Messages in this page, clamped to 1-50. Default: 30. (integer) |
| `--since` | No | [read_chat] Optional ISO-8601 floor (e.g. '2026-05-01T00:00:00Z'); only messages created or modified at or after this instant are returned. \| [search] Optional ISO-8601 floor (e.g. '2026-05-01' or '2026-05-01T00:00:00Z'); only messages created at or after this instant are returned. (string) |
| `--message_id` | No | [list_channel_replies] Root channel message ID whose replies should be listed. \| [download_attachment] The message ID holding the attachment (for a channel reply: the reply's own ID). \| [react] ID of the message to react to. \| [delete_message] ID of the message to delete. \| [update_message] ID of the message to edit. (string) |
| `--hosted_content_id` | No | [download_attachment] hostedContents item ID — for inline images pasted into the message. (string) |
| `--attachment_id` | No | [download_attachment] Attachment ID from the message's attachments list — for file attachments with a contentUrl. (string) |
| `--path` | No | [api] Graph resource path starting with '/', query string allowed, e.g. '/me/chats?$top=5'. Passed through verbatim — percent-encode segment values yourself. (string) |
| `--graph_version` | No | [api] Graph API version. Default v1.0; 'beta' is an explicit opt-in. (string, one of: v1.0, beta) |
| `--method` | No | [api] HTTP method. Default GET (omitting it runs immediately). Write methods are held for user confirmation before executing. (string, one of: GET, POST, PATCH, PUT, DELETE, default: `GET`) |
| `--body` | No | [api] JSON request body for write methods (object or array, passed to Graph verbatim). Not allowed on GET. (string) |
| `--query` | No | [search] The search query using KQL (Keyword Query Language). **Query Behavior**: • Spaces = AND: 'project meeting' finds messages with BOTH terms • OR operator: 'project OR meeting' finds messages with EITHER term • KQL modifiers: 'from:john', 'hasAttachment:true', 'IsRead:false' • Date filters: prefer the ``since``/``until`` arguments; inline date ops ('sent>=2026-02-01 sent<=2026-03-05', 'sent:2026-02-01..2026-03-05') are also honored — both bounds are enforced • Examples: 'urgent project', 'bug OR issue', 'from:alice budget', 'hasAttachment:true report' \| [search_users] Search query - can be a name, email, or partial match. Example: 'John', 'john@company.com', 'Smith' (string) |
| `--unread_only` | No | [search] Set to true to search for unread messages only. Default is false. (boolean) |
| `--question` | No | [search] A specific question to answer based on the search results. (string) |
| `--raw` | No | [search] Return structured JSON (``{success, count, messages, next_cursor}`` with the same message fields as ``microsoft_teams_read_chat``) instead of an LLM-summarized prose digest. ``success: false`` with ``error`` on failure, so callers can tell an empty result from an error. Default false. (boolean) |
| `--until` | No | [search] Optional ISO-8601 ceiling; only messages created at or before this instant are returned. Combine with ``since`` for a window. (string) |
| `--order` | No | [search] Result ordering. 'recency' (default) sorts the returned hits newest-first by timestamp; 'relevance' preserves Graph's relevance ranking. (Graph can't recency-rank chatMessage server-side, so this sorts the relevance-selected page client-side — pair with ``since``/``until`` to target a window.) (string, one of: recency, relevance) |
| `--include_chat_id` | No | [search_users] If true, also return the chat_id for existing 1:1 chats with each user. This allows direct messaging without create_chat. Default: true (boolean) |
| `--member_emails` | No | [create_chat] List of email addresses of users to add to the chat. One email for 1:1 chat, multiple for group chat. \| [create_team] Emails of org users to add as members (the creator is the owner and must not be listed). Unresolvable emails are reported in members_failed without failing the creation. (array) |
| `--reply_id` | No | [react] Optional: ID of a threaded reply under the channel message identified by message_id — reacts to that reply instead. Channel target only. \| [delete_message] Optional: ID of a threaded reply under the channel message identified by message_id — deletes that reply instead. Channel target only. \| [update_message] Optional: ID of a threaded reply under the channel message identified by message_id -- edits that reply instead. Channel target only. (string) |
| `--reaction` | No | [react] The emoji to react with, as a unicode character (e.g. '👍', '❤️', '😂'). (string) |
| `--remove` | No | [react] Set true to remove your existing reaction of this emoji instead of adding it. Default: false. (boolean) |
| `--file_path` | No | [upload] File to upload: a local server file path, a Genspark file-wrapper URL (https://…/api/files/s/<code>), or an AI Drive path (aidrive://…). Provide exactly one of 'content' or 'file_path'. (string) |
| `--file_name` | No | [upload] File name shown in Teams (include the extension). Required with 'content'; defaults to the path basename for 'file_path'. (string) |
| `--message` | No | [upload] Optional message text posted together with the file card. (string) |
| `--display_name` | No | [create_team] Name of the new team. (string) |
| `--description` | No | [create_team] Optional team description. (string) |
| `--visibility` | No | [create_team] Team visibility. Default: 'private'. (string, one of: private, public) |

## Write Confirmation

Confirmation-gated actions: `send`, `api` (except `method=GET` or `method` omitted, which runs immediately), `react`, `upload`, `delete_message`, `update_message`. An action marked `(except <param>=<values>)` is gated only for the other values of that argument — the listed values run immediately with no prompt and no confirmation step. The CLI shows a preview and asks `[y/N]` on stderr before the single server call; pass `--yes` (`-y`) for unattended runs. `--no-input` (or `--args-file -`, which consumes stdin) makes a gated call exit 2 with no server call instead of hanging. Never re-run a command to 'confirm' it — every call is a real execution. `--skip_confirmation true` / `--auto_skip_confirmation` are deprecated on this CLI (still accepted, warn on stderr): use `--yes`.

## See Also

- [gsk-shared](../gsk-shared/SKILL.md) — Authentication and global flags
