study-mcp
by italoo97
README.md
# ๐ study-mcp
> A Model Context Protocol (MCP) server that turns video transcripts and study materials into a searchable, AI-powered knowledge base โ directly inside Claude Desktop.
[](https://github.com/italoo97/study-mcp/actions/workflows/ci.yml)
[](https://www.python.org)
[](#-development)
[](LICENSE)
---
## โจ What it does
Paste a video transcript or point to a PDF, slide deck, DOCX, or image and instantly:
- ๐ฌ **Ingest video transcripts** โ paste raw text or load `.srt`/`.vtt` caption files; timestamps are preserved so you can jump back to the exact moment in the video
- ๐ **Search semantically** โ ask questions in natural language across all your materials, powered by local embeddings (no API cost)
- ๐ฏ **Generate quizzes** โ sample representative context from any material so Claude can quiz you on it
- ๐ง **Summarize & create flashcards** โ saved directly to Notion
- ๐ **Track your library** โ list materials, inspect overviews, view stats, delete what you no longer need
Everything runs locally by default (ChromaDB + HuggingFace embeddings). Set a single environment variable to switch to pgvector on Supabase/Postgres.
---
## ๐งฐ Tech Stack
| Layer | Technology |
|---|---|
| Language | Python 3.13 |
| MCP server | [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) (FastMCP) |
| Embeddings | [sentence-transformers](https://sbert.net) + HuggingFace models (local inference, PyTorch) |
| Vector stores | [ChromaDB](https://www.trychroma.com) (local) ยท [pgvector](https://github.com/pgvector/pgvector) on Supabase/Postgres (cloud) |
| Document parsing | [Docling](https://github.com/docling-project/docling) (PDF, DOCX, PPTX, HTML, images) + native SRT/VTT parser |
| Integrations | [Notion API](https://developers.notion.com) (`notion-client`) |
| Configuration | pydantic-settings (typed, env-based) |
| Tooling | Poetry ยท pytest (+coverage) ยท ruff ยท mypy `--strict` ยท pre-commit ยท commitizen |
| CI | GitHub Actions (lint, type check, tests on every push/PR) |
---
## ๐๏ธ Architecture
```
study-mcp/
โโโ src/study_mcp/
โ โโโ core/
โ โ โโโ config.py # Settings via environment variables (pydantic-settings)
โ โ โโโ embeddings.py # sentence-transformers, local inference, E5 prefixing
โ โ โโโ chunker.py # Heading โ paragraph โ sentence-aware chunking
โ โ โโโ transcript.py # SRT/VTT parser with timestamp preservation
โ โโโ db/
โ โ โโโ __init__.py # VectorRepository protocol + backend auto-detection
โ โ โโโ chroma.py # Local vector store (ChromaDB, zero setup)
โ โ โโโ pgvector.py # Cloud vector store (Supabase/Postgres, HNSW index)
โ โโโ tools/
โ โ โโโ ingest.py # File & raw-text ingestion (Docling + native parsers)
โ โ โโโ search.py # Semantic search
โ โ โโโ materials.py # Overview, quiz context, stats, deletion
โ โ โโโ list_materials.py
โ โ โโโ notion.py # Notion integration (summaries & flashcards)
โ โโโ server.py # FastMCP server: tools, resource, prompt, lifespan
โโโ tests/ # 60 tests, ~96% coverage, no model download needed
โโโ docs/
โโโ claude_desktop_config.json
```
**Design highlights:**
- **Repository pattern** โ both vector backends implement the same `VectorRepository` protocol; the backend is chosen at startup from `DATABASE_URL` with no code changes.
- **E5 query/passage prefixing** โ `intfloat/multilingual-e5-*` models are trained with `query:` / `passage:` prefixes; applying them measurably improves retrieval quality. Applied automatically when an E5 model is configured.
- **Sentence-aware chunking** โ text is split by heading, then paragraph, then grouped by whole sentences with sentence-level overlap. Chunks never cut a word or sentence in half.
- **Idempotent ingestion** โ `material_id` is a SHA-256 content hash, so re-ingesting the same material is a no-op (`already_indexed`) instead of a duplicate.
- **Timestamp-aware transcripts** โ SRT/VTT cues are grouped into paragraphs by speech pauses; search results on transcripts carry a `start_time` so you can jump back into the video.
---
## ๐ ๏ธ Available Tools
| Tool | Description |
|---|---|
| `ingest_text_tool` | Ingest raw text โ e.g. a pasted video transcript โ into the vector store |
| `ingest_file_tool` | Convert and index a file: PDF, DOCX, PPTX, HTML, images, `.txt`, `.md`, `.srt`, `.vtt` |
| `search_tool` | Semantic search across all indexed materials (optionally scoped to one) |
| `list_materials_tool` | List all indexed materials |
| `get_material_overview_tool` | Preview the first chunks of a material before summarizing or quizzing |
| `generate_quiz_context_tool` | Sample chunks spread across a material so Claude can write quiz questions |
| `study_stats_tool` | Totals: materials, chunks, chunks per material |
| `delete_material_tool` | Remove a material and all of its chunks |
| `save_summary_tool` | Save a summary to Notion |
| `save_flashcards_tool` | Save Q&A flashcards to Notion |
| `create_quiz_tool` | Create an interactive quiz page in Notion (open or multiple-choice, answer in Notion then paste back for checking) |
The three Notion tools also accept `related_pages` (a list of
`notion_url` values from earlier saves in the same conversation) to
link a new page to related materials via Notion's native mentions -
see [`docs/NOTION_SETUP.md`](docs/NOTION_SETUP.md).
The server also exposes an MCP **resource** (`study://materials`, the current library as JSON) and a **prompt** (`study_prompt`, a ready-made study-plan workflow for any material).
---
## ๐ Quick Start
### 1. Clone and install
```bash
git clone https://github.com/italoo97/study-mcp.git
cd study-mcp
poetry install
```
### 2. Configure environment
```bash
cp .env.example .env
```
All variables have sensible defaults โ the server works out of the box with ChromaDB and no external services. See [`.env.example`](.env.example) for every option.
### 3. Configure Claude Desktop
Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (see [`docs/claude_desktop_config.json`](docs/claude_desktop_config.json) for a full example):
```json
{
"mcpServers": {
"study-mcp": {
"command": "poetry",
"args": [
"--directory", "/absolute/path/to/study-mcp",
"run", "python", "-m", "study_mcp.server"
],
"env": {
"CHROMA_PATH": "/absolute/path/to/study-mcp/chroma_db"
}
}
}
}
```
> โ ๏ธ Claude Desktop launches the server from its own working directory, so relative paths (like the `.env` file or the default `./chroma_db`) won't resolve to the project folder. Set `CHROMA_PATH` to an absolute path as above, and pass any other variables (`NOTION_TOKEN`, `DATABASE_URL`, ...) in the `env` block โ see [`docs/claude_desktop_config.json`](docs/claude_desktop_config.json) for a complete example.
> **Vector backend is auto-detected:**
> - `DATABASE_URL` empty โ ChromaDB locally (zero setup)
> - `DATABASE_URL` set โ pgvector on Supabase/Postgres (free tier works; table and HNSW index are created automatically)
### 4. Restart Claude Desktop
The tools appear automatically.
---
## ๐ฌ Ingesting video transcripts
The main workflow this server was built for:
1. Open a video (YouTube, a recorded lecture, a course platform) and copy its transcript โ or download the captions as `.srt`/`.vtt`.
2. Paste it into Claude: *"Ingest this transcript as 'Linear Algebra โ Lecture 3': ..."* โ Claude calls `ingest_text_tool`.
3. Ask anything: *"According to my lecture, what is an eigenvector?"* โ `search_tool` returns the most relevant passages, each with a `start_time` when available, so you can jump back to that moment in the video.
4. Study actively: *"Quiz me on this lecture"* โ `generate_quiz_context_tool` samples passages spread across the whole material and Claude writes the questions.
`.srt`/`.vtt` files are parsed natively: cue numbers and markup are stripped, consecutive cues are merged into paragraphs at natural speech pauses, and paragraph start times are preserved as metadata.
---
## ๐ง Embedding Models
Set `EMBEDDING_MODEL` to any [sentence-transformers](https://sbert.net) compatible model:
| Model | Languages | Dims |
|---|---|---|
| `intfloat/multilingual-e5-small` *(default)* | PT + EN + 90 more | 384 |
| `intfloat/multilingual-e5-base` | PT + EN + 90 more | 768 |
| `BAAI/bge-small-en-v1.5` | EN only | 384 |
> Update `EMBEDDING_DIM` to match โ the server validates the dimension at startup and fails fast on a mismatch.
---
## ๐ Notion Setup (optional)
Only needed for `save_summary_tool` and `save_flashcards_tool`. Full
walkthrough (including a script that creates the database for you)
in [`docs/NOTION_SETUP.md`](docs/NOTION_SETUP.md).
Quick version:
1. Create an integration at [notion.so/my-integrations](https://www.notion.so/my-integrations)
2. Create the database โ either run
`poetry run python scripts/create_notion_database.py <parent_page_id>`
(creates it with the right schema and shares it automatically), or
create it by hand with these properties: `Name` (Title), `Type`
(Select), `Material` (Rich text), `Tags` (Multi-select) โ then
share it with your integration manually.
3. Set `NOTION_TOKEN` and `NOTION_DATABASE_ID` in the `env` block of
your Claude Desktop config (**not** `.env` โ see
[`docs/claude_desktop_config.json`](docs/claude_desktop_config.json)).
---
## ๐ก Example usage in Claude
```
"Ingest this transcript as 'ML Course โ Gradient Descent': [pasted transcript]"
"Ingest this file: /Users/me/Downloads/algorithms_lecture.pdf"
"Search my materials: what is dynamic programming?"
"Give me an overview of material a1b2c3d4"
"Quiz me with 10 questions about my gradient descent lecture"
"Summarize it and save to Notion with tags: ML, optimization"
"Show my study stats"
```
---
## ๐ง Development
```bash
poetry install
poetry run task lint # ruff check
poetry run task format # ruff format
poetry run task type_check # mypy --strict
poetry run task test # pytest (60 tests, coverage gate at 80%)
```
The test suite runs without downloading any embedding model โ embeddings are faked with deterministic vectors and the repository layer is tested against an in-memory double plus a real ChromaDB instance in a temp directory.
CI (GitHub Actions) runs lint, strict type checking, and the full test suite on every push and PR.
---
## ๐ License
[MIT](LICENSE)
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues