Skip to main content
Glama
kmprograms

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