background.search
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
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | 検索クエリ(自然言語、1-500文字) | |
| limit | No | 取得件数(1-50、デフォルト: 10) | |
| offset | No | オフセット(0以上、デフォルト: 0) | |
| filters | No | 検索フィルター | |
| profile_id | No | 嗜好プロファイル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", ]); - apps/mcp-server/src/tools/index.ts:807-808 (registration)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,