Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions mcp_plex/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,25 @@
import click
import httpx
from fastembed import SparseTextEmbedding, TextEmbedding
from qdrant_client.async_qdrant_client import AsyncQdrantClient
from qdrant_client import models
from qdrant_client.async_qdrant_client import AsyncQdrantClient

from .types import (
AggregatedItem,
ExternalIDs,
IMDbTitle,
PlexGuid,
PlexItem,
PlexPerson,
TMDBEpisode,
TMDBItem,
TMDBMovie,
TMDBShow,
PlexGuid,
PlexPerson,
)

try: # Only import plexapi when available; the sample data mode does not require it.
from plexapi.server import PlexServer
from plexapi.base import PlexPartialObject
from plexapi.server import PlexServer
except Exception:
PlexServer = None # type: ignore[assignment]
PlexPartialObject = object # type: ignore[assignment]
Expand Down
17 changes: 11 additions & 6 deletions mcp_plex/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,21 @@
from __future__ import annotations

import asyncio
import os
import json
import os
from collections import OrderedDict
from typing import Any, Annotated
from typing import Annotated, Any

from fastembed import SparseTextEmbedding, TextEmbedding
from fastmcp.server import FastMCP
from qdrant_client.async_qdrant_client import AsyncQdrantClient
from qdrant_client import models
from fastembed import TextEmbedding, SparseTextEmbedding
from pydantic import Field
from qdrant_client import models
from qdrant_client.async_qdrant_client import AsyncQdrantClient

try:
from sentence_transformers import CrossEncoder
except Exception:
CrossEncoder = None

try:
from sentence_transformers import CrossEncoder
Expand Down Expand Up @@ -151,7 +156,7 @@ async def search_media(
) -> list[dict[str, Any]]:
"""Hybrid similarity search across media items using dense and sparse vectors."""
dense_task = asyncio.to_thread(lambda: list(_dense_model.embed([query]))[0])
sparse_task = asyncio.to_thread(lambda: _sparse_model.query_embed(query))
sparse_task = asyncio.to_thread(lambda: next(_sparse_model.query_embed(query)))
dense_vec, sparse_vec = await asyncio.gather(dense_task, sparse_task)
named_dense = models.NamedVector(name="dense", vector=dense_vec)
sv = models.SparseVector(
Expand Down
2 changes: 1 addition & 1 deletion mcp_plex/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from __future__ import annotations

from dataclasses import dataclass
from typing import List, Optional, Literal
from typing import List, Literal, Optional

from pydantic import BaseModel, Field

Expand Down
1 change: 1 addition & 0 deletions tests/test_load_from_plex.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import asyncio
import types

import httpx

from mcp_plex import loader
Expand Down
3 changes: 2 additions & 1 deletion tests/test_loader_cli.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import asyncio
from click.testing import CliRunner

import pytest
from click.testing import CliRunner

from mcp_plex import loader

Expand Down
3 changes: 2 additions & 1 deletion tests/test_loader_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
from pathlib import Path
from types import SimpleNamespace

from mcp_plex import loader
from qdrant_client import models

from mcp_plex import loader


class DummyTextEmbedding:
def __init__(self, name: str):
Expand Down
12 changes: 6 additions & 6 deletions tests/test_loader_unit.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import types
import asyncio
import httpx

import types
from pathlib import Path

import httpx

from mcp_plex.loader import (
_extract_external_ids,
_load_from_sample,
_build_plex_item,
_extract_external_ids,
_fetch_imdb,
_fetch_tmdb_episode,
_fetch_tmdb_movie,
_fetch_tmdb_show,
_fetch_tmdb_episode,
_load_from_sample,
)


Expand Down
13 changes: 7 additions & 6 deletions tests/test_server.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
from typing import Any
import asyncio
from pathlib import Path
import importlib
import types
import json
import time
import sys
import time
import types
from pathlib import Path
from typing import Any

import pytest
from qdrant_client import models

from mcp_plex import loader
from qdrant_client import models


class DummyTextEmbedding:
Expand Down Expand Up @@ -51,7 +52,7 @@ def passage_embed(self, texts):

def query_embed(self, text):
time.sleep(0.1)
return DummySparseVector([0], [1.0])
yield DummySparseVector([0], [1.0])


class DummyReranker:
Expand Down