import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { toolName } from "../brand.js"; import { z } from "zod"; import { Env } from "../types.js"; /** * arcrun_search_components — 語意搜尋零件庫 * 呼叫 Component Registry GET /components/search?q=... */ export function registerSearchComponents(server: McpServer, env: Env, orgNamespace: string) { server.tool( toolName("search_components"), "用自然語言語意搜尋零件庫,找出符合需求的零件。例如:「查詢 Google Sheets 資料」、「發送 LINE 訊息」、「驗證 JSON 格式」。回傳零件清單含 canonical_id、描述、評分。", { query: z.string().describe("自然語言搜尋詞,如「查詢 Google Sheets 資料」"), }, async ({ query }) => { try { if (!env.COMPONENT_REGISTRY) { return { content: [{ type: "text", text: "Error: COMPONENT_REGISTRY service binding is not configured." }], isError: true, }; } const response = await env.COMPONENT_REGISTRY.fetch( `http://component-registry/components/search?q=${encodeURIComponent(query)}`, { method: "GET", headers: { "Content-Type": "application/json" } }, ); if (!response.ok) { const errorText = await response.text(); return { content: [{ type: "text", text: `Search failed: ${errorText}` }], isError: true, }; } const result = await response.json() as { data?: { results?: unknown[]; count?: number } }; const results = result.data?.results ?? []; const count = result.data?.count ?? 0; if (count === 0) { return { content: [{ type: "text", text: `找不到符合「${query}」的零件。可以用 arcrun_publish_component 提交新零件。`, }], }; } return { content: [{ type: "text", text: `找到 ${count} 個零件:\n${JSON.stringify(results, null, 2)}`, }], }; } catch (error) { return { content: [{ type: "text", text: `Internal Error: ${error instanceof Error ? error.message : String(error)}` }], isError: true, }; } } ); }