Teams MCP Server
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 MCP Serverlist my recent chats"
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 MCP Server
Microsoft Teams MCP-Server auf Basis einer Multi-Tenant Playwright Browser-Bridge. Steuert den echten Teams-Webclient im Chromium/Chrome über CDP – kein offizielles API-Integration, dafür mit echten Browser-Sessions und ohne Cloud-Relay.
Ermöglicht LLM-Agenten (opencode, Claude, Cursor, …) den Lese-/Schreibzugriff auf Microsoft Teams: Chats listen, Nachrichten lesen, durchsuchen, Teams/Channels auflisten und Nachrichten senden – jeweils in einem isolierten Browser-Profil pro Konto/Tenant.
Hinweis: Dieses Repository ist komplett organisationsneutral. Es enthält keine firmenspezifischen Tenants, Accounts oder Zugangsdaten. Alle Zugänge werden von dir selbst pro Tenant konfiguriert und per einmaligem Browser-Login eingerichtet.
Features
Multi-Tenant: Jeder Tenant/Account bekommt ein isoliertes Browser-Profil (
.teams-browser-profile-<tenant>) – keine Session-Kollisionen.Tools:
teams_status,teams_login,teams_list_chats,teams_get_messages,teams_get_channel_messages,teams_search,teams_list_teams,teams_send_message,teams_inspect,teams_meeting_status,teams_start_tracking,teams_stop_tracking,teams_close.Kanal-Nachrichten lesen:
teams_get_channel_messagesnavigiert über den Team-/Kanal-Baum (Sektion „Teams and channels“ der linken Rail) und liest Nachrichten aus Team-Kanälen — inkl. Autor, Zeitstempel (ISO), Text (Markdown), Reaktionen und Anhänge-Metadaten. Parameter:team_name,channel_name(Default „Allgemein“),limit. Ein Sicherheitsnetz verifiziert nach der Navigation, dass der geöffnete Kanal dem Ziel entspricht (Header,document.title, Baum- Selektion) — sonst klarer Fehler statt falscher Daten.teams_list_teamsliefert dazu die Team-/Kanal-Struktur (teams: [{ name, channels: [...] }]).Message Reactions (Emojis/Reaktionen):
teams_get_messagesundteams_get_channel_messagesliefern je Nachricht einreactions-Array mit{ type, emoji, custom, count, byMe, label }. Reaktionen stehen im Teams-DOM als eigenes Control neben dem Text-Body (.fui-ChatMessage__reactions/button[data-tid="diverse-reaction-pill-button"]) und tauchen daher nicht im Nachrichten-Text auf.typeist der sprachunabhängige Teams-Slug (heart,yes/Like,laugh,rofl,cry,surprised,headstone,2705_whiteheavycheckmark/✅ …),byMeunterscheidet eigene von fremden Reaktionen (aria-pressed). Bei Custom-Emoji istemoji: nullundcustom: true(Teams liefert dort eine ID statt eines Glyphs). Praxisrelevant: formale Freigaben werden in Teams häufig ausschließlich per ✅-Reaktion erteilt — eine solche Reaktion ist inreactionssichtbar und darf nicht als „keine Rückmeldung“ gewertet werden. Reaktions-Chrome wird aus dem Markdown-Text entfernt, damit das Emoji den Nachrichtentext nicht verfälscht.Autoren & Zeitstempel:
authorliefert den echten Anzeigenamen (nicht mehr „Unbekannt“),isOwnkennzeichnet eigene Nachrichten. Für Kanal-Nachrichten wird der Subheader-Zeitstempel („6/23 4:44 PM“, „23.06. 16:44“) inkl. abgeleitetem Jahr zu ISO-8601 normalisiert (parseChannelDateTime); das Jahr wird aus dem Zeitstempel der vorherigen Nachricht bzw. über eine Plausibilitätsprüfung gegen „jetzt“ bestimmt.timestampRawenthält weiterhin den Originalwert.Nachrichten-Suche:
teams_searchliest die echte Teams-Suchansicht aus ([data-tid="search-layout"]-Karten) und liefert strukturierte Treffer:{ kind: message|file|meeting, chat, channel|members, author, timestamp (ISO), timestampRaw, snippet, highlighted, attachments, preview }. Der Autor wird aus der Avatar-URL (?displayname=…) gewonnen, nackten Uhrzeitangaben („9:27 AM“) wird „heute“ zugeordnet. Hinweis: Treffer sind wie im Teams-UI relevanzsortiert, nicht chronologisch — dafür wird der aufsteigende Jahres-Anker bewusst nicht angewendet.Anhänge herunterladen:
teams_get_messagesundteams_get_channel_messagesakzeptierendownload_attachments: true(optionaldownload_limit,download_extensionsz.B.[".pptx", ".pdf"]als Whitelist). Playwright-native Downloads (page.on('download')+saveAs) landen in~/.teams-downloads/(perTEAMS_MCP_DOWNLOAD_DIRänderbar). Drei Kaskaden: Attachment-Karten über das „More actions“-Menü, direkte Download-Buttons, SharePoint-Links via Temp-Page mit&download=1. Ein hängender Download wird nach 25s übersprungen (Warnung indownloads.skipped[]) — das Scraping blockiert nie.Aktivitätstab-Analyse:
teams_get_activity(Roh-Extraktion),teams_analyze_activity(Klassifikation),teams_generate_activity_report(täglicher Markdown-Report) undteams_schedule_activity_report(geplanter proaktiver Lauf 2x/Tag) – siehe Abschnitt Aktivitätstab-Analyse & Bericht.Dateianhänge unterstützen:
teams_send_messageakzeptiert optionale lokale Dateipfade (attachments: ["/tmp/file.zip"]oderattachment: "/tmp/file.zip"). Automatischer Upload via FileChooser / Input-Bridge inklusive Upload-Fortschritts-Überwachung vor dem Versand.Inline-Bilder persistieren:
teams_get_messageslöst flüchtigeblob:-Screenshot-/Bild-URLs direkt im Browser auf und speichert sie als Dateien nach~/.teams-media/(perTEAMS_MCP_MEDIA_DIRänderbar). Dateiname:{tenant}_{chat}_{timestamp}_{index}.{ext}. Im Markdown erscheint statt der unbrauchbarenblob:-URL ein lokalerfile://-Pfad, den multimodale Agenten direkt laden können. Flüchtige UI-Icons (Buttons/Avatare/Reaktionen) werden dabei bewusst ignoriert.Konsistente Chat- & Adressbuch-Auflösung:
chat_indexundchat_namelösen auf die vollständige Chatliste auf — die Liste wird vor der Auflösung automatisch nachgeladen (Paginator-Klicks bis zur Stabilisierung,listChatsmeldettotalAvailable).getMessagesverifiziert nach dem Öffnen (Sicherheitsnetz), dass der geöffnete Chat dem Ziel entspricht — bei Nicht-Chat-Einträgen gibt es einen klaren Fehler statt stiller Fehlresolvenz. Ist ein Kollege noch nicht in der Chat-Liste, startetteams_send_messagevollautomatisch einen neuen Chat über das globale Unternehmensadressbuch (GAL / People-Picker).Sichere Sendesemantik:
teams_send_messagesendet nicht blind in den aktiven Chat, wenn der Ziel-Chat nicht eindeutig gefunden wird – es wirft stattdessen einen Fehler. Vor dem Versand verifiziert ein Sicherheitsnetz, dass der tatsächlich geöffnete Chat dem Ziel entspricht, sonst wird abgebrochen (kein Fehlversand).Mehrzeilige Nachrichten: Nachrichten werden per Clipboard-Paste eingefügt statt per Tastatureingabe – dadurch bleiben Umlaute/Sonderzeichen intakt und Zeilenumbrüche werden nicht fälschlich als „Absenden“ interpretiert (kein Zersplittern in mehrere Fragmente).
Robust: Retry gegen Browser-Profil-Lock-Kollisionen (parallele Sessions), klare Fehler bei abgelaufener Login-Session.
Related MCP server: Teams MCP
Voraussetzungen
Node.js ≥ 20
Ein installiertes Chromium/Chrome/Edge. Automatische Erkennung an gängigen Orten (Playwright-Cache,
/usr/bin, macOS-Apps). Alternativ perTEAMS_MCP_CHROME_PATHsetzen.(Optional) WSLg / eine grafische Umgebung für das einmalige Login-Fenster.
Installation
git clone <your-repo-url> teams-mcp
cd teams-mcp
npm installKonfiguration (Umgebungsvariablen)
Alle Optionen sind optional. Im Standardfall funktioniert der Server org-neutral,
indem der tenant-Wert, den du an die Tools übergibst, direkt als Konto/Realm
verwendet wird (z.B. tenant: "deine-org.onmicrosoft.com").
Variable | Beschreibung | Default |
| Pfad zur Chrome/Chromium/Edge-Executable | Auto-Detect |
| Basis-Verzeichnis für die Browser-Profile |
|
| Kommagetrennte Whitelist erlaubter Tenant-Keys (für validierte Auswahl in den Tool-Schemas) | – |
| JSON-Objekt | – (tenant = realm) |
| Eigener Anzeigename für „Ich“-Nachrichten |
|
| Headless-Default ( |
|
| Zielverzeichnis für persistierte inline-Bilder/Screenshots aus Nachrichten |
|
Beispiele
Kurznamen auf Realms mappen (z.B. für zwei Konten bei zwei Organisationen):
export TEAMS_MCP_TENANT_REALMS='{"arbeit":"arbeit.onmicrosoft.com","privat":"privat.onmicrosoft.com"}'
export TEAMS_MCP_TENANTS='arbeit,privat'Oder ganz ohne Konfiguration – einfach immer den vollständigen Realm übergeben:
# tools mit tenant: "meine-org.onmicrosoft.com"In opencode konfigurieren
Ergänze in opencode.json einen MCP-Server-Eintrag (Pfade anpassen):
{
"mcp": {
"teams": {
"type": "local",
"command": ["node", "/abs/path/zu/teams-mcp/index.js"],
"enabled": true
}
}
}Für andere MCP-Clients (Claude Desktop, Cursor, …) starte den Server entsprechend
über index.js bzw. das teams-mcp-Binärskript.
Erste Schritte (Login)
teams_login({ tenant: "deine-org.onmicrosoft.com" })– öffnet ein sichtbares Browserfenster.Melde dich dort einmalig an (inkl. MFA). Die Session wird dauerhaft im Tenant-Profil (
~/.teams-browser-profile-<tenant>) gespeichert.Danach sind alle Tools für diesen Tenant bereit.
Hinweis: Das Login ist immer sichtbar. Headless wird nur für die Lese-/ Schreib-Tools verwendet, nachdem du dich einmalig angemeldet hast.
Bedienung & Architektur
Chat-Adresse: Nutze
teams_list_chatsfür den Chat-indexODER den exakten Chat-name. Beide Wege führen zuverlässig zum selben Chat (exakter Titel-Match, danach Präfix-/Token-Match).Tenant-Pflicht: Jedes Tool erwartet einen
tenant-Wert. Ohne Konfiguration ist das der Realm deiner Organisation (z.B.deine-org.onmicrosoft.com).Chrome-Pfad: Wird kein Browser erkannt, warnt der Server beim Start und erwartet
TEAMS_MCP_CHROME_PATH.Profil-Lock: Wird ein Profil gerade von einer anderen Instanz genutzt (z.B. eine zweite parallele Agenten-Session), wartet der Server mit Backoff und wirft sonst eine klare Meldung.
Aktivitätstab-Analyse & Bericht
Das Toolset kann den Teams-Aktivitätstab systematisch auslesen, klassifizieren und dir als proaktiven Bericht präsentieren – damit du den Tab nicht selbst anklicken musst. Vier-Schichten-Architektur:
Schicht | Datei | Zweck |
Layer 1 – Extraktion |
| Reads the Activity-Feed (scroll-enabled) und liefert Roh-Items (Text, Autor, Zeitstempel) |
Layer 2 – Analyse |
| Klassifiziert Einträge in Meeting, Task, Entscheidung, Risiko, Sonstiges mit Relevanz-Score + erzeugt Markdown-Report |
Layer 3 – Planung |
| Geplanter proaktiver Lauf 2x/Tag + Steuerung |
Layer 4 – Zustellung |
| Outbox für den |
Tools:
teams_get_activity– Roh-Items aus dem Aktivitätstab (ohne Klassifikation).teams_analyze_activity– Extrahiert + klassifiziert, liefert gruppierte Analyse (ohne Datei).teams_generate_activity_report– Extrahiert + klassifiziert + speichert täglichen Markdown-Report nachreports/activity-summary-YYYY-MM-DD.md(Top-3 je Kategorie, nach Relevanz).teams_schedule_activity_report– Steuert den geplanten proaktiven Lauf:action: "status"– aktueller Scheduler-Zustand (Running? Zeiten? letzter Lauf?)action: "start"– aktiviert den 2x/Tag-Scheduler (Standard["09:00","17:00"]), optional mittimes,tenant,max_itemsaction: "stop"– deaktiviert den Scheduleraction: "run-once"– führt sofort eine volle Analyse+Bericht aus (On-Demand)action: "config"– zeigt die aktuelle Konfiguration an
teams_list_pending_deliveries– Listet noch nicht zugestellte (pending) Activity-Berichte aus der Zustell-Outbox (reports/outbox/) auf — für dentim-Agenten, damit er weiss, welcher Bericht an den Nutzer präsentiert werden soll (chronologisch, inkl. Report-Text).teams_mark_delivered– Markiert eine Outbox-Zustellung (austeams_list_pending_deliveries) als übergeben (rename auf*.delivered.json), sodass kein Doppel-Versand erfolgt.
Kategorien (breite Content-Range des Feeds): Der Klassifikator sortiert eingehende
Einträge in die fünf Kategorien. Risiko (Blocker, Fehler, Fristrisiko) und Task
(Aufgaben/Anfragen) werden als hoch priorisiert, Entscheidung und Meeting als
mittel, der Rest als niedrig. Jeder Lauf speichert einen Markdown-Report nach
reports/ und legt eine strukturierte Zustell-Nachricht in reports/outbox/ ab.
Der tim-Agent holt diese via teams_list_pending_deliveries ab, präsentiert den Bericht
proaktiv an den Nutzer (im "Chat mit mir") und markiert ihn via teams_mark_delivered
als übergeben — robuste Zustell-Kette ohne Prozesskopplung zwischen MCP-Server und Agent.
Verifizierte Konfiguration (Stand 16.09.2026): Ein Smoke-Test über das MCP-Protokoll
(tools/list + tools/call mit action:"status") bestätigt: teams_schedule_activity_report
ist registriert und der Scheduler läuft mit running: true, tenant: "adesso",
times: ["09:00","17:00"], maxItems: 50, topN: 3, Reports nach
reports/. Beim Serverstart wird der Scheduler automatisch gestartet
(EnV TEAMS_MCP_ACTIVITY_SCHEDULER=0 deaktiviert, TEAMS_MCP_ACTIVITY_TIMES überschreibt
die Zeiten).
Zustellung (Layer 4) – Abschlussbericht (Stand 16.09.2026)
Die Zustellkette für den proaktiven Activity-Bericht ist fertiggestellt und verifiziert.
Sie überbrückt robust die Prozessgrenze zwischen teams-mcp (MCP-Server) und dem
tim-Agenten (opencode-Subagent), ohne dass der Nutzer den Aktivitätstab selbst
anklicken muss. Zentrale Idee: Outbox als entkoppelter Übergabepunkt.
Ablauf (End-to-End):
Scheduler erzeugt Bericht – Zur konfigurierten Zeit (
09:00/17:00) führt Layer 3 (activityReportScheduler) die Analyse aus und speichert den Markdown-Report nachreports/activity-YYYY-MM-DD-HHmm.md.Sender legt Outbox-Nachricht an – Der in
index.jsverdrahtetecreateOutboxSender()(aussrc/reportDelivery.js) serialisiert das Bericht-Ergebnis als strukturierte JSON-Nachricht nachreports/outbox/activity-delivery-*.json(Kindteams-activity-report, Recipienttim, inkl.report,counts,tenant,date).tim-Agent holt ab – Der
tim-Agent ruftteams_list_pending_deliveriesauf, erhält die chronologisch sortierten, noch nicht übergebenen Nachrichten und präsentiert den Bericht proaktiv an den Nutzer (im "Chat mit mir").Übergabe bestätigen – Der
tim-Agent markiert die Zustellung viateams_mark_deliveredals übergeben. Dadurch wird die Datei auf*.delivered.jsonumbenannt und vonlistPendingDeliverieskünftig übersprungen – kein Doppel-Versand.
Verifikation: npm test 79/79 grün (inkl. Outbox- und Self-Chat-Name-Tests),
npm run check syntaktisch sauber. End-to-End-Demo: node tests/report-delivery.demo.mjs
(Outbox → tim-Agent → übergeben, ohne echten Browser).
Design-Merkmale: Keine Prozesskopplung (nur Datei-Outbox); kanonische
extractSelfNameFromTitle-Logik für die Self-Chat-Erkennung in src/reportDelivery.js;
kaputte Outbox-Dateien werden über stderr geloggt und übersprungen, ohne die Kette zu
stören.
Projektstruktur
teams-mcp/
├── index.js # MCP-Server (Tool-Schema + Dispatch)
├── src/
│ ├── config.js # Zentrale, per Env überschreibbare Konfiguration
│ ├── browserManager.js # Playwright-Profil-Management (Multi-Tenant, Locks)
│ ├── teamsClient.js # Teams-Web-Automation (Chats, Messages, Search, Send)
│ ├── activityClient.js # Layer 1: Activity-Feed-Extraktion
│ ├── activityAnalyzer.js# Layer 2: Klassifikation + Report-Pipeline
│ ├── activityReportScheduler.js # Layer 3: geplanter proaktiver Lauf
│ ├── reportDelivery.js # Zustellebene: Outbox für den tim-Agenten
│ └── speakerTracker.js # Active Speaker Tracking (Meetings)
└── package.jsonSicherheit & Compliance
Dieser Server interagiert mit Microsoft Teams Web über deine eigenen Browser-Sessions – es werden keine Zugangsdaten gespeichert oder übertragen.
Die Browser-Profile mit den Login-Sessions liegen ausschließlich lokal (
~/.teams-browser-profile-<tenant>) und sind in.gitignoreausgeschlossen.Stelle sicher, dass die Nutzung die Richtlinien deiner Organisation und die geltenden Datenschutz-Anforderungen (z.B. DSGVO) erfüllt.
Tests
Das Projekt verwendet den eingebauten Node-Test-Runner (node:test) – keine zusätzlichen
Abhängigkeiten.
Unit-Tests (kein Browser, keine Netzwerkzugriffe):
npm test # = node --test tests/unit.test.mjsIntegrationstests (gegen einen echten, bereits angemeldeten Teams-Tenant):
npm run test:integration # LANGSAM, sendet NICHT (Standard: Sende-Test gesperrt)Der Integrationstest prüft status, list_chats (Index-Konsistenz), get_messages
(Name↔Index-Auflösung), search, list_teams und send_message.
Aktivität-Demos (ohne echten Browser, mit Beispiel-/Simulationsdaten):
node tests/activity.demo.mjs # Layer 1: Activity-Feed-Extraktion (Mock)
node tests/activity-analyzer.demo.mjs # Layer 2: Klassifikation + Report
node tests/scheduler.demo.mjs # Layer 3: Scheduler-Pipeline (simuliert)
node tests/report-delivery.demo.mjs # Zustellebene: Outbox -> tim-Agent -> übergeben⚠️ Sicherheit beim Senden: Standardmäßig wird der Sende-Teil des Integrationstests übersprungen. Nur wenn du ihn explizit freigibst UND als Empfänger deinen eigenen Self-Chat angegeben hast, wird tatsächlich eine Nachricht gesendet:
TMS_TEST_TENANT=deine-org.onmicrosoft.com \ TMS_TEST_SEND_ALLOWED=true \ TMS_TEST_RECIPIENT="Dein Name" \ # unbedingt dein eigener Self-Chat! node tests/integration.test.mjsSo wird in Testläufen garantiert nur an dich selbst gesendet – niemals in einen fremden oder Gruppen-Chat.
Lizenz
Siehe LICENSE. (Standard: zum privaten/internen Gebrauch oder wie in der LICENSE-Datei
angegeben.)
This server cannot be deployed
Maintenance
Related MCP Connectors
Provides cloud browser automation capabilities using Stagehand and Browserbase, enabling LLMs to i…
Control a real browser from AI agents: navigate, click, type, screenshot, read the page.
Hosted browser for agents: open pages, search the web, extract data, read PDFs and take screenshots.
Let your AI agent operate any website through a real, logged-in browser session.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants to interact with Microsoft Teams and Microsoft Graph through OAuth-authenticated tools for messaging, chat and channel management, message search, file uploads and downloads, and user directory lookups. Supports rich Markdown formatting, mentions, attachments, and LLM-friendly HTML-to-Markdown content conversion.5 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants to interact with Microsoft Teams and Microsoft Graph, covering channel and chat messaging, message editing and search, user and team member lookup, attachment downloads, and file uploads. Supports Markdown-formatted messages, HTML-to-Markdown conversion for LLM-friendly output, and OAuth device-code authentication with an optional read-only mode.5 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants to interact with Microsoft Teams and Microsoft Graph APIs for user, team, channel, chat, message search, file, and attachment management. Supports authentication, rich Markdown formatting, and LLM-friendly content conversion.5 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants to interact with Microsoft Teams and Microsoft Graph, covering chats and channel messaging, message search, user and team member lookups, and file upload or attachment downloads. Supports OAuth device-code authentication, rich Markdown formatting, and LLM-friendly conversion of Teams HTML into Markdown.5 npmMIT