Skip to main content
Glama
jeffkit
by jeffkit

search_photos

Find high-quality photos on Unsplash using search terms, with options to filter by orientation and content safety. Returns base64-encoded images.

Instructions

Search for photos on Unsplash. Returns base64-encoded images.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYesSearch term for photos
pageNoPage number (default: 1)
per_pageNoNumber of photos per page (default: 10, max: 30)
orientationNoFilter by orientation
content_filterNoContent safety filter

Implementation Reference

  • The main handler function that executes the search_photos tool logic. It queries the Unsplash API with search parameters (query, page, per_page, orientation, content_filter), handles the response, and returns either base64-encoded images or JSON metadata depending on the response format setting.
    private async searchPhotos(args: any) {
      try {
    
        const { query, page = 1, per_page = 10, orientation, content_filter = "low" } = args;
    
        const searchParams = new URLSearchParams({
          query,
          page: page.toString(),
          per_page: per_page.toString(),
          content_filter,
        });
    
        if (orientation) {
          searchParams.append("orientation", orientation);
        }
    
        const response = await fetch(
          `${UNSPLASH_API_URL}/search/photos?${searchParams}`,
          {
            headers: {
              Authorization: `Client-ID ${this.accessKey}`,
            },
          }
        );
    
        if (!response.ok) {
          throw new Error(`Unsplash API error: ${response.status} ${response.statusText}`);
        }
    
        const data: UnsplashSearchResponse = await response.json();
    
        if (this.responseFormat === 'text') {
          // Return JSON with URLs
          const formattedResults = data.results.map((photo) => ({
            id: photo.id,
            description: photo.description || photo.alt_description || "No description",
            urls: photo.urls,
            user: {
              name: photo.user.name,
              username: photo.user.username,
            },
            dimensions: {
              width: photo.width,
              height: photo.height,
            },
            likes: photo.likes,
            color: photo.color,
            created_at: photo.created_at,
          }));
    
          return {
            content: [
              {
                type: "text",
                text: JSON.stringify({
                  total: data.total,
                  total_pages: data.total_pages,
                  current_page: page,
                  per_page,
                  results: formattedResults,
                }, null, 2),
              },
            ],
          };
        } else {
          // Return base64 encoded images with metadata
          const contentItems: Array<{ type: "text"; text: string } | { type: "image"; data: string; mimeType: string }> = [
            {
              type: "text",
              text: `Found ${data.total} photos (page ${page}/${data.total_pages}):`,
            }
          ];
    
          for (const photo of data.results) {
            try {
              // Add metadata as JSON using original Unsplash API response
              contentItems.push({
                type: "text",
                text: JSON.stringify(photo, null, 2),
              });
    
              // Add the actual image
              const imageData = await this.fetchImageAsBase64(photo.urls.regular);
              contentItems.push({
                type: "image",
                data: imageData.base64,
                mimeType: imageData.mimeType,
              });
            } catch (error) {
              // If image fetch fails, return error info
              contentItems.push({
                type: "text",
                text: `Failed to fetch image ${photo.id}: ${error instanceof Error ? error.message : 'Unknown error'}`,
              });
            }
          }
    
          return {
            content: contentItems,
          };
        }
      } catch (error) {
        return {
          content: [
            {
              type: "text",
              text: `Error searching photos: ${error instanceof Error ? error.message : "Unknown error"}`,
            },
          ],
          isError: true,
        };
      }
    }
  • Input schema definition for the search_photos tool, defining parameters: query (required string), page (optional number), per_page (1-30), orientation (landscape/portrait/squarish), and content_filter (low/high).
    inputSchema: {
      type: "object",
      properties: {
        query: {
          type: "string",
          description: "Search term for photos",
        },
        page: {
          type: "number",
          description: "Page number (default: 1)",
          minimum: 1,
        },
        per_page: {
          type: "number",
          description: "Number of photos per page (default: 10, max: 30)",
          minimum: 1,
          maximum: 30,
        },
        orientation: {
          type: "string",
          description: "Filter by orientation",
          enum: ["landscape", "portrait", "squarish"],
        },
        content_filter: {
          type: "string",
          description: "Content safety filter",
          enum: ["low", "high"],
        },
      },
      required: ["query"],
    },
  • src/index.ts:112-152 (registration)
    Tool registration via ListToolsRequestSchema handler that defines the search_photos tool with its name, description, and inputSchema.
    this.server.setRequestHandler(ListToolsRequestSchema, async () => {
      return {
        tools: [
          {
            name: "search_photos",
            description: `Search for photos on Unsplash. Returns ${this.responseFormat === 'image' ? 'base64-encoded images' : 'photo URLs and metadata as JSON'}.`,
            inputSchema: {
              type: "object",
              properties: {
                query: {
                  type: "string",
                  description: "Search term for photos",
                },
                page: {
                  type: "number",
                  description: "Page number (default: 1)",
                  minimum: 1,
                },
                per_page: {
                  type: "number",
                  description: "Number of photos per page (default: 10, max: 30)",
                  minimum: 1,
                  maximum: 30,
                },
                orientation: {
                  type: "string",
                  description: "Filter by orientation",
                  enum: ["landscape", "portrait", "squarish"],
                },
                content_filter: {
                  type: "string",
                  description: "Content safety filter",
                  enum: ["low", "high"],
                },
              },
              required: ["query"],
            },
          },
        ],
      };
    });
  • Routing logic that dispatches to the searchPhotos handler when the tool name matches 'search_photos'.
    if (name === "search_photos") {
      return await this.searchPhotos(args);
  • Helper function fetchImageAsBase64 that fetches an image from a URL and converts it to base64 encoding, used by searchPhotos to return image content.
    private async fetchImageAsBase64(url: string): Promise<{base64: string, mimeType: string}> {
      try {
        const response = await fetch(url);
        if (!response.ok) {
          throw new Error(`Failed to fetch image: ${response.status}`);
        }
        
        const arrayBuffer = await response.arrayBuffer();
        const base64 = Buffer.from(arrayBuffer).toString('base64');
        
        // Determine MIME type from URL or response headers
        const contentType = response.headers.get('content-type') || 'image/jpeg';
        
        return { base64, mimeType: contentType };
      } catch (error) {
        throw new Error(`Error fetching image: ${error instanceof Error ? error.message : 'Unknown error'}`);
      }
    }
Install Server

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

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