manage_media_requests
Handle media requests in Overseerr: retrieve, filter, approve, decline, or delete requests for movies and TV shows in your Plex ecosystem.
Instructions
Manage requests: get/list/approve/decline/delete. Supports filters and batching. Filters: all|pending|approved|available|processing|unavailable|failed
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | Action | |
| requestId | No | Request ID (single) | |
| requestIds | No | Request IDs (batch) | |
| format | No | compact | |
| summary | No | Stats instead of list | |
| filter | No | all | |
| take | No | ||
| skip | No | ||
| sort | No | added |
Implementation Reference
- src/index.ts:525-572 (registration)Registration of the 'manage_media_requests' tool in the ListTools response, including name, description, and detailed inputSchema matching ManageRequestsArgs{ name: 'manage_media_requests', description: 'Manage requests: get/list/approve/decline/delete. Supports filters and batching.\n' + 'Filters: all|pending|approved|available|processing|unavailable|failed', inputSchema: { type: 'object', properties: { action: { type: 'string', enum: ['get', 'list', 'approve', 'decline', 'delete'], description: 'Action', }, requestId: { type: 'number', description: 'Request ID (single)', }, requestIds: { type: 'array', items: { type: 'number' }, description: 'Request IDs (batch)', }, format: { type: 'string', enum: ['compact', 'standard', 'full'], default: 'compact', }, summary: { type: 'boolean', description: 'Stats instead of list', default: false, }, filter: { type: 'string', enum: ['all', 'pending', 'approved', 'available', 'processing', 'unavailable', 'failed'], default: 'all', }, take: { type: 'number', default: 20 }, skip: { type: 'number', default: 0 }, sort: { type: 'string', enum: ['added', 'modified'], default: 'added', }, }, required: ['action'], }, },
- src/types.ts:131-141 (schema)TypeScript interface defining the input parameters for manage_media_requests tool (ManageRequestsArgs)export interface ManageRequestsArgs { action: 'get' | 'list' | 'approve' | 'decline' | 'delete'; requestId?: number; requestIds?: number[]; format?: 'compact' | 'standard' | 'full'; summary?: boolean; filter?: 'all' | 'pending' | 'approved' | 'available' | 'processing' | 'unavailable' | 'failed'; take?: number; skip?: number; sort?: 'added' | 'modified'; }
- src/index.ts:1732-1752 (handler)Primary handler dispatcher for manage_media_requests tool, routes to action-specific sub-handlersprivate async handleManageRequests(args: any) { const manageArgs = args as ManageRequestsArgs; switch (manageArgs.action) { case 'get': return this.handleGetRequest(manageArgs); case 'list': return this.handleListRequests(manageArgs); case 'approve': return this.handleApproveRequests(manageArgs); case 'decline': return this.handleDeclineRequests(manageArgs); case 'delete': return this.handleDeleteRequests(manageArgs); default: throw new McpError( ErrorCode.InvalidParams, `Unknown action: ${manageArgs.action}` ); } }
- src/index.ts:1754-1782 (handler)Handler for 'get' action: fetches single request details with cachingprivate async handleGetRequest(args: ManageRequestsArgs) { if (!args.requestId) { throw new McpError(ErrorCode.InvalidParams, 'requestId is required for get action'); } const cacheKey = { requestId: args.requestId }; let request = this.cache.get<MediaRequest>('requests', cacheKey); if (!request) { const response = await this.axiosInstance.get<MediaRequest>( `/request/${args.requestId}` ); request = response.data; this.cache.set('requests', cacheKey, request); } return { content: [ { type: 'text', text: JSON.stringify( args.format === 'full' ? request : this.formatCompactRequest(request), null, 2 ), }, ], }; }
- src/index.ts:1784-1858 (handler)Handler for 'list' action: lists requests with pagination, filtering, sorting, summary stats, and cachingprivate async handleListRequests(args: ManageRequestsArgs) { const { filter, take, skip, sort, summary } = args; // If summary mode, fetch all results (don't use pagination) if (summary) { const params: any = { take: 1000, // Fetch large batch to get all/most results skip: 0, sort: sort || 'added', }; if (filter && filter !== 'all') { params.filter = filter; } // Don't cache summary queries as they need fresh data const response = await this.axiosInstance.get('/requests', { params }); const requests = response.data; const statusCounts: Record<string, number> = {}; requests.results.forEach((r: MediaRequest) => { const status = this.getStatusString(r.status); statusCounts[status] = (statusCounts[status] || 0) + 1; }); return { content: [ { type: 'text', text: JSON.stringify({ total: requests.results.length, statusBreakdown: statusCounts, filter: filter || 'all', }, null, 2), }, ], }; } // Regular list mode - use pagination const cacheKey = { filter, take, skip, sort }; let requests = this.cache.get<{ results: MediaRequest[]; PageInfo: any }>('requests', cacheKey); if (!requests) { const params: any = { take: take || 20, skip: skip || 0, sort: sort || 'added', }; if (filter && filter !== 'all') { params.filter = filter; } const response = await this.axiosInstance.get('/requests', { params }); requests = response.data; this.cache.set('requests', cacheKey, requests); } const formatted = requests ? requests.results.map(r => args.format === 'full' ? r : this.formatCompactRequest(r) ) : []; return { content: [ { type: 'text', text: JSON.stringify({ results: formatted, pageInfo: requests?.PageInfo, }, null, 2), }, ], }; }