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.
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:
- Open Settings, then Connectors.
- Choose Add custom connector.
- Paste
https://marketz.mcp.smartzees.com/mcpand save. - 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.
One command:
claude mcp add --transport http smartmarket https://marketz.mcp.smartzees.com/mcp
Add --scope user to make it available in every project rather
than only the current one. Confirm with claude mcp list.
Add it to ~/.cursor/mcp.json for every project, or .cursor/mcp.json for one:
{
"mcpServers": {
"smartmarket": {
"url": "https://marketz.mcp.smartzees.com/mcp"
}
}
}
Add it to .vscode/mcp.json in the workspace:
{
"servers": {
"smartmarket": {
"type": "http",
"url": "https://marketz.mcp.smartzees.com/mcp"
}
}
}
The server speaks MCP over streamable HTTP and is stateless, so every request carries what it needs and there is no session to establish. Any compliant client works from the endpoint URL alone.
curl -X POST https://marketz.mcp.smartzees.com/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
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 onlyFind 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.
| Parameter | Type | Notes |
|---|---|---|
| query required | string | What the shopper is looking for, in their own words. |
| limit | integer | How many to return. Defaults to 5, capped at 10. |
| category | string | Narrow 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 onlyFind 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.
| Parameter | Type | Notes |
|---|---|---|
| product required | string | The 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
WritesFill 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.
| Parameter | Type | Notes |
|---|---|---|
| items required | array | Up to 40 lines. Duplicate ids are merged rather than repeated. |
| items[].product_id | integer | The id from a search_products result. |
| items[].quantity | integer | How 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.
| Method | Path | Returns |
|---|---|---|
| GET | /v1/products/search | Ranked products for a query. |
| GET | /v1/products/categories | Categories with counts. |
| GET | /v1/stores | The supermarkets in the catalogue. |
| GET | /v1/cart | A basket by session id. |
| POST | /v1/cart/items | Adds one product to a basket. |
Search
curl -H "X-API-Key: $SMARTMARKET_KEY" \ "https://marketz.mcp.smartzees.com/v1/products/search?q=lactose+free+milk&limit=5"
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
| What | Limit | Why |
|---|---|---|
| Read requests | 120 per minute | Counted per API key, not per IP address. |
| Basket writes | 20 per minute | Every basket line is a row in a live database. |
| Search results | 10 maximum | Keeps a model's context small and stops the catalogue being downloaded one page at a time. |
| Basket lines | 40 maximum | A shopping list is tens of items, not thousands. |
| Quantity per line | 24 maximum | Guards 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
| Symptom | Cause |
|---|---|
| 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.