Developers
Swervie is a cross-retailer product catalog. Its MCP server gives an AI assistant one consolidated, scored answer per product: duplicate listings collapsed, comparable specs, live prices, and a buy link for every seller. Answers are precomputed, so no language model runs while serving a request — responses are deterministic and fast.
Add it to any MCP client that supports remote servers. In a client that takes a JSON config:
{
"mcpServers": {
"swervie": {
"url": "https://swervie.xyz/mcp"
}
}
}The server sends instructions on initialize that describe each tool and the fields its results carry, so no prompt engineering is needed on your side. They describe the data and never direct the agent. Each initialize response carries an Mcp-Session-Id header; echoing it is optional and used only for usage counting. The legacy endpoint https://us-central1-swervie-prod.cloudfunctions.net/mcp serves the same server.
Recommended flow: search_products for a normal shopping question. Use find_category then browse_category when the agent wants explicit control of filters, and get_products only when it needs full offers, review evidence, or provenance.
| Tool | Inputs | What it does |
|---|---|---|
search_products read-only | query, sort?, limit? (1-50), cursor?, user_signature? | The one-call path. Resolves the category, parses price bounds and spec constraints from free text, and returns the ranked shelf plus an interpretation receipt. |
find_category read-only | query, user_signature? | The matching category and its filter contract: every filterable spec with type, units, allowed values and importance, plus budget / mid / premium price bands. |
browse_category read-only | category, filters[]? ({dimension, equals | min | max | any_of}), sort?, limit? (1-50), cursor?, user_signature? | One ranked row per product, duplicate seller listings already collapsed: price, price band, buy_url and buy_seller, image, star rating, key specs. |
lookup_product read-only | query? (product name), identifiers? (asin, upc, ean, gtin, mpn, model_number), brand?, category?, user_signature? | One named product: exact, likely, ambiguous (candidates, best first), or none. A hit carries full detail, every offer, and its rank on its category shelf. |
get_products read-only | ids[] (1-25), user_signature? | Full detail: every spec with its provenance, review-derived ratings with verbatim evidence quotes, and every seller offer with price and buy_url. |
Sort options are value (default), quality, and price_asc. Lists page with next_cursor. Every tool carries MCP annotations and is readOnlyHint: true: the server only provides data. Nothing a tool does can buy, change, or delete anything a user owns.
search_products, browse_category, and get_products also link an interactive results view (MCP Apps, io.modelcontextprotocol/ui). Hosts without that extension ignore it and get the same data as JSON text.
MCP=https://swervie.xyz/mcp
H=(-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream")
# 1. Handshake: server info, capabilities, and agent instructions
curl -s -X POST $MCP "${H[@]}" -d '{"jsonrpc":"2.0","id":1,
"method":"initialize","params":{"protocolVersion":"2025-06-18",
"capabilities":{},"clientInfo":{"name":"my-agent","version":"1.0"}}}'
# 2. List the tools
curl -s -X POST $MCP "${H[@]}" -d '{"jsonrpc":"2.0","id":2,
"method":"tools/list"}'
# 3. Answer a shopping question in one call
curl -s -X POST $MCP "${H[@]}" -d '{"jsonrpc":"2.0","id":3,
"method":"tools/call","params":{"name":"search_products",
"arguments":{"query":"65 inch OLED TV under $1500","limit":3}}}'The third call returns the shelf as JSON text content, trimmed here:
{
"category": "Televisions",
"interpretation": {
"category": "Televisions",
"match_quality": "strong",
"resolved_child": "OLED TVs",
"price_max_cents": 150000,
"filters": [
{"dimension": "Screen Size", "min": 65, "source": "65 inch"},
{"dimension": "Display Technology", "equals": "OLED", "source": "OLED"}
],
"unparsed_tokens": []
},
"total_matching": 3,
"next_cursor": "1",
"card_specs": [{"name": "Screen Size", "unit": "inches"},
{"name": "Display Technology"}, {"name": "Resolution"}, "..."],
"rows": [
{
"id": "x867BnXduwLjzQUsOKzf",
"title": "Panasonic Z8BAP 77\" OLED 4K Smart Fire TV, 144Hz",
"brand": "Panasonic",
"price_usd": 1399.99,
"swervie_score": 70.8,
"price_band": "premium",
"buy_url": "https://us-central1-swervie-prod.cloudfunctions.net/go?p=...",
"buy_seller": "amazon",
"star_rating": 4.7,
"star_rating_count": 111,
"attributes": {"Screen Size": 77, "Display Technology": "OLED",
"Refresh Rate": 144, "HDMI 2.1 Support": true}
}
],
"disclosure": "Swervie may earn a commission when a shopper buys ..."
}interpretation is the receipt for how the query was understood: the category, the filters parsed from the text (each with its source words), and unparsed_tokens for anything that did not become a filter. Soft preferences like “quiet” land there and do not reorder rows — weigh them yourself.match_quality is strong, partial, or weak. On weak the category itself is suspect and rows are withheld; tell the user rather than presenting the shelf.swervie_score is 0-100, higher is better; price_band is budget, mid, or premium for that category.card_specs lists the specs each product card shows, in order. Present specs in that order for every product so comparisons line up.buy_url is a Swervie redirect to the seller named in buy_seller. The purchase happens on the seller's site.disclosure text wherever you show buy links. Some links earn Swervie a commission; commissions never affect rankings, scores, or which products are shown (see the affiliate disclosure).find_category query has no matching category, the response says so and the request is queued as demand for a new category.Every tool accepts an optional user_signature, a pseudonymous id that gives each shopper their own rate-limit quota and attributes their buy-link clicks. Every tool works without it.
// id = the user's most stable identifier, normalized:
// lowercase, trimmed; email preferred, with +tags stripped
user_signature = "sv1-" + sha256hex("swervie/v1|" + id).slice(0, 24)"sv1r-" + a random UUID stored for that user. Never send a fresh random value per session.| Scope | Per minute | Per day |
|---|---|---|
| Per user_signature, or per IP when none is sent | 60 | 2,000 |
| Per IP, across all signatures | 300 | 20,000 |
| Partner key (default) | 600 | 100,000 |
Requests without a user_signature share their IP's 60-per-minute limit, so a platform serving many users from a few addresses should send signatures or use a partner key. Over the limit, the server answers HTTP 429 with a Retry-After header and a JSON-RPC error.
Assistant platforms whose traffic leaves from shared IP addresses can ask for a partner key. Send it as Authorization: Bearer svk_… or X-Swervie-Api-Key: svk_…. It replaces the shared IP ceiling with the partner's own quota (adjustable per partner) while the per-signature limit keeps users fair within it. An unknown or revoked key is served at the anonymous tier, never refused. Keys are stored only as hashes. Email info@plum-app.com to request one.
user_signature — no account, email, device id, or conversation history.See the privacy policy and terms.
/api/ucp/mcp with standard search_catalog / lookup_catalog.Questions, partner keys, outages, or catalog corrections: info@plum-app.com. Swervie is built and operated by Plum Applications, Inc. More about the catalog on the about page.