teams-reader
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@teams-readersearch my Teams chats for the release timeline"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
teams-reader
Read your own Microsoft Teams chats from the new Teams (v2) desktop app's local cache (and, optionally, the Teams web session) into a searchable SQLite store, and expose them to Claude over MCP — no Microsoft Graph, no admin consent. macOS only. Each user reads only their own chats.
It reads only your own local Teams data. Nothing is uploaded by the tool itself.
How it works
The new Teams app stores chat in a Chromium IndexedDB/LevelDB cache. teams-reader:
locate the work (
teams.microsoft.com) LevelDB under the Teams container.snapshot it (copy, drop
LOCK) so Teams can stay running.dump it to JSONL with
dfindexeddb.parse messages (sender, time, text; reply quotes split out) and chat names.
store them in SQLite with an FTS5 index, idempotently (re-ingest never duplicates).
serve tools to Claude via MCP:
list_chats,read_chat,search,recent,ask,chat_profile, andsuggest_reply.
Each MCP tool first runs a debounced incremental ingest, so queries always see
the latest cached messages without running ingest/daemon by hand.
suggest_reply(chat) returns the recent thread, the chat kind, and a heuristic
profile of each participant (language, tone, message length) — Claude uses that
to write 2-3 adaptive reply options to copy into the chat. It never sends.
Related MCP server: Apple Messages MCP
Images
Messages reference images by URL on the AMS service; the bytes need the
logged-in session. teams-reader records image URLs per message during ingest,
then downloads the bytes through the same browser context used for backfill
(cookie auth, no CORS). The model reads the downloaded file.
teams-reader fetch-image --chat "Project Sigma" --limit 10Then, over MCP: list_images("Project Sigma") to see a chat's images, and
read_image(msg_id) to get the image inline; the downloaded file is deleted right after it is read.
Full history (browser backfill)
The cache holds only recently synced messages. To pull a chat's full history,
teams-reader can read it from the Teams web client's internal chatsvc messages
API, reusing your own logged-in session — no Graph, no admin consent.
It drives a real browser (Playwright/Chromium) optionally through a proxy (e.g. a corporate VPN),
captures one live chatsvc request (URL + session token), then replays it per
conversation and follows the backward-pagination links until history is exhausted.
It only reads; nothing is sent.
pip install -e '.[browser]'
python -m playwright install chromium
# If the profile uses a VPN proxy, bring it up first.
teams-reader login # one-time: a window opens, log in (MFA)
teams-reader backfill # sync new/changed chats (real titles from the server)
teams-reader backfill --full # refetch every chat's history
teams-reader backfill --chat Sigma --max-pages 100The login persists, so later backfill runs (and the MCP sync_history tool) can
reuse the session headless. Set the profile's proxy if Teams is only reachable
through a VPN proxy.
Warm browser (MCP server)
The MCP server keeps one headless reader browser open after the first tool
call. While the tools are in use it re-syncs changed chats every ~30s in the
background (backing off when the VPN or login is unavailable), and
sync_history, read_image and read_link reuse it, so they take seconds
instead of ~30s. Disable it with live_sync = false in the profile. While it
runs it holds that profile's browser, so CLI browser commands for the same
profile report "in use" — stop the MCP server first.
Unattended re-login
When the Teams session has expired, user-initiated actions (sync_history,
read_image, read_link, CLI login/backfill/fetch-image) sign in again by
themselves, using the profile's credentials_env dotenv file and its
email_key/password_key (no file configured = never signs in by itself;
disable with autologin = false). MFA still
needs your phone: the number to enter shows as a macOS notification. A rejected
password is never retried. The background sync never signs in, so it cannot
spam MFA prompts; it reports login required instead.
Try it safely in a throwaway profile: venv/bin/python tools/try_autologin.py.
Requirements
macOS, the new Teams app signed into the target account and synced at least once.
brew install snappy(the LevelDB reader needs it).Python 3.10+.
Install
macOS with the new Teams desktop app and Homebrew. One command:
curl -fsSL https://raw.githubusercontent.com/dungpham259dev/teams-reader/main/install.sh | bashIt installs snappy and uv if missing, installs the teams-reader CLI,
downloads its browser, then runs teams-reader setup, which asks a few
questions (profile name, which Teams cache, proxy/VPN, optional automatic
re-login, background sync), writes the config, registers the MCP server with
Claude Code, and offers to sign in to Teams. Re-run teams-reader setup any
time to add or change a profile.
Manual install, if you prefer:
brew install snappy uv
export CPPFLAGS="-I$(brew --prefix snappy)/include" LDFLAGS="-L$(brew --prefix snappy)/lib"
uv tool install --python-preference only-managed --python 3.13 \
"teams-reader[browser] @ git+https://github.com/dungpham259dev/teams-reader"
teams-reader install-browser
teams-reader setupThe CPPFLAGS/LDFLAGS are needed because a dependency pins python-snappy
0.6.1, which compiles against Homebrew's snappy.
Configuration
Settings live in ~/.config/teams-reader/config.toml as named profiles
(see config.example.toml): local cache source, optional proxy (VPN), optional
credentials file for unattended re-login, background sync on/off, data folder.
Without a config file the default profile reads the work cache, connects
directly and never signs in by itself.
teams-reader config # show the active profile (no secrets)
teams-reader --profile client-b config # another profileEach profile keeps its own store and browser login, and a browser profile can be used by one process at a time (a second one fails fast with "in use"). Register one MCP server per profile so accounts never mix:
claude mcp add teams-reader -- teams-reader mcp # default_profile
claude mcp add teams-client-b -- teams-reader --profile client-b mcpUse
teams-reader setup # interactive setup: add/change a profile, register with Claude
teams-reader config # show the active profile's settings
teams-reader locate # show the Teams cache databases found
teams-reader ingest # read the cache into the store (one shot)
teams-reader daemon # keep the store fresh (polls every 45s)
teams-reader login # one-time browser login for full-history backfill
teams-reader backfill # sync new/changed chats via the browser session
teams-reader fetch-image # download chat images via the browser session
teams-reader mcp # run the MCP server (stdio) for Claude
teams-reader wipe --yes # delete the store and snapshotsRegister the MCP server with Claude Code (see Configuration for profiles):
claude mcp add teams-reader -- teams-reader mcpThen ask Claude things like "tóm tắt chat Project Sigma" or "tìm tin nhắn về keycloak".
Permissions (macOS)
Cache files live in your own user container, so no admin/sudo is needed. If a run can't read them ("Operation not permitted"), grant your terminal Full Disk Access (System Settings → Privacy & Security → Full Disk Access) and restart it.
Data governance
This stores a local copy of chat content, which may belong to a client. Decide
per tenant whether that is acceptable. teams-reader wipe --yes removes the store
and all snapshots. The store lives at
~/Library/Application Support/teams-reader/.
Tenant limits
The cache approach depends on the tenant: Conditional Access can block sync on
unmanaged devices (empty cache), and Intune app-protection can encrypt the cache
(unreadable). Try teams-reader locate and teams-reader ingest on a tenant before relying on it.
Development
PYTHONPATH=. venv/bin/pytest --cov=teams_readerTests use synthetic fixtures only — no real chat data is committed.
License
MIT, see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Mac & Windows: let ChatGPT, Claude & Cursor use your email, calendar, iMessage, Teams, files.
Your own WhatsApp in Claude and ChatGPT: read chats, draft replies, send messages you approve.
- RoomtoneOAuthio.roomtone
Ask Claude about your meetings: summaries, action items and transcripts from Roomtone
Let Claude or ChatGPT search, read and send your WhatsApp messages over MCP. OAuth sign-in.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceProvides Claude with read-only access to your WhatsApp chat history entirely on your local machine, enabling natural language search, summarization, and retrieval of messages without sending data to the cloud.18 npmMIT
- AlicenseAqualityAmaintenanceEnables Claude on macOS to read, search, and send iMessage, SMS, and RCS messages, with tools for stats, chat history, attachments, and message composition.9MIT
- FlicenseNot gradedqualityCmaintenanceLets a Claude Code agent read and post in a fixed allowlist of Microsoft Teams group chats using an ordinary user account, with tools for messaging, replying, editing, deleting, and polling.1-
- AlicenseNot gradedqualityDmaintenanceEnables Claude to read, send, and search messages across Microsoft Teams, including channels, chats, and profiles, using your own Microsoft 365 work account with one-click OAuth sign-in.42 npm2MIT