npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

shopping-assistant-mcp-sdk

v1.1.1

Published

Shopping Assistant SDK - Vanilla JS Core + React Wrapper

Readme

Shopping Assistant SDK v5.0 🛒✨

A powerful, framework-agnostic JavaScript SDK for integrating AI-powered shopping assistance into any web application. Built with TypeScript and Web Components for maximum compatibility and modern development practices.

📖 Table of Contents

  1. What is Shopping Assistant SDK v5?
  2. Key Features
  3. Installation
  4. Quick Start
  5. Configuration
  6. Framework Integration
  7. Events & API Reference
  8. Advanced Features
  9. Troubleshooting
  10. Examples

🌟 What is Shopping Assistant SDK v5?

The Shopping Assistant SDK v5 is a comprehensive solution that provides intelligent shopping assistance through a modern, embeddable chat interface. It combines AI-powered natural language processing with rich UI components to create seamless shopping experiences.

✨ Core Capabilities

  • 🤖 AI-Powered Chat Interface: Intelligent shopping assistance with natural language processing
  • 📱 Multiple Display Modes: Sidebar, overlay, and full-page chat interfaces
  • ⚡ Real-time Streaming: Live text streaming with Server-Sent Events (SSE) support
  • 🎨 Rich Resource Rendering: Advanced UI resource rendering using MCP (Model Context Protocol)
  • 🔧 Framework Agnostic: Works with React, Vue, Angular, vanilla JavaScript, or any web framework
  • 📝 TypeScript Support: Full type safety and IntelliSense support
  • 🎯 Customizable UI: Configurable themes, action chips, and suggestions
  • 🛒 Shopping Cart Integration: Built-in cart management with real API integration
  • 🔄 Event-Driven Architecture: Comprehensive event system for all interactions

🚀 Key Features

✅ Display Modes

1. Sidebar Mode (Default)

  • 30% viewport width with responsive design
  • Minimum width: 40rem, Maximum width: 500px
  • Toggle button positioned at right center
  • Persistent across page navigation
  • Close and reset functionality

2. Overlay Mode

  • Configurable dimensions and positioning
    • Bottom-right positioned by default
  • Modal-style interaction with smooth animations
  • Toggle button at bottom-right

3. Full-Page Mode

  • Takes full viewport for dedicated chat pages
  • No external toggle button needed
  • Ideal for standalone chat applications

✅ Advanced Capabilities

  • 🔄 Streaming Support: Real-time text chunk accumulation with loading animations
  • 📦 Resource Management: Handles HTML, URIs, and rich interactive content
  • 🎯 MCP Integration: Uses @mcp-ui/client for advanced resource rendering
  • 🎤 Voice Assistant: Built-in speech recognition for hands-free shopping queries
  • 📡 Event System: Comprehensive event handling for all user interactions
  • 🖼️ Auto-iframe Resizing: Dynamic content sizing for embedded resources
  • ♿ Accessibility: ARIA-compliant components with keyboard navigation
  • 🎨 Loading States: Beautiful animated loading indicators during AI responses
  • 🔄 Intent Handling: Automatic handling of product interactions (view details, add to cart)

📦 Installation

NPM Installation (Recommended)

# Using npm
npm install @shopping-assistant/sdk

# Using yarn
yarn add @shopping-assistant/sdk

# Using pnpm
pnpm add @shopping-assistant/sdk

📦 NPM Registry: https://www.npmjs.com/package/shopping-assistant-mcp-sdk

Local Development

# Clone and build locally
git clone https://github.com/varadharajan007/new-mcpui-nextjs.git
cd new-mcpui-nextjs/sdk-v5
npm install
npm run build

🔗 GitHub Repository: https://github.com/varadharajan007/new-mcpui-nextjs

Note: The SDK includes all necessary dependencies including MCP UI Resource Renderer. No additional setup required!


🚀 Quick Start

Basic HTML Integration

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>My Store with Shopping Assistant</title>
</head>
<body>
  <header>
    <h1>Welcome to My Store</h1>
  </header>
  
  <main>
    <!-- Your store content here -->
    <div id="assistant-container"></div>
  </main>
  
  <script type="module">
    // Initialize the Shopping Assistant SDK with Web Component
    const initializeAssistant = async () => {
      try {
        console.log('🚀 Initializing Shopping Assistant Web Component SDK...');
        
        // Dynamic import to avoid SSR issues
        const { ShoppingAssistant } = await import('@shopping-assistant/sdk');
        
        const assistantInstance = new ShoppingAssistant({
          apiKey: 'demo-key',
          userId: '123',
          container: document.getElementById('assistant-container'),
          theme: {
            primaryColor: '#000',
            backgroundColor: '#ffffff'
          },
          // Streaming mode: 'builtin' (default) or 'external'
          streamingMode: 'builtin' // Default - SDK handles everything automatically
        });

        // Set up event listeners
        assistantInstance.on('assistant:ready', () => {
          console.log('✅ Shopping Assistant is ready!');
        });

        assistantInstance.on('assistant:userQuery', async (data) => {
          // Only handle userQuery in external mode
          if (assistantInstance.getStreamingMode() === 'external') {
            console.log('🔍 User query received (External Mode):', data);
            // Use these events to stream data to chat window 
            assistantInstance.streamData(/* your streaming data */);
            assistantInstance.completeStreaming();
          } else {
            console.log('🚀 Built-in mode active - SDK will handle the query internally');
          }
        });

        assistantInstance.on('assistant:action', (data) => {
          console.log('🔗 MCP Resource action:', data);
          
          // Handle different intent actions
          if (data.action === 'view_details') {
            console.log('👀 Product view details requested:', data.params);
            // The SDK will automatically handle the view_details intent internally
            // Parent apps can also add custom logic here if needed
          } else if (data.action === 'add_to_cart') {
            console.log('🛒 Add to cart requested:', data.params);
            // Handle real add to cart API call
            handleAddToCart(data.params);
          }
        });

        assistantInstance.on('assistant:error', (error) => {
          console.error('❌ Assistant error:', error);
        });

        assistantInstance.on('assistant:reset', (data) => {
          console.log('🔄 Assistant was reset:', data);
        });

        assistantInstance.on('assistant:closed', (data) => {
          console.log('✕ Assistant was closed by user:', data);
        });

        // Auto-open the assistant once page loaded
        setTimeout(() => {
          assistantInstance.open();
        }, 1000);

      } catch (error) {
        console.error('Failed to initialize Shopping Assistant:', error);
      }
    };

    initializeAssistant();
  </script>
</body>
</html>

⚙️ Configuration

ShoppingAssistantConfig Interface

interface ShoppingAssistantConfig {
  // Required
  apiKey: string;                    // Your API key
  
  // Optional
  apiBaseUrl?: string;               // API endpoint URL
  userId?: string;                   // User identifier
  mode?: 'sidebar' | 'overlay' | 'full-page'; // Display mode
  container?: string | HTMLElement;  // Container element for the assistant
  
  // UI Customization
  customChips?: Array<{              // Custom action buttons
    label: string;
    callback: string;
  }>;
  
  defaultSuggestions?: Array<{       // Initial suggestions
    name: string;
    icon: string;
    description: string;
  }>;
  
  theme?: {                          // UI theming
    primaryColor?: string;
    backgroundColor?: string;
  };
  
  // Streaming Configuration
  streamingMode?: 'builtin' | 'external'; // Streaming mode (defaults to 'builtin')
}

Example Configuration

const assistant = new ShoppingAssistant({
  apiKey: 'your-api-key',
  apiBaseUrl: 'https://api.yourstore.com',
  userId: 'user-123',
  mode: 'sidebar',
  container: '#assistant-container', // or document.getElementById('container')
  
  // Streaming mode (defaults to 'builtin')
  streamingMode: 'builtin', // 'builtin' | 'external'
  
  // Custom action chips
  customChips: [
    { label: 'Track Order', callback: 'onTrackOrder' },
    { label: 'Size Guide', callback: 'onSizeGuide' },
    { label: 'Customer Support', callback: 'onCustomerSupport' }
  ],
  
  // Custom default suggestions
  defaultSuggestions: [
    { name: 'Tops', icon: '👚', description: 'Stylish tops for every occasion' },
    { name: 'Dresses', icon: '👗', description: 'Beautiful dresses for any event' },
    { name: 'Jeans', icon: '👖', description: 'Comfortable and stylish jeans' }
  ],
  
  // Custom theme
  theme: {
    primaryColor: '#007bff',
    backgroundColor: '#ffffff'
  }
});

// Define global callback functions
window.onTrackOrder = () => {
  window.location.href = '/orders';
};

window.onSizeGuide = () => {
  // Open size guide modal
  openSizeGuideModal();
};

window.onCustomerSupport = () => {
  // Open support chat
  window.open('/support', '_blank');
};

🔧 Framework Integration

React Integration

// components/ShoppingAssistant.tsx
import React, { useEffect, useRef, useState } from 'react';
import { ShoppingAssistant } from '@shopping-assistant/sdk';

interface Props {
  apiKey: string;
  userId?: string;
  mode?: 'sidebar' | 'overlay' | 'full-page';
  streamingMode?: 'builtin' | 'external';
}

export const ShoppingAssistantComponent: React.FC<Props> = ({
  apiKey,
  userId,
  mode = 'sidebar',
  streamingMode = 'builtin'
}) => {
  const containerRef = useRef<HTMLDivElement>(null);
  const [assistant, setAssistant] = useState<ShoppingAssistant | null>(null);
  const [isConnected, setIsConnected] = useState(false);

  useEffect(() => {
    const initializeAssistant = async () => {
      try {
        const assistantInstance = new ShoppingAssistant({
          apiKey,
          userId: userId || 'user-123',
          container: containerRef.current,
          mode,
          streamingMode,
          theme: {
            primaryColor: '#007bff',
            backgroundColor: '#ffffff'
          }
        });

        // Set up event listeners
        assistantInstance.on('assistant:ready', () => {
          console.log('✅ Shopping Assistant is ready!');
          setIsConnected(true);
        });

        assistantInstance.on('assistant:userQuery', async (data: any) => {
          if (streamingMode === 'external') {
            console.log('🔍 User query received (External Mode):', data);
            // Handle external streaming here
            // assistantInstance.streamData(/* your data */);
            // assistantInstance.completeStreaming();
          } else {
            console.log('🚀 Built-in mode active - SDK handles internally');
          }
        });

        assistantInstance.on('assistant:action', (data: any) => {
          console.log('🔗 MCP Resource action:', data);
          
          if (data.action === 'add_to_cart') {
            console.log('🛒 Add to cart requested:', data.params);
            // Handle add to cart logic
            handleAddToCart(data.params);
          }
        });

        assistantInstance.on('assistant:error', (error: any) => {
          console.error('❌ Assistant error:', error);
        });

        assistantInstance.on('assistant:reset', () => {
          console.log('🔄 Assistant was reset');
        });

        assistantInstance.on('assistant:closed', () => {
          console.log('✕ Assistant was closed by user');
        });

        setAssistant(assistantInstance);

        // Auto-open the assistant
        setTimeout(() => {
          assistantInstance.open();
        }, 1000);

      } catch (error) {
        console.error('Failed to initialize Shopping Assistant:', error);
      }
    };

    initializeAssistant();

    // Cleanup
    return () => {
      if (assistant) {
        assistant.destroy();
      }
    };
  }, [apiKey, userId, mode, streamingMode]);

  const handleAddToCart = async (params: any) => {
    // Your add to cart implementation
    console.log('Adding to cart:', params);
  };

  return (
    <div 
      ref={containerRef}
      style={{ 
        width: '100%', 
        height: '100%',
        position: 'relative'
      }}
    >
      {!isConnected && (
        <div style={{ padding: '20px', textAlign: 'center' }}>
          Loading Shopping Assistant...
        </div>
      )}
    </div>
  );
};

Angular Integration

// shopping-assistant.component.ts
import { Component, Input, OnInit, OnDestroy, ElementRef, ViewChild } from '@angular/core';
import { ShoppingAssistant } from '@shopping-assistant/sdk';

@Component({
  selector: 'app-shopping-assistant',
  template: `
    <div #assistantContainer 
         style="width: 100%; height: 100%; position: relative;">
      <div *ngIf="!isConnected" style="padding: 20px; text-align: center;">
        Loading Shopping Assistant...
      </div>
    </div>
  `
})
export class ShoppingAssistantComponent implements OnInit, OnDestroy {
  @Input() apiKey!: string;
  @Input() userId?: string;
  @Input() mode: 'sidebar' | 'overlay' | 'full-page' = 'sidebar';
  @Input() streamingMode: 'builtin' | 'external' = 'builtin';

  @ViewChild('assistantContainer', { static: true }) 
  containerRef!: ElementRef<HTMLDivElement>;

  private assistant: ShoppingAssistant | null = null;
  public isConnected = false;

  async ngOnInit() {
    try {
      this.assistant = new ShoppingAssistant({
        apiKey: this.apiKey,
        userId: this.userId || 'user-123',
        container: this.containerRef.nativeElement,
        mode: this.mode,
        streamingMode: this.streamingMode,
        theme: {
          primaryColor: '#007bff',
          backgroundColor: '#ffffff'
        }
      });

      // Set up event listeners
      this.assistant.on('assistant:ready', () => {
        console.log('✅ Shopping Assistant is ready!');
        this.isConnected = true;
      });

      this.assistant.on('assistant:userQuery', async (data: any) => {
        if (this.streamingMode === 'external') {
          console.log('🔍 User query received (External Mode):', data);
          // Handle external streaming here
          // this.assistant.streamData(/* your data */);
          // this.assistant.completeStreaming();
        } else {
          console.log('🚀 Built-in mode active - SDK handles internally');
        }
      });

      this.assistant.on('assistant:action', (data: any) => {
        console.log('🔗 MCP Resource action:', data);
        
        if (data.action === 'add_to_cart') {
          console.log('🛒 Add to cart requested:', data.params);
          this.handleAddToCart(data.params);
        }
      });

      this.assistant.on('assistant:error', (error: any) => {
        console.error('❌ Assistant error:', error);
      });

      this.assistant.on('assistant:reset', () => {
        console.log('🔄 Assistant was reset');
      });

      this.assistant.on('assistant:closed', () => {
        console.log('✕ Assistant was closed by user');
      });

      // Auto-open the assistant
      setTimeout(() => {
        this.assistant?.open();
      }, 1000);

    } catch (error) {
      console.error('Failed to initialize Shopping Assistant:', error);
    }
  }

  ngOnDestroy() {
    if (this.assistant) {
      this.assistant.destroy();
    }
  }

  private handleAddToCart(params: any) {
    // Your add to cart implementation
    console.log('Adding to cart:', params);
  }
}

📡 Events & API Reference

Core Methods

create(options?)

Creates and mounts the shopping assistant component.

assistant.create({
  container: '#my-container' // string selector or HTMLElement
});

open(options?)

Opens the chat interface.

assistant.open({
  productId: 'product-123',
  initialMessage: 'Tell me about this product'
});

close()

Closes the chat interface.

assistant.close();

toggle()

Toggles the chat interface open/closed state.

assistant.toggle();

streamData(data)

Sends streaming data to the chat interface.

assistant.streamData({
  type: 'text_chunk',
  text: 'Hello from server',
  is_complete: true
});

completeStreaming()

Completes the current streaming session.

assistant.completeStreaming();

sendMessagePublic(messageText)

Programmatically send a message to the assistant.

assistant.sendMessagePublic('view cart');

resetChat()

Programmatically reset the chat history.

assistant.resetChat();

destroy()

Destroys the assistant instance and cleans up resources.

assistant.destroy();

Event System

User Interaction Events

assistant:userQuery

Fired when user sends a message (only in external mode).

assistant.on('assistant:userQuery', (data: {
  query: string;
  conversationHistory: ChatMessage[];
  userId: string;
}) => {
  console.log('User query:', data.query);
  // Only handle in external mode - builtin mode handles automatically
  if (assistant.getStreamingMode() === 'external') {
    // Handle the query and stream response back
    handleUserQuery(data);
  }
});
assistant:action

Fired when a resource action is triggered (product interactions, cart actions).

assistant.on('assistant:action', (data: {
  action: string; // 'view_details', 'add_to_cart', 'remove_from_cart'
  params: any;
  timestamp: string;
  intentId: string;
}) => {
  console.log('Resource action:', data.action, data.params);
  
  if (data.action === 'add_to_cart') {
    handleAddToCart(data.params);
  } else if (data.action === 'view_details') {
    handleViewDetails(data.params);
  } else if (data.action === 'remove_from_cart') {
    handleRemoveFromCart(data.params);
  }
});
assistant:chipsListener

Fired when custom action chips are clicked.

assistant.on('assistant:chipsListener', (data: {
  chipLabel: string;
  callback: string;
}) => {
  console.log('Chip clicked:', data.chipLabel);
  // Handle custom chip actions
  if (window[data.callback]) {
    window[data.callback]();
  }
});

System Events

assistant:ready

Fired when the assistant is fully initialized and ready.

assistant.on('assistant:ready', () => {
  console.log('Assistant is ready!');
});
assistant:reset

Fired when the chat is reset (reset button clicked).

assistant.on('assistant:reset', (data: {
  timestamp: string;
}) => {
  console.log('Assistant was reset at:', data.timestamp);
});
assistant:closed

Fired when the user closes the assistant using the close button.

assistant.on('assistant:closed', (data: {
  timestamp: string;
}) => {
  console.log('Assistant was closed by user at:', data.timestamp);
});
assistant:error

Fired when an error occurs in the assistant.

assistant.on('assistant:error', (error: {
  message: string;
  timestamp: string;
}) => {
  console.error('Assistant error:', error.message);
});

Streaming Data Format

Text Chunk (Streaming)

{
  type: 'text_chunk',
  text: 'Accumulated text content',
  resource: null,
  is_complete: boolean
}

Resource (Interactive Components)

{
  type: 'resource',
  text: null,
  resource: {
    uri: 'https://example.com/product-catalog.html',
    mimeType: 'text/uri-list',
    text: 'Resource content'
  },
  is_complete: true
}

Complete Text

{
  type: 'text',
  text: 'Complete text message',
  resource: null,
  is_complete: true
}

🔥 Advanced Features

Intent Handling System

The SDK automatically handles product interactions from embedded resources:

// When user clicks a product in a catalog, the SDK automatically:
// 1. Dispatches 'mcp-resource:action' event with action 'view_details'
// 2. Sends internal message "show me the details of [product]"
// 3. Streams product details from your API
// 4. Handles add-to-cart actions from product detail pages

assistant.on('mcp-resource:action', (data) => {
  if (data.action === 'view_details') {
    console.log('User wants to view:', data.params.product);
    // SDK handles this automatically, but you can add custom logic
  }
  
  if (data.action === 'add_to_cart') {
    // Handle real cart API call
    handleAddToCart(data.params);
  }
});

Real-time Cart Integration

const handleAddToCart = async (params) => {
  try {
    const cartItem = {
      productId: params.productId,
      name: params.name,
      price: params.price,
      quantity: params.quantity || 1,
      size: params.size,
      color: params.color,
      image: params.image
    };
    
    const response = await fetch('http://localhost:8080/api/cart/add?userId=123', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ cartItem })
    });
    
    const result = await response.json();
    
    if (result.success) {
      alert(`✅ ${cartItem.name} added to cart!`);
      
      // Automatically show cart after successful add
      setTimeout(() => {
        assistant.sendMessagePublic('view cart');
      }, 1000);
    } else {
      alert('❌ Failed to add item to cart');
    }
  } catch (error) {
    console.error('Error adding to cart:', error);
    alert('❌ Error adding item to cart');
  }
};

Loading States & Animations

The SDK includes beautiful loading animations that appear during AI responses:

  • Animated dots: Three pulsing dots with staggered timing
  • Message-level loading: Appears as a chat bubble where the response will be
  • Automatic replacement: Loading disappears when streaming starts
  • Consistent styling: Matches the overall chat design

Resource Deduplication

The SDK prevents multiple loading of the same resources during streaming:

// Automatically handled by the SDK:
// - Tracks processed resource URIs
// - Reuses existing resource elements
// - Prevents duplicate MCP UI component creation
// - Maintains chat history integrity

Voice Assistant 🎤

The SDK includes built-in speech recognition for hands-free shopping:

Features

  • 🎤 Speech-to-Text: Convert voice commands to chat messages
  • 🔴 Recording Indicator: Visual feedback in the header during recording
  • 🌐 Browser Support: Works in Chrome, Edge, Safari (with limitations)
  • ❌ Error Handling: Graceful fallback for unsupported browsers

Usage

// Voice assistant is automatically enabled
// Users click the 🎤 microphone button in the input area
// Speak their query: "Show me red dresses under $50"
// Voice is converted to text and sent as a chat message

Voice Commands Examples

  • "Show me the latest arrivals"
  • "I want to see tops in blue color"
  • "Add this item to my cart"
  • "What's in my shopping cart?"
  • "Find dresses under fifty dollars"

Browser Compatibility

  • ✅ Chrome/Chromium: Full support
  • ✅ Edge: Full support
  • ⚠️ Safari: Limited support (iOS restrictions)
  • ⚠️ Firefox: Requires manual enabling in some versions

Public Methods

// Toggle voice recognition programmatically
assistant.toggleVoiceRecognition();

// Check if voice is currently listening
const isListening = assistant.isListening; // Read-only property

Close & Reset Functionality

The SDK includes built-in UI controls:

  • Close Button (✕): Hides the sidebar, shows chat icon, preserves chat history
  • Reset Button (🔄): Clears all chat history, shows default questions
  • Event Dispatching: Both actions dispatch events for parent app handling

🛠 Troubleshooting

Common Issues

Web Component Not Rendering

// Check browser compatibility
import { isSupported } from '@shopping-assistant/sdk';

if (!isSupported) {
  console.error('Shopping Assistant not supported in this browser');
  // Provide fallback UI
}

Events Not Firing

// Make sure to set up event listeners before creating the component
assistant.on('userQuery', handleUserQuery);
assistant.on('mcp-resource:action', handleResourceAction);
assistant.create({ container: '#container' });

API Connection Issues

// Verify API configuration
const assistant = new ShoppingAssistant({
  apiKey: 'your-valid-api-key',
  apiBaseUrl: 'https://your-correct-endpoint.com'
});

// Check network requests in browser dev tools
// Ensure CORS is properly configured on your API

Loading Animation Not Showing

// Ensure you're calling completeStreaming() after streaming is done
assistant.on('userQuery', async (data) => {
  try {
    // ... handle streaming ...
  } finally {
    assistant.completeStreaming(); // Always call this
  }
});

MCP Resources Not Loading

<!-- Ensure MCP UI component is loaded before SDK -->
<script src="https://cdn.jsdelivr.net/gh/varadharajan007/[email protected]/sdk/src/mcp-ui-resource-component.js"></script>
<script type="module">
  import { ShoppingAssistant } from '@shopping-assistant/sdk';
  // ... your code
</script>

Browser Compatibility

  • Modern Browsers: Chrome 70+, Firefox 65+, Safari 12+, Edge 79+
  • Required Features:
    • Web Components (Custom Elements)
    • ES6 Modules
    • Fetch API
    • Promises
    • Shadow DOM

Performance Optimization

// Dynamic import for better performance
const initializeAssistant = async () => {
  const { ShoppingAssistant } = await import('@shopping-assistant/sdk');
  
  const assistant = new ShoppingAssistant({
    apiKey: 'your-key'
  });
  
  assistant.create();
};

// Initialize on user interaction
document.addEventListener('click', initializeAssistant, { once: true });

📚 Examples

Complete E-commerce Integration

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Complete E-commerce with Shopping Assistant</title>
  
  <!-- Load MCP UI Resource Renderer -->
  <script src="https://cdn.jsdelivr.net/gh/varadharajan007/[email protected]/sdk/src/mcp-ui-resource-component.js"></script>
</head>
<body>
  <header>
    <h1>My Fashion Store</h1>
    <div id="cart-badge">🛒 <span id="cart-count">0</span></div>
  </header>
  
  <main>
    <section class="hero">
      <h2>Welcome to Our Store</h2>
      <p>Find the perfect outfit with our AI shopping assistant!</p>
    </section>
    
    <section class="products">
      <!-- Your product grid here -->
    </section>
  </main>
  
  <script type="module">
    import { ShoppingAssistant } from '@shopping-assistant/sdk';
    
    // Initialize the assistant
    const assistant = new ShoppingAssistant({
      apiKey: 'your-api-key',
      apiBaseUrl: 'http://localhost:8080',
      userId: 'user-' + Date.now(),
      mode: 'sidebar',
      
      customChips: [
        { label: 'Track Order', callback: 'onTrackOrder' },
        { label: 'Size Guide', callback: 'onSizeGuide' },
        { label: 'Returns', callback: 'onReturns' }
      ],
      
      defaultSuggestions: [
        { name: 'Tops', icon: '👚', description: 'Stylish tops for every occasion' },
        { name: 'Dresses', icon: '👗', description: 'Beautiful dresses for any event' },
        { name: 'Jeans', icon: '👖', description: 'Comfortable and stylish jeans' },
        { name: 'Shoes', icon: '👠', description: 'Trendy footwear collection' }
      ],
      
      theme: {
        primaryColor: '#e74c3c',
        backgroundColor: '#ffffff'
      }
    });
    
    // Global callback functions
    window.onTrackOrder = () => {
      window.location.href = '/orders';
    };
    
    window.onSizeGuide = () => {
      openModal('size-guide');
    };
    
    window.onReturns = () => {
      window.location.href = '/returns';
    };
    
    // Create the assistant
    assistant.create();
    
    // Handle user queries with streaming
    assistant.on('userQuery', async (data) => {
      console.log('🔍 User query received:', data.query);
      
      try {
        const response = await fetch('/api/copilot-chat', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            message: data.query,
            conversationHistory: data.conversationHistory || []
          })
        });
        
        if (!response.body) {
          throw new Error('No response body');
        }
        
        const reader = response.body.getReader();
        const decoder = new TextDecoder();
        
        while (true) {
          const { done, value } = await reader.read();
          if (done) break;
          
          const chunk = decoder.decode(value);
          const lines = chunk.split('\n').filter(line => line.trim() !== '');
          
          for (const line of lines) {
            if (line.startsWith('data: ')) {
              try {
                const eventData = JSON.parse(line.substring(6));
                assistant.streamData(eventData);
              } catch (parseError) {
                console.error('Error parsing SSE data:', parseError);
              }
            } else if (line === 'event: done') {
              assistant.completeStreaming();
              return;
            }
          }
        }
        
        assistant.completeStreaming();
      } catch (error) {
        console.error('Error handling user query:', error);
        assistant.completeStreaming();
      }
    });
    
    // Handle resource actions (product interactions)
    assistant.on('mcp-resource:action', (data) => {
      console.log('🔗 MCP Resource action:', data.action, data.params);
      
      if (data.action === 'add_to_cart') {
        handleAddToCart(data.params);
      } else if (data.action === 'view_details') {
        console.log('👀 User wants to view product details:', data.params.productId);
        // SDK handles this automatically by streaming product details
      } else if (data.action === 'buy_now') {
        handleBuyNow(data.params);
      }
    });
    
    // Handle navigation requests
    assistant.on('navigationRequest', (data) => {
      console.log('🧭 Navigation requested:', data.action);
      
      switch (data.action) {
        case 'viewCart':
          window.location.href = '/cart';
          break;
        case 'checkout':
          window.location.href = '/checkout';
          break;
      }
    });
    
    // Handle assistant lifecycle events
    assistant.on('assistant:opened', () => {
      console.log('✅ Assistant opened');
      // Track analytics
      gtag('event', 'assistant_opened');
    });
    
    assistant.on('assistant:closed-by-user', () => {
      console.log('❌ Assistant closed by user');
      gtag('event', 'assistant_closed');
    });
    
    assistant.on('assistant:reset', () => {
      console.log('🔄 Assistant reset');
      gtag('event', 'assistant_reset');
    });
    
    // Add to cart handler
    const handleAddToCart = async (params) => {
      try {
        const cartItem = {
          productId: params.productId,
          name: params.name,
          price: parseFloat(params.price?.replace(/[^0-9.]/g, '') || '0'),
          quantity: params.quantity || 1,
          size: params.size,
          color: params.color,
          image: params.image
        };
        
        console.log('🛒 Adding to cart:', cartItem);
        
        const response = await fetch(`http://localhost:8080/api/cart/add?userId=123`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ cartItem })
        });
        
        const result = await response.json();
        
        if (result.success && result.data) {
          // Update cart badge
          updateCartBadge(result.data.items?.length || 0);
          
          // Show success message
          showNotification(`✅ ${cartItem.name} added to cart!`, 'success');
          
          // Automatically show cart after 1 second
          setTimeout(() => {
            assistant.sendMessagePublic('view cart');
          }, 1000);
        } else {
          showNotification('❌ Failed to add item to cart', 'error');
        }
      } catch (error) {
        console.error('Error adding to cart:', error);
        showNotification('❌ Error adding item to cart', 'error');
      }
    };
    
    // Buy now handler
    const handleBuyNow = (params) => {
      // Add to cart first, then redirect to checkout
      handleAddToCart(params).then(() => {
        setTimeout(() => {
          window.location.href = '/checkout';
        }, 500);
      });
    };
    
    // Utility functions
    const updateCartBadge = (count) => {
      const cartCountElement = document.getElementById('cart-count');
      if (cartCountElement) {
        cartCountElement.textContent = count.toString();
      }
    };
    
    const showNotification = (message, type) => {
      // Create and show notification
      const notification = document.createElement('div');
      notification.className = `notification ${type}`;
      notification.textContent = message;
      notification.style.cssText = `
        position: fixed;
        top: 20px;
        right: 20px;
        padding: 12px 24px;
        border-radius: 8px;
        color: white;
        font-weight: 500;
        z-index: 10000;
        background-color: ${type === 'success' ? '#28a745' : '#dc3545'};
      `;
      
      document.body.appendChild(notification);
      
      setTimeout(() => {
        notification.remove();
      }, 3000);
    };
    
    const openModal = (modalId) => {
      // Your modal opening logic
      console.log('Opening modal:', modalId);
    };
  </script>
</body>
</html>

🔒 Security Considerations

  • Always validate API keys on your backend
  • Implement rate limiting for API calls
  • Sanitize user inputs before processing
  • Use HTTPS for all API communications
  • Regularly update the SDK to latest version
  • Implement proper CORS policies
  • Validate all resource URLs before rendering

📈 Performance Best Practices

  • Lazy Loading: Load the SDK only when needed
  • Resource Deduplication: Automatically handled by the SDK
  • Streaming Optimization: Throttled UI updates during streaming
  • Memory Management: Automatic cleanup on component destruction
  • Code Splitting: Use dynamic imports for better performance

🤝 Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.


🆘 Support & Resources


Built with ❤️ by the Shopping Assistant Team

Transform your e-commerce experience with AI-powered shopping assistance!