内容
# tgkb 知识库
**将您关注的 Telegram 频道和群组转换为一个私有的、可搜索的知识库,您可以从任何与 MCP 兼容的 AI 助手查询,答案直接引用原始消息。**
`tgkb` 验证为您的 Telegram 账户,导出消息历史到一个本地 SQLite 数据库,并通过一个**只读的 MCP 服务器**公开它。您用自然语言提问;助手搜索您的档案并用链接到实际消息的答案回复 - 而不是您自己滚动浏览多年的聊天记录。
由于它通过 stdio 使用标准的 Model Context Protocol,因此它与**任何 MCP 客户端**一起工作 - Claude Code、Claude Desktop、Cursor 和其他具有 MCP 功能的 AI 工具。以下示例使用 Claude Code;设置方式相同,但配置文件的路径不同。
它构建为两个进程,共享**一个** SQLite 文件,彼此之间从不直接通信:
- **写入者** (`tgkb` CLI) - 验证 Telegram,导出历史记录,并保持实时同步运行。它是唯一写入的地方。
- **读取者** (`tgkb-mcp` MCP 服务器) - 一个只读的 MCP 服务器,您的 AI 客户端通过 stdio 启动。它从不写入,从不需要 AI 密钥,并公开三个工具:`server_status`、`search_messages`、`read_query`。
所有本地内容都位于 `./.tgkb-data/`(gitignored):加密会话、配置文件和 SQLite 数据库。
---
## 功能
- **基于自然语言的聊天问答** - 用自然语言向 AI 助手提问;它为您编写搜索/SQL 调用,并从您自己的消息档案中回答。
- **与任何 MCP 客户端配合使用** - 标准 Model Context Protocol 通过 stdio,因此任何具有 MCP 功能的 AI 工具(Claude Code、Claude Desktop、Cursor 等)都可以使用它。没有锁定到一个助手。
- **引用的答案** - 每个命中都带回发送者、日期、聊天和 `t.me` 深度链接(或私人聊天的 `null`)以及周围的上下文消息,因此您可以验证源。
- **俄语形态搜索** - 在自定义 `ru_lemma` 分词器上进行全文搜索:像 `договор` 这样的屈折查询匹配 `договоры` / `договором` / `договорами`。无需嵌入,无需 AI 密钥。
- **受保护的只读 SQL** - 用于精确查找的 `read_query` 工具(计数、过滤器、日期范围、线程重建)。仅运行单个 `SELECT` / `WITH … SELECT` / `EXPLAIN`;通过构造,AI 通过读取者执行的所有操作都是只读的(写入在边界处拒绝 * 和连接以只读方式打开),因此它永远无法修改您的存储库或在 Telegram 上采取行动。
- **本地和私有** - 您的档案是您机器上的一个普通 SQLite 文件。无需上传;读取者不需要云服务和 AI 密钥。
- **完整的历史记录 + 编辑 + 删除** - 通过 Telegram 的导出功能进行批量导出,然后实时摄入新消息和编辑消息。已删除的消息被标记为墓碑(不被搜索结果返回,而是被静默丢失)。
- **账户安全的摄入** - 积极的请求速率限制 + FLOOD_WAIT 合规性将导出/同步保持在 Telegram 的限制内。
---
## 先决条件
- **Python ≥ 3.12** 和 **[uv](https://docs.astral.sh/uv/)** (所有命令都通过 `uv run` 运行,它为您管理虚拟环境)。
- **Telegram API 凭证** - 在 <https://my.telegram.org> → *API 开发工具* 中创建一个应用程序以获取 **api_id** 和 **api_hash**。您还需要该账户的 **电话号码**。
安装依赖项(第一个 `uv run …` 自动执行此操作,或强制执行):
```bash
uv sync
```
---
## 快速入门
完整的设置,从头到尾。每个命令都在下面的编号步骤中详细解释 - 从这里开始,如果需要更多步骤,请向下滚动。
```bash
# 1. Telegram 凭证 - 复制模板并填写您的 api_id / api_hash / phone
cp .env.example .env
$EDITOR .env
# 2. 身份验证一次(打开登录代码;设置休息密码)
uv run tgkb auth
# 3. 声明要跟踪的聊天 - 复制模板并列出您的聊天
cp config.json.example .tgkb-data/config.json
$EDITOR .tgkb-data/config.json
uv run tgkb config-check # 在导出前离线验证
# 4. 拉取历史记录,然后保持同步
uv run tgkb export # 每个跟踪聊天的一次性批量回填
uv run tgkb sync # 补齐 + 实时;运行直到 Ctrl-C
# 5. 在您的 AI 客户端中注册读取器(参见步骤 5 中的配置块)
```
您总共配置**三个**内容:`.env`(凭证,步骤 1)、`.tgkb-data/config.json`(跟踪的聊天,步骤 3)和您的 MCP 客户端的配置(读取器注册,步骤 5)。其他一切都是自动的。
> 在 Windows PowerShell 上,请使用 `Copy-Item .env.example .env` 和 `notepad .env` 代替 `cp` / `$EDITOR`。
---
## 步骤 1 - 提供您的 Telegram 凭证
写入者读取三个值:`TG_API_ID`、`TG_API_HASH`、`TG_PHONE`。通过本地 `.env`(推荐)或实际环境变量提供它们。任何缺失的内容都会交互式提示(秘密使用无回显输入)。
复制模板(`.env.example`)到 `.env` 在项目根目录 - `.env` 是 gitignored 的,因此您的实际 `api_hash` 永远不会被提交:
```bash
cp .env.example .env
```
然后编辑 `.env` 以填写您的值:
```dotenv
TG_API_ID=1234567
TG_API_HASH=0123456789abcdef0123456789abcdef
TG_PHONE=+15551234567
```
这些仅在**首次** `tgkb auth` 时需要。之后,它们将加密保存在会话中,后续运行从中读取 - 无需环境变量。
## 步骤 2 - 身份验证(一次性)
```bash
uv run tgkb auth
```
- 输入 Telegram 发送给您的**登录代码**(以及您的账户的 **2FA 密码**,如果有)。
- 系统将要求您设置一个**密码短语**。此密码短语加密保存在 `./.tgkb-data/` 下的会话 + `api_hash`。您将在后续的每次 `export`/`sync` 中重新输入此密码短语。**没有恢复** - 如果您忘记了它,请删除 `./.tgkb-data/` 并重新运行 `tgkb auth`。
## 步骤 3 - 声明要跟踪的聊天
创建 `./.tgkb-data/config.json`(复制 `config.json.example` 作为起点)。它是一个 JSON 对象,包含一个 `chats` 数组;每个条目需要**恰好一个** `username` 或 `id`:
```json
{
"chats": [
{ "username": "durov", "title": "Pavel Durov 的频道" },
{ "id": -1001234567890, "title": "团队群组" }
],
"throttle": { "rate_per_second": 1.0 }
}
```
字段参考(JSON 没有注释,因此字段在此处记录):
| 字段 | 位置 | 必需 | 含义 |
|---|---|---|---|
| `chats` | 根 | 是 | 聊天条目数组;必须至少有一个。 |
| `chats[].username` | 条目 | 用户名/id 之一 | 公共 `@name`,**不带** 前导 `@`(剥离前导 `@`)。 |
| `chats[].id` | 条目 | 用户名/id 之一 | 数值 peer id,**不带引号** 的整数(例如 `-1001234567890`)。 |
| `chats[].title` | 条目 | 否 | 您自己的可读性自由文本标签;解析时忽略。 |
| `throttle.rate_per_second` | 根 | 否 | 主动请求速率上限(Telegram 防洪等待安全)。省略整个 `throttle` 对象以使用内置默认值;`0` 禁用主动限制。 |
在导出前离线验证:
```bash
uv run tgkb config-check
```
错误条目被报告并跳过;好条目仍然运行。
## 步骤 4 - 导出历史记录,然后保持同步
```bash
uv run tgkb export # 每个跟踪聊天的批量回填(通过导出会话)
uv run tgkb sync # 补齐 + 实时监听器;运行直到您停止它(Ctrl-C)
```
- `export` 是**一次性**批量拉取。每个新跟踪的聊天运行一次。
- `sync` 补齐任何遗漏的内容,然后保持运行以实时摄入新消息和编辑消息。添加 `--log-level DEBUG` 以跟踪每个事件(类型 + 聊天 ID + 消息 ID - 永远不会是消息文本)。
之后,`./.tgkb-data/tgkb.sqlite3` 包含您的可搜索知识库(带有俄语词干化全文索引)。
## 步骤 5 - 从 AI 助手查询
在您的 MCP 客户端中注册读取器,方法是在其 MCP 配置中添加此条目。
配置文件的位置取决于客户端:
- **Claude Code** - 项目根目录中的 `.mcp.json` 或 `~/.claude.json`。
- **Claude Desktop** - `claude_desktop_config.json`(设置 → 开发者 → 编辑配置)。
- **Cursor** - 项目中的 `.cursor/mcp.json` 或 `~/.cursor/mcp.json`。
- **其他 MCP 客户端** - 请参阅客户端的文档;它们都采用相同的 `mcpServers` 形状。
将 `tgkb` 块合并到现有的 `mcpServers` 对象中:
```json
{
"mcpServers": {
"tgkb": {
"command": "uv",
"args": ["--directory", "/absolute/path/to/tgkb-mcp", "run", "tgkb-mcp"]
}
}
}
```
用**绝对路径**替换 `/absolute/path/to/tgkb-mcp` **到您的存储库克隆**。`uv --directory <path>` 使 `uv` 解析此项目的环境,无论您的 MCP 客户端从哪个工作目录启动 - 因此您不必从存储库内部启动客户端。在 Windows 上,请使用带有转义反斜杠的绝对路径,例如 `"C:\\Users\\you\\projects\\tgkb-mcp"`。
如果您使用 Claude Code,其 CLI 可以为您编写相同的条目(从存储库内部运行,以便自动捕获路径):
```bash
claude mcp add tgkb -- uv --directory "$(pwd)" run tgkb-mcp
```
批准 MCP 服务器时,您的客户端会提示。(如果项目虚拟环境已在 `PATH` 上,则 `"command": "tgkb-mcp"` 也不需要 `args`。)
您现在有三个工具可用:
| 工具 | 它做什么 |
|------|--------------|
| `server_status` | 运行状况探测:消息数,搜索可用性,只读标志。 |
| `search_messages` | 排名俄语全文搜索。返回引用的命中 - 文本,发送者,日期,聊天,`t.me` 链接(或私人聊天的 `null`),以及周围的上下文消息。屈折查询有效(`договор` 找到 `договоры`/`договором`)。 |
| `read_query` | **受保护的** 只读 SQL,用于精确的结构化查找。仅运行单个 `SELECT` / `WITH … SELECT` / `EXPLAIN`;任何写入,DDL,多语句或注释混淆的写入都在边界处被拒绝。返回行为按列键控的字典(`[]` 当没有匹配时)。 |
只需用自然语言询问您的助手 - 它会编写工具调用。示例:
- *"知识库中有多少条消息?"* → `read_query("SELECT count(*) FROM messages")` 或 `server_status`。
- *"查找有关预算会议的消息并引用它们。"* → `search_messages(query="бюджет совещание")`。
- *"显示聊天 1 中最新的 10 条消息,按最新顺序。"* → `read_query("SELECT message_id, sender_name, text FROM messages WHERE chat_id = 1 ORDER BY message_id DESC", limit=10)`。
### 您查询的数据(`read_query` 架构)
- **`messages`** - `chat_id`、`message_id`、`sender_id`、`sender_name`、`text`、`date_utc`、`reply_to_msg_id`、`edit_date`、`deleted`(`1` = 墓碑;`search_messages` 已经排除这些)。
- **`chats`** - `chat_id`、`title`、`username`、`is_public`。
- **`sync_state`** - 导出/同步记账(每个聊天的 `last_id`)。
---
## 故障排除
- **`uv run tgkb doctor`** - 离线自检(无网络),快速确认安装是否正常。
- **读取器启动失败** - 您尚未运行 `tgkb export` / `tgkb sync`;读取器永远不会创建数据库。
- **`search index is stale (tokenizer drift)`** - 持久化的分词器指纹不再与正在运行的 `ru_lemma` 匹配,因此读取者 **拒绝搜索** 而不是返回错误结果。它无法修复索引(这是写入者的工作)- 运行 `tgkb sync` / `tgkb export` 以重建。
- **忘记密码短语** - 删除 `./.tgkb-data/` 并重新运行 `tgkb auth`。
- **检查读取器启动** - `uv run tgkb-mcp` 直接启动_stdio MCP 服务器(Ctrl-C 停止)。它在 stdout 上使用 MCP JSON-RPC 协议,没有人类可读的输出;诊断信息输出到 stderr。它旨在由 MCP 客户端驱动,而不是手动运行 - 但干净的启动确认了线路连接。
---
## 限制
- **仅限文本。** 只有消息文本被索引和可搜索。媒体、文件、贴纸、投票和反应不存储。
- **针对俄语优化。** 全文搜索使用俄语词干化器(`ru_lemma`)。其他语言仍然可搜索,但仅限于类似英语的精确/宽松匹配 - 屈折匹配是俄语特有的。
- **不是实时 Telegram。** 您查询本地存档,因此结果仅限于您上次 `sync`/`export` 的新鲜度。消息在几秒前发布,在摄入之前不可搜索。
- **您必须具有访问权限。** 您验证的账户必须是 / 已订阅每个跟踪聊天的成员;`tgkb` 读取该账户可以看到的内容,不会为您加入任何内容。
---
## 安全和隐私
- **此使用的是 *用户* 账户,而不是机器人。** 您通过 Telethon(MTProto)登录为自己。自动化个人账户是**您的责任**,并且根据 Telegram 服务条款存在被封禁的风险 - 账户安全节流减少但不消除此风险。请使用您愿意自动化的账户。
- **所有内容都保留在本地。** 消息、配置和数据库永远不会离开您的机器。没有服务器,没有遥测,没有云组件。读取者没有 **任何** AI/LLM/嵌入式 API 密钥,也没有读取密钥的代码路径 - 它是确定性、无密钥的代码。
- **密钥存储在本地加密。** 您的 Telegram 会话和 `api_hash` 存储在 `./.tgkb-data/` 下的密码短语加密保护下。该目录(和 `.env`)是 gitignore 的 - 任何敏感信息都不会被提交。请将 SQLite 数据库视为敏感信息:它包含您的聊天全文。
---
## 开发
项目分为三个包,永远不会跨导入,除共享的 SQLite 文件外:
- `tgkb/writer/` - `tgkb` CLI:身份验证、导出、同步、节流、医生。
- `tgkb/reader/` - `tgkb-mcp` 只读 MCP 服务器。
- `tgkb/common/` - 共享代码:配置、DB 访问、架构、`ru_lemma` 分词器、加密秘密存储。
在无网络、无真实 Telegram 的情况下运行测试套件(所有内容都已存根):
```bash
uv run pytest -q
```
欢迎贡献 - 开启一个问题或拉取请求。请在提交前运行测试。
---
## 它如何组合
```
(writes) (reads, read-only)
Telegram ──► tgkb (writer CLI) ──► .tgkb-data/tgkb.sqlite3 ◄── tgkb-mcp (reader) ◄── MCP client (any AI)
auth / export / sync shared SQLite file 3 MCP tools over stdio
```
- 编写者和读取者永远不会相互导入;它们仅共享 SQLite 文件。
- 读取者添加 **没有 AI/LLM 依赖和 API 密钥** - 它是确定性、无密钥代码。
- 所有诊断信息输出到 **stderr**;读取者的 stdout 仅携带 MCP 协议。
---
## 许可证
[MIT](LICENSE) - 免费使用、修改和分发(包括商业用途)。
只需保留版权和许可证通知。