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_authenticatedandauthorize) 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:
- Go to Azure Portal > Azure Active Directory > App registrations
- Click "New registration"
- Set redirect URI to
http://localhost:3000/auth/callback(Web platform) - Grant these API permissions (Delegated):
Chat.ReadWriteChatMessage.SendUser.Readoffline_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:
- First use - Claude will provide an authentication URL
- Open the URL in your browser and sign in with your Microsoft account
- Copy the authorization code from the redirect URL
- 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 URLteams_authorize- Complete OAuth2 flow with authorization code
Teams Tools
teams_list_chats- List all chats with optional filteringteams_create_chat- Create new one-on-one or group chatsteams_send_message- Send messages to a chatteams_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 servergithub_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-pythonuvx 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)
| File | Size | Uploaded | |
|---|---|---|---|
| teams_mcp_python-0.2.1.tar.gz | 21.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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
|