Teams会议记录Webhook管理服务器

一个用于管理Teams会议记录和录制变更通知的Microsoft Graph Webhook订阅的MCP服务器,采用应用级认证。

  • by ITSpecialist111
  • TypeScript
  • 本地部署
  • 3 星标
  • 更新于
在 GitHub 查看 ITSpecialist111/MicrosoftGraph_Transcript_Webhook_MCP

使用说明

转录Webhook MCP服务器

一个MCP服务器,用于管理团队会议记录的Microsoft Graph webhook订阅并记录更改通知。用途 应用层 (客户端凭据)身份验证。

伴侣: 转录MCP服务器 (委托OBO认证)——按需转录检索服务器。


建筑

┌─────────────────────────────────────────┐
│  Transcripts Webhook MCP Server         │
│  Auth: Application (Client Credentials) │
│                                         │
│  POST /mcp ─────── MCP Protocol         │
│    Tools (8):                           │
│    • subscribe_to_transcripts           │
│    • subscribe_to_recordings            │
│    • list_subscriptions                 │
│    • renew_subscription                 │
│    • delete_subscription                │
│    • get_notification_log               │
│    • get_transcript_content             │
│    • get_recording_url                  │
│                                         │
│    Resources (5):                       │
│    • webhook://status                   │
│    • webhook://subscriptions/{id}       │
│    • webhook://notifications/{index}    │
│    • webhook://transcripts/{u}/{m}/{t}  │
│    • webhook://recordings/{u}/{m}/{r}   │
│                                         │
│  POST /notifications ─── Graph Webhook  │
│    • Validation handshake               │
│    • Notification processing            │
│    • Lifecycle event handling            │
│                                         │
│  GET /health ────── Health Check        │
└─────────────────┬───────────────────────┘
                  │
      ┌───────────┴──────────┐
      ▼                      ▼
┌──────────┐         ┌──────────────┐
│  Graph   │         │  Agent /     │
│  Webhooks│         │  Copilot     │
│  (push)  │         │  (pull MCP)  │
└──────────┘         └──────────────┘

授权与应用程序授权

转录MCP服务器 此Webhook服务器
认证流程 委托OBO(用户在场) 仅应用程序客户端凭据
身份 充当登录用户 充当应用程序
范围 仅限用户会议 所有用户会议
用例 按需检索 事件驱动自动化
扩展 缩放到0(按需) 始终打开(webhook侦听器)

工具

工具 说明
subscribe_to_transcripts 为所有用户的新转录事件创建webhook订阅
subscribe_to_recordings 为所有用户的新录制事件创建webhook订阅
list_subscriptions 列出所有活动的webhook订阅(本地+可选Graph API检查)
renew_subscription 在订阅到期之前延长订阅期限(最长约70小时)
delete_subscription 删除webhook订阅
get_notification_log 查看最近收到的通知和处理结果
get_transcript_content 使用用户ID、会议ID和转录ID从通知日志中获取特定会议的完整转录(VTT格式)
get_recording_url 使用通知日志中的userId、meetingId和recordingId获取特定会议录制的限时下载URL

资源

MCP资源提供了结构化的、URI可寻址的数据,代理可以直接读取这些数据,从而补充了上述工具。

资源 URI 描述
服务器状态 webhook://status 带有健康状况、活动订阅、通知统计和配置的实时仪表板
订阅详细信息 webhook://subscriptions/{subscriptionId} 特定跟踪订阅的详细信息(到期、通知URL、剩余时间)
通知条目 webhook://notifications/{index} 按索引(0=最新)显示的特定通知,包含所有字段,包括成绩单内容
成绩单内容 webhook://transcripts/{userId}/{meetingId}/{transcriptId} 从Microsoft Graph实时获取完整的VTT成绩单
录制URL webhook://recordings/{userId}/{meetingId}/{recordingId} 从Microsoft Graph实时获取的限时下载URL

注: 资源模板通过以下方式列出 resources/templates/list 并支持自动完成通知日志中的变量。


场景和用例

1.自动会议记录

AI代理监控整个组织的所有团队会议。创建成绩单时,它会自动获取内容,生成包含操作项的摘要,并将其发布到Teams频道或SharePoint网站。

Meeting ends → Graph notification → auto-fetch transcript → agent summarises → posts to channel

使用的工具: subscribe_to_transcripts → get_notification_log → get_transcript_content

2.合规与记录保存

合规团队需要对所有记录的会议进行审计跟踪。webhook服务器实时捕获每个记录事件,代理定期检查日志并将记录URL存档到合规系统。

Recording created → Graph notification → agent retrieves download URL → archives to compliance store

使用的工具: subscribe_to_recordings → get_notification_log → get_recording_url

3.实时会议智能仪表板

连接到此MCP服务器的Copilot Studio代理为管理人员提供了一个对话界面,可以提出以下问题:

  • “今天有会议记录吗?”
  • “给我看上次项目脱口秀的记录”
  • “本周收到了多少份成绩单通知?”

使用的工具: get_notification_log → get_transcript_content

4.会议情绪与主题分析

每次会议后,代理都会获取记录并运行情绪分析或主题提取。结果存储在数据库中用于趋势跟踪,例如跟踪团队士气在冲刺周期中的变化。

Transcript notification → fetch VTT content → parse speakers & dialogue → analyse sentiment → store trends

使用的工具: subscribe_to_transcripts → get_transcript_content

5.自动跟进电子邮件

代理人观察新的记录,总结讨论,提取行动项目和所有者,然后起草后续电子邮件给会议参与者。

Transcript created → fetch content → extract action items → draft & send follow-up email

使用的工具: get_notification_log → get_transcript_content

6.多租户监控

MSP或IT团队部署具有应用程序级权限的此服务器,以监控整个租户的会议活动,无需单个用户登录。始终在线的webhook侦听器确保即使在工作时间之外也不会错过任何事件。

主要优势:应用程序身份验证意味着服务器独立于任何用户会话运行。

7.培训和知识库

自动捕获培训课程、入职电话或客户演示的会议记录。代理获取成绩单,清理VTT格式,并将其作为可搜索文档存储在知识库中。

Training meeting ends → transcript notification → fetch content → clean & index → add to knowledge base

使用的工具: subscribe_to_transcripts → get_transcript_content

8.订阅健康监测

代理会定期检查订阅状态,并在订阅到期前自动续订(最大生存期约为70小时)。如果Graph删除了订阅,代理将检测生命周期事件并重新创建。

Agent on schedule → list_subscriptions (with Graph check) → renew if < 12h remaining → alert if missing

使用的工具: list_subscriptions → renew_subscription → subscribe_to_transcripts


先决条件

Azure应用程序注册

创建一个 分开 应用程序注册(或向现有应用程序添加应用程序权限):

  1. 首选 Azure 门户 → 应用程序注册 → 新注册
  2. 姓名: Transcripts Webhook MCP (或类似)
  3. 支持的帐户类型: 仅此组织目录中的帐户

应用程序权限

权限 类型 为什么
OnlineMeetingTranscript.Read.All 应用程序 接收创建的成绩单通知
OnlineMeetingRecording.Read.All 应用程序 接收录制创建的通知
OnlineMeetings.Read.All 应用程序 读取任何用户的会议详细信息

重要:这些是 应用 权限(未委派)。他们要求 管理员同意.

管理员同意

az ad app permission admin-consent --id <your-app-object-id>

客户端密钥

  1. 首选 证书和秘密 → 新客户机密
  2. 复制机密值(您将不会再看到它)
  3. 设置为 AZURE_CLIENT_SECRET 环境变量

环境变量

变量 必填 描述
AZURE_CLIENT_ID 是 应用程序注册中的应用程序(客户端)ID
AZURE_CLIENT_SECRET 是 客户端机密值
AZURE_TENANT_ID 是 目录(租户)ID
NOTIFICATION_URL 推荐 用于webhook通知的公共HTTPS URL(例如。 https://your-app.azurecontainerapps.io/notifications)
PORT 无 服务器端口(默认:8080)

部署

码头工人

docker build -t transcripts-webhook-mcp .
docker run -p 8080:8080 \
  -e AZURE_CLIENT_ID=your-client-id \
  -e AZURE_CLIENT_SECRET=your-secret \
  -e AZURE_TENANT_ID=your-tenant-id \
  -e NOTIFICATION_URL=https://your-app.example.com/notifications \
  transcripts-webhook-mcp

Azure容器应用

# Create ACR and build
az acr create -n <acr-name> -g <rg> --sku Basic --admin-enabled
az acr build -r <acr-name> -t transcripts-webhook-mcp:v1 .

# Create always-on container app (min replicas = 1)
az containerapp create \
  --name transcripts-webhook-mcp \
  --resource-group <rg> \
  --image <acr-name>.azurecr.io/transcripts-webhook-mcp:v1 \
  --target-port 8080 \
  --ingress external \
  --min-replicas 1 \
  --max-replicas 2 \
  --env-vars \
    AZURE_CLIENT_ID=<client-id> \
    AZURE_CLIENT_SECRET=secretref:client-secret \
    AZURE_TENANT_ID=<tenant-id> \
    NOTIFICATION_URL=https://<app-fqdn>/notifications

备注: --min-replicas 1 --此服务器必须保持运行才能接收webhook通知。与可以扩展到0的委托MCP服务器不同。


Webhooks的工作原理

1. Agent calls subscribe_to_transcripts
     │
     ▼
2. Server POSTs to Graph /subscriptions
     │
     ▼
3. Graph POSTs to /notifications?validationToken=xxx
     │
     ▼
4. Server echoes validationToken → subscription confirmed
     │
     ▼
5. User creates a meeting transcript in Teams
     │
     ▼
6. Graph POSTs notification to /notifications
   {
     "subscriptionId": "...",
     "changeType": "created",
     "resource": "users/{userId}/onlineMeetings/{meetingId}/transcripts/{id}",
     "tenantId": "..."
   }
     │
     ▼
7. Server logs notification, extracts user/meeting/transcript IDs
8. Server auto-fetches transcript content (VTT) or recording URL
9. Agent can retrieve content on-demand via get_transcript_content / get_recording_url

订阅生命周期

  • 最大寿命:约4230分钟(约70.5小时)用于在线会议资源
  • 续订:必须致电 renew_subscription 到期前
  • 生命周期事件:图形发送 reauthorizationRequired, subscriptionRemoved, missed 通知

本地开发

npm install
npm run build
npm start

对于本地测试,通知URL必须可公开访问。使用类似隧道的 吸烟 或 Azure开发隧道:

# Using dev tunnels
devtunnel create --allow-anonymous
devtunnel port create -p 8080
devtunnel host
# Use the tunnel URL as NOTIFICATION_URL

测试

健康检查

curl http://localhost:8080/health

MCP工具(通过curl)

所有工具均通过调用 POST /mcp 使用具有SSE响应格式的JSON-RPC 2.0。

订阅成绩单

为所有用户创建用于成绩单更改通知的webhook订阅。

# With defaults (uses server's NOTIFICATION_URL, 4200 min expiry)
curl -s -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"subscribe_to_transcripts","arguments":{}}}'

# With custom options
curl -s -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"subscribe_to_transcripts","arguments":{"notificationUrl":"https://your-app.example.com/notifications","expirationMinutes":4230,"clientState":"my-secret-state"}}}'

订阅录音

创建一个webhook订阅,用于记录所有用户的更改通知。

curl -s -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"subscribe_to_recordings","arguments":{}}}'

列出订阅

列出所有活动的webhook订阅。根据Graph API进行可选验证。

# Local state only (fast)
curl -s -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list_subscriptions","arguments":{}}}'

# With Graph API verification (slower but more accurate)
curl -s -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list_subscriptions","arguments":{"includeGraphCheck":true}}}'

续订订阅

延长订阅的到期时间。必须在订阅失效前调用(最大生存期约为70小时)。

curl -s -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"renew_subscription","arguments":{"subscriptionId":"YOUR-SUBSCRIPTION-ID"}}}'

# With custom expiry
curl -s -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"renew_subscription","arguments":{"subscriptionId":"YOUR-SUBSCRIPTION-ID","expirationMinutes":4230}}}'

删除订阅

删除webhook订阅,停止所有未来的通知。

curl -s -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"delete_subscription","arguments":{"subscriptionId":"YOUR-SUBSCRIPTION-ID"}}}'

获取通知日志

查看服务器最近收到的webhook通知。

# Default (last 20 notifications)
curl -s -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_notification_log","arguments":{}}}'

# Last 5 notifications
curl -s -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_notification_log","arguments":{"limit":5}}}'

获取成绩单内容

获取特定会议的完整成绩单(VTT格式)。使用通知日志中的userId、meetingId和transcriptId。

curl -s -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_transcript_content","arguments":{"userId":"USER-ID-FROM-LOG","meetingId":"MEETING-ID-FROM-LOG","transcriptId":"TRANSCRIPT-ID-FROM-LOG"}}}'

获取录制URL

获取特定会议录制的限时下载URL。使用通知日志中的userId、meetingId和recordingId。

curl -s -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_recording_url","arguments":{"userId":"USER-ID-FROM-LOG","meetingId":"MEETING-ID-FROM-LOG","recordingId":"RECORDING-ID-FROM-LOG"}}}'

MCP资源(通过curl)

列出静态资源:

curl -s -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"resources/list","params":{}}'

列出资源模板:

curl -s -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"resources/templates/list","params":{}}'

读取服务器状态:

curl -s -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"resources/read","params":{"uri":"webhook://status"}}'

阅读特定订阅:

curl -s -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"resources/read","params":{"uri":"webhook://subscriptions/SUBSCRIPTION-ID"}}'

按索引读取通知(0=最新):

curl -s -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"resources/read","params":{"uri":"webhook://notifications/0"}}'

阅读成绩单:

curl -s -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"resources/read","params":{"uri":"webhook://transcripts/USER-ID/MEETING-ID/TRANSCRIPT-ID"}}'

读取录制URL:

curl -s -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"resources/read","params":{"uri":"webhook://recordings/USER-ID/MEETING-ID/RECORDING-ID"}}'

Copilot工作室/代理提示

如果通过Copilot Studio或其他MCP感知代理连接,请使用以下自然语言提示:

提示 使用的工具
“订阅成绩单通知” subscribe_to_transcripts
“订阅录制通知” subscribe_to_recordings
“显示所有活动的webhook订阅” list_subscriptions
“检查我们的订阅是否仍在Graph中处于活动状态” list_subscriptions (带图形检查)
“续订成绩单订阅” renew_subscription
“删除订阅 <id>" delete_subscription
“检查通知日志中最近的活动” get_notification_log
“显示最近5条通知” get_notification_log
“获取最新通知的完整成绩单” get_transcript_content
获取用户X、会议Y、记录Z的记录内容 get_transcript_content
“从最新通知中获取录制下载URL” get_recording_url
“总结最近的会议记录” get_notification_log → get_transcript_content

小贴士:代理将自动链接工具,例如首先检查通知日志,提取ID,然后获取转录内容。

Webhook验证(模拟Graph握手)

curl -s -X POST "http://localhost:8080/notifications?validationToken=test-token-123"
# Should return: test-token-123

模拟通知

curl -s -X POST http://localhost:8080/notifications \
  -H "Content-Type: application/json" \
  -d '{
    "value": [{
      "subscriptionId": "test-sub-id",
      "changeType": "created",
      "resource": "users/user-123/onlineMeetings/meeting-456/transcripts/transcript-789",
      "tenantId": "tenant-abc",
      "resourceData": {
        "@odata.type": "#microsoft.graph.callTranscript",
        "id": "transcript-789"
      }
    }]
  }'
# Should return: 202 Accepted

Microsoft文档


安全注意事项

  • 应用程序权限强大 --他们授予对所有用户会议数据的访问权限
  • 在可能的情况下,部署网络隔离(ExpressRoute、专用端点)
  • 使用 clientState 在订阅中验证通知真实性
  • 将客户端机密存储在Azure密钥库中,而不是生产环境中的环境变量中
  • 监控通知日志中的意外活动
  • 此服务器不需要或接受用户承载令牌,它使用自己的应用程序标识

免责声明

此MCP服务器是 独立开源项目 作为社区资源而建立。它是基于官方 Microsoft Graph API的Microsoft学习文档 并遵循公开记录的模式 变更通知 和 在线会议记录/录音.

本项目按“原样”提供,不提供任何明示或暗示的保证。 对于因使用本软件而产生的任何损害、数据丢失、安全事件或其他问题,作者不承担任何责任。您全权负责:

  • 在将代码部署到您的环境中之前,请先对其进行审查和理解
  • 保护您的Azure应用程序注册凭据和权限
  • 遵守贵组织的数据治理和隐私政策
  • 在使用访问所有用户会议数据的应用程序级权限时,确保适当的访问控制

这个项目是 不隶属于微软、不受微软认可或不受微软支持Microsoft Graph、Microsoft Teams、Azure和Copilot Studio是微软公司的商标。

使用风险自负。始终首先在非生产环境中进行测试。


许可证

麻省理工学院