Skip to main content
Glama

search_images_for_essay

Find openly-licensed images tailored for essays by specifying your topic, key concepts, and preferred style. Ideal for enhancing academic or research content with relevant visuals.

Instructions

Search for images suitable for illustrating an essay

Input Schema

NameRequiredDescriptionDefault
conceptsYesList of key concepts to find images for
essay_topicYesMain topic/title of the essay
max_imagesNoMaximum images to return (default: 10)
styleNoPreferred image style (default: any)

Input Schema (JSON Schema)

{ "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "concepts": { "description": "List of key concepts to find images for", "items": { "type": "string" }, "type": "array" }, "essay_topic": { "description": "Main topic/title of the essay", "type": "string" }, "max_images": { "description": "Maximum images to return (default: 10)", "type": "number" }, "style": { "description": "Preferred image style (default: any)", "enum": [ "photo", "illustration", "any" ], "type": "string" } }, "required": [ "essay_topic", "concepts" ], "type": "object" }

Implementation Reference

  • The core handler function (execute) for the 'search_images_for_essay' tool. It destructures input args, defines an internal search helper, performs searches for the essay topic and each concept, compiles featured images and concept-specific images, and returns structured JSON results or error.
    execute: async (args) => { const { essay_topic, concepts = [], style = 'any', max_images = 10 } = args; const results = { topic: essay_topic, images_by_concept: {} as Record<string, any[]>, featured_images: [] as any[], total_images: 0 }; // Helper function to search images const searchImages = async (query: string, pageSize: number, filters: Record<string, string> = {}): Promise<{results: any[]}> => { const params: Record<string, string> = { q: query, page_size: String(pageSize), mature: 'false', ...filters }; if (style === 'photo') { params.extension = 'jpg,png'; } const queryParams = new URLSearchParams(params); try { const response = await fetch(`${OPENVERSE_API_BASE}/images/?${queryParams}`, { headers: { 'User-Agent': 'MCP-Openverse/1.0' } }); if (!response.ok) { return { results: [] }; } return await response.json() as {results: any[]}; } catch { return { results: [] }; } }; try { // Search for main topic const mainSearch = await searchImages(essay_topic, Math.min(5, max_images)); if (mainSearch.results) { results.featured_images = mainSearch.results.slice(0, 3).map((img: any) => ({ id: img.id, title: img.title || '', url: img.url, thumbnail: img.thumbnail || '', creator: img.creator || 'Unknown', license: img.license || '', attribution: img.attribution || '', source: img.source || '' })); results.total_images += results.featured_images.length; } // Search for each concept const imagesPerConcept = concepts.length ? Math.max(1, Math.floor(max_images / concepts.length)) : max_images; for (const concept of concepts) { if (results.total_images >= max_images) break; const conceptSearch = await searchImages( `${concept} ${essay_topic}`, imagesPerConcept ); if (conceptSearch.results && conceptSearch.results.length > 0) { results.images_by_concept[concept] = conceptSearch.results .slice(0, imagesPerConcept) .map((img: any) => ({ id: img.id, title: img.title || '', url: img.url, thumbnail: img.thumbnail || '', creator: img.creator || 'Unknown', license: img.license || '', attribution: img.attribution || '', source: img.source || '' })); results.total_images += results.images_by_concept[concept].length; } } return JSON.stringify(results, null, 2); } catch (error) { return JSON.stringify({ error: error instanceof Error ? error.message : 'Failed to search for essay images', topic: essay_topic }); } } });
  • Zod schema defining the input parameters for the search_images_for_essay tool, including essay_topic (required), concepts (array), style (enum), and max_images (optional).
    const essayImagesSchema = z.object({ essay_topic: z.string().describe('Main topic/title of the essay'), concepts: z.array(z.string()).describe('List of key concepts to find images for'), style: z.enum(['photo', 'illustration', 'any']).optional().describe('Preferred image style (default: any)'), max_images: z.number().optional().describe('Maximum images to return (default: 10)') });
  • src/index.ts:179-285 (registration)
    The server.addTool call registering the 'search_images_for_essay' tool, specifying name, description, parameters schema, and inline execute handler.
    // Tool: search_images_for_essay server.addTool({ name: 'search_images_for_essay', description: 'Search for images suitable for illustrating an essay', parameters: essayImagesSchema, execute: async (args) => { const { essay_topic, concepts = [], style = 'any', max_images = 10 } = args; const results = { topic: essay_topic, images_by_concept: {} as Record<string, any[]>, featured_images: [] as any[], total_images: 0 }; // Helper function to search images const searchImages = async (query: string, pageSize: number, filters: Record<string, string> = {}): Promise<{results: any[]}> => { const params: Record<string, string> = { q: query, page_size: String(pageSize), mature: 'false', ...filters }; if (style === 'photo') { params.extension = 'jpg,png'; } const queryParams = new URLSearchParams(params); try { const response = await fetch(`${OPENVERSE_API_BASE}/images/?${queryParams}`, { headers: { 'User-Agent': 'MCP-Openverse/1.0' } }); if (!response.ok) { return { results: [] }; } return await response.json() as {results: any[]}; } catch { return { results: [] }; } }; try { // Search for main topic const mainSearch = await searchImages(essay_topic, Math.min(5, max_images)); if (mainSearch.results) { results.featured_images = mainSearch.results.slice(0, 3).map((img: any) => ({ id: img.id, title: img.title || '', url: img.url, thumbnail: img.thumbnail || '', creator: img.creator || 'Unknown', license: img.license || '', attribution: img.attribution || '', source: img.source || '' })); results.total_images += results.featured_images.length; } // Search for each concept const imagesPerConcept = concepts.length ? Math.max(1, Math.floor(max_images / concepts.length)) : max_images; for (const concept of concepts) { if (results.total_images >= max_images) break; const conceptSearch = await searchImages( `${concept} ${essay_topic}`, imagesPerConcept ); if (conceptSearch.results && conceptSearch.results.length > 0) { results.images_by_concept[concept] = conceptSearch.results .slice(0, imagesPerConcept) .map((img: any) => ({ id: img.id, title: img.title || '', url: img.url, thumbnail: img.thumbnail || '', creator: img.creator || 'Unknown', license: img.license || '', attribution: img.attribution || '', source: img.source || '' })); results.total_images += results.images_by_concept[concept].length; } } return JSON.stringify(results, null, 2); } catch (error) { return JSON.stringify({ error: error instanceof Error ? error.message : 'Failed to search for essay images', topic: essay_topic }); } } });
  • Internal helper function used within the handler to perform API searches on Openverse with query, page size, filters, and style-specific adjustments.
    // Helper function to search images const searchImages = async (query: string, pageSize: number, filters: Record<string, string> = {}): Promise<{results: any[]}> => { const params: Record<string, string> = { q: query, page_size: String(pageSize), mature: 'false', ...filters }; if (style === 'photo') { params.extension = 'jpg,png'; } const queryParams = new URLSearchParams(params); try { const response = await fetch(`${OPENVERSE_API_BASE}/images/?${queryParams}`, { headers: { 'User-Agent': 'MCP-Openverse/1.0' } }); if (!response.ok) { return { results: [] }; } return await response.json() as {results: any[]}; } catch { return { results: [] }; } };

Other Tools

Related Tools

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/neno-is-ooo/mcp-openverse'

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