teams-mcp-python


Nameteams-mcp-python JSON
Version 0.2.1 PyPI version JSON
download
home_pageNone
SummaryMicrosoft Teams MCP server with reusable OAuth2 authentication
upload_time2025-07-12 17:32:34
maintainerNone
docs_urlNone
authorTeams MCP Python Contributors
requires_python>=3.8
licenseMIT
keywords chat mcp messaging microsoft oauth2 teams
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 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](https://github.com/astral-sh/uv), which allows you to run Python applications without manual installation:

```bash
# 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

```bash
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:

```env
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)

```json
{
  "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

```json
{
  "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

```json
{
  "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:

```python
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:

```json
// 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:

```json
// 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

```python
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

```python
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

```python
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:

```python
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:

```json
{
  "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:

```json
{
  "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:

```json
{
  "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

```bash
# 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

```bash
# Run tests
pytest

# With coverage
pytest --cov=src

# Type checking
mypy src
```

### Code Quality

```bash
# Format code
black src tests

# Lint
ruff src tests
```

### Publishing

To publish a new version to PyPI:

```bash
# 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.
            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "teams-mcp-python",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "chat, mcp, messaging, microsoft, oauth2, teams",
    "author": "Teams MCP Python Contributors",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/80/e1/1ed607e297fb72d5a1014f892d45531158fa723458fd4ea132a9c1e35c1c/teams_mcp_python-0.2.1.tar.gz",
    "platform": null,
    "description": "# Teams MCP Python\n\nA 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.\n\n## Features\n\n### Reusable OAuth2 Library (`mcp_oauth2`)\n\n- **Generic OAuth2 implementation** that works with any OAuth2 provider\n- **Built-in providers** for Microsoft, Google, and generic OAuth2 services  \n- **Standardized MCP tools** (`is_authenticated` and `authorize`) for OAuth2 flow\n- **PKCE support** for public clients (no client secret required)\n- **Automatic token refresh** handling\n- **Easy to extend** for new OAuth2 providers\n\n### Teams MCP Server\n\n- **Full Microsoft Teams integration** via Graph API\n- **Chat management**: List, create, and manage Teams chats\n- **Messaging**: Send and retrieve messages\n- **Rate limiting** with exponential backoff\n- **Async/await** throughout for performance\n\n## Installation\n\n### Using uvx (Recommended)\n\nThe easiest way to use this MCP server is with [uvx](https://github.com/astral-sh/uv), which allows you to run Python applications without manual installation:\n\n```bash\n# Run the Teams MCP server directly\nuvx teams-mcp-python\n\n# Or specify with full package name\nuvx --from teams-mcp-python teams-mcp\n```\n\n### Using pip\n\n```bash\npip install teams-mcp-python\n```\n\n## Quick Start\n\n### 1. Azure AD Setup\n\nFirst, register an app in Azure Portal:\n\n1. Go to Azure Portal > Azure Active Directory > App registrations\n2. Click \"New registration\"\n3. Set redirect URI to `http://localhost:3000/auth/callback` (Web platform)\n4. Grant these API permissions (Delegated):\n   - `Chat.ReadWrite`\n   - `ChatMessage.Send`\n   - `User.Read`\n   - `offline_access`\n\n### 2. Configuration\n\nCreate a `.env` file in your project:\n\n```env\nAZURE_CLIENT_ID=your-client-id\nAZURE_TENANT_ID=your-tenant-id\nAZURE_CLIENT_SECRET=your-client-secret  # Optional for public clients\nAZURE_REDIRECT_URI=http://localhost:3000/auth/callback\nDEBUG=true\n```\n\n### 3. Using with Claude Desktop\n\nAdd to your Claude Desktop configuration file:\n\n**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`  \n**Windows:** `%APPDATA%\\Claude\\claude_desktop_config.json`\n\n#### Option 1: Using uvx (Recommended)\n\n```json\n{\n  \"mcpServers\": {\n    \"teams\": {\n      \"command\": \"uvx\",\n      \"args\": [\"teams-mcp-python\"],\n      \"env\": {\n        \"AZURE_CLIENT_ID\": \"your-client-id\",\n        \"AZURE_TENANT_ID\": \"your-tenant-id\",\n        \"AZURE_REDIRECT_URI\": \"http://localhost:3000/auth/callback\"\n      }\n    }\n  }\n}\n```\n\n#### Option 2: Using Python\n\n```json\n{\n  \"mcpServers\": {\n    \"teams\": {\n      \"command\": \"python\",\n      \"args\": [\"-m\", \"teams_mcp\"],\n      \"env\": {\n        \"AZURE_CLIENT_ID\": \"your-client-id\",\n        \"AZURE_TENANT_ID\": \"your-tenant-id\",\n        \"AZURE_REDIRECT_URI\": \"http://localhost:3000/auth/callback\"\n      }\n    }\n  }\n}\n```\n\n#### Option 3: If installed globally\n\n```json\n{\n  \"mcpServers\": {\n    \"teams\": {\n      \"command\": \"teams-mcp\",\n      \"env\": {\n        \"AZURE_CLIENT_ID\": \"your-client-id\",\n        \"AZURE_TENANT_ID\": \"your-tenant-id\",\n        \"AZURE_REDIRECT_URI\": \"http://localhost:3000/auth/callback\"\n      }\n    }\n  }\n}\n```\n\n### 4. Authentication Flow\n\nWhen using the Teams MCP server in Claude:\n\n1. **First use** - Claude will provide an authentication URL\n2. **Open the URL** in your browser and sign in with your Microsoft account\n3. **Copy the authorization code** from the redirect URL\n4. **Provide the code** to Claude to complete authentication\n\nExample conversation:\n```\nYou: List my Teams chats\n\nClaude: I'll help you list your Teams chats. First, I need to check your authentication status.\n\n[Calls teams_is_authenticated]\n\nYou need to authenticate. Please visit this URL:\nhttps://login.microsoftonline.com/common/oauth2/v2.0/authorize?...\n\nAfter signing in, you'll be redirected to a URL with a code parameter. Please provide that code.\n\nYou: The URL shows: http://localhost:3000/auth/callback?code=ABC123...\n\nClaude: [Calls teams_authorize with the code]\n\nGreat! I've successfully authenticated. Now let me list your chats.\n\n[Calls teams_list_chats]\n\nHere are your Teams chats:\n1. Project Team - Group chat with 5 members\n2. John Doe - One-on-one chat\n...\n```\n\n## Available Tools\n\nThe Teams MCP server provides these tools:\n\n### Authentication Tools\n- `teams_is_authenticated` - Check authentication status or get auth URL\n- `teams_authorize` - Complete OAuth2 flow with authorization code\n\n### Teams Tools\n- `teams_list_chats` - List all chats with optional filtering\n- `teams_create_chat` - Create new one-on-one or group chats\n- `teams_send_message` - Send messages to a chat\n- `teams_get_messages` - Retrieve messages from a chat\n\n## Creating Your Own OAuth2 MCP Server\n\nThe `mcp_oauth2` library makes it easy to create MCP servers for any OAuth2 service:\n\n```python\nfrom mcp_oauth2 import OAuth2Config, GenericOAuth2Provider, create_oauth2_tools\nfrom mcp.server import Server\n\n# Configure your OAuth2 provider\noauth_config = OAuth2Config(\n    client_id=\"your-client-id\",\n    client_secret=\"your-client-secret\",  # Optional for PKCE\n    redirect_uri=\"http://localhost:3000/auth/callback\",\n    scopes=[\"scope1\", \"scope2\"],\n    authorization_endpoint=\"https://provider.com/oauth/authorize\",\n    token_endpoint=\"https://provider.com/oauth/token\"\n)\n\n# Create provider instance\nprovider = GenericOAuth2Provider(\"myprovider\", oauth_config)\n\n# Get OAuth2 MCP tools\noauth_tools = create_oauth2_tools(provider)  # Creates is_authenticated and authorize tools\n\n# Add to your MCP server\nserver = Server(\"my-mcp-server\")\n\n@server.list_tools()\nasync def list_tools():\n    return oauth_tools + your_custom_tools\n```\n\n## OAuth2 Authentication Flow\n\nThe library implements a standard OAuth2 flow with two MCP tools:\n\n### 1. `{provider}_is_authenticated`\n\nCheck if tokens are valid or generate an auth URL:\n\n```json\n// Request without tokens - generates auth URL\n{\n  \"callback_url\": \"http://localhost:3000/auth/callback\",\n  \"callback_state\": { \"custom\": \"data\" }\n}\n\n// Response\n{\n  \"authenticated\": false,\n  \"auth_url\": \"https://provider.com/oauth/authorize?...\",\n  \"state\": \"random-state-string\"\n}\n\n// Request with tokens - validates them\n{\n  \"tokens\": {\n    \"access_token\": \"...\",\n    \"refresh_token\": \"...\"\n  }\n}\n\n// Response\n{\n  \"authenticated\": true,\n  \"tokens\": { /* refreshed tokens if needed */ }\n}\n```\n\n### 2. `{provider}_authorize`\n\nExchange authorization code for tokens:\n\n```json\n// Request\n{\n  \"code\": \"auth-code-from-callback\",\n  \"callback_url\": \"http://localhost:3000/auth/callback?code=...&state=...\",\n  \"callback_state\": { \"custom\": \"data\" }\n}\n\n// Response\n{\n  \"success\": true,\n  \"tokens\": {\n    \"access_token\": \"...\",\n    \"refresh_token\": \"...\",\n    \"expires_in\": 3600\n  }\n}\n```\n\n## Built-in OAuth2 Providers\n\n### Microsoft Provider\n\n```python\nfrom mcp_oauth2 import MicrosoftProvider, OAuth2Config\n\nconfig = OAuth2Config(\n    client_id=\"your-client-id\",\n    client_secret=\"your-secret\",  # Optional\n    scopes=[\"User.Read\", \"Mail.Read\"]\n)\n\nprovider = MicrosoftProvider(config, tenant_id=\"common\")\n```\n\n### Google Provider\n\n```python\nfrom mcp_oauth2 import GoogleProvider, OAuth2Config\n\nconfig = OAuth2Config(\n    client_id=\"your-client-id\",\n    client_secret=\"your-secret\",\n    scopes=[\"https://www.googleapis.com/auth/drive.readonly\"]\n)\n\nprovider = GoogleProvider(config)\n```\n\n### Generic Provider\n\n```python\nfrom mcp_oauth2 import GenericOAuth2Provider, OAuth2Config\n\nconfig = OAuth2Config(\n    client_id=\"your-client-id\",\n    client_secret=\"your-secret\",\n    authorization_endpoint=\"https://example.com/oauth/authorize\",\n    token_endpoint=\"https://example.com/oauth/token\",\n    scopes=[\"read\", \"write\"]\n)\n\nprovider = GenericOAuth2Provider(\"custom\", config)\n```\n\n## Creating a Custom OAuth2 Provider\n\nExtend the base `OAuth2Provider` class:\n\n```python\nfrom mcp_oauth2 import OAuth2Provider, OAuth2Config, TokenResponse\n\nclass MyCustomProvider(OAuth2Provider):\n    @property\n    def name(self) -> str:\n        return \"mycustom\"\n    \n    async def exchange_code(self, code: str, code_verifier: Optional[str] = None) -> TokenResponse:\n        # Custom implementation\n        pass\n    \n    async def refresh_token(self, refresh_token: str) -> TokenResponse:\n        # Custom implementation\n        pass\n```\n\n## Examples\n\nSee the `examples/` directory for complete implementations:\n\n- `google_drive_mcp.py` - Google Drive MCP server\n- `github_mcp.py` - GitHub MCP server\n\n### Using Example Servers with Claude Desktop\n\nYou can run the example servers using uvx as well:\n\nFor the Google Drive example:\n\n```json\n{\n  \"mcpServers\": {\n    \"google-drive\": {\n      \"command\": \"uvx\",\n      \"args\": [\"--from\", \"teams-mcp-python\", \"python\", \"-m\", \"examples.google_drive_mcp\"],\n      \"env\": {\n        \"GOOGLE_CLIENT_ID\": \"your-client-id\",\n        \"GOOGLE_CLIENT_SECRET\": \"your-client-secret\"\n      }\n    }\n  }\n}\n```\n\nOr with a local installation:\n\n```json\n{\n  \"mcpServers\": {\n    \"google-drive\": {\n      \"command\": \"python\",\n      \"args\": [\"/path/to/examples/google_drive_mcp.py\"],\n      \"env\": {\n        \"GOOGLE_CLIENT_ID\": \"your-client-id\",\n        \"GOOGLE_CLIENT_SECRET\": \"your-client-secret\"\n      }\n    }\n  }\n}\n```\n\nFor the GitHub example:\n\n```json\n{\n  \"mcpServers\": {\n    \"github\": {\n      \"command\": \"uvx\",\n      \"args\": [\"--from\", \"teams-mcp-python\", \"python\", \"-m\", \"examples.github_mcp\"],\n      \"env\": {\n        \"GITHUB_CLIENT_ID\": \"your-client-id\",\n        \"GITHUB_CLIENT_SECRET\": \"your-client-secret\"\n      }\n    }\n  }\n}\n```  \n\n## Architecture\n\n### OAuth2 Library Structure\n\n```\nmcp_oauth2/\n\u251c\u2500\u2500 base.py          # Base classes and interfaces\n\u251c\u2500\u2500 tools.py         # MCP tool creation\n\u2514\u2500\u2500 providers/       # OAuth2 provider implementations\n    \u251c\u2500\u2500 generic.py   # Generic OAuth2 provider\n    \u251c\u2500\u2500 microsoft.py # Microsoft-specific provider\n    \u2514\u2500\u2500 google.py    # Google-specific provider\n```\n\n### Teams MCP Structure\n\n```\nteams_mcp/\n\u251c\u2500\u2500 server.py        # Main MCP server\n\u251c\u2500\u2500 config.py        # Configuration\n\u251c\u2500\u2500 api/            # Teams API client\n\u2502   \u251c\u2500\u2500 client.py   # Graph API wrapper\n\u2502   \u2514\u2500\u2500 rate_limiter.py\n\u2514\u2500\u2500 tools/          # Teams-specific MCP tools\n    \u251c\u2500\u2500 list_chats.py\n    \u251c\u2500\u2500 create_chat.py\n    \u251c\u2500\u2500 send_message.py\n    \u2514\u2500\u2500 get_messages.py\n```\n\n## Development\n\n### Setup\n\n```bash\n# Clone the repository\ngit clone https://github.com/shmaxi/teams-mcp-python.git\ncd teams-mcp-python\n\n# Install in development mode\npip install -e \".[dev]\"\n```\n\n### Testing\n\n```bash\n# Run tests\npytest\n\n# With coverage\npytest --cov=src\n\n# Type checking\nmypy src\n```\n\n### Code Quality\n\n```bash\n# Format code\nblack src tests\n\n# Lint\nruff src tests\n```\n\n### Publishing\n\nTo publish a new version to PyPI:\n\n```bash\n# Build the package\npython -m build\n\n# Upload to PyPI (requires PyPI credentials)\npython -m twine upload dist/*\n```\n\nAfter publishing, the package will be available via:\n- `pip install teams-mcp-python`\n- `uvx teams-mcp-python` (for direct execution without installation)\n\n## License\n\nMIT License - see LICENSE file for details.\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Microsoft Teams MCP server with reusable OAuth2 authentication",
    "version": "0.2.1",
    "project_urls": null,
    "split_keywords": [
        "chat",
        " mcp",
        " messaging",
        " microsoft",
        " oauth2",
        " teams"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "53f3ef29bbfe5a0d78580fb6a6486144689fa5b960720f6ae381fe2c48834f3c",
                "md5": "a433faf22eb0ed12c2a9c2914ab936fc",
                "sha256": "426b7ec26be5aae5d009a762f995a507deb6a6f8eb4ec5e01255fe374dce405f"
            },
            "downloads": -1,
            "filename": "teams_mcp_python-0.2.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "a433faf22eb0ed12c2a9c2914ab936fc",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 25278,
            "upload_time": "2025-07-12T17:32:33",
            "upload_time_iso_8601": "2025-07-12T17:32:33.360240Z",
            "url": "https://files.pythonhosted.org/packages/53/f3/ef29bbfe5a0d78580fb6a6486144689fa5b960720f6ae381fe2c48834f3c/teams_mcp_python-0.2.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "80e11ed607e297fb72d5a1014f892d45531158fa723458fd4ea132a9c1e35c1c",
                "md5": "7db010f792de88fda56d307322bfd693",
                "sha256": "0bca70ca559649d1ae0f0c4babcdf1799184d7d61a0a78013baf9974bd8b99a3"
            },
            "downloads": -1,
            "filename": "teams_mcp_python-0.2.1.tar.gz",
            "has_sig": false,
            "md5_digest": "7db010f792de88fda56d307322bfd693",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 21457,
            "upload_time": "2025-07-12T17:32:34",
            "upload_time_iso_8601": "2025-07-12T17:32:34.597229Z",
            "url": "https://files.pythonhosted.org/packages/80/e1/1ed607e297fb72d5a1014f892d45531158fa723458fd4ea132a9c1e35c1c/teams_mcp_python-0.2.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-12 17:32:34",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "teams-mcp-python"
}
        
Elapsed time: 1.31879s