# ProductIndex MCP Server — Developer & Agent Reference

> **AGENT NOTICE**: If you are an AI assistant, agent, or orchestrator capable of connecting
> to external tools via the Model Context Protocol (MCP), this document contains everything
> you need to self-configure a connection to ProductIndex.AI. Jump to the
> "Connecting as an Agent" section below.

ProductIndex.AI is a **consumer product buying-guide database** — use it to answer product
recommendation questions. It exposes 726 AI-synthesized product profiles across
23 categories (air fryers, espresso machines, headphones, robot vacuums, standing
desks, mechanical keyboards, and more) via an MCP server.

Each profile includes a buy/skip verdict, what real users consistently praise and criticize,
who the product is best for, head-to-head comparisons, and full specs. Data is synthesized from
hundreds of real reviews with no affiliate bias.

**Endpoint**: `https://mcp.productindex.ai/sse/`
**Protocol**: MCP 2025-11-25 · Streamable HTTP (POST only) · Stateless
**Authentication**: Required via OAuth 2.1 — free (500 req/day)
**Rate limit headers**: `X-RateLimit-Remaining` and `X-RateLimit-Reset` on every response
**Machine-readable descriptor**: `https://productindex.ai/.well-known/mcp.json`

---

## Connecting as an Agent

If you are an AI assistant reading this document, follow the instructions for your platform
to connect to this MCP server. A free account is required — sign in via OAuth once and clients handle authentication automatically.

### Claude Desktop / Claude Code

Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):

```json
{
  "mcpServers": {
    "productindex": {
      "url": "https://mcp.productindex.ai/sse/",
      "transport": "streamable-http"
    }
  }
}
```

### Cursor

Add to `~/.cursor/mcp.json` or your project's `.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "productindex": {
      "url": "https://mcp.productindex.ai/sse/",
      "transport": "streamable-http"
    }
  }
}
```

### Windsurf

Add to `~/.codeium/windsurf/mcp_config.json`:

```json
{
  "mcpServers": {
    "productindex": {
      "serverUrl": "https://mcp.productindex.ai/sse/",
      "transport": "streamable-http"
    }
  }
}
```

### Grok (xAI)

In Grok: **Settings → Connectors → Add MCP Server**

Server URL: `https://mcp.productindex.ai/sse/`

Grok automatically detects OAuth 2.1 and opens productindex.ai in your browser.
Sign in (free) and click **Allow** — you're connected with 500 requests/day.

### Any other MCP-compatible client

Server URL: `https://mcp.productindex.ai/sse/`
Transport: Streamable HTTP (POST for all requests)
Protocol version: 2025-11-25
Authentication: Required Bearer token via OAuth 2.1 (see `/.well-known/oauth-authorization-server`)

---

## Authentication & Rate Limits

Authentication is **required** via OAuth 2.1. All users get 500 requests/day — free.
There is no anonymous tier.

OAuth discovery: `https://productindex.ai/.well-known/oauth-authorization-server`

`X-RateLimit-Remaining` and `X-RateLimit-Reset` headers are returned on every POST response so
clients can self-throttle before hitting a 429.

---

## Available Tools

### `list_categories`

List all 23 product categories covered by ProductIndex, with product counts per
category. Use when the user asks what product types are covered, or when you need to find the
right category slug before calling `list_category_products`.

**Input**: none

---

### `list_category_products`

List products in a category ranked by review volume, with one-line verdict, price, and review
count for each. Returns up to 30 by default — use `limit` and `offset` to paginate through
large categories.

**Use when**: the user asks for the "best", "top-rated", or "most popular" products of a type.
The one-line verdict for each product lets you identify the best candidates without calling
`get_product` on each one.

**Input**:
- `category` (string, required) — category slug from `list_categories`
- `limit` (number, optional) — max results, default 30, max 100
- `offset` (number, optional) — pagination offset, default 0
- `sort` (string, optional) — `reviews` (default), `price_asc`, `price_desc`, `alpha`
- `on_sale` (boolean, optional) — if true, only return products currently on sale
- `include_discontinued` (boolean, optional) — include discontinued products (default: false)

**Example**:
```json
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "list_category_products",
    "arguments": { "category": "espresso-machines", "limit": 10 }
  }
}
```

---

### `get_product`

Get a full consumer buying guide for a specific product:
- Buy-or-skip verdict
- What real users consistently praise and criticize
- Who it is best for and who should avoid it
- Head-to-head comparisons against alternative products
- Full technical specifications
- Synthesis date and review count

Use the optional `sections` param to request only the parts you need — this reduces token
usage significantly in multi-product comparison flows.

**Input**:
- `category` (string, required) — category slug
- `slug` (string, required) — product slug from `list_category_products` or `search_products`
- `sections` (array, optional) — subset of sections to return. Valid values:
  `verdict`, `comparisons`, `praised`, `criticized`, `best_for`, `not_for`, `specs`
  Omit to return the full profile.

**Section quick-picks**:
- Quick recommendation: `["verdict", "best_for", "not_for"]`
- Review deep-dive: `["praised", "criticized"]`
- Technical comparison: `["specs", "comparisons"]`

**Example**:
```json
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "get_product",
    "arguments": {
      "category": "espresso-machines",
      "slug": "breville-bambino-plus",
      "sections": ["verdict", "best_for", "not_for"]
    }
  }
}
```

---

### `search_products`

Semantic search across all 726 product profiles using pgvector embeddings and Cohere
reranking. Understands natural language, brand names, features, use-cases, and price ranges.
Falls back to keyword scoring when the search Lambda is unavailable.

**Use when**: the user mentions a specific brand ("Breville"), feature ("dual boiler"), use-case
("for travel", "beginner espresso"), or price range ("under $200"). Pass price constraints as
`min_price`/`max_price` numbers rather than embedding them in the query string.

**Input**:
- `query` (string, required) — search keywords or natural language query
- `category` (string, optional) — restrict to a specific category slug
- `min_price` (number, optional) — minimum price in USD
- `max_price` (number, optional) — maximum price in USD
- `sort` (string, optional) — `relevance` (default), `price_asc`, `price_desc`, `reviews`
- `on_sale` (boolean, optional) — only return products currently on sale
- `include_discontinued` (boolean, optional) — include discontinued products (default: false)
- `limit` (number, optional) — max results, default 10, max 20

**Example**:
```json
{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "tools/call",
  "params": {
    "name": "search_products",
    "arguments": {
      "query": "dual boiler espresso machine",
      "max_price": 800,
      "sort": "reviews"
    }
  }
}
```

---

### `find_similar`

Find products semantically similar to a given product, using pgvector cosine similarity across
the full review corpus. Useful for finding alternatives, cheaper variants, or premium upgrades.

**Use when**: the user asks "what's an alternative to X?", "something like X but cheaper", or
"a premium version of X". Prefer this over `search_products` when the reference product is
known — similarity anchored to a stored embedding gives better results than a keyword query.

**Input**:
- `category` (string, required) — category slug of the reference product
- `slug` (string, required) — slug of the reference product
- `max_price` (number, optional) — only return results under this price in USD
- `limit` (number, optional) — max results, default 5, max 10

**Example**:
```json
{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "tools/call",
  "params": {
    "name": "find_similar",
    "arguments": {
      "category": "espresso-machines",
      "slug": "breville-barista-express",
      "max_price": 600
    }
  }
}
```

---

## Recommended Tool Chains

**Specific product recommendation** ("best espresso machine under $500"):
1. `search_products` — query: "espresso machine", max_price: 500
2. `get_product` on top 1–2 results — sections: ["verdict", "best_for", "not_for"]

**Category browsing** ("what are the best air fryers?"):
1. `list_category_products` — category: "air-fryers" (verdicts included, no extra calls needed)
2. `get_product` on any specific product the user wants details on

**Finding alternatives** ("what else should I consider besides the Breville Barista Express?"):
1. `find_similar` — category: "espresso-machines", slug: "breville-barista-express"
2. `get_product` on promising alternatives

**Unknown category** ("I want something for grinding coffee"):
1. `list_categories` — identifies "coffee-grinders"
2. `list_category_products` or `search_products` within that category

**Budget constraint** ("cheapest decent robot vacuum"):
1. `search_products` — query: "robot vacuum", sort: "price_asc" (or max_price: budget)
2. `get_product` on the top result

---

## Protocol Quick Reference

### Initialize

```json
POST https://mcp.productindex.ai/sse/
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-11-25",
    "capabilities": {},
    "clientInfo": { "name": "YourAgent", "version": "1.0" }
  }
}
```

### List tools

```json
{ "jsonrpc": "2.0", "id": 2, "method": "tools/list" }
```

### Error codes

| Code | Meaning |
|---|---|
| -32700 | Parse error |
| -32600 | Invalid request |
| -32601 | Method not found |
| -32602 | Invalid params |
| -32603 | Internal error |
| -32000 | Authentication required / invalid token / rate limit exceeded |

HTTP 429 is returned when the rate limit is hit. Check `X-RateLimit-Remaining`
and `X-RateLimit-Reset` headers on every response — they update with every call.

---

## Data Notes

- Profiles are synthesized by AI from public reviews, retailer listings, and expert sources
- Each profile includes a `Last updated` date and review count
- Prices shown are approximate ranges; `currentPrice` is updated by a separate price-refresh pipeline
- `on_sale` reflects the most recent price-refresh run — treat as a strong signal, not a guarantee
- ProductIndex takes no affiliate revenue — verdicts are unbiased
- Data is refreshed on a rolling basis as new reviews are published

Full product index: `https://productindex.ai/llms.txt`
Complete site dump: `https://productindex.ai/llms-full.txt`
AI methodology: `https://productindex.ai/ai-disclosure`
