Skip to main content
Glama

search_entries

Find videos and media content by searching across titles, descriptions, tags, and transcripts. Filter results by date, category, or custom metadata to discover relevant content in Kaltura's media library.

Instructions

SEARCH for videos or LIST all content. USE WHEN: Finding videos by keyword, listing newest content, discovering what's available, filtering by date/category. POWERFUL SEARCH across titles, descriptions, tags, captions. EXAMPLES: 'Find videos about python', 'Show newest 10 videos' (use query='*' sort_field='created_at'), 'Search in transcripts for keyword', 'List videos from last week'. This is your primary discovery tool!

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYesSearch terms or '*' for all. EXAMPLES: '*' = list all videos, 'marketing' = find marketing content, '"exact phrase"' = exact match, 'python programming' = videos containing both words. ALWAYS use '*' when listing newest/all videos.
search_typeNoSearch scope: 'unified' (all fields), 'entry' (titles/descriptions), 'caption' (transcripts), 'metadata' (custom fields), 'cuepoint' (chapters). Default: 'unified'
match_typeNoMatch type: 'partial' (contains), 'exact_match' (exact phrase), 'starts_with' (prefix), 'exists' (has value), 'range' (numeric/date). Default: 'partial'
specific_fieldNoSpecific field to search within the selected scope. Common fields: 'name', 'description', 'tags', 'created_at'. Leave blank to search all fields.
boolean_operatorNoBoolean operator for multi-term queries: 'and' (all terms), 'or' (any term), 'not' (exclude). Default: 'and'
include_highlightsNoInclude highlighted matching text snippets in results. Default: true
custom_metadataNoCustom metadata search parameters. Requires both profile_id and xpath. Used for searching custom metadata fields.
date_rangeNoFilter entries by creation date range. Use YYYY-MM-DD format.
max_resultsNoMaximum number of results to return (default: 20, max: 100)
sort_fieldNoField to sort by. Options: 'created_at' (creation date), 'updated_at' (last modified), 'name' (alphabetical), 'views' (view count), 'plays' (play count), 'last_played_at' (recent activity), 'rank' (relevance), 'start_date' (schedule start), 'end_date' (schedule end). Default: 'created_at'
sort_orderNoSort direction. Use 'desc' for newest/highest first (default), 'asc' for oldest/lowest first. For finding latest content, use 'desc' with 'created_at'

Implementation Reference

  • Primary handler for 'search_entries' tool. Intelligently handles parameters, calls esearch_entries, adds rich search context, and formats results for MCP.
    async def search_entries_intelligent(
        manager: KalturaClientManager,
        query: str,
        search_type: str = "unified",
        match_type: str = "partial",
        specific_field: Optional[str] = None,
        boolean_operator: str = "and",
        include_highlights: bool = True,
        custom_metadata: Optional[Dict[str, Any]] = None,
        date_range: Optional[Dict[str, str]] = None,
        max_results: int = 20,
        sort_field: str = "created_at",
        sort_order: str = "desc",
    ) -> str:
        """
        Advanced search function that exposes the full power of Kaltura's eSearch API.
    
        This is the PRIMARY tool for finding and listing media entries. Use this for:
        - General searches with keywords
        - Listing all entries (query="*")
        - Filtering by date ranges, content types, fields
        - Searching in transcripts, metadata, or specific fields
        - Complex boolean queries with multiple criteria
    
        This function provides access to all eSearch capabilities while maintaining
        clear parameter naming and comprehensive documentation for LLM usage.
        """
    
        # Validate and cap max_results
        max_results = min(max_results, 100)
    
        # Handle special case for listing all entries
        if query == "*":
            # For wildcard searches, we need to avoid field-specific restrictions
            # Use unified search with a common term that should match most entries
            search_type = "unified"  # Force unified search to avoid field restrictions
            match_type = "partial"  # Use partial matching
            # Use common terms that are likely to appear in most entries (video, audio, or metadata)
            # "e" is the most common letter in English and should match most content
            query = "e"
            specific_field = None  # Clear any specific field to avoid API restrictions
    
        # Extract date range if provided
        date_after = None
        date_before = None
        if date_range:
            date_after = date_range.get("after")
            date_before = date_range.get("before")
    
        # Extract custom metadata parameters
        metadata_profile_id = None
        metadata_xpath = None
        if custom_metadata:
            metadata_profile_id = custom_metadata.get("profile_id")
            metadata_xpath = custom_metadata.get("xpath")
    
        # Call the underlying eSearch function with all parameters
        try:
            result = await esearch_entries(
                manager=manager,
                search_term=query,
                search_type=search_type,
                item_type=match_type,
                field_name=specific_field,
                add_highlight=include_highlights,
                operator_type=boolean_operator,
                metadata_profile_id=metadata_profile_id,
                metadata_xpath=metadata_xpath,
                date_range_start=date_after,
                date_range_end=date_before,
                limit=max_results,
                sort_field=sort_field,
                sort_order=sort_order,
            )
    
            # Parse the result to add comprehensive search context
            import json
    
            result_data = json.loads(result)
    
            # Add detailed search context information
            if "entries" in result_data:
                # Determine operation type
                original_query = query if query else "*"
                operation_type = "list_all" if original_query == "*" else "search"
    
                search_context = {
                    "searchQuery": original_query,
                    "operationType": operation_type,
                    "searchConfiguration": {
                        "scope": search_type,
                        "matchType": match_type,
                        "specificField": specific_field,
                        "booleanOperator": boolean_operator,
                        "highlightsEnabled": include_highlights,
                    },
                    "filters": {
                        "dateRange": date_range,
                        "customMetadata": custom_metadata if custom_metadata else None,
                    },
                    "results": {
                        "count": len(result_data["entries"]),
                        "totalMatches": result_data.get("totalCount", 0),
                        "maxRequested": max_results,
                    },
                    "searchCapabilities": {
                        "availableScopes": [
                            "unified (all content)",
                            "entry (metadata)",
                            "caption (transcripts)",
                            "metadata (custom fields)",
                            "cuepoint (temporal markers)",
                        ],
                        "availableMatchTypes": [
                            "partial (contains)",
                            "exact_match (exact phrase)",
                            "starts_with (prefix)",
                            "exists (field has value)",
                            "range (numeric/date)",
                        ],
                        "advancedFeatures": [
                            "highlighting",
                            "boolean operators",
                            "custom metadata search",
                            "date filtering",
                            "field-specific search",
                        ],
                    },
                }
                result_data["searchContext"] = search_context
    
            return json.dumps(result_data, indent=2)
    
        except Exception as e:
            # If eSearch fails, provide detailed error information
            logger.error(f"eSearch failed: {e}")
            return handle_kaltura_error(
                e,
                "search entries",
                {
                    "searchQuery": query,
                    "searchType": search_type,
                    "suggestion": "Try using simpler parameters or check your search syntax",
                },
            )
  • Input schema and description for the 'search_entries' tool, defining all parameters like query, search_type, sort_field, etc.
        name="search_entries",
        description="SEARCH for videos or LIST all content. USE WHEN: Finding videos by keyword, listing newest content, discovering what's available, filtering by date/category. POWERFUL SEARCH across titles, descriptions, tags, captions. EXAMPLES: 'Find videos about python', 'Show newest 10 videos' (use query='*' sort_field='created_at'), 'Search in transcripts for keyword', 'List videos from last week'. This is your primary discovery tool!",
        inputSchema={
            "type": "object",
            "properties": {
                "query": {
                    "type": "string",
                    "description": "Search terms or '*' for all. EXAMPLES: '*' = list all videos, 'marketing' = find marketing content, '\"exact phrase\"' = exact match, 'python programming' = videos containing both words. ALWAYS use '*' when listing newest/all videos.",
                },
                "search_type": {
                    "type": "string",
                    "enum": ["unified", "entry", "caption", "metadata", "cuepoint"],
                    "description": "Search scope: 'unified' (all fields), 'entry' (titles/descriptions), 'caption' (transcripts), 'metadata' (custom fields), 'cuepoint' (chapters). Default: 'unified'",
                },
                "match_type": {
                    "type": "string",
                    "enum": ["partial", "exact_match", "starts_with", "exists", "range"],
                    "description": "Match type: 'partial' (contains), 'exact_match' (exact phrase), 'starts_with' (prefix), 'exists' (has value), 'range' (numeric/date). Default: 'partial'",
                },
                "specific_field": {
                    "type": "string",
                    "description": "Specific field to search within the selected scope. Common fields: 'name', 'description', 'tags', 'created_at'. Leave blank to search all fields.",
                },
                "boolean_operator": {
                    "type": "string",
                    "enum": ["and", "or", "not"],
                    "description": "Boolean operator for multi-term queries: 'and' (all terms), 'or' (any term), 'not' (exclude). Default: 'and'",
                },
                "include_highlights": {
                    "type": "boolean",
                    "description": "Include highlighted matching text snippets in results. Default: true",
                },
                "custom_metadata": {
                    "type": "object",
                    "properties": {
                        "profile_id": {
                            "type": "integer",
                            "description": "Custom metadata profile ID",
                        },
                        "xpath": {
                            "type": "string",
                            "description": "XPath to specific metadata field",
                        },
                    },
                    "description": "Custom metadata search parameters. Requires both profile_id and xpath. Used for searching custom metadata fields.",
                },
                "date_range": {
                    "type": "object",
                    "properties": {
                        "after": {
                            "type": "string",
                            "description": "Created after this date (YYYY-MM-DD format)",
                        },
                        "before": {
                            "type": "string",
                            "description": "Created before this date (YYYY-MM-DD format)",
                        },
                    },
                    "description": "Filter entries by creation date range. Use YYYY-MM-DD format.",
                },
                "max_results": {
                    "type": "integer",
                    "description": "Maximum number of results to return (default: 20, max: 100)",
                },
                "sort_field": {
                    "type": "string",
                    "enum": [
                        "created_at",
                        "updated_at",
                        "name",
                        "views",
                        "plays",
                        "last_played_at",
                        "rank",
                        "start_date",
                        "end_date",
                    ],
                    "description": "Field to sort by. Options: 'created_at' (creation date), 'updated_at' (last modified), 'name' (alphabetical), 'views' (view count), 'plays' (play count), 'last_played_at' (recent activity), 'rank' (relevance), 'start_date' (schedule start), 'end_date' (schedule end). Default: 'created_at'",
                },
                "sort_order": {
                    "type": "string",
                    "enum": ["desc", "asc"],
                    "description": "Sort direction. Use 'desc' for newest/highest first (default), 'asc' for oldest/lowest first. For finding latest content, use 'desc' with 'created_at'",
                },
            },
            "required": ["query"],
        },
    ),
  • Dispatch/registration in call_tool handler mapping 'search_entries' to search_entries_intelligent function.
    elif name == "search_entries":
        result = await search_entries_intelligent(kaltura_manager, **arguments)
  • Core helper implementing Kaltura eSearch API calls, used by search_entries_intelligent.
    async def esearch_entries(
        manager: KalturaClientManager,
        search_term: str,
        search_type: str = "unified",
        item_type: str = "partial",
        field_name: Optional[str] = None,
        add_highlight: bool = True,
        operator_type: str = "and",
        metadata_profile_id: Optional[int] = None,
        metadata_xpath: Optional[str] = None,
        date_range_start: Optional[str] = None,
        date_range_end: Optional[str] = None,
        limit: int = 20,
        sort_field: str = "created_at",
        sort_order: str = "desc",
    ) -> str:
        """Enhanced search using Kaltura eSearch API with advanced capabilities."""
    
        client = manager.get_client()
    
        try:
            # Use the ElasticSearch service through the client
    
            # Create search items based on search type
            search_items = []
    
            if search_type == "unified":
                # Unified search across all entry data
                unified_item = KalturaESearchUnifiedItem()
                unified_item.searchTerm = search_term
                unified_item.itemType = _get_item_type(item_type)
                unified_item.addHighlight = add_highlight
                search_items.append(unified_item)
    
            elif search_type == "entry":
                # Search in specific entry fields
                entry_item = KalturaESearchEntryItem()
                entry_item.searchTerm = search_term
                entry_item.itemType = _get_item_type(item_type)
                entry_item.fieldName = _get_entry_field_name(field_name or "name")
                entry_item.addHighlight = add_highlight
                search_items.append(entry_item)
    
            elif search_type == "caption":
                # Search in captions
                caption_item = KalturaESearchCaptionItem()
                caption_item.searchTerm = search_term
                caption_item.itemType = _get_item_type(item_type)
                caption_item.fieldName = _get_caption_field_name(field_name or "content")
                caption_item.addHighlight = add_highlight
                search_items.append(caption_item)
    
            elif search_type == "metadata":
                # Search in custom metadata
                metadata_item = KalturaESearchEntryMetadataItem()
                metadata_item.searchTerm = search_term
                metadata_item.itemType = _get_item_type(item_type)
                metadata_item.addHighlight = add_highlight
    
                if metadata_profile_id:
                    metadata_item.metadataProfileId = metadata_profile_id
                if metadata_xpath:
                    metadata_item.xpath = metadata_xpath
    
                search_items.append(metadata_item)
    
            elif search_type == "cuepoint":
                # Search in cue points
                cuepoint_item = KalturaESearchCuePointItem()
                cuepoint_item.searchTerm = search_term
                cuepoint_item.itemType = _get_item_type(item_type)
                cuepoint_item.fieldName = _get_cuepoint_field_name(field_name or "text")
                cuepoint_item.addHighlight = add_highlight
                search_items.append(cuepoint_item)
    
            # Add date range filtering if specified
            if date_range_start and date_range_end:
                try:
                    start_timestamp = int(datetime.strptime(date_range_start, "%Y-%m-%d").timestamp())
                    end_timestamp = int(datetime.strptime(date_range_end, "%Y-%m-%d").timestamp())
    
                    range_item = KalturaESearchRange()
                    range_item.greaterThanOrEqual = start_timestamp
                    range_item.lessThanOrEqual = end_timestamp
    
                    date_item = KalturaESearchEntryItem()
                    date_item.itemType = KalturaESearchItemType.RANGE
                    date_item.fieldName = KalturaESearchEntryFieldName.CREATED_AT
                    date_item.range = range_item
    
                    search_items.append(date_item)
                except ValueError:
                    return json.dumps({"error": "Invalid date format. Use YYYY-MM-DD"})
    
            # Create search operator
            search_operator = KalturaESearchEntryOperator()
            search_operator.operator = _get_operator_type(operator_type)
            search_operator.searchItems = search_items
    
            # Create search parameters
            search_params = KalturaESearchEntryParams()
            search_params.searchOperator = search_operator
    
            # Add sorting
            order_by = KalturaESearchOrderBy()
            order_item = KalturaESearchEntryOrderByItem()
            order_item.sortField = _get_sort_field(sort_field)
            order_item.sortOrder = _get_sort_order(sort_order)
            order_by.orderItems = [order_item]
            search_params.orderBy = order_by
    
            # Add paging
            pager = KalturaFilterPager()
            pager.pageSize = limit
    
            # Execute search using the client's elasticsearch service
            search_results = client.elasticSearch.eSearch.searchEntry(search_params, pager)
    
            # Process results
            entries = []
            for result in search_results.objects:
                entry_data = {
                    "id": result.object.id,
                    "name": result.object.name,
                    "description": result.object.description,
                    "mediaType": result.object.mediaType.value
                    if hasattr(result.object.mediaType, "value")
                    else result.object.mediaType,
                    "createdAt": datetime.fromtimestamp(result.object.createdAt).isoformat()
                    if result.object.createdAt
                    else None,
                    "duration": result.object.duration,
                    "tags": result.object.tags,
                    "thumbnailUrl": result.object.thumbnailUrl,
                    "plays": result.object.plays,
                    "views": result.object.views,
                }
    
                # Add highlights if available
                if hasattr(result, "highlight") and result.highlight:
                    highlights = []
                    for highlight in result.highlight:
                        highlight_data = {
                            "fieldName": highlight.fieldName,
                            "hits": [hit.value for hit in highlight.hits] if highlight.hits else [],
                        }
                        highlights.append(highlight_data)
                    entry_data["highlights"] = highlights
    
                # Add items data (for captions, metadata, etc.)
                if hasattr(result, "itemsData") and result.itemsData:
                    items_data = []
                    for item_data in result.itemsData:
                        item_info = {"totalCount": item_data.totalCount, "items": []}
    
                        if hasattr(item_data, "items") and item_data.items:
                            for item in item_data.items:
                                item_detail = {}
    
                                # Handle different item types
                                if hasattr(item, "line"):  # Caption item
                                    item_detail.update(
                                        {
                                            "line": item.line,
                                            "startsAt": item.startsAt,
                                            "endsAt": item.endsAt,
                                            "language": item.language,
                                            "captionAssetId": item.captionAssetId,
                                        }
                                    )
                                elif hasattr(item, "valueText"):  # Metadata item
                                    item_detail.update(
                                        {
                                            "xpath": item.xpath,
                                            "metadataProfileId": item.metadataProfileId,
                                            "metadataFieldId": item.metadataFieldId,
                                            "valueText": item.valueText,
                                        }
                                    )
    
                                # Add highlights for this item
                                if hasattr(item, "highlight") and item.highlight:
                                    item_highlights = []
                                    for highlight in item.highlight:
                                        item_highlight = {
                                            "fieldName": highlight.fieldName,
                                            "hits": [hit.value for hit in highlight.hits]
                                            if highlight.hits
                                            else [],
                                        }
                                        item_highlights.append(item_highlight)
                                    item_detail["highlights"] = item_highlights
    
                                item_info["items"].append(item_detail)
    
                        items_data.append(item_info)
                    entry_data["itemsData"] = items_data
    
                entries.append(entry_data)
    
            return json.dumps(
                {
                    "searchTerm": search_term,
                    "searchType": search_type,
                    "totalCount": search_results.totalCount,
                    "entries": entries,
                },
                indent=2,
            )
    
        except Exception as e:
            return json.dumps(
                {
                    "error": f"eSearch failed: {str(e)}",
                    "searchTerm": search_term,
                    "searchType": search_type,
                },
                indent=2,
            )
  • Exports search_entries and search_entries_intelligent for import in server.py.
    from .search import (
        esearch_entries,
        list_categories,
        search_entries,
        search_entries_intelligent,
    )
    from .utils import (
        handle_kaltura_error,
        safe_serialize_kaltura_field,
        validate_entry_id,
    )
    
    # Export all tools
    __all__ = [
        # Utilities
        "handle_kaltura_error",
        "safe_serialize_kaltura_field",
        "validate_entry_id",
        # Media operations
        "get_download_url",
        "get_media_entry",
        "get_thumbnail_url",
        "list_media_entries",
        # Analytics operations
        "get_analytics",
        "get_analytics_timeseries",
        "get_video_retention",
        "get_realtime_metrics",
        "get_quality_metrics",
        "get_geographic_breakdown",
        "list_analytics_capabilities",
        # Search operations
        "esearch_entries",
        "list_categories",
        "search_entries",
        "search_entries_intelligent",

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/zoharbabin/kaltura-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server