Skip to main content

Teams MCP Python

A Python implementation of Microsoft Teams MCP (Model Context Protocol) server with a reusable OAuth2 authentication library that can be used for building MCP servers for any OAuth2-based service.

Features

Reusable OAuth2 Library (mcp_oauth2)

  • Generic OAuth2 implementation that works with any OAuth2 provider
  • Built-in providers for Microsoft, Google, and generic OAuth2 services
  • Standardized MCP tools (is_authenticated and authorize) for OAuth2 flow
  • PKCE support for public clients (no client secret required)
  • Automatic token refresh handling
  • Easy to extend for new OAuth2 providers

Teams MCP Server

  • Full Microsoft Teams integration via Graph API
  • Chat management: List, create, and manage Teams chats
  • Messaging: Send and retrieve messages
  • Rate limiting with exponential backoff
  • Async/await throughout for performance

Installation

Using uvx (Recommended)

The easiest way to use this MCP server is with uvx, which allows you to run Python applications without manual installation:

# Run the Teams MCP server directly
uvx teams-mcp-python

# Or specify with full package name
uvx --from teams-mcp-python teams-mcp

Using pip

pip install teams-mcp-python

Quick Start

1. Azure AD Setup

First, register an app in Azure Portal:

  1. Go to Azure Portal > Azure Active Directory > App registrations
  2. Click "New registration"
  3. Set redirect URI to http://localhost:3000/auth/callback (Web platform)
  4. Grant these API permissions (Delegated):
    • Chat.ReadWrite
    • ChatMessage.Send
    • User.Read
    • offline_access

2. Configuration

Create a .env file in your project:

AZURE_CLIENT_ID=your-client-id
AZURE_TENANT_ID=your-tenant-id
AZURE_CLIENT_SECRET=your-client-secret  # Optional for public clients
AZURE_REDIRECT_URI=http://localhost:3000/auth/callback
DEBUG=true

3. Using with Claude Desktop

Add to your Claude Desktop configuration file:

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json

Option 1: Using uvx (Recommended)

{
  "mcpServers": {
    "teams": {
      "command": "uvx",
      "args": ["teams-mcp-python"],
      "env": {
        "AZURE_CLIENT_ID": "your-client-id",
        "AZURE_TENANT_ID": "your-tenant-id",
        "AZURE_REDIRECT_URI": "http://localhost:3000/auth/callback"
      }
    }
  }
}

Option 2: Using Python

{
  "mcpServers": {
    "teams": {
      "command": "python",
      "args": ["-m", "teams_mcp"],
      "env": {
        "AZURE_CLIENT_ID": "your-client-id",
        "AZURE_TENANT_ID": "your-tenant-id",
        "AZURE_REDIRECT_URI": "http://localhost:3000/auth/callback"
      }
    }
  }
}

Option 3: If installed globally

{
  "mcpServers": {
    "teams": {
      "command": "teams-mcp",
      "env": {
        "AZURE_CLIENT_ID": "your-client-id",
        "AZURE_TENANT_ID": "your-tenant-id",
        "AZURE_REDIRECT_URI": "http://localhost:3000/auth/callback"
      }
    }
  }
}

4. Authentication Flow

When using the Teams MCP server in Claude:

  1. First use - Claude will provide an authentication URL
  2. Open the URL in your browser and sign in with your Microsoft account
  3. Copy the authorization code from the redirect URL
  4. Provide the code to Claude to complete authentication

Example conversation:

You: List my Teams chats

Claude: I'll help you list your Teams chats. First, I need to check your authentication status.

[Calls teams_is_authenticated]

You need to authenticate. Please visit this URL:
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?...

After signing in, you'll be redirected to a URL with a code parameter. Please provide that code.

You: The URL shows: http://localhost:3000/auth/callback?code=ABC123...

Claude: [Calls teams_authorize with the code]

Great! I've successfully authenticated. Now let me list your chats.

[Calls teams_list_chats]

Here are your Teams chats:
1. Project Team - Group chat with 5 members
2. John Doe - One-on-one chat
...

Available Tools

The Teams MCP server provides these tools:

Authentication Tools

  • teams_is_authenticated - Check authentication status or get auth URL
  • teams_authorize - Complete OAuth2 flow with authorization code

Teams Tools

  • teams_list_chats - List all chats with optional filtering
  • teams_create_chat - Create new one-on-one or group chats
  • teams_send_message - Send messages to a chat
  • teams_get_messages - Retrieve messages from a chat

Creating Your Own OAuth2 MCP Server

The mcp_oauth2 library makes it easy to create MCP servers for any OAuth2 service:

from mcp_oauth2 import OAuth2Config, GenericOAuth2Provider, create_oauth2_tools
from mcp.server import Server

# Configure your OAuth2 provider
oauth_config = OAuth2Config(
    client_id="your-client-id",
    client_secret="your-client-secret",  # Optional for PKCE
    redirect_uri="http://localhost:3000/auth/callback",
    scopes=["scope1", "scope2"],
    authorization_endpoint="https://provider.com/oauth/authorize",
    token_endpoint="https://provider.com/oauth/token"
)

# Create provider instance
provider = GenericOAuth2Provider("myprovider", oauth_config)

# Get OAuth2 MCP tools
oauth_tools = create_oauth2_tools(provider)  # Creates is_authenticated and authorize tools

# Add to your MCP server
server = Server("my-mcp-server")

@server.list_tools()
async def list_tools():
    return oauth_tools + your_custom_tools

OAuth2 Authentication Flow

The library implements a standard OAuth2 flow with two MCP tools:

1. {provider}_is_authenticated

Check if tokens are valid or generate an auth URL:

// Request without tokens - generates auth URL
{
  "callback_url": "http://localhost:3000/auth/callback",
  "callback_state": { "custom": "data" }
}

// Response
{
  "authenticated": false,
  "auth_url": "https://provider.com/oauth/authorize?...",
  "state": "random-state-string"
}

// Request with tokens - validates them
{
  "tokens": {
    "access_token": "...",
    "refresh_token": "..."
  }
}

// Response
{
  "authenticated": true,
  "tokens": { /* refreshed tokens if needed */ }
}

2. {provider}_authorize

Exchange authorization code for tokens:

// Request
{
  "code": "auth-code-from-callback",
  "callback_url": "http://localhost:3000/auth/callback?code=...&state=...",
  "callback_state": { "custom": "data" }
}

// Response
{
  "success": true,
  "tokens": {
    "access_token": "...",
    "refresh_token": "...",
    "expires_in": 3600
  }
}

Built-in OAuth2 Providers

Microsoft Provider

from mcp_oauth2 import MicrosoftProvider, OAuth2Config

config = OAuth2Config(
    client_id="your-client-id",
    client_secret="your-secret",  # Optional
    scopes=["User.Read", "Mail.Read"]
)

provider = MicrosoftProvider(config, tenant_id="common")

Google Provider

from mcp_oauth2 import GoogleProvider, OAuth2Config

config = OAuth2Config(
    client_id="your-client-id",
    client_secret="your-secret",
    scopes=["https://www.googleapis.com/auth/drive.readonly"]
)

provider = GoogleProvider(config)

Generic Provider

from mcp_oauth2 import GenericOAuth2Provider, OAuth2Config

config = OAuth2Config(
    client_id="your-client-id",
    client_secret="your-secret",
    authorization_endpoint="https://example.com/oauth/authorize",
    token_endpoint="https://example.com/oauth/token",
    scopes=["read", "write"]
)

provider = GenericOAuth2Provider("custom", config)

Creating a Custom OAuth2 Provider

Extend the base OAuth2Provider class:

from mcp_oauth2 import OAuth2Provider, OAuth2Config, TokenResponse

class MyCustomProvider(OAuth2Provider):
    @property
    def name(self) -> str:
        return "mycustom"
    
    async def exchange_code(self, code: str, code_verifier: Optional[str] = None) -> TokenResponse:
        # Custom implementation
        pass
    
    async def refresh_token(self, refresh_token: str) -> TokenResponse:
        # Custom implementation
        pass

Examples

See the examples/ directory for complete implementations:

  • google_drive_mcp.py - Google Drive MCP server
  • github_mcp.py - GitHub MCP server

Using Example Servers with Claude Desktop

You can run the example servers using uvx as well:

For the Google Drive example:

{
  "mcpServers": {
    "google-drive": {
      "command": "uvx",
      "args": ["--from", "teams-mcp-python", "python", "-m", "examples.google_drive_mcp"],
      "env": {
        "GOOGLE_CLIENT_ID": "your-client-id",
        "GOOGLE_CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}

Or with a local installation:

{
  "mcpServers": {
    "google-drive": {
      "command": "python",
      "args": ["/path/to/examples/google_drive_mcp.py"],
      "env": {
        "GOOGLE_CLIENT_ID": "your-client-id",
        "GOOGLE_CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}

For the GitHub example:

{
  "mcpServers": {
    "github": {
      "command": "uvx",
      "args": ["--from", "teams-mcp-python", "python", "-m", "examples.github_mcp"],
      "env": {
        "GITHUB_CLIENT_ID": "your-client-id",
        "GITHUB_CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}

Architecture

OAuth2 Library Structure

mcp_oauth2/
├── base.py          # Base classes and interfaces
├── tools.py         # MCP tool creation
└── providers/       # OAuth2 provider implementations
    ├── generic.py   # Generic OAuth2 provider
    ├── microsoft.py # Microsoft-specific provider
    └── google.py    # Google-specific provider

Teams MCP Structure

teams_mcp/
├── server.py        # Main MCP server
├── config.py        # Configuration
├── api/            # Teams API client
│   ├── client.py   # Graph API wrapper
│   └── rate_limiter.py
└── tools/          # Teams-specific MCP tools
    ├── list_chats.py
    ├── create_chat.py
    ├── send_message.py
    └── get_messages.py

Development

Setup

# Clone the repository
git clone https://github.com/shmaxi/teams-mcp-python.git
cd teams-mcp-python

# Install in development mode
pip install -e ".[dev]"

Testing

# Run tests
pytest

# With coverage
pytest --cov=src

# Type checking
mypy src

Code Quality

# Format code
black src tests

# Lint
ruff src tests

Publishing

To publish a new version to PyPI:

# Build the package
python -m build

# Upload to PyPI (requires PyPI credentials)
python -m twine upload dist/*

After publishing, the package will be available via:

  • pip install teams-mcp-python
  • uvx teams-mcp-python (for direct execution without installation)

License

MIT License - see LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Metadata

Release files for teams-mcp-python 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for teams-mcp-python 0.2.1
File Size Uploaded
teams_mcp_python-0.2.1.tar.gz 21.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for teams-mcp-python 0.2.1
File Interpreter ABI Platform
teams_mcp_python-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 46.7 kB

Release files / teams_mcp_python-0.2.1.tar.gz

Download URL teams_mcp_python-0.2.1.tar.gz
Size 21.5 kB
Tags Source
SHA-256 checksum
How to use checksums
0bca70ca559649d1ae0f0c4babcdf1799184d7d61a0a78013baf9974bd8b99a3
BLAKE2b-256 checksum
How to use checksums
80e11ed607e297fb72d5a1014f892d45531158fa723458fd4ea132a9c1e35c1c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.11.5

Release files / teams_mcp_python-0.2.1-py3-none-any.whl

Download URL teams_mcp_python-0.2.1-py3-none-any.whl
Size 25.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
426b7ec26be5aae5d009a762f995a507deb6a6f8eb4ec5e01255fe374dce405f
BLAKE2b-256 checksum
How to use checksums
53f3ef29bbfe5a0d78580fb6a6486144689fa5b960720f6ae381fe2c48834f3c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.11.5

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

0.2.0

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page