Skip to main content
Glama

background.search

Read-onlyIdempotent

Semantically search background design patterns using natural language queries. Find gradients, glassmorphism, SVG backgrounds, and more. Filter results by design type, industry, audience, or web page for targeted matches.

Instructions

BackgroundDesignをセマンティック検索します。グラデーション、グラスモーフィズム、SVG背景等の背景デザインパターンを自然言語で検索できます。designType(14種類)やwebPageIdでフィルタリング可能です。

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYes検索クエリ(自然言語、1-500文字)
limitNo取得件数(1-50、デフォルト: 10)
offsetNoオフセット(0以上、デフォルト: 0)
filtersNo検索フィルター
profile_idNo嗜好プロファイルID(検索結果のリランキングに使用) / Preference profile ID (used for search result reranking)

Implementation Reference

  • Main handler function for background.search. Validates input via Zod, generates embeddings with e5 model (query: prefix), performs vector search (or hybrid search if available), applies preference reranking, and returns paginated search results.
    export async function backgroundSearchHandler(input: unknown): Promise<BackgroundSearchOutput> {
      const startTime = Date.now();
    
      if (isDevelopment()) {
        logger.info("[MCP Tool] background.search called", {
          query: (input as Record<string, unknown>)?.query,
        });
      }
    
      // 入力バリデーション
      let validated: BackgroundSearchInputType;
      try {
        validated = backgroundSearchInputSchema.parse(input);
      } catch (error) {
        if (error instanceof ZodError) {
          const errorMessage = error.errors.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
    
          logger.warn("[MCP Tool] background.search validation error", {
            errors: error.errors,
          });
    
          return {
            success: false,
            error: {
              code: BACKGROUND_MCP_ERROR_CODES.VALIDATION_ERROR,
              message: `Validation error: ${errorMessage}`,
            },
          };
        }
        throw error;
      }
    
      // サービスファクトリーチェック
      if (!backgroundSearchServiceDI.get()) {
        if (isDevelopment()) {
          logger.error("[MCP Tool] background.search service factory not set");
        }
    
        return {
          success: false,
          error: {
            code: BACKGROUND_MCP_ERROR_CODES.SERVICE_UNAVAILABLE,
            message: "Background search service is not available",
          },
        };
      }
    
      const service = backgroundSearchServiceDI.get()!();
    
      // Search result cache check / 検索キャッシュチェック
      const cacheKey = generateCacheKey(
        "background.search",
        validated as unknown as Record<string, unknown>
      );
      const cached = getCachedResult<BackgroundSearchOutput>(cacheKey);
      if (cached) {
        return cached;
      }
    
      try {
        // E5 モデル用 query: プレフィックスを付与
        const processedQuery = `query: ${validated.query}`;
    
        // Embedding 生成
        const queryEmbedding = await service.generateQueryEmbedding(processedQuery);
    
        // Embedding が null の場合は空結果を返す
        if (queryEmbedding === null) {
          if (isDevelopment()) {
            logger.warn(
              "[MCP Tool] background.search embedding not available, returning empty results"
            );
          }
    
          return {
            success: true,
            data: {
              results: [],
              total: 0,
              query: validated.query,
              searchTimeMs: Date.now() - startTime,
            },
          };
        }
    
        // 検索オプション構築
        const searchOptions: {
          limit: number;
          offset: number;
          filters?: {
            designType?: string;
            webPageId?: string;
            webPageUrl?: string;
            tags?: string[];
            industry?: string;
            audience?: string;
          };
        } = {
          limit: validated.limit,
          offset: validated.offset,
        };
    
        // フィルターが存在する場合のみ追加
        if (validated.filters) {
          const filters: {
            designType?: string;
            webPageId?: string;
            webPageUrl?: string;
            tags?: string[];
            industry?: string;
            audience?: string;
          } = {};
          if (validated.filters.designType) {
            filters.designType = validated.filters.designType;
          }
          if (validated.filters.webPageId) {
            filters.webPageId = validated.filters.webPageId;
          }
          if (validated.filters.webPageUrl) {
            filters.webPageUrl = validated.filters.webPageUrl;
          }
          if (validated.filters.tags && validated.filters.tags.length > 0) {
            filters.tags = validated.filters.tags;
          }
          if (validated.filters.industry) {
            filters.industry = validated.filters.industry;
          }
          if (validated.filters.audience) {
            filters.audience = validated.filters.audience;
          }
          if (Object.keys(filters).length > 0) {
            searchOptions.filters = filters;
          }
        }
    
        // 検索実行(ハイブリッド検索優先)
        const searchResult = service.searchBackgroundDesignsHybrid
          ? await service.searchBackgroundDesignsHybrid(validated.query, queryEmbedding, searchOptions)
          : await service.searchBackgroundDesigns(queryEmbedding, searchOptions);
    
        // 結果マッピング
        let mappedResults: BackgroundSearchResultItem[] = searchResult.results.map((r) => ({
          id: r.id,
          designType: r.designType,
          cssValue: r.cssValue,
          similarity: r.similarity,
          source: {
            webPageId: r.webPageId,
          },
          name: r.name,
          selector: r.selector,
          colorInfo: r.colorInfo,
          textRepresentation: r.textRepresentation,
        }));
    
        const searchTimeMs = Date.now() - startTime;
    
        if (isDevelopment()) {
          logger.info("[MCP Tool] background.search completed", {
            query: validated.query,
            resultCount: mappedResults.length,
            total: searchResult.total,
            searchTimeMs,
          });
        }
    
        // 嗜好プロファイルによるリランキング / Preference profile reranking
        mappedResults = await applyPreferenceReranking(
          mappedResults,
          validated.profile_id,
          prismaClientDI.get(),
          "background",
          "background.search"
        );
    
        const result: BackgroundSearchOutput = {
          success: true,
          data: {
            results: mappedResults,
            total: searchResult.total,
            query: validated.query,
            searchTimeMs,
          },
        };
        // Cache successful results / 成功結果をキャッシュ
        setCachedResult(cacheKey, result);
        return result;
      } catch (error) {
        const errorInstance = error instanceof Error ? error : new Error(String(error));
        const errorCode = mapErrorToCode(errorInstance);
    
        logger.error("[MCP Tool] background.search error", {
          code: errorCode,
          error: errorInstance.message,
        });
    
        return {
          success: false,
          error: {
            code: errorCode,
            message: sanitizeErrorMessage(error),
          },
        };
      }
    }
  • Zod input schema for background.search: query (1-500 chars), limit (1-50, default 10), offset (0+, default 0), filters (designType + common filters), and optional profile_id.
    export const backgroundSearchInputSchema = z.object({
      /** 検索クエリ(1-500文字) */
      query: z.string().min(1).max(500),
      /** 取得件数(1-50、デフォルト: 10) */
      limit: z.number().int().min(1).max(50).default(10),
      /** オフセット(0以上、デフォルト: 0) */
      offset: z.number().min(0).default(0),
      /** 検索フィルター */
      filters: backgroundSearchFiltersSchema,
      /**
       * 嗜好プロファイルID(検索結果のリランキングに使用)
       * Preference profile ID (used for search result reranking)
       */
      profile_id: z.string().uuid().optional(),
    });
    
    export type BackgroundSearchInput = z.infer<typeof backgroundSearchInputSchema>;
  • Filter schema with designType and common filters (webPageId, webPageUrl, industry, audience, tags).
    export const backgroundSearchFiltersSchema = z
      .object({
        designType: backgroundDesignTypeSchema.optional(),
      })
      .merge(commonSearchFiltersSchema)
      .optional();
  • Enum schema for BackgroundDesignType with 14 possible values (solid_color, linear_gradient, radial_gradient, etc.).
    export const backgroundDesignTypeSchema = z.enum([
      "solid_color",
      "linear_gradient",
      "radial_gradient",
      "conic_gradient",
      "mesh_gradient",
      "image_background",
      "pattern_background",
      "video_background",
      "animated_gradient",
      "glassmorphism",
      "noise_texture",
      "svg_background",
      "multi_layer",
      "unknown",
    ]);
  • Tool registration: maps 'background.search' to backgroundSearchHandler in the toolHandlers record, includes it in allToolDefinitions, and exports from the barrel file.
    // background.search(BackgroundDesignセマンティック検索)
    "background.search": backgroundSearchHandler,
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate readOnlyHint=true and idempotentHint=true, which the description does not contradict. The description adds context about semantic search and filter capabilities, reinforcing the non-destructive, read-only nature. No behavioral traits are missing.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two concise sentences, front-loading the core purpose. Every sentence adds value: first states the action, second explains filtering capability. No unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With full schema coverage and annotations, the description completes the picture for a search tool. It lacks mention of result format or pagination, but these are typical for search and can be inferred from the schema's limit/offset parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema has 100% description coverage, so each parameter is already well-documented. The description only mentions query and two filter fields, adding minimal extra meaning. Baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it performs semantic search for background designs, specifying types like gradients, glassmorphism, and SVG backgrounds. It distinguishes from siblings such as design.search_by_image and layout.search by focusing on background design patterns.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for natural language search of background designs and mentions filtering, but does not explicitly state when to use this tool versus alternatives like design.search_by_image or search.facets. No exclusion criteria or comparisons are provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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/TKMD/ReftrixMCP'

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