search_pixabay_videos
Search for videos on Pixabay using query terms, with filters for video type, orientation, duration, and results per page.
Instructions
Search for videos on Pixabay
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search query terms | |
| video_type | No | Filter results by video type | all |
| orientation | No | Filter results by video orientation | all |
| per_page | No | Number of results per page (3-200) | |
| min_duration | No | Minimum video duration in seconds | |
| max_duration | No | Maximum video duration in seconds |
Implementation Reference
- src/index.ts:453-536 (handler)Core execution logic for the search_pixabay_videos tool: validates parameters, calls Pixabay Video API, formats and returns results or handles errors.if (request.params.name === 'search_pixabay_videos') { if (!isValidVideoSearchArgs(request.params.arguments)) { throw new McpError( ErrorCode.InvalidParams, 'Invalid video search arguments. "query" (string) is required.' ); } assertValidVideoSearchParams(request.params.arguments); const { query, video_type = 'all', orientation = 'all', per_page = 20, min_duration, max_duration } = request.params.arguments; try { const params: any = { key: API_KEY, q: query, video_type: video_type, orientation: orientation, per_page: per_page, safesearch: true }; // 只有在提供了时长参数时才添加到请求中 if (min_duration !== undefined) { params.min_duration = min_duration; } if (max_duration !== undefined) { params.max_duration = max_duration; } const response = await axios.get<PixabayVideoResponse>(PIXABAY_VIDEO_API_URL, { params }); if (response.data.hits.length === 0) { return { content: [{ type: "text", text: `No videos found for query: "${query}"` }] }; } // 格式化视频搜索结果 const resultsText = response.data.hits.map((hit: PixabayVideo) => { const duration = Math.floor(hit.duration); const videoUrl = hit.videos.medium?.url || hit.videos.small?.url || hit.videos.tiny?.url || 'No video URL available'; return `- ${hit.tags} (User: ${hit.user}, Duration: ${duration}s): ${videoUrl}`; }).join('\n'); return { content: [{ type: "text", text: `Found ${response.data.totalHits} videos for "${query}":\n${resultsText}` }] }; } catch (error: unknown) { let errorMessage = 'Failed to fetch videos from Pixabay.'; if (axios.isAxiosError(error)) { errorMessage = `Pixabay Video API error: ${error.response?.status} ${error.response?.data?.message || error.message}`; if (error.response?.status === 400) { errorMessage += '. Please check if the API key is valid.'; } } else if (error instanceof Error) { errorMessage = error.message; } logPixabayError('video', error); return { content: [{ type: "text", text: errorMessage }], isError: true }; } }
- src/index.ts:312-354 (registration)Tool registration in the listTools handler, defining name, description, and input schema for search_pixabay_videos.{ name: "search_pixabay_videos", description: "Search for videos on Pixabay", inputSchema: { type: "object", properties: { query: { type: "string", description: "Search query terms" }, video_type: { type: "string", enum: ["all", "film", "animation"], description: "Filter results by video type", default: "all" }, orientation: { type: "string", enum: ["all", "horizontal", "vertical"], description: "Filter results by video orientation", default: "all" }, per_page: { type: "number", description: "Number of results per page (3-200)", default: 20, minimum: 3, maximum: 200 }, min_duration: { type: "number", description: "Minimum video duration in seconds", minimum: 0 }, max_duration: { type: "number", description: "Maximum video duration in seconds", minimum: 0 } }, required: ["query"] } }
- src/index.ts:162-228 (schema)Input parameter validation function for search_pixabay_videos tool parameters, ensuring they match Pixabay API requirements.function assertValidVideoSearchParams(args: { video_type?: string; orientation?: string; per_page?: number; min_duration?: number; max_duration?: number; }): void { const { video_type, orientation, per_page, min_duration, max_duration } = args; if (video_type !== undefined && !VIDEO_TYPE_OPTIONS.includes(video_type)) { throw new McpError( ErrorCode.InvalidParams, `video_type 必须是 ${VIDEO_TYPE_OPTIONS.join(', ')} 之一。` ); } if (orientation !== undefined && !ORIENTATION_OPTIONS.includes(orientation)) { throw new McpError( ErrorCode.InvalidParams, `orientation 必须是 ${ORIENTATION_OPTIONS.join(', ')} 之一。` ); } if (per_page !== undefined) { if (!Number.isInteger(per_page)) { throw new McpError( ErrorCode.InvalidParams, 'per_page 必须是整数。' ); } if (per_page < MIN_PER_PAGE || per_page > MAX_PER_PAGE) { throw new McpError( ErrorCode.InvalidParams, `per_page 需在 ${MIN_PER_PAGE}-${MAX_PER_PAGE} 范围内。` ); } } if (min_duration !== undefined) { if (!Number.isInteger(min_duration) || min_duration < 0) { throw new McpError( ErrorCode.InvalidParams, 'min_duration 必须是大于等于 0 的整数。' ); } } if (max_duration !== undefined) { if (!Number.isInteger(max_duration) || max_duration < 0) { throw new McpError( ErrorCode.InvalidParams, 'max_duration 必须是大于等于 0 的整数。' ); } } if ( min_duration !== undefined && max_duration !== undefined && max_duration < min_duration ) { throw new McpError( ErrorCode.InvalidParams, 'max_duration 需大于或等于 min_duration。' ); } }
- src/index.ts:111-122 (helper)Type guard function to validate the structure of arguments passed to the search_pixabay_videos tool.const isValidVideoSearchArgs = ( args: any ): args is { query: string; video_type?: string; orientation?: string; per_page?: number; min_duration?: number; max_duration?: number } => typeof args === 'object' && args !== null && typeof args.query === 'string' && (args.video_type === undefined || typeof args.video_type === 'string') && (args.orientation === undefined || typeof args.orientation === 'string') && (args.per_page === undefined || typeof args.per_page === 'number') && (args.min_duration === undefined || typeof args.min_duration === 'number') && (args.max_duration === undefined || typeof args.max_duration === 'number');
- src/index.ts:91-95 (helper)Type definition for Pixabay video search API response.interface PixabayVideoResponse { total: number; totalHits: number; hits: PixabayVideo[]; }