Microsoft Teams for Claude — read your chats, teams, channels, and open messages, via your browser
MCP server for Microsoft Teams — list your chats, teams and channels, and read whichever chat or channel is currently open, routed through your signed-in browser tab.
This project was developed and is maintained by AI (Claude Code). Use at your own discretion.
Teams Web's chat and message data lives only in a client-side cache fed by a
WebSocket/registrar sync channel — there is no REST or GraphQL endpoint that
returns it. So this server does not capture a token and make plain server-side
requests the way an API-backed MCP would; instead every call routes through
the fetchproxy browser bridge and
reads the DOM your signed-in teams.cloud.microsoft tab has already
rendered. teams.microsoft.com (the old host) is not supported.
That has one real consequence: this server can only read whichever chat or
channel is currently displayed in your browser tab. The bridge can fetch
and read — it cannot navigate a tab to a different conversation.
teams_list_chats and teams_list_teams_and_channels always work (their
sidebars are always rendered once that nav section is open);
teams_get_open_chat_messages and teams_get_open_channel_posts read
whatever conversation you have open. To read a different chat or channel,
open it in the browser first.
The bridge is on the request path for every call here, not just once to mint a token — unlike an API-backed MCP, there is nothing to cache between calls.
npm i -g @chrischall/microsoft-teams-mcp
Requires the Transporter Chrome extension and @fetchproxy/cli, on a
matching major version:
npm i -g @fetchproxy/cli
The first call prints a 6-digit pair code to approve in the Transporter popup; the grant persists.
opencode reads MCP servers from opencode.json (project) or
~/.config/opencode/opencode.json (global):
{
"mcp": {
"servers": {
"teams": {
"type": "local",
"command": ["npx", "-y", "@chrischall/microsoft-teams-mcp"]
}
}
}
}
Everything is optional — this server needs no credentials of its own.
| variable | purpose |
|---|---|
TEAMS_WS_PORT | fetchproxy concentrator port. Defaults to 37149, the fleet-wide shared port. |
teams_list_chats — the Chat sidebar: title, last-message preview,
last-activity time, and Teams' own conversation id for each chat.teams_get_open_chat_messages — the message thread of whichever chat is
currently open: sender, ISO-8601 time, message id, and text.teams_list_teams_and_channels — the Teams-and-Channels sidebar (a
DIFFERENT view from Chat): every team and channel the user belongs to,
with each channel's parent team name.teams_get_open_channel_posts — the top-level posts of whichever channel
is currently open: sender, subject (when present), prose time (not
ISO-8601 — Teams doesn't expose one for these), message id, and text.
Threaded replies under a post are not included.teams_get_activity — the Activity feed (the bell icon in the left nav):
mentions, replies, reactions, and the like across every chat and channel,
each with its title, message preview, prose time, and location (the
team/channel or chat it happened in). Requires the Activity view open.teams_healthcheck — verifies the bridge can reach a signed-in tab.All five data tools are read-only and take no arguments.
No Calendar tool here. Teams Web's Calendar renders inside an embedded
outlook.office.com iframe, which the fetchproxy bridge (DOM reads only
against the top-level tab, no iframe crossing) cannot reach — and isn't the
right place for it anyway. Use
office-outlook-mcp's
outlook_list_events / outlook_get_event / outlook_list_calendars
instead: real Outlook REST API calls via a captured token, with no
"must have it open" limitation at all.
sender is populated on every row regardless.text — a limitation of
bulk text extraction, not a bug.teams.cloud.microsoft tabs so only one remains.read_dom_list name not in declared set error, the extension's approved scope is behind the server's declared
one — this shouldn't happen in a released version, but if it does, revoke
and re-pair teams-mcp in the Transporter popup.npm install
npm run build
npm test # typecheck + suite
npm run test:coverage # CI's gate
This server depends on read_dom_list, a fetchproxy capability added
alongside this repo — it needs @fetchproxy/protocol/@fetchproxy/server
>= 3.1.0, the first published versions that include it
(chrischall/fetchproxy#381).
MIT
Source-derived launch command. Check the maintainer’s required arguments and credentials before running:
npx -y @chrischall/microsoft-teams-mcpMerge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.
{
"mcpServers": {
"io-github-chrischall-microsoft-teams-mcp": {
"command": "npx",
"args": [
"-y",
"@chrischall/microsoft-teams-mcp"
]
}
}
}Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.
Claude Desktop setup reference@chrischall/microsoft-teams-mcpnpmio.github.chrischall/microsoft-teams-mcp works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.