YouTube Transcripts MCP Server
by kmprograms
README.md
# Serwer MCP z transkrypcjami YouTube
**Język / Language:** **Polski** | [English](README.en.md)
---
Serwer MCP (Model Context Protocol), który udostępnia transkrypcje filmów YouTube jako narzędzia dla hostów AI, na przykład Claude Code. Host prosi o transkrypcję po adresie URL albo identyfikatorze filmu, a serwer pobiera ją z YouTube i zwraca jako czysty tekst wraz z metadanymi. Dzięki temu model może streścić film, wyszukać w nim fragment albo odpowiedzieć na pytania o jego treść bez oglądania nagrania.
Serwer działa lokalnie na transporcie stdio, więc uruchamia go host jako podproces na tym samym komputerze.
---
> 📺 **Wolisz obejrzeć niż czytać?** Cały projekt omawiam na YouTube:
> **[Część 1](https://youtu.be/VEfx75k5g7k)** · **[Część 2](https://youtu.be/DP6PpkdxDSo)**
---
## Spis treści
- [Funkcjonalność](#funkcjonalność)
- [Narzędzia MCP](#narzędzia-mcp)
- [Architektura](#architektura)
- [Wymagania](#wymagania)
- [Instalacja](#instalacja)
- [Konfiguracja](#konfiguracja)
- [Podłączenie do Claude Code](#podłączenie-do-claude-code)
- [Przykład użycia](#przykład-użycia)
- [Struktura projektu](#struktura-projektu)
- [Narzędzia deweloperskie](#narzędzia-deweloperskie)
---
## Funkcjonalność
- Pobieranie transkrypcji filmu YouTube na podstawie adresu URL lub 11-znakowego identyfikatora.
- Rozpoznawanie wielu formatów adresu: `youtube.com/watch?v=<id>`, skrócony `youtu.be/<id>` oraz ścieżki `/shorts/<id>`, `/embed/<id>` i `/live/<id>`.
- Wybór języka transkrypcji według listy preferencji, na przykład najpierw polski, potem angielski.
- Sprawdzenie listy dostępnych transkrypcji filmu bez pobierania ich treści.
- Zwracanie czytelnych metadanych: identyfikator filmu, język, kod języka, informacja czy transkrypcja jest generowana automatycznie oraz liczba fragmentów.
- Twardy limit czasu na każde żądanie sieciowe, żeby host nie czekał w nieskończoność.
- Czytelne komunikaty błędów zamiast wewnętrznych szczegółów biblioteki, na przykład gdy film nie istnieje albo nie ma transkrypcji w żądanym języku.
---
## Narzędzia MCP
Serwer wystawia dwa narzędzia, które host widzi przez `tools/list` i wywołuje przez `tools/call`.
| Narzędzie | Argumenty | Zwraca |
| ------------------ | ----------------------------------------------------- | --------------------------------------------------------------------- |
| `get_transcript` | `video: str`, `languages: list[str] \| None` | Pełny tekst transkrypcji plus metadane (język, liczba fragmentów). |
| `list_transcripts` | `video: str` | Lista dostępnych transkrypcji z językiem i informacją o tłumaczeniu. |
### `get_transcript`
Pobiera transkrypcję i skleja jej fragmenty w jeden ciągły tekst. W argumencie `video` podaj adres URL filmu albo sam identyfikator. W opcjonalnym `languages` podaj listę kodów języków w kolejności preferencji, na przykład `["pl", "en"]`. Gdy pominiesz `languages`, serwer użyje domyślnej listy z konfiguracji.
Odpowiedź zawiera pola `video_id`, `language`, `language_code`, `is_generated`, `snippet_count` oraz `text`.
### `list_transcripts`
Zwraca listę transkrypcji dostępnych dla filmu, bez pobierania ich treści. Przydatne, gdy chcesz najpierw sprawdzić, w jakich językach istnieje transkrypcja. Każda pozycja zawiera `language`, `language_code`, `is_generated` oraz `is_translatable`.
---
## Architektura
Serwer ma trzy warstwy, rozdzielone tak, żeby logika pobierania transkrypcji nie zależała od MCP.
```
Host (Claude Code)
│ stdio (JSON-RPC 2.0)
▼
server.py ── warstwa MCP: definicje narzędzi, obsługa błędów
│
▼
transcripts.py ── warstwa domenowa: pobieranie i model wyniku
│
├── youtube.py ── wyciąganie identyfikatora filmu z URL
└── config.py ── ustawienia z .env (pydantic-settings)
```
### Warstwy
| Plik | Rola |
| ----------------- | ------------------------------------------------------------------------------------------------------------ |
| `server.py` | Tworzy serwer FastMCP, definiuje narzędzia `get_transcript` i `list_transcripts`, mapuje wyjątki na komunikaty. |
| `transcripts.py` | Pobiera transkrypcję przez `youtube-transcript-api`, buduje modele wynikowe, rozróżnia typy błędów. |
| `youtube.py` | Zamienia adres URL lub identyfikator na 11-znakowy identyfikator filmu. |
| `config.py` | Wczytuje ustawienia ze zmiennych środowiskowych i pliku `.env` przez `pydantic-settings`. |
### Nieblokująca pętla zdarzeń
Pobieranie transkrypcji jest operacją blokującą, bo czeka na sieć. Narzędzia serwera są asynchroniczne, więc samą pracę blokującą uruchamiamy przez `asyncio.to_thread`. Dzięki temu pętla zdarzeń serwera pozostaje wolna i host nie blokuje się na czasie odpowiedzi YouTube.
### Transport stdio i logowanie
Serwer działa na transporcie stdio. Standardowe wyjście jest zarezerwowane dla wiadomości protokołu MCP, więc nie wolno nic wypisywać na nie zwykłym `print`. Wszystkie logi idą na standardowe wyjście błędów przez moduł `logging`. Poziom logowania ustawia zmienna `MCP_YT_LOG_LEVEL`.
### Limit czasu żądań
Warstwa transkrypcji korzysta z własnej sesji HTTP, która dokłada timeout do każdego żądania. Limit bierze wartość ze zmiennej `MCP_YT_REQUEST_TIMEOUT_SECONDS`. To chroni serwer przed zawieszeniem na wolnym albo niereagującym połączeniu.
---
## Wymagania
- **Python 3.14+** (wersja zapięta w `.python-version`).
- **[uv](https://docs.astral.sh/uv/)** — menedżer pakietów i wirtualnych środowisk (rekomendowany).
- **Host obsługujący MCP**, na przykład Claude Code, który uruchomi serwer i będzie z nim rozmawiał.
Serwer nie wymaga klucza API. Transkrypcje pobiera publicznie dostępna biblioteka `youtube-transcript-api`.
---
## Instalacja
```bash
git clone <url-repo> mcp-yt
cd mcp-yt
uv sync
```
`uv sync` utworzy `.venv/` i zainstaluje wszystkie zależności z `uv.lock` (deterministyczne wersje). Instalacja rejestruje też polecenie `mcp-yt`, które uruchamia serwer.
Szybki test, że serwer startuje:
```bash
uv run mcp-yt
```
Proces czeka na wiadomości protokołu przez stdio, więc w terminalu nie zobaczysz nic poza logami startu na standardowym wyjściu błędów. Przerwij działanie przez `Ctrl+C`. W normalnej pracy serwera nie uruchamiasz ręcznie — robi to host.
---
## Konfiguracja
Konfiguracja jest opcjonalna. Bez pliku `.env` serwer działa na wartościach domyślnych. Aby zmienić ustawienia, utwórz plik `.env` w katalogu głównym projektu:
```env
# Języki transkrypcji w kolejności preferencji.
MCP_YT_DEFAULT_LANGUAGES=["en","pl"]
# Maksymalny czas pojedynczego żądania w sekundach.
MCP_YT_REQUEST_TIMEOUT_SECONDS=20
# Poziom logowania.
MCP_YT_LOG_LEVEL=INFO
```
### Wszystkie zmienne środowiskowe
| Zmienna | Wymagana | Domyślnie | Opis |
| -------------------------------- | -------- | ----------- | ---------------------------------------------------------------- |
| `MCP_YT_DEFAULT_LANGUAGES` | nie | `["en"]` | Domyślna lista języków transkrypcji w kolejności preferencji. |
| `MCP_YT_REQUEST_TIMEOUT_SECONDS` | nie | `20.0` | Twardy limit czasu na każde żądanie sieciowe. |
| `MCP_YT_LOG_LEVEL` | nie | `INFO` | Poziom logowania, na przykład `DEBUG`, `INFO`, `WARNING`. |
Wszystkie zmienne mają prefiks `MCP_YT_`. Ustawienia są walidowane przez `pydantic-settings` na starcie aplikacji. Plik `.env` jest w `.gitignore` i nie trafia do repozytorium.
---
## Podłączenie do Claude Code
Claude Code czyta konfigurację serwerów MCP z pliku `.mcp.json` w katalogu projektu (zasięg `project`). Przykładowy wpis:
```json
{
"mcpServers": {
"youtube-transcripts": {
"type": "stdio",
"command": "uv",
"args": ["run", "--directory", "C:/ścieżka/do/mcp-yt", "mcp-yt"],
"env": {}
}
}
}
```
Podmień ścieżkę w `--directory` na miejsce, w którym leży projekt. Opcja `--directory` pilnuje, żeby serwer zawsze wystartował we właściwym katalogu, niezależnie od tego, skąd uruchomisz Claude Code.
### Zasięgi konfiguracji
Claude Code przechowuje konfigurację serwerów MCP w trzech zasięgach. Wybór zasięgu decyduje o tym, gdzie zapisze się konfiguracja i skąd serwer będzie widoczny.
- **local** — konfiguracja prywatna, tylko dla Ciebie i tylko w bieżącym projekcie. To zasięg domyślny.
- **project** — konfiguracja w pliku `.mcp.json` w katalogu projektu. Plik trafia do repozytorium, więc serwer działa dla każdego, kto sklonuje projekt. Jest widoczny tylko po uruchomieniu Claude Code w katalogu z tym plikiem.
- **user** — konfiguracja w globalnym pliku użytkownika. Serwer jest widoczny w każdym katalogu, ale konfiguracji nie da się współdzielić przez repozytorium.
Przy zasięgu `project` musisz otwierać Claude Code w katalogu projektu. Przy zasięgu `user` katalog nie ma znaczenia. Żeby zmienić zasięg przy dodawaniu serwera przez CLI, podmień `--scope project` na `--scope user`.
---
## Przykład użycia
Po podłączeniu serwera po prostu poproś hosta o pracę na filmie. Model sam wybierze odpowiednie narzędzie i wywoła je z identyfikatorem albo adresem filmu.
```
Streść mi ten film: https://youtu.be/VEfx75k5g7k
```
Host wywoła `get_transcript` z tym adresem, dostanie tekst transkrypcji i przygotuje streszczenie. Jeśli chcesz najpierw sprawdzić dostępne języki, poproś o to wprost:
```
W jakich językach jest transkrypcja tego filmu?
```
Wtedy host użyje `list_transcripts` i pokaże listę bez pobierania pełnej treści.
---
## Struktura projektu
```
mcp-yt/
├── src/
│ └── mcp_yt/
│ ├── __init__.py
│ ├── server.py # Warstwa MCP — serwer FastMCP i definicje narzędzi
│ ├── transcripts.py # Warstwa domenowa — pobieranie i modele wyniku
│ ├── youtube.py # Wyciąganie identyfikatora filmu z URL
│ └── config.py # Ustawienia z .env (pydantic-settings)
├── .mcp.json # Konfiguracja serwera dla Claude Code
├── .env # Zmienne środowiskowe — gitignored, opcjonalny
├── pyproject.toml # Zależności, skrypt mcp-yt, konfiguracja ruff i mypy
├── uv.lock # Lockfile uv
├── .python-version # 3.14
├── TEORIA.md # Wprowadzenie do MCP i różnic względem API
└── README.md
```
### Separation of concerns
- **`server.py`** zna tylko MCP i mapowanie błędów na komunikaty. Nie wie, jak pobiera się transkrypcję.
- **`transcripts.py`** zna bibliotekę YouTube i modele wyniku. Nie wie nic o MCP, więc można ją testować i używać osobno.
- **`youtube.py`** to czysta funkcja bez zależności sieciowych — łatwa do testowania.
- **`config.py`** to jedno źródło prawdy dla konfiguracji, walidowane na starcie.
---
## Narzędzia deweloperskie
Zależności deweloperskie instalują się razem z `uv sync`.
### Linter i formatowanie
```bash
uv run ruff check .
```
`ruff` jest skonfigurowany w `pyproject.toml` z zestawem reguł `E`, `F`, `I`, `UP`, `B`, `SIM` i długością linii 100.
### Type-check
```bash
uv run mypy .
```
`mypy` działa w trybie `strict` na katalogu `src`, więc wymusza pełne typowanie.
---
Więcej o tym, czym jest MCP i czym różni się od zwykłego API, znajdziesz w pliku [TEORIA.md](TEORIA.md).
TDQS
A4.1/5.0
Scored across 2 tools
Disambiguation5/5
The two tools serve clearly distinct purposes: one fetches full transcript content, the other lists available transcripts without content. No overlap.
Naming Consistency5/5
Both tools follow a consistent verb_noun snake_case pattern: get_transcript and list_transcripts.
Tool Count4/5
Two tools is minimal but appropriate for a focused read-only transcript service. Could add more but not needed.
Completeness5/5
The tool set covers the essential operations: listing available transcripts and retrieving one. No gaps for the stated purpose.
Maintenance
ActivityStale
ResponsivenessNo issues