diff --git a/mcp_plex/loader.py b/mcp_plex/loader.py index f5ddf23..5c0b942 100644 --- a/mcp_plex/loader.py +++ b/mcp_plex/loader.py @@ -86,11 +86,17 @@ async def _fetch_tmdb_show( async def _fetch_tmdb_episode( - client: httpx.AsyncClient, tmdb_id: str, api_key: str + client: httpx.AsyncClient, + show_id: int, + season_number: int, + episode_number: int, + api_key: str, ) -> Optional[TMDBEpisode]: - """Attempt to fetch TMDb data for a TV episode by its ID.""" + """Fetch TMDb data for a TV episode.""" - url = f"https://api.themoviedb.org/3/tv/episode/{tmdb_id}" + url = ( + f"https://api.themoviedb.org/3/tv/{show_id}/season/{season_number}/episode/{episode_number}" + ) resp = await client.get(url, headers={"Authorization": f"Bearer {api_key}"}) if resp.is_success: return TMDBEpisode.model_validate(resp.json()) @@ -178,9 +184,11 @@ async def _augment_episode( imdb_task = ( _fetch_imdb(client, ids.imdb) if ids.imdb else asyncio.sleep(0, result=None) ) + season = getattr(episode, "parentIndex", None) + ep_num = getattr(episode, "index", None) tmdb_task = ( - _fetch_tmdb_episode(client, ids.tmdb, tmdb_api_key) - if ids.tmdb + _fetch_tmdb_episode(client, show_tmdb.id, season, ep_num, tmdb_api_key) + if show_tmdb and season is not None and ep_num is not None else asyncio.sleep(0, result=None) ) imdb, tmdb_episode = await asyncio.gather(imdb_task, tmdb_task) diff --git a/pyproject.toml b/pyproject.toml index 5541645..3e2eeb3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "mcp-plex" -version = "0.26.12" +version = "0.26.13" description = "Plex-Oriented Model Context Protocol Server" requires-python = ">=3.11,<3.13" diff --git a/tests/test_load_from_plex.py b/tests/test_load_from_plex.py index 254e64b..0df8f60 100644 --- a/tests/test_load_from_plex.py +++ b/tests/test_load_from_plex.py @@ -31,6 +31,8 @@ def add_fetch(obj): guid="plex://episode/102", type="episode", title="Pilot", + parentIndex=1, + index=1, guids=[ types.SimpleNamespace(id="imdb://tt0959621"), types.SimpleNamespace(id="tmdb://62085"), @@ -95,10 +97,10 @@ async def handler(request): ) if "/movie/27205" in url: return httpx.Response(200, json={"id": 27205, "title": "Inception"}) + if "/tv/1396/season/1/episode/1" in url: + return httpx.Response(200, json={"id": 62085, "name": "Pilot"}) if "/tv/1396" in url: return httpx.Response(200, json={"id": 1396, "name": "Breaking Bad"}) - if "/episode/62085" in url: - return httpx.Response(200, json={"id": 62085, "name": "Pilot"}) return httpx.Response(404) transport = httpx.MockTransport(handler) diff --git a/tests/test_loader_unit.py b/tests/test_loader_unit.py index dfdc5b5..267ff05 100644 --- a/tests/test_loader_unit.py +++ b/tests/test_loader_unit.py @@ -96,7 +96,7 @@ async def tmdb_show_mock(request): async def tmdb_episode_mock(request): assert request.headers.get("Authorization") == "Bearer k" - if "good" in str(request.url): + if "/tv/1/season/2/episode/3" in str(request.url): return httpx.Response(200, json={"id": 1, "name": "E"}) return httpx.Response(404) @@ -119,7 +119,7 @@ async def main(): assert (await _fetch_tmdb_show(client, "bad", "k")) is None async with httpx.AsyncClient(transport=episode_transport) as client: - assert (await _fetch_tmdb_episode(client, "good", "k")) is not None - assert (await _fetch_tmdb_episode(client, "bad", "k")) is None + assert (await _fetch_tmdb_episode(client, 1, 2, 3, "k")) is not None + assert (await _fetch_tmdb_episode(client, 1, 2, 4, "k")) is None asyncio.run(main()) diff --git a/uv.lock b/uv.lock index 3898f30..73c469c 100644 --- a/uv.lock +++ b/uv.lock @@ -690,7 +690,7 @@ wheels = [ [[package]] name = "mcp-plex" -version = "0.26.12" +version = "0.26.13" source = { editable = "." } dependencies = [ { name = "fastapi" },