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