Teams-MCP — Unique AI Documentation
Teams-MCP
12 min read
Experimental Software Disclaimerteams-mcp is experimental software.
- No SLA/SSLA: No service level agreements or support level agreements apply
- No Support: No guaranteed support, response times, or issue resolution
- Breaking Changes: APIs, configurations, and behavior may change without notice between versions
- No Stability Guarantees: Features may be incomplete, modified, or removed at any time
- Data Loss Risk: Bugs or changes may result in data loss or corruption
- Use at Your Own Risk: This software is provided "as-is" without warranties of any kind
Experimental software is intended for evaluation and testing purposes only. Do not rely on this software for production workloads without understanding these limitations.
Overview
The Teams MCP Server is a cloud-native application that automatically captures meeting transcripts and recordings from Microsoft Teams and ingests them into the Unique knowledge base. This guide provides administrators with essential information about requirements, features, and limitations.
Note: This is a connector-style MCP server that does two things. First, it automatically ingests meeting transcripts and recordings into the Unique knowledge base in the background, where they are then queried from within Unique. Second, it exposes an interactive tool surface of 12 MCP tools — 8 chat/messaging tools and 4 transcript/KB management tools. Through these tools, chat and channel messages are accessible in Unique on demand, but are never ingested into it — they are fetched live from the Microsoft Graph API and exist only in Microsoft, whereas transcripts and recordings are copied into the Unique knowledge base. This ingested-vs-live distinction is the key thing to understand; see Where the data lives. Chat and channel tools take ids obtained from the list_* tools. See Technical Reference — Tools for the full tool reference.
For deployment, configuration, and operational details, see the IT Operator Guide.
Quick Summary
What it does: Two things. (1) Automatically captures meeting transcripts and recordings from Microsoft Teams and ingests them into Unique's AI knowledge base with participant-based access controls, where they are queried from within Unique. (2) Exposes interactive tools that make Teams chat and channel messages accessible in Unique on demand — fetched live from the Microsoft Graph API and never ingested (they exist only in Microsoft, not in the Unique knowledge base).
Deployment: Kubernetes-based NestJS microservice
Authentication: Uses delegated OAuth2 with Microsoft Entra ID (user signs in and consents)
Processing: Real-time webhook-driven (notifications received immediately when transcripts are available)
Requirements
Microsoft 365 / Teams
| Requirement | Details |
|---|---|
| Microsoft Teams | Active tenant with transcription enabled for meetings |
| Microsoft Entra ID | Tenant with Application Administrator rights for app registration |
| License | Microsoft 365 license with Teams meeting transcription capabilities |
Prerequisites:
- Access to Microsoft Entra ID for app registration
- Microsoft Teams meetings with transcription enabled by policy
- Users must be able to consent to delegated permissions (or admin consent granted)
Permissions
All permissions are Delegated (not Application), meaning they act on behalf of the signed-in user and can only access data that user has access to.
| Permission | Type | Admin Consent | Required |
|---|---|---|---|
User.Read |
Delegated | No | Yes |
Calendars.Read |
Delegated | No | Yes |
OnlineMeetings.Read |
Delegated | No | Yes |
OnlineMeetingRecording.Read.All |
Delegated | Yes | Yes |
OnlineMeetingTranscript.Read.All |
Delegated | Yes | Yes |
offline_access |
Delegated | No | Yes |
ChannelMessage.Send |
Delegated | No | Yes |
ChatMessage.Send |
Delegated | No | Yes |
Chat.ReadBasic |
Delegated | No | Yes |
Chat.Read |
Delegated | No | Yes |
Team.ReadBasic.All |
Delegated | No | Yes |
Channel.ReadBasic.All |
Delegated | No | Yes |
ChannelMessage.Read.All |
Delegated | Yes | Yes |
For detailed permission justifications, see Microsoft Graph Permissions.
Features
The server offers two independent capability tracks:
- Meeting Transcripts & Recordings — background ingestion of meeting transcripts (and their recordings) into the Unique knowledge base, plus tools to search and manage that ingestion. Webhook-driven and asynchronous.
- Chats & Channels Messaging — an interactive tool surface for reading, searching, and sending Teams chat and channel messages live via Microsoft Graph. Synchronous and on-demand.
Where the Data Lives: Ingested vs. Live
This is the single most important distinction between the two tracks. Both are accessible through Unique — the difference is where the data is stored.
Both are accessible in Unique; only transcripts are ingested
Meeting transcripts and recordings are ingested — copied into the Unique knowledge base — and queried from that stored copy. Teams chat and channel messages are also accessible in Unique, through this server's MCP tools, but they are never ingested: they are fetched live from the Microsoft Graph API on demand and exist only in Microsoft, never as a copy in Unique.
Messages being "not ingested" means only that Unique keeps no copy of them — not that they are inaccessible. The Unique AI can read, search, and send them at any time via the tools; it just reaches back to Microsoft each time instead of reading a stored copy.
| Meeting transcripts & recordings | Chats & channels messages | |
|---|---|---|
| Accessible through Unique? | Yes — via Unique AI and the transcript tools | Yes — via the MCP messaging tools |
| Ingested (copied) into Unique? | Yes — stored in the knowledge base | No — never copied; the data lives only in Microsoft |
| How it is served | Queried from the stored copy in Unique — indexed and searchable from within Unique | Fetched live from the Microsoft Graph API on every call (get_*_messages, search_messages) |
| Freshness | Point-in-time snapshot captured at ingestion | Always current — reflects Teams in real time |
| If this server is disconnected | The copy remains in Unique and stays queryable | No longer reachable — nothing was stored, so there is no copy to fall back on |
| Data flow | Teams → Unique knowledge base (once) → query the copy | Teams → live fetch on each call → returned to the caller (no copy kept) |
Meeting Transcripts & Recordings
This is the connector track: once a user connects, meeting transcripts (and recordings) are captured automatically and ingested into Unique. Chat and channel messages are not part of this track — they are never ingested.
Real-time Transcript and Recording Capture
- Webhook-based notifications from Microsoft Graph API
- Automatic capture when meeting transcripts become available
- VTT format transcript content ingested into Unique
- MP4 recording files stored alongside transcripts (with
SKIP_INGESTIONmode) - Both artifacts linked via
content_correlation_idin metadata
Participant-Based Access Control
- Meeting organizer receives write + read access in Unique
- Meeting participants receive read access in Unique
- Users resolved by email or username in Unique platform
Automatic Subscription Management
- Microsoft Graph webhook subscriptions created automatically on user connection
- Subscriptions renewed automatically before expiration
- Failed renewals handled gracefully with user reconnection required
Reliability
- RabbitMQ message queue for asynchronous webhook processing
- Dead Letter Exchange (DLX) for failed message inspection and retry
- Meets Microsoft's strict webhook response requirements (< 10 seconds)
Ingestion & management tools (see Technical Reference — Tools):
ingest_meeting: Ingest a specific meeting's transcript on demandstart_kb_integration/stop_kb_integration/verify_kb_integration_status: Manage and inspect the ingestion subscription
Chats & Channels Messaging
This is the interactive track: tools that read, search, and send Teams messages live through Microsoft Graph. These messages are fetched on every call and are never ingested into the Unique knowledge base.
Chat and messaging tools target chats and channels by id: call a list_* tool to obtain an id (and distinguishing metadata), then pass that id to a read, write, or search tool. See Technical Reference — Tools.
list_teams: List all Microsoft Teams the user is a member of; returns team id andisArchivedflaglist_channels: List all channels in a team (by team id); returns channel id,createdDateTime, andmembershipTypelist_chats: List the user's recent chats (1:1, group, and meeting chats) by chat id; returnscreatedDateTime,lastMessageAt, and members for topic-less or 1:1 chatsget_chat_messages: Retrieve recent messages from a chat (by chat id)get_channel_messages: Retrieve recent messages from a channel (by team id + channel id)search_messages: Search messages by keyword across chats and channels via the Microsoft Search API; returns chat/channel ids alongside results, enabling subsequent reads or sendssend_channel_message: Send a plain text message to a Teams channel (by team id + channel id)send_chat_message: Send a plain text message to a Teams chat (by chat id)
Cross-Cutting Capabilities
These apply to both tracks.
Self-Service User Connection
- Users connect their own Microsoft account via OAuth 2.1 with PKCE
- No IT administrator involvement required for individual connections
Security
- OAuth 2.1 with PKCE for authentication ( RFC 7636)
- Microsoft tokens encrypted at rest using AES-256-GCM
- Refresh token rotation with family-based revocation
- Short-lived access tokens (60 seconds default)
How It Works
High-Level Architecture
User Connection Flow
Transcript Processing Flow
Messaging Flow
The two flows above cover the transcript track, which is webhook-driven and asynchronous. The messaging track works differently: chat and channel tools are handled synchronously and inline — each tool call queries Microsoft Graph and returns immediately, with no queue, background worker, or ingestion. The caller discovers an id with a list_* tool, then passes it to a read, search, or send tool.
User Workflows
Both tracks begin with the same one-time connection, then diverge — because their data models differ (see Where the data lives).
One-time setup (both tracks)
- Open MCP client and connect to Teams MCP Server
- Sign in with Microsoft account
- Grant required permissions
Transcripts & Recordings Workflow — ingest once, then query in Unique
- Enable ingestion (One-time) — call
start_kb_integration(or rely onMICROSOFT_AUTO_START_INGESTIONif the operator enabled it) - Automatic capture (Ongoing) - Attend Microsoft Teams meetings with transcription enabled - Meeting ends and transcript becomes available - Teams MCP automatically receives a webhook notification - Transcript and recording (if available) are captured and ingested into the Unique knowledge base
- Query in Unique (Ongoing) - Meeting content lives in the Unique knowledge base — organizer gets write + read, participants get read - Search and query it from within Unique via Unique AI - Content remains available in Unique even after the user disconnects
Chats & Channels Workflow — always query live from the API
- Discover the target (Each use) — call a
list_*tool (list_chats,list_teams→list_channels) orsearch_messagesto obtain the chat/channel id - Read, search, or send (Each use) - Pass the id to
get_chat_messages/get_channel_messages,search_messages, orsend_*_message - Accessible, but never stored in Unique
Limitations and Constraints
Authentication Constraints
| Constraint | Reason |
|---|---|
| Delegated permissions only | Requires user sign-in; application-only access would need admin-configured policies per user |
| No certificate auth | Certificate auth only works with Client Credentials flow, incompatible with delegated permissions |
| Single app registration | Each MCP server deployment uses one Entra ID app registration (multi-tenant capable) |
| Admin consent required | OnlineMeetingRecording.Read.All and OnlineMeetingTranscript.Read.All need admin approval |
Operational Constraints
| Constraint | Impact | Mitigation |
|---|---|---|
| 90-day token expiry | User must reconnect after ~90 days of inactivity | Monitor for disconnected users |
| Webhook timeout | Microsoft requires response in <10 seconds | RabbitMQ decouples reception from processing |
| Subscription expiry | Graph subscriptions expire after 3 days max | Automatic renewal via lifecycle notifications |
| Encryption key change | All stored tokens become unreadable | Users must reconnect; plan for maintenance window |
Scaling Considerations
| Factor | Limit | Notes |
|---|---|---|
| Microsoft Graph rate limits | ~10,000 requests/10 min per app | Shared across all users of the app registration |
| Concurrent user lookups | Configurable (default: 5) | Set via UNIQUE_USER_FETCH_CONCURRENCY |
| Database connections | PostgreSQL pool size | Monitor connection usage under load |
Not Supported
Meeting transcripts & recordings:
- Real-time transcription: Only processes completed transcripts, not live captions
- Meeting creation: Read-only access; cannot create or modify meetings
- Selective meeting capture: All meetings with transcription enabled are captured (no organizer-only or meeting-type filter)
- Historical/full sync: No mechanism to backfill transcripts from meetings that took place before the user connected; see Why can't historical transcripts be synced?
- Delta/incremental sync: No ability to poll for missed or updated transcripts since a given point in time; see Why is there no delta sync?
- Missed-notification recovery: If a subscription lapses, any transcripts produced during the gap are permanently lost — there is no catch-up or replay mechanism
- Transcript format variants: Only VTT-format transcripts are processed; meetings with transcripts in other formats are silently skipped
- Recording size assurance: No application-level size check on recordings; very large files (e.g., multi-hour all-hands) may time out during download and be skipped, while the transcript is still ingested
Chats & channels messaging:
- Rich message sends:
send_chat_messageandsend_channel_messagesend plain text only — no@mentions, no rich content (bold, tables, adaptive cards), and no attachment upload - Message threading/replies: There is no tool for replying to a specific message in a thread; only new top-level messages can be sent
- Chat/channel message ingestion: Messages read or searched via the messaging tools are fetched live from Microsoft Graph on every call and are not ingested into the Unique knowledge base; only meeting transcripts are ingested
General:
- Token introspection: Tokens validated locally with short TTLs for performance
- Multi-tenant in one session: A user belonging to multiple Microsoft tenants must authenticate separately for each tenant; one OAuth session covers exactly one tenant
Microsoft Graph API Constraints
The following limitations originate directly from the Microsoft Graph API and cannot be worked around while using delegated permissions.
No Delta Sync with Delegated Permissions
Microsoft Graph does expose a delta API for transcripts and recordings: none
GET /users/{userId}/onlineMeetings/getAllTranscripts(...)/delta
GET /users/{userId}/onlineMeetings/getAllRecordings(...)/delta
These APIs support both full initial synchronization and incremental sync (returning only transcripts added since the last $deltaToken). However, the official permission table is:
| Permission type | Support |
|---|---|
| Delegated (work or school account) | Not supported |
| Delegated (personal Microsoft account) | Not supported |
| Application | OnlineMeetingTranscript.Read.All / OnlineMeetingRecording.Read.All |
Source: callTranscript: delta — Microsoft Graph API reference · callRecording: delta — Microsoft Graph API reference
Teams MCP uses delegated permissions so that users can connect their own Microsoft account without IT administrator involvement. Switching to application permissions would enable delta sync, but would require tenant administrators to configure Application Access Policies via PowerShell for every user — defeating the self-service connection model.
No Historical/Full Sync with Delegated Permissions
The only Microsoft Graph API capable of listing transcripts across all of a user's meetings (without knowing individual meeting IDs in advance) is getAllTranscripts:
none
GET /users/{userId}/onlineMeetings/getAllTranscripts(meetingOrganizerUserId='{userId}',startDateTime=...)
This API also requires application permissions only — delegated permissions are explicitly not supported.
Source: onlineMeeting: getAllTranscripts — Microsoft Graph API reference
With delegated permissions, the only available path to read transcripts is GET /users/{userId}/onlineMeetings/{meetingId}/transcripts, which requires knowing the meeting ID in advance. There is no delegated-permission API that enumerates past meetings and their transcripts in bulk. As a result, Teams MCP can only capture transcripts going forward from the moment the user connects — not from any earlier meetings.
Additional constraints on historical data (even with application permissions):
- Transcripts are only accessible for meetings that have not expired. One-time meetings expire 60 days after their scheduled time; recurring meetings with no end date expire 1 year after the last activity.
- Recording and transcript files are subject to the tenant's admin-configured expiration policy (Microsoft default: 120 days after creation).
Single App Registration Architecture
Each Teams MCP Server deployment uses one Microsoft Entra ID app registration:
- Multi-tenant support: Configure app as "Accounts in any organizational directory"
- Enterprise Application: Created in each tenant when admin grants consent
- Shared infrastructure: One deployment serves all tenants
- Data isolation: Each user's data scoped by their Microsoft user ID
Future Versions
Planned enhancements will be documented here.