Skip to main content
Glama

find_product

Locate where to buy or access digital products like music and games. Automatically identifies product type and directs to appropriate purchasing or streaming platforms.

Instructions

Find the best place to buy or access any digital product (music, games, etc). Automatically detects the product category and routes to the right resolver. Use this when you're not sure whether the user is asking about music or games, or when the query is ambiguous.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYesA natural language product query. Examples: 'Aphex Twin Windowlicker', 'Elden Ring DLC', 'where can I stream Bad Guy by Billie Eilish'
categoryNoProduct category. Use 'auto' (default) to let RootVine detect the category automatically.

Implementation Reference

  • Main handler function findProduct that routes product queries to the appropriate resolver (music or game) based on category detection or user-specified category
    export async function findProduct(input: FindProductInput): Promise<FindProductResult> { const { query } = input; const category = input.category === "auto" || !input.category ? detectCategory(query) : input.category; const slug = queryToSlug(query); if (category === "music") { const result = await resolveMusic({ slug }); return { success: result.success, category: "music", response: result.response, formatted: result.response ? formatMusicResponse(result.response) : `❌ ${result.error || "Unknown error"}`, error: result.error, }; } if (category === "game") { const result = await resolveGame({ slug }); return { success: result.success, category: "game", response: result.response, formatted: result.response ? formatGameResponse(result.response) : `❌ ${result.error || "Unknown error"}`, error: result.error, }; } return { success: false, category: "music", formatted: `❌ Unknown category: ${category}`, error: `Unknown category: ${category}`, }; }
  • Type definitions for FindProductInput (query string and optional category) and FindProductResult (success status, detected category, response, formatted output, and optional error)
    export interface FindProductInput { query: string; category?: "music" | "game" | "auto"; } export interface FindProductResult { success: boolean; category: "music" | "game"; response?: RootVineResponseV1; formatted: string; error?: string; }
  • src/index.ts:125-154 (registration)
    MCP tool registration for 'find_product' with input schema validation using Zod and the handler that wraps findProduct function and returns formatted text response
    server.registerTool( "find_product", { description: "Find the best place to buy or access any digital product (music, games, etc). Automatically detects the product category and routes to the right resolver. Use this when you're not sure whether the user is asking about music or games, or when the query is ambiguous.", inputSchema: { query: z .string() .describe("A natural language product query. Examples: 'Aphex Twin Windowlicker', 'Elden Ring DLC', 'where can I stream Bad Guy by Billie Eilish'"), category: z .enum(["music", "game", "auto"]) .optional() .describe("Product category. Use 'auto' (default) to let RootVine detect the category automatically."), }, }, async ({ query, category }) => { const result = await findProduct({ query, category: category || "auto", }); return { content: [ { type: "text" as const, text: result.formatted, }, ], }; }, );
  • Helper function detectCategory that analyzes query text for keywords to determine if the product is a game or music item, defaulting to music
    function detectCategory(query: string): "music" | "game" { const q = query.toLowerCase(); // Game indicators const gameKeywords = [ "game", "dlc", "expansion", "steam", "xbox", "playstation", "ps5", "ps4", "nintendo", "switch", "pc game", "goty", "edition", "gameplay", ]; for (const kw of gameKeywords) { if (q.includes(kw)) return "game"; } // Music indicators (default — music is more common for now) const musicKeywords = [ "song", "album", "track", "listen", "stream", "spotify", "apple music", "vinyl", "single", "ep ", "lp ", "feat", "ft.", "remix", "acoustic", ]; for (const kw of musicKeywords) { if (q.includes(kw)) return "music"; } // Default to music (BeatsVine is the first tree) return "music"; }
  • Helper function queryToSlug that normalizes a query string into a URL-safe slug by converting to lowercase, removing special chars, and replacing spaces with hyphens
    function queryToSlug(query: string): string { return query .toLowerCase() .trim() .replace(/[^a-z0-9\s-]/g, "") // Remove special chars .replace(/\s+/g, "-") // Spaces to hyphens .replace(/-+/g, "-") // Collapse multiple hyphens .replace(/^-|-$/g, ""); // Trim leading/trailing hyphens }
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/RagingOrangutan/rootvine-mcp'

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