SmartMarket MCP server

SmartMarket MCP server

Grocery catalogue and baskets for Miami area supermarkets. Search by meaning, compare the same item between shops, and build a basket a shopper can check out. Available as an MCP connector and as a REST API.

MCP endpoint, streamable HTTP https://marketz.mcp.smartzees.com/mcp
  • 41,752products
  • 4supermarket chains
  • 4tools
  • <50mstypical search

Install

No sign up and no API key for the MCP side. Pick your client.

On claude.ai and in the Claude desktop app:

  1. Open Settings, then Connectors.
  2. Choose Add custom connector.
  3. Paste https://marketz.mcp.smartzees.com/mcp and save.
  4. Start a new chat. The four tools appear under the connector.

Custom connectors need a paid plan. Pro, Max, Team or Enterprise. On a free account the option is not offered at all.

Verify it works

Ask for something only the live catalogue could answer.

Compare the price of eggs across the stores you can see

You should get three or more named Miami stores at different prices, cheapest first. A generic answer with no store names means the connector is not attached to that conversation.

Tools

Three read the catalogue and one writes a basket. The readers carry readOnlyHint, which clients use to decide what may run without asking a person first.

search_products

Read only

Find groceries by describing what you want. Understands meaning, not just keywords: "something for a barbecue" and "lactose free milk" both work. Returns the product, its price and the store selling it, best match first.

ParameterTypeNotes
query requiredstringWhat the shopper is looking for, in their own words.
limitintegerHow many to return. Defaults to 5, capped at 10.
categorystringNarrow to one category. Use a name from list_categories.
{"query": "lactose free milk", "limit": 2}

{
  "products": [
    { "id": 238327, "name": "fairlife Whole Ultra-Filtered Milk, Lactose Free",
      "price": 6.99, "store": "Sabor Tropical Supermarket Kendall",
      "category": "Beverages", "in_stock": true },
    { "id": 267229, "name": "fairlife Fat Free Ultra-Filtered Milk, Lactose Free",
      "price": 5.89, "store": "BJ's Wholesale Kendall",
      "category": "Beverages", "in_stock": true }
  ],
  "count": 2
}

list_categories

Read only

The categories of grocery available, with how many products each holds. Takes no parameters. Use one of these names as the category filter on search_products.

compare_stores

Read only

Find where a product is cheapest. Searches for the item and groups what comes back by store, so you can see the same thing priced at one chain against another.

ParameterTypeNotes
product requiredstringThe item to price, for example "eggs" or "olive oil".
{"product": "eggs"}

{
  "product": "eggs",
  "stores": [
    { "store": "Sabor Tropical Supermarket Kendall", "price": 3.99,
      "name": "SunUps Eggs, Farm Fresh, Large" },
    { "store": "Restaurant Depot", "price": 4.99,
      "name": "James Farm - Liquid Eggs, Just Whites - 2 lbs" },
    { "store": "BJ's Wholesale Kendall", "price": 8.39,
      "name": "Eggland's Best Eggs, Medium, Hard-Cooked" }
  ],
  "cheapest": { "store": "Sabor Tropical Supermarket Kendall",
                "price": 3.99, "name": "SunUps Eggs, Farm Fresh, Large" }
}

build_basket

Writes

Fill a basket and get back a link the shopper opens to review and check out. Takes catalogue ids, so search first. Subtotal, tax and total are read back from the shop rather than added up here.

ParameterTypeNotes
items requiredarrayUp to 40 lines. Duplicate ids are merged rather than repeated.
items[].product_idintegerThe id from a search_products result.
items[].quantityintegerHow many. Clamped to 24.
{"items": [{"product_id": 267229, "quantity": 2},
           {"product_id": 256108, "quantity": 1}]}

{
  "basket": [
    { "name": "fairlife Fat Free Ultra-Filtered Milk, Lactose Free",
      "quantity": 2, "unit_price": 5.89, "subtotal": 11.78 },
    { "name": "James Farms - Large Loose Eggs - 7.5 Dz",
      "quantity": 1, "unit_price": 8.99, "subtotal": 8.99 }
  ],
  "count": 3,
  "subtotal": 20.77,
  "tax": 1.66,
  "total": 22.43,
  "checkout_url": "https://marketz.smartzees.com/chat?cart=7b54037a9ba9...",
  "note": "Nothing has been ordered and no payment has been taken."
}

If one product is unavailable the rest of the basket is still built, and the result carries a not_added list giving the shop's own reason for each line it refused.

What it will not do

Nothing here can spend money. The assistant fills a basket and returns a link. The shopper opens it, sees the total, and checks out on the website themselves.

There is deliberately no tool that places an order or completes a payment. The moment a model can finish a purchase, every piece of text it reads becomes a way to make somebody buy something. The basket is the right boundary, and the step where money moves is the step the shopper takes.

build_basket does not carry readOnlyHint, so a well behaved client asks before running it. That is intended: it puts a real basket in a real shop.

REST API

For code rather than assistants. Every endpoint takes an API key in the X-API-Key header. Ask SmartZees for one.

MethodPathReturns
GET/v1/products/searchRanked products for a query.
GET/v1/products/categoriesCategories with counts.
GET/v1/storesThe supermarkets in the catalogue.
GET/v1/cartA basket by session id.
POST/v1/cart/itemsAdds one product to a basket.

Search

Build a basket

Two calls and a link. Mint a session id, add products to it, then send the shopper to the shop.

SESSION=$(openssl rand -hex 16)

curl -H "X-API-Key: $SMARTMARKET_KEY" -H "Content-Type: application/json" \
  -d "{\"session_id\":\"$SESSION\",\"item_id\":267229,\"quantity\":2}" \
  https://marketz.mcp.smartzees.com/v1/cart/items

echo "https://marketz.smartzees.com/chat?cart=$SESSION"

Send the shopper to /chat, not to the site root. The home page ignores the cart parameter and drops it on the first click through, so a link to / opens an empty basket and reports no error.

OpenAPI spec

Machine readable at /openapi.json. Try it out is switched off here on purpose: the basket endpoints write to a live catalogue, so call them from your own code with your own key.

Limits

WhatLimitWhy
Read requests120 per minuteCounted per API key, not per IP address.
Basket writes20 per minuteEvery basket line is a row in a live database.
Search results10 maximumKeeps a model's context small and stops the catalogue being downloaded one page at a time.
Basket lines40 maximumA shopping list is tens of items, not thousands.
Quantity per line24 maximumGuards a model that means a dozen eggs and sends 12 of the box.
  • Stock is a yes or no. The catalogue's raw stock figure is a placeholder often enough that reporting it as fact would mislead. Whether there is any is accurate.
  • Prices are live and they change. Nothing is cached between a search and a basket, so a quote and a checkout page agree.
  • Rate limits return 429 with a JSON body. A missing or unknown key returns 401.

Troubleshooting

SymptomCause
No option to add a custom connector The Claude account is on the free plan. Custom connectors need Pro, Max, Team or Enterprise.
Tools do not appear after adding Start a new conversation. Connectors attach at the start of a chat, not to one already running.
A search reports a deployment fault The catalogue API behind this server is unreachable. The connector itself is fine and nothing on your side will fix it.
The checkout link opens an empty basket The link points at the site root. It must be /chat?cart=.
401 from a /v1 path Missing or unrecognised X-API-Key. The MCP endpoint needs no key, but every REST path does.
404 from a /v1 path That path is not published. Only the five endpoints listed above are reachable through this host.

Health check: /health reports the server and which catalogue it is pointed at.