Skip to main content
Glama
collections-users.ts11.9 kB
// Collection and user tools import { z } from "zod"; import { UnsplashClient } from "../services/unsplash-client.js"; import { SearchCollectionsSchema, GetCollectionPhotosSchema, SearchUsersSchema, GetUserPhotosSchema } from "../schemas/index.js"; import { SearchCollectionsResponse, SearchUsersResponse, UnsplashPhoto, ResponseFormat } from "../types.js"; import { formatCollectionsListMarkdown, formatPhotosListMarkdown, formatUsersListMarkdown, truncateIfNeeded } from "../services/formatters.js"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; export function registerCollectionAndUserTools( server: McpServer, client: UnsplashClient ): void { // Search collections server.registerTool( "unsplash_search_collections", { title: "Search Photo Collections", description: `Search for curated photo collections on Unsplash. Collections are curated sets of photos organized by theme, created by Unsplash users. Use this to find themed photo sets. Args: - query (string): Search keywords for collections - page (number): Page number for pagination (default: 1) - per_page (number): Results per page, 1-30 (default: 10) - response_format (string): Output as 'markdown' (default) or 'json' Returns: For JSON format: Search results with collection metadata { "total": number, "total_pages": number, "results": [ { "id": string, "title": string, "description": string, "total_photos": number, "user": { ... }, "links": { ... } } ] } Examples: - Find travel collections: query="travel" - Architecture collections: query="architecture"`, inputSchema: SearchCollectionsSchema, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true } }, async (params: z.infer<typeof SearchCollectionsSchema>) => { try { const data = await client.makeRequest<SearchCollectionsResponse>( "/search/collections", { query: params.query, page: params.page, per_page: params.per_page } ); if (data.results.length === 0) { return { content: [{ type: "text", text: `No collections found for query: "${params.query}"` }] }; } const output = { total: data.total, total_pages: data.total_pages, page: params.page, per_page: params.per_page, results: data.results }; if (params.response_format === ResponseFormat.JSON) { return { content: [{ type: "text", text: JSON.stringify(output, null, 2) }], structuredContent: output }; } let markdown = `# Collection Search Results for "${params.query}"\n\n`; markdown += `Found ${data.total.toLocaleString()} collections (Page ${params.page} of ${data.total_pages})\n\n`; markdown += formatCollectionsListMarkdown(data.results); if (params.page < data.total_pages) { markdown += `\n\n*Use page=${params.page + 1} to see more results*`; } return { content: [{ type: "text", text: truncateIfNeeded(markdown) }] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : "Unknown error occurred"; return { content: [{ type: "text", text: `Error searching collections: ${errorMessage}` }], isError: true }; } } ); // Get collection photos server.registerTool( "unsplash_get_collection_photos", { title: "Get Collection Photos", description: `Get all photos from a specific Unsplash collection. Use this to retrieve photos from a curated collection. First use unsplash_search_collections to find collection IDs. Args: - id (string): Collection ID - page (number): Page number for pagination (default: 1) - per_page (number): Results per page, 1-30 (default: 10) - orientation (string, optional): Filter by 'landscape', 'portrait', or 'squarish' - response_format (string): Output as 'markdown' (default) or 'json' Returns: Array of photos from the collection Examples: - Get collection photos: id="3330445" - Portrait photos only: id="3330445", orientation="portrait"`, inputSchema: GetCollectionPhotosSchema, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true } }, async (params: z.infer<typeof GetCollectionPhotosSchema>) => { try { const requestParams: Record<string, string | number | boolean> = { page: params.page, per_page: params.per_page }; if (params.orientation) { requestParams.orientation = params.orientation; } const photos = await client.makeRequest<UnsplashPhoto[]>( `/collections/${params.id}/photos`, requestParams ); if (photos.length === 0) { return { content: [{ type: "text", text: `No photos found in collection ${params.id}` }] }; } if (params.response_format === ResponseFormat.JSON) { return { content: [{ type: "text", text: JSON.stringify(photos, null, 2) }], structuredContent: { photos } }; } let markdown = `# Photos from Collection ${params.id}\n\n`; markdown += `Page ${params.page}\n\n`; markdown += formatPhotosListMarkdown(photos); return { content: [{ type: "text", text: truncateIfNeeded(markdown) }] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : "Unknown error occurred"; return { content: [{ type: "text", text: `Error fetching collection photos: ${errorMessage}` }], isError: true }; } } ); // Search users server.registerTool( "unsplash_search_users", { title: "Search Photographers", description: `Search for photographers and users on Unsplash. Find photographers by name or username to explore their portfolio. Args: - query (string): Search keywords for users/photographers - page (number): Page number for pagination (default: 1) - per_page (number): Results per page, 1-30 (default: 10) - response_format (string): Output as 'markdown' (default) or 'json' Returns: For JSON format: User search results { "total": number, "total_pages": number, "results": [ { "id": string, "username": string, "name": string, "total_photos": number, "total_likes": number, "total_collections": number, "links": { ... } } ] } Examples: - Find photographer: query="John Doe" - Search username: query="photographer123"`, inputSchema: SearchUsersSchema, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true } }, async (params: z.infer<typeof SearchUsersSchema>) => { try { const data = await client.makeRequest<SearchUsersResponse>("/search/users", { query: params.query, page: params.page, per_page: params.per_page }); if (data.results.length === 0) { return { content: [{ type: "text", text: `No users found for query: "${params.query}"` }] }; } const output = { total: data.total, total_pages: data.total_pages, page: params.page, per_page: params.per_page, results: data.results }; if (params.response_format === ResponseFormat.JSON) { return { content: [{ type: "text", text: JSON.stringify(output, null, 2) }], structuredContent: output }; } let markdown = `# User Search Results for "${params.query}"\n\n`; markdown += `Found ${data.total.toLocaleString()} users (Page ${params.page} of ${data.total_pages})\n\n`; markdown += formatUsersListMarkdown(data.results); if (params.page < data.total_pages) { markdown += `\n\n*Use page=${params.page + 1} to see more results*`; } return { content: [{ type: "text", text: truncateIfNeeded(markdown) }] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : "Unknown error occurred"; return { content: [{ type: "text", text: `Error searching users: ${errorMessage}` }], isError: true }; } } ); // Get user photos server.registerTool( "unsplash_get_user_photos", { title: "Get User's Photos", description: `Get photos uploaded by a specific Unsplash user/photographer. Retrieve the portfolio of a photographer. Use unsplash_search_users first to find usernames. Args: - username (string): Unsplash username - page (number): Page number for pagination (default: 1) - per_page (number): Results per page, 1-30 (default: 10) - order_by (string): Sort by 'latest' (default), 'oldest', or 'popular' - orientation (string, optional): Filter by 'landscape', 'portrait', or 'squarish' - response_format (string): Output as 'markdown' (default) or 'json' Returns: Array of photos by the user Examples: - Get user photos: username="johndoe" - Popular photos: username="johndoe", order_by="popular"`, inputSchema: GetUserPhotosSchema, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true } }, async (params: z.infer<typeof GetUserPhotosSchema>) => { try { const requestParams: Record<string, string | number | boolean> = { page: params.page, per_page: params.per_page, order_by: params.order_by }; if (params.orientation) { requestParams.orientation = params.orientation; } const photos = await client.makeRequest<UnsplashPhoto[]>( `/users/${params.username}/photos`, requestParams ); if (photos.length === 0) { return { content: [{ type: "text", text: `No photos found for user: ${params.username}` }] }; } if (params.response_format === ResponseFormat.JSON) { return { content: [{ type: "text", text: JSON.stringify(photos, null, 2) }], structuredContent: { photos } }; } let markdown = `# Photos by @${params.username}\n\n`; markdown += `Page ${params.page} (${params.order_by})\n\n`; markdown += formatPhotosListMarkdown(photos); return { content: [{ type: "text", text: truncateIfNeeded(markdown) }] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : "Unknown error occurred"; return { content: [{ type: "text", text: `Error fetching user photos: ${errorMessage}` }], isError: true }; } } ); }

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/mjordi/unsplash-mcp-server'

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