Skip to main content
Glama

enrich_product

Extract structured product data from URLs, including name, price, brand, images, and availability using schema.org and AI fallback.

Instructions

Extract comprehensive product data from a URL including name, price, brand, images, availability, and more. Uses schema.org structured data when available, with LLM fallback. Costs $0.02 per call (cached results are free).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlYesProduct page URL to extract data from
payment_method_idNoStripe payment method ID for MPP payment

Implementation Reference

  • src/server.ts:22-32 (registration)
    The 'enrich_product' tool is registered on the McpServer, accepting a URL and optional payment method, then calling handleEnrichment.
    server.tool(
      'enrich_product',
      'Extract comprehensive product data from a URL including name, price, brand, images, availability, and more. Uses schema.org structured data when available, with LLM fallback. Costs $0.02 per call (cached results are free).',
      {
        url: z.string().url().describe('Product page URL to extract data from'),
        payment_method_id: z.string().optional().describe('Stripe payment method ID for MPP payment'),
      },
      async ({ url, payment_method_id }) => {
        return handleEnrichment('enrich_product', url, payment_method_id, cache, payments);
      },
    );
  • The handleEnrichment function handles the logic for 'enrich_product', including caching, payment gating, and extracting product data using extractProduct.
    async function handleEnrichment(
      toolName: 'enrich_product' | 'enrich_basic',
      url: string,
      paymentMethodId: string | undefined,
      cache: EnrichmentCache,
      payments: PaymentManager,
    ): Promise<{ content: Array<{ type: 'text'; text: string }>; isError?: boolean }> {
      // Check cache first (free, no payment needed)
      const cached = cache.get(url);
      if (cached) {
        const result: EnrichmentResult = {
          product: cached,
          cached: true,
        };
        return {
          content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
        };
      }
    
      // No payment method — return 402 challenge
      if (!paymentMethodId) {
        const challenge: MppChallenge = payments.createChallenge(toolName);
        return {
          content: [{
            type: 'text' as const,
            text: JSON.stringify({
              error: 'payment_required',
              status: 402,
              challenge,
              message: `Payment required. Include a payment_method_id to proceed. Cost: $${(TOOL_PRICING[toolName] / 100).toFixed(2)}`,
            }, null, 2),
          }],
          isError: true,
        };
      }
    
      // Process payment
      let receipt;
      try {
        receipt = await payments.processPayment(toolName, paymentMethodId);
      } catch (err) {
        const message = err instanceof Error ? err.message : 'Payment processing failed';
        return {
          content: [{
            type: 'text' as const,
            text: JSON.stringify({ error: 'payment_failed', message }, null, 2),
          }],
          isError: true,
        };
      }
    
      // Extract product data
      let product: ProductData;
      try {
        product = await extractProduct(url);
      } catch (err) {
        const message = err instanceof Error ? err.message : 'Extraction failed';
        return {
          content: [{
            type: 'text' as const,
            text: JSON.stringify({
              error: 'extraction_failed',
              message,
              receipt,
            }, null, 2),
          }],
          isError: true,
        };
      }
    
      // For basic enrichment, strip image analysis fields
      if (toolName === 'enrich_basic') {
        product.image_urls = [];
        product.primary_image_url = null;
      }
    
      // Cache the result
      cache.set(url, product);
    
      const result: EnrichmentResult = {
        product,
        receipt,
        cached: false,
      };
    
      return {
        content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
      };
    }
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/laundromatic/shopgraph'

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