Releases: samson-art/transcriptor-mcp
Releases · samson-art/transcriptor-mcp
v0.6.7
Added
- VTT word-by-word deduplication:
parseVTTnow groups and deduplicates consecutive cues with identical text, fixing duplicated words in word-level VTT subtitles (e.g. from YouTube auto-generated captions). - Reddit support: Reddit (reddit.com, old.reddit.com, v.redd.it) added as a supported platform for video transcripts and metadata. Documentation, validation, and MCP tool descriptions updated.
extractPlatformFromUrl(): New helper extracts platform identifier from input URL hostname (youtube, reddit, vimeo, etc.) for flexible source reporting.
Changed
- Subtitle validation and download logic: Refactored
validateAndDownloadSubtitles— introducedthrowNoSubtitlesErrorfor centralized "subtitles not found" handling; split auto-discovery and explicit-request flows intohandleAutoDiscoverFlowandhandleExplicitRequestFlowfor clearer structure and maintainability. - Error messages: Improved guidance for subtitle availability and Whisper fallback attempts when subtitles are not found.
- README and documentation: Refined introduction and connection options; added "supported platforms" section emphasizing multi-platform support; clarified Whisper fallback and Redis caching in
docs/configuration.md; streamlined quick-start with Smithery and Glama no-install options. sourcefield: Response schemas and validation now accept generic strings forsource(e.g.youtube,whisper,reddit) instead of fixed literals, allowing new platforms without schema changes.- Publish Docker workflow: Extracts and outputs built image tags; removed unused release trigger.
0.6.5
Added
- Publish Docker workflow: Manual run via
workflow_dispatchwith optionalversioninput (e.g.0.6.5orv0.6.5) andlatest_onlyflag. Whenlatest_only=true, builds from default branch and pushes only:latest(no version tag). - Docker image verification: Publish workflow logs the yt-dlp version installed in the built image for easier debugging.
- docs/configuration.md: Section on container memory limits for long Whisper transcriptions —
deploy.resources.limits.memory(e.g. 4–6 GB) to avoid OOM kills on CPU.
Changed
- WHISPER_TIMEOUT default: Increased from 2 minutes (120000 ms) to 10 minutes (600000 ms) to better support long videos.
- 404 error messages: When Whisper fallback fails, the "Subtitles not found" response now explicitly mentions that Whisper was attempted and suggests increasing
WHISPER_TIMEOUT(e.g. 3600000 for 1-hour videos). - Whisper error logging: Local and API modes now distinguish timeout (AbortError) vs network/service error in log messages.
- docs/configuration.md: Updated WHISPER_TIMEOUT description and flow text for 1-hour videos on CPU;
.env.exampleanddocker-compose.example.ymluse 600000 as the example value.
0.6.4
Added
- MCP tool
get_playlist_transcripts: Fetch cleaned subtitles for multiple videos from a playlist in one call. Parameters:url(playlist or watch with list=), optionalplaylistItems(yt-dlp -I spec, e.g. "1:5", "1,3,7", "-1"),maxItems,type,lang. NewdownloadPlaylistSubtitles()insrc/youtube.ts; tool registered inmcp-core.tsand server card. - Configurable subtitle format (srt, vtt, ass, lrc): New env
YT_DLP_SUB_FORMATand optionalformatparameter for MCP toolsget_transcript,get_raw_subtitles, andget_playlist_transcripts. REST APIPOST /subtitlesacceptsformat. Default remainssrt. Cache keys include format. ExportedSubtitleFormatandresolveSubtitleFormat()insrc/youtube.ts;get_raw_subtitlesoutput schema and server card includeassandlrc. search_videosextended with yt-dlp filters: OptionaldateBefore(e.g. "now-1year"),date(exact date),matchFilter(e.g. "!is_live", "duration < 3600").searchVideos()insrc/youtube.tsnow accepts these inSearchVideosOptions; yt-dlp receives--datebefore,--date,--match-filterwhen set.search_videosextended: Optionaloffset(pagination),uploadDateFilter(hour|today|week|month|year), andresponse_format(json|markdown).searchVideos()insrc/youtube.tsnow acceptsSearchVideosOptions(offset,dateAfter); yt-dlp receives--dateafterwhen filter is set. Server card and README tool reference updated.- Dynamic transcript resource: New MCP resource template
transcriptor://transcript/{videoId}. Clients can read a video transcript by URI (e.g.transcriptor://transcript/dQw4w9WgXcQ) without calling a tool. UsesResourceTemplatefrom the MCP SDK; handler fetches and parses subtitles and returns JSON (videoId,type,lang,text, optionalsource). - MCP prompt
search_and_summarize: New prompt with argsquery(required) andurl(optional). Builds a user message that asks the model to search YouTube for the query and summarize the first result's transcript, or to summarize the given video URL. Exposed in server card and intranscriptor://info. - Discoverable info resource: New MCP resource
transcriptor://info(Smithery discoverable) returning JSON with server message,availableResources(info, transcript template, supported-platforms, usage),tools, andprompts. Registered inmcp-core.tsand listed in server card. - Use-case documentation: Four new guides in
docs/: IDE and AI assistants (Cursor, Claude, VS Code), No-code automation (n8n), Researchers and batch processing, Self-hosted and enterprise. Earlier guides: summarize video, search and transcript. Linked from main README anddocs/README.md. - 404 response
availablefield: When subtitles are not found, the API now returnsavailable: { official, auto }in the 404 payload so clients can show supported languages without an extra/subtitles/availablecall. GET /changelogs: REST API and MCP HTTP servers now exposeGET /changelogs, returningCHANGELOG.mdastext/markdownfor programmatic access.- CORS for MCP HTTP discovery:
@fastify/corsenabled for MCP HTTP server (origin: true, methods: GET). Allows Smithery and other registries to fetch/.well-known/mcp/server-card.jsonand/.well-known/mcp/config-schema.jsonfrom cross-origin requests (SEP-1649). - SEP-1649 server card fields: Server card now includes
$schema,version,protocolVersion,transport(streamable-http /mcp), andcapabilities. Improves compatibility with MCP Server Cards spec and Smithery tool discovery. - Quick Start reordered: Smithery URL is now the first option ("no install"); Docker and local Node follow. Explicit "Connect by URL — no local install" messaging. README links to Smithery server page in header, Quick Start, Features, and "When to use".
- Smithery badge and VS Code install badges (README): Smithery badge added to the badge row; Overview now states "Optimized for Smithery with resources, prompts, and flexible configuration". Quick Start includes one-click install badges for VS Code and VS Code Insiders (URL-based config for the Smithery server).
- README "When to use Transcriptor MCP": New section describing when to choose transcriptor-mcp (transcripts/metadata without downloads, multi-platform, Whisper fallback, remote/HTTP, monitoring).
- yt-dlp
--no-playlistfor single-video tools:downloadSubtitles,fetchYtDlpJson, anddownloadAudionow pass--no-playlistso URLs likewatch?v=X&list=Yprocess only the single video instead of the full playlist. - yt-dlp env filters: New optional env vars:
YT_DLP_MAX_FILESIZE(e.g. "50M") for Whisper audio;YT_DLP_DOWNLOAD_ARCHIVE(path) and--break-on-existingforget_playlist_transcripts;YT_DLP_AGE_LIMITforsearch_videos. Documented indocs/configuration.mdand.env.example. YT_DLP_AUDIO_TIMEOUT: Separate timeout for audio download (Whisper fallback). Falls back toYT_DLP_TIMEOUTwhen unset. Enables processing videos up to 5 hours at slow download speeds (e.g. at ~420 KiB/s, 5 h audio needs ~15 min; set900000ms). Documented indocs/configuration.mdand.env.example.- Optimal audio quality for Whisper: When downloading audio via yt-dlp for Whisper fallback, the app now prefers smaller streams to reduce download time without hurting speech recognition. Format selector
bestaudio[abr<=192]/bestaudio(prefer streams ≤192 kbps; fallback to best audio) and--audio-quality 5(~128 kbps VBR for m4a) are used by default. Configurable viaYT_DLP_AUDIO_FORMATandYT_DLP_AUDIO_QUALITY(0–9, default:5). Documented indocs/configuration.mdand.env.example. - Sentry Performance / tracing: Optional
SENTRY_TRACES_SAMPLE_RATE(0–1, default0.1) andSENTRY_SEND_DEFAULT_PIIenv vars. Performance monitoring is active when running viastart/start:mcp/start:mcp:http. Documented indocs/sentry.mdand.env.example. - Sentry:
beforeSendfilters out expected client errors (NotFoundError, ValidationError) to reduce noise; expected 404s are monitored via Prometheus instead. - Prometheus metric
http_404_expected_total: Counter for expected 404 responses (NotFoundError) with labelsmethodandroute. - Load scenario "10 VU, 1 min": New k6 script
load/ten-users-1min.js— 10 concurrent users, each requests one video at a time until 1 minute; uses VIDEO_POOL. Make targetload-test-10vu-1min, npm scriptload-test:10vu-1min. Documented inload/load-testing.mdwith thresholds. - Load scenario "100 VU, 2h podcasts": New k6 script
load/podcast-2h-100vu.js— 100 VU at once, one 2h podcast per VU; usesPODCAST_2H_POOLandgetPodcast2hRequest()inload/config.js. Make targetload-test-podcast-2h, npm scriptload-test:podcast-2h. - Load test result report:
load/load-test-result-2025-02-15.md— results for subtitles, mixed, 10 VU 1 min, and podcast 2h scenarios (k6, BASE_URL, thresholds, metrics). - yt-dlp retries and extra args (all calls):
YT_DLP_RETRIES(-R),YT_DLP_RETRY_SLEEP(e.g.linear=1::2),YT_DLP_EXTRA_ARGS(space-separated). Documented indocs/configuration.mdand.env.example. - yt-dlp sleep options (rate limits):
YT_DLP_SLEEP_REQUESTS,YT_DLP_SLEEP_INTERVAL,YT_DLP_MAX_SLEEP_INTERVAL,YT_DLP_SLEEP_SUBTITLES. Documented indocs/configuration.mdand.env.example. - yt-dlp subtitle encoding:
YT_DLP_ENCODING(e.g.utf-8,cp1251) for subtitle downloads (--encoding). - yt-dlp audio download options (Whisper only):
YT_DLP_AUDIO_CONCURRENT_FRAGMENTS,YT_DLP_AUDIO_LIMIT_RATE,YT_DLP_AUDIO_THROTTLED_RATE, retries, buffer, downloader args for DASH/HLS reliability and speed. Documented indocs/configuration.mdand.env.example. YT_DLP_NO_WARNINGS: When set to1, pass--no-warningsto all yt-dlp calls. Reduces log noise.YT_DLP_IGNORE_NO_FORMATS: When not set to0, pass--ignore-no-formats-errorwhen fetching video metadata (info, chapters, available subtitles), so region-locked or undownloadable videos still return metadata. Set to0to fail on "No video formats" (default yt-dlp behavior). Documented indocs/configuration.md.- Unit tests for Tool Quality: In
mcp-http.test.ts, tests for server card: "includes title for each tool (Tool Quality)" asserts every tool has the expectedtitle; "includes parameter descriptions for get_raw_subtitles (Tool Quality)"; "includes SEP-1649 fields" for$schema,version,protocolVersion,transport, andcapabilities.
Changed
- README: Use-case section now references
docs/README.mdwith the full list of guides (summarize video, search and transcript, IDE/Cursor/Claude, n8n, researchers/batch, self-hosted). - Tool Quality (Smithery): Server card now includes
titlefor every tool (e.g. "Get video transcript", "Get raw video subtitles") anddescriptionfor every parameter ofget_raw_subtitles(type, lang, response_limit, next_cursor). Inmcp-core.ts, optional fields ofsubtitleInputSchemanow have.describe()so live MCPtools/listreturns parameter descriptions. Improves Smithery Tool Quality score. - Error messages: NotFoundError messages now hint at
/subtitles/availableand auto-discovery (omit type/lang). - README Features: First bullet is "Connect by URL (Smithery)" — use the server without installing Docker or Node. MCP quick start section retitled to "Docker and self-hosted" with a pointer to Smithery for one-click connection.
- MCP config schema and .well-known/mcp-config: Enriched
documentationwith expandedgettingStarted(three steps including Smithery URL and tool names),apiLink(GitHub readme), and updatedsecurity...
v0.5.5: Update to version 0.5.5 and add `search_videos` tool
Added
- MCP tool
search_videos: Search videos on YouTube via yt-dlp (ytsearch). No required parameters; providequeryand optionallimit(default 10, max 50). Returns list of videos with metadata (id, title, url, duration, uploader, viewCount, thumbnail). NewsearchVideos(query, limit, log)insrc/youtube.ts; tool registered inmcp-core.tsand exposed in server card. - Sentry breadcrumbs from Pino logs: When a 4xx or 5xx error is sent to Sentry, the event now includes a full trail of log calls (debug, info, warn, error) that led up to the error. REST API and MCP HTTP use a Pino logger that writes each log line to stdout and adds a Sentry breadcrumb;
maxBreadcrumbsset to 100 in Sentry init. New modulesrc/logger-sentry-breadcrumbs.ts(createLoggerWithSentryBreadcrumbs()); docs/sentry.md updated with a Breadcrumbs section. MCP_PUBLIC_URLS: Comma-separated list of public base URLs for multi-origin MCP deployments (e.g. Smithery + direct domain). The server selects the matching URL per request usingHostorX-Forwarded-Host. When set, takes precedence overMCP_PUBLIC_URL. Backward compatible: singleMCP_PUBLIC_URLstill works.- POST /sse compatibility: Some MCP clients (e.g. Cursor via Smithery) POST to
/ssefor streamable HTTP. The server now accepts POST on/sseand delegates to the streamable handler; canonical endpoint remains POST/mcp.
0.4.8
Added
- Unit tests:
ensureWritableCookiesFile— returns original path when writable; copies to temp and cleans up when read-only. - CI (GitHub Actions):
.github/workflows/ci.ymlruns on push/PR tomain:npm ci,make check-no-smoke(format-check, lint, typecheck, test, build). On push tomain, optional smoke job runs REST API smoke withSMOKE_SKIP_MCP=1..github/workflows/publish-docker.ymlruns on tag pushv*: build and push REST API and MCP images to Docker Hub (multi-arch linux/amd64, linux/arm64). RequiresDOCKERHUB_USERNAMEandDOCKERHUB_TOKENsecrets. - Readiness and metrics (REST API):
GET /health/ready— whenCACHE_MODE=redis, pings Redis; returns 503 if Redis is unreachable (for Kubernetes readiness).GET /metrics— Prometheus text format with counters:http_requests_total,http_request_errors_total,cache_hits_total,cache_misses_total. Newsrc/metrics.ts; validation layer records cache hit/miss; REST error handler and onResponse hook record errors and requests. - Cache:
cache.ping()insrc/cache.tsfor Redis liveness. Unit tests forping()when cache off and when Redis URL unset. - Documentation: README — repo/package name note (yt-captions-downloader vs transcriptor-mcp), Versioning subsection (version from package.json, tagging), Security section (do not commit or log
WHISPER_API_KEY,CACHE_REDIS_URL,MCP_AUTH_TOKEN, cookies path; use env or secret manager).docs/configuration.md— Health and metrics (health, health/ready, metrics), Recommended values for production table.docs/caching.md— section “When Redis is unavailable” (graceful degradation: request still served via yt-dlp). - E2E smoke: MCP streamable HTTP smoke now includes
checkMcpStreamableGetTranscript: after initialize, callstools/callforget_transcriptand asserts content or structuredContent.load/load-testing.md— “Recommended thresholds for regression” (e.g.http_req_failedrate<0.05, p95<120s;k6 run --throwfor CI). - Pre-commit (Husky):
huskydevDependency andpreparescript;.husky/pre-commitrunsnpm run format-check && npm run lint. - verify-pool script:
npm run verify-pool(and Make target) runsload/verify-pool.jsto validate the k6 load-test video ID pool. - Optional Redis cache: Responses for subtitles, video info, available subtitles, and chapters can be cached in Redis to reduce repeated yt-dlp calls. Configure via env:
CACHE_MODE(offorredis),CACHE_REDIS_URL(required whenredis),CACHE_TTL_SUBTITLES_SECONDS(default 7 days for subtitles),CACHE_TTL_METADATA_SECONDS(default 1 hour for video info, available subtitles, chapters). Newsrc/cache.tswithgetCacheConfig(),get(),set(),close(). Both REST API and MCP use the cache when enabled. Documented indocs/caching.md,docs/configuration.md, and.env.example. - MCP uses validation layer: MCP tools now call
validateAndDownloadSubtitles,validateAndFetchAvailableSubtitles,validateAndFetchVideoInfo, andvalidateAndFetchVideoChaptersinstead of calling youtube/whisper directly, so MCP benefits from the same cache and validation as the REST API. Removed privatefetchSubtitlesContentfrommcp-core.ts; tools catchValidationErrorandNotFoundErrorand return tool errors. - Unit tests:
cache.test.tsforgetCacheConfig(mode, TTLs from env), get/set whenCACHE_MODE=off, andclose().validation.test.tsmocks./cache.jsso existing tests run with cache disabled.mcp-core.test.tsupdated to mock validation’s validateAnd* and expect corresponding calls. - REST/MCP error types:
src/errors.tsexportsHttpError,ValidationError, andNotFoundErrorwith status codes and error labels. Validation helpers throw these; REST global error handler maps them to 4xx/5xx and consistent JSON (error,message). - MCP HTTP auth module:
src/mcp-auth.tsprovidesensureAuth(request, reply, authToken)andgetHeaderValue(); MCP HTTP server uses them whenMCP_AUTH_TOKENis set. Token comparison is timing-safe to prevent timing attacks. - Unit tests:
mcp-auth.test.tsforgetHeaderValueandensureAuth(no auth, missing/ malformed Bearer, wrong token, correct token).mcp-http.test.tsfor 401 on/mcpwhen auth required and no/ invalid header, and that/healthremains allowed without auth when token is set. - Load testing:
docs/load-testing.mddocuments k6-based load tests for the REST API (health, subtitles, mixed). Make targets:load-test,load-test-health,load-test-subtitles,load-test-mixed(Docker k6); npm scripts:load-test,load-test:subtitles,load-test:mixed. Configurable viaLOAD_BASE_URL/BASE_URLandRATE_LIMIT_MAXfor throughput. - Export:
YtDlpVideoInfotype is now exported fromyoutube.tsfor callers that pass pre-fetched data intofetchVideoChapters. - Unit tests:
youtube.test.ts—fetchVideoChapterswithpreFetchedData(no execFile call, correct chapter mapping; null handling).validation.test.ts—fetchYtDlpJsoncalled once and data passed tofetchVideoChapters; Vimeo test expects three-argument call.mcp-core.test.ts— chapters tool expectations updated for fetch order and three-argumentfetchVideoChapterscall. - yt-dlp proxy (optional): All yt-dlp requests (subtitle download, video info, chapters, audio for Whisper) can be routed through a proxy. Set
YT_DLP_PROXYto a URL; supported schemes:http://,https://,socks5://(e.g.http://user:password@proxy.example.com:8080,socks5://127.0.0.1:9050for Tor). Documented indocs/configuration.mdand.env.example; in Docker, set the variable in the containerenvironmentif needed. - Unit tests:
mcp-core.test.ts— Whisper fallback with omittedlang(auto-detect).whisper.test.ts— nolanguageparam whenlangis empty. - yt-dlp cookies file logging: When
COOKIES_FILE_PATHis set, the app now logs cookies file status before each yt-dlp call (subtitle download, audio download, video info/chapters). Logs include path, existence, file size, or access error message (no cookie contents). Helps diagnose "Sign in to confirm you're not a bot" and other YouTube auth issues when running in Docker or with mounted cookies.
Changed
- Graceful shutdown: REST API (
src/index.ts) and MCP HTTP (src/mcp-http.ts) now callcloseCache()after closing the server so the Redis connection is closed cleanly. - yt-dlp-check: Fallback logger uses
console.warninstead ofconsole.infofor the info-level message to satisfy the no-console lint rule. - Dependencies: Bumped Fastify plugins (
@fastify/cors^11.2.0,@fastify/multipart^9.4.0,@fastify/rate-limit^10.3.0,@fastify/swagger^9.7.0,@fastify/swagger-ui^5.2.5,@fastify/type-provider-typebox^6.1.0),@sinclair/typebox^0.34.48,ioredis^5.9.3. Dev:@types/jest^30.0.0,@types/node^25.2.3,@typescript-eslint/*andtypescript-eslint^8.55.0,eslint^9.18.0,jest^30.2.0,prettier^3.8.1,ts-jest^29.4.6,typescript^5.9.3,husky^9.1.7. - Dependency: Added
ioredisfor Redis cache backend (used only whenCACHE_MODE=redis). - MCP: Shared logic for subtitle fetch and Whisper fallback is now in a private
fetchSubtitlesContent(resolved, log)inmcp-core.ts. Toolsget_transcriptandget_raw_subtitlescall it and only handle final processing (parse + paginate vs raw + paginate). Removes duplication ofresolveSubtitleArgs,downloadSubtitles, and Whisper fallback between the two tools. - Docker: single Dockerfile with shared base. One Dockerfile now builds both REST API and MCP images via multi-stage build. Stages:
builder(Node, npm ci, build) →base(node, python3, pip, curl, unzip, ffmpeg, Deno, yt-dlp -U, YT_DLP_JS_RUNTIMES) →api(REST, port 3000) andmcp(MCP, port 4200). Build withdocker build -f Dockerfile --target api .or--target mcp ..Dockerfile.mcpremoved; Makefile targetsdocker-build-apianddocker-build-mcp(and buildx variants) use the same Dockerfile with the appropriate target. README anddocs/quick-start.mcp.mdupdated to use--target api/--target mcp. - Chapters: single yt-dlp fetch.
validateAndFetchVideoChapters(REST/video-info/chapters) and MCP toolget_video_chaptersnow perform one yt-dlp network call instead of two.fetchVideoChaptersinyoutube.tsaccepts an optional third argumentpreFetchedData; when provided, it reuses that data and skips the internalfetchYtDlpJsoncall. Validation and MCP handlers fetch once and pass the result intofetchVideoChapters, so video ID and chapters are derived from the same response. - Unit tests:
youtube.test.ts—getYtDlpEnvandappendYtDlpEnvArgsnow coverYT_DLP_PROXY/proxyFromEnv(trim, presence of--proxyin args, omission when unset). - MCP tools
get_transcriptandget_raw_subtitles: Parameterlangis now optional. When omitted, subtitle download still usesenfor yt-dlp; when Whisper fallback is used, language is auto-detected (nolanguagequery param sent to Whisper). Tool descriptions updated to mention optionallangand auto-detect behavior.
Security
- MCP HTTP auth: Bearer token validation uses
crypto.timingSafeEqualso comparison time does not depend on the token value.
Fixed
- yt-dlp cookies on read-only volume: When
COOKIES_FILE_PATHpoints to a read-only file (e.g. Docker volume mounted without write access), yt-dlp failed withPermissionErrorwhile saving cookies at exit, even when the download succeeded. The app now copies the cookies file to a writable temp location before passing it to yt-dlp; the temp file is removed after each call. NewensureWritableCookiesFile()inyoutube.tschecks read/write access and returns either the original path or a temp copy. Used by `downloadSubti...
transcriptor-mcp
Changed
- Project rename:
yt-captions-downloader→transcriptor-mcp. Package name, GitHub repo, Docker images, and docker-compose service names have been updated. - Package:
transcriptor-mcp(wasyt-captions-downloader-mcp). - GitHub:
samson-art/transcriptor-mcp. - Docker images:
artsamsonov/transcriptor-mcp(MCP),artsamsonov/transcriptor-mcp-api(REST API). - docker-compose services:
transcriptor-mcp(MCP),transcriptor-mcp-api(REST API). - MCP server name:
transcriptor-mcp(reported in MCP initialize). - User-Agent:
transcriptor-mcp(for yt-dlp requests). - MCP config key: Use
transcriptorinclaude_desktop_config.json/ Cursor MCP settings (shorter UX). docs/configuration.md: DocumentedYT_DLP_SKIP_VERSION_CHECKandYT_DLP_REQUIRED; startup checks referencesrc/yt-dlp-check.ts. Added "Whisper fallback" section for allWHISPER_*variables and usage (local container vs API).
Added
- Multi-platform support: Subtitles, available subtitles, video info, and chapters work with URLs from YouTube, Twitter/X, Instagram, TikTok, Twitch, Vimeo, Facebook, Bilibili, VK, and Dailymotion (via yt-dlp). Bare video IDs are supported for YouTube only.
- Whisper fallback: When YouTube subtitles cannot be obtained (yt-dlp returns none), the app can transcribe video audio via Whisper. Configurable with
WHISPER_MODE(off,local,api). Local mode uses a self-hosted HTTP service (e.g. whisper-asr-webservice in Docker); API mode uses an OpenAI-compatible transcription endpoint. New env vars:WHISPER_BASE_URL,WHISPER_TIMEOUT,WHISPER_API_KEY,WHISPER_API_BASE_URL. REST responses for/subtitlesand/subtitles/rawinclude optionalsource: "youtube" | "whisper"; MCP toolsget_transcriptandget_raw_subtitlesuse the same fallback and exposesourcein structured content. - Audio download:
downloadAudio(videoId, logger)inyoutube.tsdownloads audio-only via yt-dlp for Whisper input; uses same cookies and timeout as subtitle download. - Docker:
docker-compose.example.ymladds awhisperservice (imageonerahmet/openai-whisper-asr-webservice:latest) and exampleWHISPER_*env fortranscriptor-mcp-apiandtranscriptor-mcp..env.exampleanddocs/configuration.mddocument all Whisper options. - Unit tests:
src/whisper.test.tsforgetWhisperConfigandtranscribeWithWhisper;validation.test.tsextended with Whisper fallback success and 404 when Whisper returns null. - yt-dlp startup check: REST API, MCP HTTP, and MCP stdio servers run a yt-dlp availability check at startup. If yt-dlp is missing or fails to run, the app logs an ERROR and exits (unless
YT_DLP_REQUIRED=0). If the installed version is older than the latest on GitHub, a WARNING is logged. - Environment variables:
YT_DLP_SKIP_VERSION_CHECK— when set to1, skips the GitHub version check and WARNING;YT_DLP_REQUIRED— when set to0, logs ERROR but does not exit when yt-dlp is missing or fails. - Unit tests:
src/yt-dlp-check.test.tsfor version parsing, comparison, GitHub fetch, and startup check behavior.
0.3.7
Added
- REST API:
GET /healthendpoint returning{ "status": "ok" }for liveness/readiness and DockerHEALTHCHECK. - REST API: Optional CORS allowlist via
CORS_ALLOWED_ORIGINS(comma-separated origins); when unset, all origins remain allowed. - MCP HTTP server: Rate limiting configurable via
MCP_RATE_LIMIT_MAXandMCP_RATE_LIMIT_TIME_WINDOW. - MCP HTTP server: Session TTL and periodic cleanup via
MCP_SESSION_TTL_MSandMCP_SESSION_CLEANUP_INTERVAL_MS. - Version:
src/version.tsreads version frompackage.json; REST API and MCP server use it for responses and server info. - E2E smoke test: MCP coverage — starts MCP container and verifies stdio (initialize over stdin/stdout), streamable HTTP (
POST /mcp), and SSE (GET /sse). New env vars:SMOKE_SKIP_MCP,SMOKE_MCP_IMAGE,SMOKE_MCP_URL/SMOKE_MCP_PORT,SMOKE_MCP_AUTH_TOKEN, plus API-related overrides. - Docs:
docs/configuration.md— CORS, MCP rate limit/session/cleanup, health endpoint, and E2E smoke test env vars..env.exampleupdated withCORS_ALLOWED_ORIGINSand MCP HTTP options.
Changed
- REST API and MCP server now derive version from
package.jsoninstead of hardcoded values. - REST API: global Fastify error handler returns 500 with
errorandmessage; route handlers no longer wrap in try/catch so validation/parsing errors are handled consistently. - E2E smoke test flow: single entry
npm run test:e2e:apiwith optional MCP checks; README updated with env var table and simplified run instructions. docker-compose.example.yml: reordered keys (ports after environment), addedrestart: unless-stoppedfor MCP service; API service no longer includesbuild(image-only).- Jest: exclude
src/e2e/api-smoke.tsfrom coverage (top-level await).
0.3.6
[0.3.6] - 2026-02-05
Changed
- Upgraded Fastify to v5 and related plugins (
@fastify/cors,@fastify/multipart,@fastify/rate-limit,@fastify/swagger,@fastify/swagger-ui,@fastify/type-provider-typebox) to compatible major versions. - Bumped
@modelcontextprotocol/sdkto ^1.26.0.
0.3.5
[0.3.5] - 2026-02-04
Added
- OpenAPI/Swagger documentation at
/docswith request/response schemas for all REST endpoints (subtitles, raw subtitles, available subtitles, video info, chapters). - E2E smoke test now verifies that Swagger UI at
/docsis reachable.
Changed
- REST routes registered with
@fastify/swaggerand@fastify/swagger-ui; each endpoint documents body and response schemas for generated OpenAPI spec.
[0.3.4] - 2026-02-04
0.3.4
[0.3.4] - 2026-02-04
Added
- Docker-based e2e smoke test for the REST API (
src/e2e/api-smoke.ts) that builds a local image, starts a container and verifiesPOST /subtitlesagainst a real YouTube video. - Documentation in
READMEfor running Docker smoke tests locally and as part of themake publishworkflow. - Additional unit tests for validation helpers and yt-dlp integration (URL / video ID / language sanitization, video info and chapter extraction, environment-driven yt-dlp flags).
- Dedicated test suite for MCP tools (
src/mcp-core.test.ts) covering success and error paths for transcripts, raw subtitles, available subtitles, video info and chapters.
Changed
- Hardened
validation.tshelpers to provide more explicit 4xx errors for invalid URLs, video IDs and language codes across subtitles, available subtitles, video info and chapters endpoints. - Improved
youtube.tshelpers to map more yt-dlp metadata, expose chapter markers, and sort official vs auto subtitle language codes for stable output. - Refined MCP core implementation to use stricter validation and add pagination/error handling tests for all tools.
- Updated Jest configuration to collect coverage from
src, exclude entrypoints (REST + MCP) and enable verbose output.