diff --git a/.claude/skills/add-teams-v2/SKILL.md b/.claude/skills/add-teams-v2/SKILL.md index 20324f3..8f91aa1 100644 --- a/.claude/skills/add-teams-v2/SKILL.md +++ b/.claude/skills/add-teams-v2/SKILL.md @@ -31,10 +31,20 @@ npm run build ## Credentials -1. Go to [Azure Portal](https://portal.azure.com) > **Azure Bot** > **Create**. -2. Configure the messaging endpoint: `https://your-domain/webhook/teams`. -3. Add the **Microsoft Teams** channel. -4. Note the **App ID** and **Password** from the Azure AD app registration. +### Create Azure Bot + +1. Go to [Azure Portal](https://portal.azure.com) > search **Azure Bot** > **Create** +2. Choose **Multi Tenant** (default) or **Single Tenant** depending on your org setup +3. After creation, go to **Configuration**: + - Copy the **Microsoft App ID** + - Note the **App Tenant ID** (shown for Single Tenant) + - Set **Messaging endpoint** to `https://your-domain/api/webhooks/teams` +4. Click **Manage Password** > **Certificates & secrets** > **New client secret** — copy the Value immediately (shown only once) +5. Go to **Channels** > add **Microsoft Teams** > Accept terms > Apply + +### Create Teams App Package + +Create a `manifest.json` with your App ID, zip it with two icon PNGs (32x32 outline, 192x192 color), and sideload in Teams via **Apps** > **Manage your apps** > **Upload a custom app**. Sideloading requires Teams admin or a developer tenant (free via Microsoft 365 Developer Program). ### Configure environment @@ -42,11 +52,18 @@ Add to `.env`: ```bash TEAMS_APP_ID=your-app-id -TEAMS_APP_PASSWORD=your-app-password +TEAMS_APP_PASSWORD=your-client-secret +# For Single Tenant only: +TEAMS_APP_TENANT_ID=your-tenant-id +TEAMS_APP_TYPE=SingleTenant ``` Sync to container: `mkdir -p data/env && cp .env data/env/env` +### Webhook server + +The Chat SDK bridge automatically starts a shared webhook server on port 3000 (configurable via `WEBHOOK_PORT` env var). The server handles `/api/webhooks/teams` for Teams and other webhook-based adapters. This port must be publicly reachable from the internet for Azure Bot Service to deliver activities. + ## Next Steps If you're in the middle of `/setup`, return to the setup flow now. diff --git a/src/channels/teams.ts b/src/channels/teams.ts index f184bfe..0ddf4bd 100644 --- a/src/channels/teams.ts +++ b/src/channels/teams.ts @@ -10,11 +10,13 @@ import { registerChannelAdapter } from './channel-registry.js'; registerChannelAdapter('teams', { factory: () => { - const env = readEnvFile(['TEAMS_APP_ID', 'TEAMS_APP_PASSWORD']); + const env = readEnvFile(['TEAMS_APP_ID', 'TEAMS_APP_PASSWORD', 'TEAMS_APP_TENANT_ID', 'TEAMS_APP_TYPE']); if (!env.TEAMS_APP_ID) return null; const teamsAdapter = createTeamsAdapter({ appId: env.TEAMS_APP_ID, appPassword: env.TEAMS_APP_PASSWORD, + appType: (env.TEAMS_APP_TYPE as 'SingleTenant' | 'MultiTenant') || undefined, + appTenantId: env.TEAMS_APP_TENANT_ID || undefined, }); return createChatSdkBridge({ adapter: teamsAdapter, concurrency: 'concurrent', supportsThreads: true }); },