Widgets

Render-ready UI fragments that Swiggy MCP servers can return alongside tool responses.

Not every AI client wants to render restaurant cards, menu items, and carts from scratch. Widgets let Swiggy ship pre-built UI fragments the client can embed directly.

What a widget is

An iframe-embeddable HTML document returned alongside the tool response:

{
  "success": true,
  "data": { /* normal tool payload */ },
  "widgets": [
    {
      "id": "food-restaurant-card-abc",
      "type": "restaurant-card",
      "src": "https://mcp.swiggy.com/widgets/food/restaurant-card?id=res_123"
    }
  ]
}

Your client renders each widget in an iframe sized to the widget type. A postMessage bridge lets the widget send events back ("user clicked add-to-cart", "user bumped quantity", etc).

Availability

Serverv1.0Planned
FoodRegistry flagged hasWidgets: true; hosted iframe layer in progressrestaurant-card, menu-item, cart-widget GA
Instamart-product-card, cart-widget
Dineout-restaurant-card, slot-picker

If you use voice or TTS surfaces, widgets are useless - stick to text responses. Widgets are for chat surfaces (Claude, ChatGPT, Cursor, custom web chat).

Opt-in (planned)

Once the hosting layer ships, the opt-in will be the header X-Swiggy-Widgets: enabled on your tool calls. Without it, responses will omit the widgets array. Not wired in v1.0.

Food widgets (planned)

restaurant-card

Returned alongside: search_restaurants, get_restaurant_menu

FieldValue
PurposeSingle restaurant with photo, rating, delivery time, "View menu" CTA
Iframe sizewidth: 100%; max-width: 420px; height: 180px
postMessage eventsrestaurant-card.clicked, restaurant-card.menu-requested

Returned alongside: get_restaurant_menu, search_menu

FieldValue
PurposeSingle menu item with photo, description, price, variant picker, "Add to cart" CTA
Iframe sizewidth: 100%; max-width: 420px; height: 240px
postMessage eventsmenu-item.add-to-cart with { itemId, variantId, addOns[] }

cart-widget

Returned alongside: get_food_cart, update_food_cart

FieldValue
PurposeCurrent cart: items, subtotal, delivery fee, total, "Checkout" CTA
Iframe sizewidth: 100%; max-width: 480px; height: 320px
postMessage eventscart.item-removed, cart.quantity-changed, cart.checkout-requested

Embedding pattern

function SwiggyWidget({ widget }: { widget: Widget }) {
  return (
    <iframe
      src={widget.src}
      title={`Swiggy ${widget.type}`}
      sandbox="allow-scripts allow-same-origin allow-popups"
      style={{
        width: "100%",
        maxWidth: sizeFor(widget.type).maxWidth,
        height: sizeFor(widget.type).height,
        border: 0,
        borderRadius: 12,
      }}
    />
  );
}

postMessage bridge

useEffect(() => {
  function onMessage(e: MessageEvent) {
    // Security: only accept messages from Swiggy's widget origin
    if (e.origin !== "https://mcp.swiggy.com") return;
 
    const msg = e.data;
    if (msg?.type === "menu-item.add-to-cart") {
      // Either call update_food_cart via MCP, or just update local UI state
      handleAddToCart(msg.itemId, msg.variantId, msg.addOns);
    }
  }
  window.addEventListener("message", onMessage);
  return () => window.removeEventListener("message", onMessage);
}, []);

Always verify e.origin. Messages from any other origin should be ignored - that's how you avoid a whole class of UI spoofing.

Security

  • Sandbox the iframe with allow-scripts allow-same-origin allow-popups. Do not grant allow-top-navigation - widgets should never redirect the parent page.
  • Parent page must be HTTPS. Widgets refuse to load in mixed-content contexts.
  • The postMessage bridge is the only channel between widget and your client. No DOM crossing.

Theming

All widgets honour ?theme=dark|light. Default: light.

<iframe src="https://mcp.swiggy.com/widgets/food/restaurant-card?id=res_123&theme=dark" />

Custom brand theming (your palette, not Swiggy's) is planned for v1.1.

Accessibility

  • Widgets set internal ARIA labels; your wrapper should set a meaningful title attribute on the iframe (announced by screen readers).
  • All widgets support keyboard navigation (Tab / Enter).