内容
<div align="center">
<img src="assets/banner.png" alt="学习伙伴" width="100%" />
# 学习伙伴
**将您的笔记和往年试卷转化为专注的本地 AI 学习系统。**
MCP 服务器为 Claude 提供结构化的学习材料访问权限,以便它可以教授、测验和练习您的内容,并记住您的表现。
[](https://python.org)
[](https://modelcontextprotocol.io)
[](https://docs.astral.sh/uv/)
[](https://sqlite.org)
[](LICENSE)
[**快速开始**](#-快速开始) · [**工作原理**](#-工作原理) · [**工具与提示**](#-工具) · [**扩展**](#-扩展) · [**完整教程**](TUTORIAL.md)
</div>
---
## ✨ 为什么选择学习伙伴
大型语言模型可以推理,但它们无法访问您的世界:您的笔记、往年试卷和进度。
学习伙伴通过 **模型上下文协议(MCP)** 弥补了这一差距。您将材料放入两个文件夹中。您的 MCP 客户端(Claude Desktop、Cursor、任何兼容 MCP 的客户端)现在可以:
<table>
<tr>
<td width="33%" valign="top">
### 📚 学习
从**您的材料**中教授任何主题,风格自定:费曼、苏格拉底式、考试冲刺、ELI5 等。
</td>
<td width="33%" valign="top">
### 🧠 练习
基于您的笔记的扎实测验。**往年题目模式练习**:真实的往年题目逐字逐句,或相同风格的新题目。
</td>
<td width="33%" valign="top">
### 📈 跟踪
本地 SQLite 跟踪每个主题的掌握情况,跨会话跟踪。最薄弱的主题优先显示。存档您已经掌握的内容。
</td>
</tr>
</table>
同时作为 **MCP 协议的完整参考**:每个基本操作都经过锻炼,生产环境代码呈现。
---
## ⚡ 快速开始
```bash
# 1. 克隆
git clone https://github.com/eshitakundu/study-buddy.git
cd study-buddy
# 2. 安装
uv sync
# 3. 将笔记放入 materials/content/,往年试卷放入 materials/pyqs/
# 4. 使用 MCP 检查器验证服务器
uv run mcp dev study_buddy.py
```
然后 [连接到 Claude Desktop](#-连接到-claude-desktop) 并开始聊天:
> *"在我的材料中发现主题,注册真实的主题,然后对最薄弱的主题进行测验。*
---
## 🧬 工作原理
```mermaid
flowchart LR
A[📁 materials/<br/>content + pyqs] --> B[⚙️ study_buddy.py<br/>MCP 服务器]
B --> C[💾 SQLite<br/>主题 + 结果]
B <-->|stdio| D[🤖 Claude Desktop]
D -->|调用工具| B
D -->|渲染提示| B
D -->|读取资源| B
```
### 三个 MCP 原语,发挥实际作用
| 原语 | 在学习伙伴中的角色 | 示例 |
|:---|:---|:---|
| 🔧 **工具** | 模型调用的操作 | `search_content`, `log_result`, `extract_pyq_style` |
| 📖 **资源** | 可浏览的 URI 地址上下文 | `study://topics`, `study://content` |
| 💬 **提示** | 参数化的学习工作流 | `study`, `quiz`, `pyq_test` |
加上 **类型化输入** 通过 Pydantic `Field`,**持久状态** 通过 SQLite,以及 **路径遍历安全** 文件访问。
---
## 📁 项目结构
```
study-buddy/
├── 📦 study_buddy.py ← 整个服务器,一个文件
├── 🗄️ study.db ← 自动创建的 SQLite 跟踪器
├── 📚 materials/
│ ├── content/ ← 笔记,幻灯片,教科书摘录
│ ├── pyqs/ ← 往年试卷
│ └── archive/ ← 您已移出的文件
├── 🖼️ assets/banner.png
├── pyproject.toml
├── uv.lock
└── README.md
```
子文件夹和 `study.db` 在首次运行时自动创建。
---
## 📥 设置
<details open>
<summary><b>要求</b></summary>
- **Python 3.10+**
- **[uv](https://docs.astral.sh/uv/)**:快速的 Python 包管理器
- **MCP 兼容客户端**:Claude Desktop、Cursor、Cline 等
- **Node.js**:仅用于通过 `mcp dev` 的 MCP 检查器
固定依赖:
- `mcp[cli]>=1.27,<2`:`<2` 界限很重要;SDK v2 更改导入路径
- `pypdf`
- `python-docx`
</details>
<details open>
<summary><b>安装</b></summary>
```bash
git clone https://github.com/eshitakundu/study-buddy.git
cd study-buddy
uv sync
```
</details>
<details>
<summary><b>添加学习材料</b></summary>
**笔记** (`materials/content/`):
```
dbms-notes.md
transactions.pdf
normalization-slides.docx
er-diagram.png
```
**往年试卷** (`materials/pyqs/`):
```
dbms-midterm-2024.pdf
dbms-final-2023.txt
operating-systems-pyq.docx
```
通过 `archive_files` 移动的文件位于 `materials/archive/`。
</details>
---
## 🧪 运行和测试
```bash
uv run mcp dev study_buddy.py
```
在浏览器中打开 **MCP 检查器**(通过 `npx`)。列出并调用每个工具,读取资源,并预览渲染的提示,所有这些都在触摸客户端之前。
<img src="assets/mcp-inspector-tools.png" alt="MCP 检查器显示学习伙伴工具列表" width="100%" />
> ⚠️ **注意:** 如果 `node` 在检查器关闭后仍然在端口 6277 上运行,则下一个 `mcp dev` 将失败,提示 *Proxy Server PORT IS IN USE*。在 Windows 上修复:
> ```powershell
> Get-Process node | Stop-Process -Force
> ```
---
## 🔌 连接到 Claude Desktop
配置文件:
- **Windows** → `%APPDATA%\Claude\claude_desktop_config.json`
- **macOS** → `~/Library/Application Support/Claude/claude_desktop_config.json`
```json
{
"mcpServers": {
"study-buddy": {
"command": "C:\\Users\\<you>\\.local\\bin\\uv.exe",
"args": [
"--directory",
"C:\\Users\\<you>\\path\\to\\study-buddy",
"run",
"study_buddy.py"
]
}
}
}
```
> 🔑 **三件事容易出错:**
> 1. 使用 **绝对路径**:Claude Desktop 的工作目录不是您的项目文件夹。
> 2. 在 Windows 上,转义反斜杠为 `\\`。
> 3. **完全退出** Claude Desktop 从系统托盘。如果只关闭窗口是不够的。
调试日志 → `%APPDATA%\Claude\logs\mcp-server-study-buddy.log`
<img src="assets/claude-desktop-connected.png" alt="Claude Desktop 连接到学习伙伴" width="100%" />
---
## 🔧 工具
<details open>
<summary><b>📚 材料</b></summary>
| 工具 | 用途 |
|:---|:---|
| `list_content` | 列出 `materials/content/` 中的文件 |
| `list_pyqs` | 列出 `materials/pyqs/` 中的文件 |
| `read_file` | 从 `content`、`pyqs` 或 `archive` 读取文件 |
| `search_content` | 在内容文件中进行子字符串搜索 |
| `archive_files` | 物理移动文件到 `materials/archive/` |
</details>
<details open>
<summary><b>🎯 主题和进度</b></summary>
| 工具 | 用途 |
|:---|:---|
| `discover_topics` | 从标题、粗体文本、问题词干中排名候选主题 |
| `register_topic` | 将主题添加到跟踪器 |
| `list_topics` | 活动主题与尝试次数、掌握百分比、最后尝试时间 |
| `archive_topic` | 标记主题为已掌握(仅限元数据) |
| `log_result` | 记录测验分数对抗注册主题 |
| `weakest_topics` | 掌握程度最低的活动主题 |
</details>
<details open>
<summary><b>📋 往年试卷分析</b></summary>
| 工具 | 用途 |
|:---|:---|
| `extract_pyq_style` | 结构配置文件:类型、分数、词干、样本 |
| `extract_pyq_questions` | 从往年试卷中解析的实际问题列表 |
</details>
---
## 📖 资源
| URI | 内容 |
|:---|:---|
| `study://content` | `materials/content/` 的 Markdown 索引 |
| `study://pyqs` | `materials/pyqs/` 的 Markdown 索引 |
| `study://topics` | 掌握情况跟踪器:活动 + 存档 |
> 💡 **重要:** 在 Claude Desktop 中,资源是 **用户附加** 的,而不是自动获取的。工具由模型发起。请相应地设计。
<img src="assets/connectors.png" alt="Claude Desktop 的 + 菜单显示学习伙伴的资源和提示可用作附件" width="100%" />
---
## 💬 提示
<table>
<tr>
<td width="50%" valign="top">
### 🎓 `study`
用任意风格教授一个主题。
```
topic: normalization
style: feynman
```
**风格:** `default`、`feynman`、`socratic`、`eli5`、`summary`、`exam-cram` 或模型可以解释的任何其他风格。
</td>
<td width="50%" valign="top">
### 🏫 `study_all`
遍历每个活动的注册主题。
```
style: default
order: weakest_first | registered
```
</td>
</tr>
<tr>
<td width="50%" valign="top">
### 📝 `quiz`
基于您内容的扎实测验。一次一个问题。结果自动记录。
```
topic: functional dependencies
n: 5
```
</td>
<td width="50%" valign="top">
### 🎯 `pyq_test`
真实的往年试卷或符合试卷风格的新试卷。
```
topic: normalization
mode: ask | verbatim | style
n: 5
```
</td>
</tr>
</table>
---
## 🛡️ 安全
- 所有文件访问仅限于 `materials/content/`、`materials/pyqs/`、`materials/archive/`
- 路径通过 `Path.is_relative_to` 验证:阻止 `../../.env` 遍历
- 主题字符串规范化并与注册行模糊匹配:无沉默行创建
- 每个输入绑定(`n`、`days`、`max_results`)通过 Pydantic `Field` 元数据强制执行
---
## 📄 支持的文件
| 类型 | 扩展名 | 处理方式 |
|:---|:---|:---|
| **文本** | `.txt`、`.md` | 直接读取 |
| **PDF** | `.pdf` | `pypdf` 文本提取 |
| **Word** | `.docx` | `python-docx` 提取 |
| **图像** | `.png`、`.jpg`、`.jpeg`、`.webp` | 作为 MCP `ImageContent` 返回:视觉客户端直接读取 |
> ⚠️ **扫描的 PDF** 没有可提取的文本。`pypdf` 返回空值。OCR(Tesseract)或文本版本在丢入之前。
---
## 🎬 示例会话
```
1. 从我的材料中发现主题。
2. 注册归一化和函数依赖。
3. 用考试冲刺风格教我归一化。
4. 对归一化进行 5 题测验。
5. 显示我最薄弱的话题。
6. 给我一个关于函数依赖的往年试卷风格的测试。
```
客户端链接发现 → 注册 → 检索 → 测验 → 日志记录,所有这些都针对您自己的材料。
<img src="assets/quiz.gif" alt="Claude Desktop 运行 5 题测验,评分每个答案并记录结果" width="100%" />
---
## 🚀 扩展
相同的 MCP 框架,不同的领域:
<table>
<tr>
<td>📄 研究论文助手</td>
<td>📚 本地文档导航器</td>
<td>🧑💻 代码库解释器</td>
</tr>
<tr>
<td>💼 求职跟踪器</td>
<td>💰 个人理财教练</td>
<td>🍳 食谱和膳食规划器</td>
</tr>
</table>
配方:
```
安全的数据访问
+ 工具 (操作)
+ 资源 (可浏览的上下文)
+ 提示 (工作流程)
+ 持久状态 (SQLite)
= 一个实用的 MCP 服务器
```
---
## 🛠️ 构建工具
<div align="center">
[](https://python.org)
[](https://github.com/modelcontextprotocol/python-sdk)
[](https://pydantic.dev)
[](https://sqlite.org)
[](https://docs.astral.sh/uv/)
</div>
- **[官方 MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk)**:`mcp[cli]` 与 FastMCP
- **SQLite**:持久状态(标准库)
- **Pydantic**:类型化输入(通过 SDK)
- **`pypdf`**、 **`python-docx`**:文件提取
- **`uv`**:依赖管理
---
## 📜 许可证
MIT © [Eshita Kundu](https://github.com/eshitakundu) (参见 [LICENSE](LICENSE))。
---
<div align="center">
**为 [Codédex 每月挑战,2026 年 6 月](https://www.codedex.io/community/monthly-challenge) 而建**
⭐ 如果这教给你一些东西,请点赞 · 🐛 [问题](https://github.com/eshitakundu/study-buddy/issues) · 💬 [讨论](https://github.com/eshitakundu/study-buddy/discussions)
</div>