Skip to main content
Glama
tinobruno

Teams Puppeteer MCP Server

by tinobruno

Teams Puppeteer MCP Server

License: MIT Node.js Model Context Protocol

A high-performance Model Context Protocol (MCP) server for Microsoft Teams chat automation, message extraction, and unread notification monitoring powered by Puppeteer.


πŸ’‘ Why This Project?

Most Microsoft Teams integrations require:

  • ❌ Enterprise Azure App Registration

  • ❌ Azure Tenant Administrator Consent

  • ❌ Paid Microsoft 365 / Graph API licenses & Bot frameworks

teams-puppeteer-mcp takes a radically simpler approach:

  • βœ… Zero Setup / No API Keys: Uses npx with zero local file path configuration.

  • βœ… Direct Web Client Automation: Interacts directly with Microsoft Teams (teams.cloud.microsoft) using your standard browser profile.

  • βœ… Persistent SSO & MFA Session: Log in once interactively with your work, school, or personal account. Your session cookies and tokens persist locally in your user profile.

  • βœ… Zero Token Overhead: Optimized specifically for LLMs. Returns clean, high-density human/LLM-readable text without nested JSON bloat.

  • βœ… Full Cross-Platform Support: Works seamlessly on Windows, macOS, and Linux.


Related MCP server: Puppeteer MCP Server

πŸš€ Quick Setup (Zero Configuration)

You do not need to manually clone this repository or guess local file paths. You can add it directly to your MCP client using npx.

TIP

Merging with existing servers: If you already have other MCP servers configured in your client, do not overwrite the whole file! Simply insert the "teams" (or "teams-puppeteer") block into your existing "mcpServers" object.

1. Claude Desktop

Add this to your claude_desktop_config.json:

  • Windows: %APPDATA%\\Claude\\claude_desktop_config.json

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Linux: ~/.config/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "//": "... keep your other existing servers here ...",
    "teams": {
      "command": "npx",
      "args": [
        "-y",
        "@tinobruno/teams-puppeteer-mcp"
      ]
    }
  }
}

Note: You can also run directly from GitHub without npm: "args": ["-y", "github:tinobruno/teams-puppeteer-mcp"]


2. Cursor

Add to your Cursor MCP settings (~/.cursor/mcp.json or via Settings β†’ Features β†’ MCP):

{
  "mcpServers": {
    "//": "... keep your other existing servers here ...",
    "teams": {
      "command": "npx",
      "args": [
        "-y",
        "@tinobruno/teams-puppeteer-mcp"
      ]
    }
  }
}

3. VS Code (Cline / Roo-Code)

In your Cline MCP settings (cline_mcp_settings.json):

{
  "mcpServers": {
    "//": "... keep your other existing servers here ...",
    "teams": {
      "command": "npx",
      "args": [
        "-y",
        "@tinobruno/teams-puppeteer-mcp"
      ],
      "disabled": false,
      "autoApprove": []
    }
  }
}

4. MinnieTheMoEcher

You can add it via the Web UI (under Settings β†’ MCP Servers β†’ + Add Server) or by adding this entry into your existing mcp_servers.json:

{
  "mcpServers": {
    "//": "... keep your other existing servers here ...",
    "teams-puppeteer": {
      "command": "npx",
      "args": [
        "-y",
        "@tinobruno/teams-puppeteer-mcp"
      ],
      "enabled": true,
      "transport_type": "stdio"
    }
  }
}

πŸ”‘ First-Time Interactive Login

On your first run:

  1. When your AI assistant invokes a Teams tool, a browser window will launch and navigate to Microsoft Teams (https://teams.cloud.microsoft).

  2. Log in with your corporate SSO, password, and complete your Multi-Factor Authentication (MFA/2FA) prompt.

  3. Once you reach the Teams chat interface, your session is automatically saved to your local profile directory (~/.teams_puppeteer_profile on macOS/Linux, or %USERPROFILE%\\.teams_puppeteer_profile on Windows).

  4. Subsequent calls will automatically connect to your authenticated session.


πŸ› οΈ Available MCP Tools

Tool Name

Description

Parameters

get_last_message

Primary tool to read the single latest message from a contact, group, or channel. Matches partial names automatically.

chat_name (required, string)

get_last_unread_message

Scans for unread messages. If chat_name is omitted, scans across all conversations and returns a compact summary.

chat_name (optional, string)

get_last_messages

Retrieves the last N messages from a specific conversation.

chat_name (required), count (optional, number, default: 3)

list_teams_chats

Lists sidebar conversation names, unread flags, and latest activity timestamps.

limit (optional, number, default: 10)

send_teams_message

Types and dispatches a message into Teams using native keyboard input into CKEditor 5.

chat_name (required), message (required)


βš™οΈ Environment Variables (Optional)

You can customize the behavior by passing optional env variables in your MCP client config:

{
  "mcpServers": {
    "//": "... keep your other existing servers here ...",
    "teams": {
      "command": "npx",
      "args": ["-y", "@tinobruno/teams-puppeteer-mcp"],
      "env": {
        "TEAMS_HEADLESS": "true",
        "PUPPETEER_EXECUTABLE_PATH": "/usr/bin/google-chrome"
      }
    }
  }
}

Variable

Description

Default

TEAMS_HEADLESS

Set to "true" to run browser in the background after initial login.

"false"

TEAMS_PROFILE_DIR

Custom directory path for browser cache & persistent session cookies.

~/.teams_puppeteer_profile

PUPPETEER_EXECUTABLE_PATH

Explicit path to your Chrome or Microsoft Edge executable.

Auto-detected

DEVTOOLS_PORT

Connect to an already running Chrome instance with remote debugging.

Auto-detected / 9222


πŸ§‘β€πŸ’» Manual Installation (For Developers / Contributors)

If you are developing or modifying the server locally:

git clone https://github.com/tinobruno/teams-puppeteer-mcp.git
cd teams-puppeteer-mcp
npm install
node index.js

πŸ”’ Privacy & Security

  • Local Storage Only: Your credentials, cookies, and chat contents remain strictly on your local machine inside .teams_puppeteer_profile/.

  • Zero Cloud Proxies: No data is ever routed through external third-party servers. All automation occurs directly between your local machine and Microsoft Teams endpoints.


πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

Available Tools

5 tools
get_last_messageA

PRIMARY TOOL to read the single latest message from a specific person, group, or channel in Teams. Supports partial names (e.g. 'Alice Smith', 'Bob', 'Project Alpha'). Automatically matches the chat and returns only the author, timestamp, and text. NEVER call list_teams_chats first.

ParametersJSON Schema
NameRequiredDescriptionDefault
chat_nameYesName or partial name of the contact, group, or channel in Teams (e.g. 'Alice Smith', 'John Doe', 'Project Alpha').

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It discloses that the tool 'reads' (non-mutating), automatically matches the chat, and returns only author, timestamp, and text. However, it omits any mention of error conditions, ambiguous-name behavior, permission requirements, or whether reading the message marks it as read (relevant given the sibling get_last_unread_message). This is adequate but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences: the first establishes purpose and capability, the second states the return content. The warning 'NEVER call list_teams_chats first' is emphatic and placed at the end, making it memorable. There is no redundancy or filler; every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple, one-parameter read tool with no output schema and no annotations, the description covers the essential context: what it does, what it returns (author, timestamp, text), and a critical workflow warning. It does not address edge cases like 'no message found' or ambiguous matches, but that is a minor gap for a tool of this simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% for the single parameter chat_name, which already states 'Name or partial name.' The description repeats the partial-name capability and adds that it 'automatically matches the chat,' but that is more behavioral than parameter semantics. No meaningful new parameter-level meaning is added beyond the schema, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('read'), resource ('the single latest message'), and scope ('from a specific person, group, or channel in Teams'). It clearly differentiates from siblings like get_last_messages by emphasizing 'single' and from get_last_unread_message by not mentioning unread. The phrase 'PRIMARY TOOL' also signals its intended place among the alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly frames itself as the 'PRIMARY TOOL' for this task and gives a direct exclusion: 'NEVER call list_teams_chats first.' This is clear guidance on when to use the tool and when not to use a sibling. However, it does not discuss when to prefer get_last_unread_message or get_last_messages, so the guidance is good but not fully comprehensive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_last_messagesA

Reads the last N messages from a specific Teams chat. Use this ONLY when the user asks for multiple recent messages or recent conversation history. NEVER call list_teams_chats first.

ParametersJSON Schema
NameRequiredDescriptionDefault
countNoNumber of recent messages to return (default: 3, max: 20).
chat_nameYesName or partial name of the contact or group in Teams.

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description must carry the behavioral disclosure burden. It clearly indicates a read-only operation ('Reads'), but does not disclose return format, ordering, error behavior, or whether messages are marked as read. These are notable gaps for a no-annotation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short, purposeful sentences. The core purpose is front-loaded, followed by a crisp usage rule and a critical warning. No wasted words or redundant schema repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter read tool with full schema coverage, the description covers purpose, usage conditions, and a workflow constraint. It lacks an explicit statement about return shape or side effects, but the tool is simple enough that the missing details are minor.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents both count and chat_name fully. The description adds no additional parameter-level meaning beyond restating 'specific Teams chat,' so the baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description states a specific verb and resource: 'Reads the last N messages from a specific Teams chat.' It also clarifies the plural scope ('multiple recent messages'), which distinguishes it from singular siblings like get_last_message and get_last_unread_message.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use guidance: 'Use this ONLY when the user asks for multiple recent messages or recent conversation history.' It also gives a clear exclusion: 'NEVER call list_teams_chats first.' This strongly steers an agent away from inappropriate alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_last_unread_messageA

Reads unread messages. If 'chat_name' is provided, returns the latest unread message in that specific chat. If 'chat_name' is omitted, scans all Teams chats and returns a compact list of all unread messages with their senders and text in one single call. NEVER call list_teams_chats first.

ParametersJSON Schema
NameRequiredDescriptionDefault
chat_nameNoOptional contact or group name. Leave empty/omitted to scan unread messages across ALL Teams chats.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of disclosure. It correctly signals a read-only operation, explains both execution modes, and discloses the return format for the scan-all case ('compact list of all unread messages with their senders and text'). It doesn't cover rate limits or the empty-result case, but the core behavior is transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with zero waste: main action first, then the two-mode explanation, then a terse imperative exclusion. The most decision-relevant info (mode behavior) is front-loaded, and the 'NEVER' directive earns its place as a guardrail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple tool with one optional parameter and no annotations, the description is thorough: it covers both invocation modes, the return shape of the scan-all mode, and an exclusion. Minor gaps are the unspecified return format for the single-chat mode and the no-unread-messages case, but these are small for the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds value beyond the schema by explaining the behavioral consequence of omitting chat_name (scan all chats and return a compact list in one call) versus providing it (return latest in that specific chat), which the schema's 'Optional contact or group name' does not convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Reads') and resource ('unread messages'), and clearly distinguishes the tool from siblings by its focus on unread status. It differentiates behavior for the two invocation modes (specific chat vs. all chats), making it unambiguous what this tool does relative to get_last_message and get_last_messages.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit guidance on when to use it with vs. without chat_name, and includes a strong exclusion directive ('NEVER call list_teams_chats first') that prevents a common mistake. However, it doesn't explicitly contrast with get_last_message/get_last_messages, leaving the unread-vs-all distinction to be inferred rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_teams_chatsA

Lists chat names and activity timestamps from the Teams sidebar. Use ONLY when the user explicitly asks to list, see, or browse their conversations.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of chats to list (default: 10).

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description carries the full burden since no annotations are provided. It discloses the source (Teams sidebar) and the output contents (chat names and activity timestamps), making the read-only, listing nature clear. It could be more explicit about sorting or non-mutation, but the verb 'Lists' strongly implies a safe read operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences, with the core functionality in the first and the usage boundary in the second. No filler, repetition, or irrelevant detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple 1-param, no-output-schema tool, this is complete. The description states what is returned (chat names and timestamps), where from (Teams sidebar), and when to use it. The input schema covers the rest.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%: the only parameter, 'limit', is fully described with a default value. The description does not add any parameter semantics, which is appropriate because the schema already handles it. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Lists') tied to a clear resource: chat names and activity timestamps from the Teams sidebar. This clearly distinguishes it from sibling tools, which all deal with message-level operations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is explicitly gated: 'Use ONLY when the user explicitly asks to list, see, or browse their conversations.' This gives a precise when-to-use condition and implicitly warns against using it for message retrieval or sending, which are covered by siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

send_teams_messageA

Sends a text message to a specified Microsoft Teams chat or group.

ParametersJSON Schema
NameRequiredDescriptionDefault
messageYesThe text message to send.
chat_nameYesTarget contact or group name in Teams.

TDQS

A3.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It states the action but does not mention side effects, whether recipients are notified, required permissions, delivery guarantees, or what the return value indicates. For a message-sending tool, this is a notable transparency gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, well-structured sentence with no filler. The main action and target are front-loaded, making it easy for an agent to grasp quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple with two fully schema-documented parametersaineous, so the description is mostly adequate for invoking it. However, the absence of annotations and an output schema leaves behavioral details like success/error behavior and side effects undisclosed, which an agent may need when deciding whether and how to call it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema already explains both parameters. The description adds little beyond 'text message' and 'specified chat or group,' so it meets the baseline but does not enrich parameter meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('sends') with a clear resource ('text message to a specified Microsoft Teams chat or group'). It clearly distinguishes this write operation from the read/list siblings like get_last_message and list_teams_chats.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description makes the tool's use case clear: send a text message to a Teams chat or group. It does not explicitly name alternatives or exclusion conditions, but sibling tools are all read-oriented, so when to call send_teams_message versus them is readily inferable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv1.0.0
    • First observedget_last_message
    • First observedget_last_messages
    • First observedget_last_unread_message
    • First observedlist_teams_chats
    • First observedsend_teams_message

TDQS

A4.1/5.0

Scored across 5 tools

Disambiguation4/5

The read tools overlap somewhatβ€”get_last_message, get_last_unread_message, and get_last_messages all retrieve recent messagesβ€”but their purposes are differentiated by unread status, scope, and message count. The descriptions are explicit about when to use each, so agent misselection is unlikely but still possible.

Naming Consistency4/5

Tool names mostly follow a clear verb_noun pattern: get_last_*, send_teams_message, list_teams_chats. The get_last_message and get_last_messages singular/plural distinction is a minor inconsistency, but the overall pattern is readable and predictable.

Tool Count5/5

With only five tools, the set is tightly scoped for Teams messaging operations. Each tool serves a distinct core needβ€”read latest, read unread, read history, send, listβ€”without unnecessary bloat.

Completeness4/5

The set covers the primary Teams workflows: reading recent messages, checking unread activity, sending messages, and listing conversations. Minor gaps exist such as marking messages as read or searching historical messages, but agents can accomplish most common tasks without dead ends.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Enables browser automation with Puppeteer, supporting navigation, form interactions, and connection to active Chrome instances for comprehensive web page interaction.
    8
    3,295 npm
    484
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables LLMs to perform browser automation including web navigation, element interaction, and screenshot capture using Puppeteer. It provides capabilities for executing JavaScript in the browser and monitoring console logs for debugging and data extraction.
    36,709 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables token-efficient browser automation for AI chats like ChatGPT, Gemini, and Claude, allowing reading responses, sending messages, waiting for streaming replies, and bridging conversations between tabs via Chrome DevTools Protocol.
    5
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to scrape web pages, fill forms, take screenshots, and extract structured data via Chrome DevTools Protocol with zero external dependencies.
    MIT