Skip to content

Teams Digest MCP

你需要在当前机器上搭建一个 local-first 的 Microsoft Teams adaptive digest agent。目标是:不依赖 Microsoft Graph API 作为前提条件,优先从本机 Teams 缓存中提取聊天内容,规范化存储到 SQLite,并提供可供 agent 调用的检索和 digest 能力。并且后续需要支持开发成colleagues skill distillation 和msteams新消息整理收集成知识库markdown文件的功能

最终系统应支持以下用户目标:

  • “总结我今天 Teams 里最重要的事情”

  • “过去 24 小时有哪些 decision?”

  • “哪些 action item 分配给我?”

  • “项目 X 最近有什么变化?”

  • “Alice 最近提到过哪些 blocker?”

  • “这个 thread 最终做了什么决定?”

  • “哪些问题还 unresolved?”

  • “找到关于 ticket ABC-123 的相关讨论”

  • “给我一个带 evidence/message references 的 digest,而不是无来源的 summary”

请把系统设计成一个可靠的 retrieval + structured digest system,而不是简单地 dump 消息后全部塞给 LLM。

核心架构:

Teams local data
↓
local extractor
↓
normalization layer
↓
SQLite
├── conversations
├── messages
├── people
├── attachments
├── ingestion_state
└── digest_snapshots
↓
SQLite FTS5
↓
retrieval layer
↓
digest / agent skill

第一阶段不要引入 vector database。优先使用 SQLite FTS5、metadata filtering、时间过滤、conversation filtering、person filtering 和 exact-match retrieval。Teams 数据里项目名、ticket ID、人名、文件名、日期等 lexical signal 很重要。

只有在 lexical retrieval 明显不足时,才把 embedding 作为 optional extension,并且不要让它成为 MVP 的依赖。

  1. 优先支持 New Teams / Teams 2.x。

  2. 研究并优先复用现有 local extractor,而不是重新实现所有 Teams cache parsing。

  3. 首先评估:

    • zaungast

    • msteams-local-mcp

    • Sec42/teams-decoder

  4. teams-decoder 主要针对旧 Teams,因此不要默认它适用于 New Teams。

  5. 如果现有工具能可靠输出 Teams messages,则将它们作为 ingestion backend。

  6. 如果多个 extractor 可用,实现 adapter abstraction,让 backend 可替换。

例如:

interface TeamsExtractor:
discover()
list_conversations()
fetch_messages(since_checkpoint)
fetch_people()
fetch_attachment_metadata()

不要让上层 digest/retrieval 逻辑依赖某个 extractor 的内部 schema。

首先进行 discovery,不要直接假设 Teams cache 路径。 默认:

  • OS win32

  • Teams Teams 2.x

安全约束:

这是 local forensic-style reader,所以:

  • 禁止删除或修改 Teams cache

  • 禁止写入 Teams application directories

  • 禁止上传 Teams 内容到外部服务

  • 所有处理默认 local-only

  • 如果 Gemini CLI 本身会将 prompt/data 发送到远程模型,避免自动把整个 Teams history 塞入 prompt

  • retrieval 后只给模型必要的最小 message subset

设计 canonical schema。

建议 messages 表至少包含:

messages

  • id

  • external_id

  • conversation_id

  • parent_message_id

  • thread_id

  • sender_id

  • sender_name

  • timestamp

  • edited_timestamp

  • message_type

  • text

  • normalized_text

  • raw_source

  • source_backend

  • source_record_id

  • ingestion_timestamp

conversations

  • id

  • external_id

  • type

    • chat

    • group_chat

    • channel

    • meeting

    • unknown

  • title

  • participants

  • team_name

  • channel_name

  • created_at

  • last_activity_at

people

  • id

  • external_id

  • display_name

  • email_or_upn

  • aliases

attachments

  • id

  • message_id

  • name

  • type

  • url

  • local_path

  • mime_type

  • size

  • availability

    • metadata_only

    • local

    • remote

    • unresolved

ingestion_state

  • backend

  • conversation_id

  • checkpoint

  • last_ingested_at

digest_snapshots

  • id

  • scope_type

  • scope_id

  • window_start

  • window_end

  • generated_at

  • summary

  • structured_json

  • source_message_ids

  • previous_snapshot_id

创建 FTS5 index,至少支持:

  • message text

  • sender

  • conversation title

  • attachment names

retrieval 必须优先做 hybrid lexical + metadata filtering:

retrieve_messages(
query=None,
since=None,
until=None,
people=None,
conversation=None,
limit=...
)

不要默认返回几百条消息。

增加 thread reconstruction:

read_thread(message_id or thread_id)

需要:

  • parent/reply relationships

  • 附近上下文

  • 时间顺序

  • sender

  • thread title/context

设计高层 agent tools / CLI commands。

至少实现:

teams search ""
teams recent --since "24h"
teams thread
teams digest --since "24h"
teams digest --conversation --since "7d"
teams decisions --since "7d"
teams actions --since "7d"
teams open-questions --since "7d"

如果更适合,也可以实现 MCP server,但 CLI 必须先工作,方便 Gemini CLI 直接调用。

digest 的核心不是普通 summary。

要求模型把消息转换成以下结构:

{
"summary": "...",
"topics": [
{
"topic": "...",
"summary": "...",
"importance": "high|medium|low",
"evidence": ["message_id"]
}
],
"decisions": [
{
"decision": "...",
"status": "confirmed|tentative|reversed|unclear",
"participants": [],
"timestamp": "...",
"confidence": 0.0,
"evidence": ["message_id"]
}
],
"action_items": [
{
"task": "...",
"owner": "...",
"due": null,
"status": "open|done|unclear",
"confidence": 0.0,
"evidence": ["message_id"]
}
],
"open_questions": [
{
"question": "...",
"owner": null,
"evidence": ["message_id"]
}
],
"blockers": [
{
"blocker": "...",
"owner": null,
"evidence": ["message_id"]
}
],
"important_messages": [
{
"message_id": "...",
"reason": "..."
}
]
}

严格要求 evidence grounding。

每个:

  • decision

  • action item

  • blocker

  • open question

必须尽可能附带原始 message ID。

不要把:

  • suggestion

  • brainstorming

  • tentative proposal

  • question

  • hypothesis

误判成 confirmed decision。

例如:

“maybe we should ship Friday”

不能变成:

“Decision: ship Friday”

除非后续消息明确确认。

confidence 只表示模型对 extraction 的置信度,不代表事实本身的重要性。

实现 incremental digest。

不要每次 digest 都重新读取和总结全部历史。

流程:

previous checkpoint
↓
new messages
↓
retrieve relevant prior context
↓
digest delta
↓
merge with previous structured snapshot
↓
new snapshot

merge 时需要处理:

  • decision 被更新

  • decision 被 reversed

  • action item completed

  • action item reassigned

  • blocker resolved

  • open question answered

保留 temporal history,不要简单覆盖旧状态。

例如:

Decision v1:
Use Redis

later:
Actually switch to Postgres

最终状态应该体现:

  • Redis decision was superseded

  • current decision is Postgres

而不是同时把两者当 active decisions。

attachment 处理必须与 Teams parser 解耦。

Teams local cache 很可能只有:

  • filename

  • attachment metadata

  • SharePoint/OneDrive URL

而没有文件正文。

实现:

AttachmentResolver:
resolve_local_copy()
resolve_synced_onedrive_copy()
get_metadata()

MVP 不要求通过 Graph 自动下载 cloud attachment。

如果本地 OneDrive/SharePoint sync directory 中存在对应文件,可以建立 local_path。

支持后续扩展:

AttachmentContentExtractor:

  • txt

  • md

  • pdf

  • docx

  • pptx

  • xlsx

但 attachment content extraction 不应该阻塞 Teams message ingestion。

对模型上下文严格控制。

不要:

SELECT * FROM messages

然后把全部内容发给 Gemini。

应该:

user intent
↓
query planner
↓
FTS5 + filters
↓
top candidate messages
↓
thread expansion
↓
dedup
↓
context compression
↓
LLM digest

设计 context budget,例如默认最多:

  • 50-100 candidate messages

  • 必要时扩展 thread

  • 超限时先按 conversation/thread 做局部摘要

  • 保留 evidence IDs

尤其注意 Teams message noise:

  • emoji/reactions

  • greetings

  • automated notifications

  • meeting join/leave messages

  • quoted duplicate text

  • bot messages

  • repeated link previews

不要简单删除,而是在 normalization 中标记 noise 类型,并默认降低 retrieval priority。

实现 dedup。

Teams cache 中可能出现:

  • 同一消息多个 representation

  • edited messages

  • notification copy

  • reply preview

  • quote duplication

canonical message identity 应尽可能依据 stable Teams ID。

如果没有 stable ID,构造 deterministic fingerprint,例如:

conversation_id +
sender +
timestamp +
normalized_text hash

但 fingerprint 只能作为 fallback。

建立可检查性。

每次 digest 应允许用户进一步执行:

teams evidence

并看到:

timestamp
sender
conversation
raw/normalized text
thread context

agent 任何重要结论都应该可以 trace 回原消息。

实现 observability:

teams doctor

输出:

  • detected Teams installation

  • detected backend

  • cache path

  • extractor version

  • message count

  • conversation count

  • earliest/latest message

  • FTS status

  • last ingestion checkpoint

  • attachment statistics

实现:

teams ingest --dry-run

先显示将读取什么、发现多少数据,不写数据库。

再执行:

teams ingest

项目结构建议:

teams-digest/
├── README.md
├── pyproject.toml
├── src/
│ └── teams_digest/
│ ├── cli.py
│ ├── config.py
│ ├── db.py
│ ├── models.py
│ ├── ingestion/
│ │ ├── base.py
│ │ ├── zaungast.py
│ │ ├── local_mcp.py
│ │ └── autodetect.py
│ ├── normalize/
│ │ ├── messages.py
│ │ ├── threads.py
│ │ └── dedup.py
│ ├── retrieval/
│ │ ├── fts.py
│ │ ├── filters.py
│ │ └── context.py
│ ├── digest/
│ │ ├── schema.py
│ │ ├── prompt.py
│ │ ├── generate.py
│ │ └── merge.py
│ └── attachments/
│ ├── resolver.py
│ └── extract.py
├── tests/
└── tools/

语言优先 Python 3.11+。

优先使用标准库和轻量 dependency。

数据库使用 SQLite,不要引入 PostgreSQL 或 external service。

digest 模型执行:

target machine 使用 Gemini CLI。

请设计一个清晰的 Gemini adapter,而不是把 Gemini command hard-code 到业务逻辑里。

例如:

class DigestModel:
def generate(prompt, context) -> StructuredDigest

class GeminiCLIModel(DigestModel):
...

Gemini CLI invocation 必须:

  • 有 timeout

  • 捕获 exit code

  • 捕获 stderr

  • 能处理 malformed JSON

  • structured output 校验失败时允许有限次数 repair

  • 不自动无限 retry

  • 不让 shell injection 进入 command construction

最好通过 stdin 或临时文件提供 prompt/context,不要把大量 Teams 内容直接拼进 shell command 参数。

prompt 中明确要求 Gemini:

  • 只根据 supplied evidence 做判断

  • 不使用外部知识补足 Teams 中没有的信息

  • 区分 confirmed / tentative / unclear

  • 必须返回 message IDs

  • 缺失信息返回 null / unknown,而不是猜测

对 Gemini 输出使用 Pydantic 或等价 schema validation。

测试至少覆盖:

  1. ingest 单条 conversation

  2. incremental ingest 不重复写

  3. edited message

  4. reply/thread reconstruction

  5. FTS exact search

  6. ticket ID search

  7. person + time filter

  8. duplicate message handling

  9. tentative proposal 不变成 confirmed decision

  10. confirmed decision extraction

  11. reversed decision merge

  12. action completion merge

  13. malformed Gemini JSON

  14. empty retrieval

  15. attachment metadata with no local file

  16. local attachment resolution

增加 synthetic fixture,不要测试依赖真实 Teams 数据。

实现过程中不要一次性写完后才测试。

按下面阶段执行:

Phase 1:

  • inspect environment

  • inspect available Teams cache

  • evaluate extractor options

  • write findings

Phase 2:

  • scaffold project

  • SQLite schema

  • canonical models

  • basic ingestion

Phase 3:

  • FTS5 retrieval

  • filters

  • thread reconstruction

Phase 4:

  • Gemini CLI adapter

  • structured digest schema

  • evidence grounding

Phase 5:

  • incremental snapshots

  • decision/action merge

Phase 6:

  • attachment resolver

  • doctor command

  • documentation

每个阶段完成后:

  • run tests

  • report what works

  • report assumptions

  • report known limitations

  • then continue

不要为了“看起来完整”而实现未经验证的 Teams parser。

如果 New Teams 的 local schema 与已有项目不匹配:

  1. 先保存和描述发现的 schema

  2. 写最小 reproducible inspection

  3. 再扩展 adapter

  4. 不要在不知道结构时猜字段意义

完成后 README 至少包含:

  • architecture

  • installation

  • Teams cache discovery

  • privacy model

  • supported Teams versions

  • ingestion

  • querying

  • digest

  • Gemini CLI configuration

  • attachment limitations

  • troubleshooting

  • data deletion/reset

  • threat model

  • known limitations

最终 acceptance criteria:

我应该可以在 target machine 上执行:

teams doctor

看到 Teams 数据源被检测到。

然后:

teams ingest

把 Teams messages 增量导入本地 SQLite。

然后:

teams search "ABC-123"

得到相关 Teams messages。

然后:

teams digest --since 24h

得到:

  • concise summary

  • topics

  • decisions

  • action items

  • blockers

  • open questions

并且所有重要结论带 message evidence IDs。

然后:

teams evidence

能返回对应原始 Teams message 和必要 thread context。

系统在第二次:

teams ingest

时不能重复导入整个 history。

系统必须 local-first、read-only toward Teams、incremental、traceable、schema-validated。

优先 correctness 和 inspectability

开始时先不要写代码。

先完成: 调研现存开源实现, 理解我们的项目要求, 识别可以借鉴的部分 proposed concrete implementation plan

我们最后部署项目的机器不能从通用源pipinstall, 所以先列出dependency交给user做决策 然后在当前任务中继续实现

当存在不确定性时,明确标注:

  • confirmed

  • inferred

  • unknown

不要伪造 Teams schema、Gemini CLI behavior 或 extractor capabilities。