Skip to main content
Glama

get_recently_watched

Retrieve a list of recently watched movies, shows, or episodes from Plex Media Server. Filter results by media type and set a limit for the number of items returned.

Instructions

Get recently watched movies and shows

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
limitNoNumber of items to return (default: 25)
mediaTypeNoFilter by media type (movie, show, episode, all)all

Implementation Reference

  • Core handler function implementing the get_recently_watched tool logic. Primarily uses getWatchHistory but falls back to scanning libraries for recently viewed items based on lastViewedAt.
    private async getRecentlyWatched(limit: number, mediaType: string) { // Use the working watch history function as the foundation try { const historyResult = await this.getWatchHistory(limit, undefined, mediaType); const historyData = JSON.parse(historyResult.content[0].text); // Transform watch history into recently watched format return { content: [ { type: "text", text: JSON.stringify({ recentlyWatched: historyData.watchHistory || [], totalCount: historyData.totalSessions || 0, note: "Retrieved from watch history data", }, null, 2), }, ], }; } catch (error) { // Fallback to library metadata approach try { const librariesData = await this.makeRequest("/library/sections"); const libraries = librariesData.MediaContainer?.Directory || []; let allRecentItems: any[] = []; for (const library of libraries) { try { const params: Record<string, any> = { sort: "lastViewedAt:desc", "X-Plex-Container-Size": Math.ceil(limit / libraries.length) + 5, }; if (mediaType !== "all") { params.type = this.getPlexTypeId(mediaType); } const contentData = await this.makeRequest(`/library/sections/${library.key}/all`, params); const content = contentData.MediaContainer?.Metadata || []; // Filter items that have been viewed recently const viewedContent = content.filter((item: any) => item.lastViewedAt && item.viewCount > 0 ); allRecentItems.push(...viewedContent); } catch (libError) { continue; } } // Sort by last viewed date and take requested number allRecentItems.sort((a: any, b: any) => (b.lastViewedAt || 0) - (a.lastViewedAt || 0)); allRecentItems = allRecentItems.slice(0, limit); return { content: [ { type: "text", text: JSON.stringify({ recentlyWatched: allRecentItems.map((item: any) => ({ ratingKey: item.ratingKey, title: item.title, type: item.type, year: item.year, lastViewedAt: item.lastViewedAt, viewCount: item.viewCount, duration: item.duration, viewOffset: item.viewOffset || 0, progress: item.viewOffset && item.duration ? Math.round((item.viewOffset / item.duration) * 100) : 100, })), totalCount: allRecentItems.length, note: "Retrieved from library metadata", }, null, 2), }, ], }; } catch (fallbackError) { return { content: [ { type: "text", text: JSON.stringify({ recentlyWatched: [], totalCount: 0, error: "Recently watched data not available", message: "Unable to retrieve recently watched content from this Plex server", }, null, 2), }, ], }; } } }
  • Input schema definition for the get_recently_watched tool, specifying parameters limit and mediaType.
    inputSchema: { type: "object", properties: { limit: { type: "number", description: "Number of items to return (default: 25)", default: 25, }, mediaType: { type: "string", description: "Filter by media type (movie, show, episode, all)", enum: ["movie", "show", "episode", "all"], default: "all", }, }, },
  • src/index.ts:110-129 (registration)
    Tool registration in the ListTools response, defining name, description, and input schema for get_recently_watched.
    { name: "get_recently_watched", description: "Get recently watched movies and shows", inputSchema: { type: "object", properties: { limit: { type: "number", description: "Number of items to return (default: 25)", default: 25, }, mediaType: { type: "string", description: "Filter by media type (movie, show, episode, all)", enum: ["movie", "show", "episode", "all"], default: "all", }, }, }, },
  • Dispatcher case in the CallToolRequest handler that routes to the getRecentlyWatched method.
    case "get_recently_watched": return await this.getRecentlyWatched( ((args as any)?.limit as number) || 25, (args as any)?.mediaType as string || "all" );
  • Invocation of helper method getWatchHistory used as primary data source for recently watched items.
    const historyResult = await this.getWatchHistory(limit, undefined, mediaType); const historyData = JSON.parse(historyResult.content[0].text); // Transform watch history into recently watched format return { content: [ { type: "text", text: JSON.stringify({ recentlyWatched: historyData.watchHistory || [], totalCount: historyData.totalSessions || 0, note: "Retrieved from watch history data", }, null, 2), }, ], }; } catch (error) { // Fallback to library metadata approach try { const librariesData = await this.makeRequest("/library/sections"); const libraries = librariesData.MediaContainer?.Directory || []; let allRecentItems: any[] = []; for (const library of libraries) { try { const params: Record<string, any> = { sort: "lastViewedAt:desc", "X-Plex-Container-Size": Math.ceil(limit / libraries.length) + 5, }; if (mediaType !== "all") { params.type = this.getPlexTypeId(mediaType); } const contentData = await this.makeRequest(`/library/sections/${library.key}/all`, params); const content = contentData.MediaContainer?.Metadata || []; // Filter items that have been viewed recently const viewedContent = content.filter((item: any) => item.lastViewedAt && item.viewCount > 0 ); allRecentItems.push(...viewedContent); } catch (libError) { continue; } } // Sort by last viewed date and take requested number allRecentItems.sort((a: any, b: any) => (b.lastViewedAt || 0) - (a.lastViewedAt || 0)); allRecentItems = allRecentItems.slice(0, limit); return { content: [ { type: "text", text: JSON.stringify({ recentlyWatched: allRecentItems.map((item: any) => ({ ratingKey: item.ratingKey, title: item.title, type: item.type, year: item.year, lastViewedAt: item.lastViewedAt, viewCount: item.viewCount, duration: item.duration, viewOffset: item.viewOffset || 0, progress: item.viewOffset && item.duration ? Math.round((item.viewOffset / item.duration) * 100) : 100, })), totalCount: allRecentItems.length, note: "Retrieved from library metadata", }, null, 2), }, ], }; } catch (fallbackError) { return { content: [ { type: "text", text: JSON.stringify({ recentlyWatched: [], totalCount: 0, error: "Recently watched data not available", message: "Unable to retrieve recently watched content from this Plex server", }, null, 2), }, ], }; } } }

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/niavasha/plex-mcp-server'

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