tx-smitht

grocery-deals-mcp

Community tx-smitht
Updated

MCP server that exposes weekly grocery-store circulars for any US ZIP code — search deals across local stores, build shopping plans, track price history

grocery-deals-mcp

An MCP server that tells an AI assistant what's actually on sale at grocerystores near any US ZIP code this week.

It reads the weekly circulars that supermarkets publish — the same ads thatused to arrive in the newspaper — and turns them into something an agent canquery: "what protein is cheap this week?", "where should I buy this list?","is $1.99/lb a good price for chicken, or should I wait?"

Typical coverage for a suburban ZIP is 15–25 grocery chains and severalthousand advertised items, including Aldi, Costco, Food Lion, Giant, HarrisTeeter, H Mart, Lidl, Publix, Safeway, Sprouts, Target, Walmart, Wegmans andWeis, depending on what operates in your area.

Why it's fast

Every query tool reads a local SQLite index and never touches the network.Only refresh_deals goes out to fetch circulars (10–20 seconds), and itself-heals — the first query of the week builds the index, and every call afterthat returns in milliseconds until the circulars turn over.

Tools

Tool What it does
list_stores Which stores near a ZIP have an active ad, and how many deals each is running
search_deals Find a product across every local store's ad, cheapest first
store_circular Dump one store's entire weekly ad
shopping_plan Turn a shopping list into a per-store trip plan, capped at N stores
price_check Judge a price against the history this server accumulates
refresh_deals Force an index rebuild mid-week
kroger_search Exact SKU-level regular/promo prices (optional, see below)
kroger_find_stores Look up a Kroger-banner store ID (optional)

Setup

Requires Python 3.10+ and uv.

git clone https://github.com/tx-smitht/grocery-deals-mcp.git
cd grocery-deals-mcp && uv sync

Verify it starts:

uv run grocery-deals-mcp

It will sit silently waiting for MCP traffic on stdin — that's correct. Ctrl-Cto exit.

Setting your location

The agent passes the ZIP code. Every location-aware tool takes azip_code argument, so you can just say "what's on sale near 12345?" and itworks with no configuration at all. Nothing about any location is stored inthis repository.

If you'd rather not repeat your ZIP every conversation, set GROCERY_ZIP inyour client config (below) and the argument becomes optional. Note that thiswrites your ZIP into a local config file — keep that file out of versioncontrol. .mcp.json and .env are already in .gitignore.

All configuration

Every setting is an environment variable, all optional:

Variable Default Purpose
GROCERY_ZIP (none) Default ZIP, so tools don't need the argument
GROCERY_STORES (all) Comma-separated allowlist, e.g. Aldi,Lidl,Costco
GROCERY_CACHE_TTL_HOURS 12 How long the index stays fresh
GROCERY_DB_PATH ./data/deals.db Where the cache and price history live
KROGER_CLIENT_ID / KROGER_CLIENT_SECRET (none) Enables kroger_search
KROGER_LOCATION_ID (none) Default Kroger-banner store

To change what counts as a grocery store, edit GROCERY_CATEGORY insrc/grocery_deals_mcp/config.py — Flippalso tags circulars as Pharmacy, Pets, Home & Garden, Electronics andothers, so the same code will happily index those instead.

Connecting it

Claude Code

One command, from anywhere:

claude mcp add grocery-deals -- uv run --directory /absolute/path/to/grocery-deals-mcp grocery-deals-mcp

With a default ZIP baked in:

claude mcp add grocery-deals --env GROCERY_ZIP=12345 -- uv run --directory /absolute/path/to/grocery-deals-mcp grocery-deals-mcp

Then /mcp inside Claude Code to confirm it connected.

Claude Desktop

Edit claude_desktop_config.json (Settings → Developer → Edit Config):

{
  "mcpServers": {
    "grocery-deals": {
      "command": "uv",
      "args": ["run", "--directory", "/absolute/path/to/grocery-deals-mcp", "grocery-deals-mcp"],
      "env": { "GROCERY_ZIP": "12345" }
    }
  }
}

Restart Claude Desktop. Drop the env block to pass ZIPs per-question instead.

Codex CLI

Add to ~/.codex/config.toml:

[mcp_servers.grocery-deals]
command = "uv"
args = ["run", "--directory", "/absolute/path/to/grocery-deals-mcp", "grocery-deals-mcp"]
env = { GROCERY_ZIP = "12345" }

Anything else

It's a standard stdio MCP server. Any client that speaks MCP can runuv run --directory <path> grocery-deals-mcp.

A copyable starting point is in.mcp.json.example.

Optional: exact Kroger-banner pricing

The circular tells you "Boneless Chicken Breast $1.99/lb". Kroger's officialAPI tells you the exact SKU, size, regular price and promo price at onespecific store. It covers every Kroger banner — Kroger, Harris Teeter, Ralphs,Fred Meyer, King Soopers, QFC, Smith's, Fry's.

  1. Register a free app at developer.kroger.comand request the Products API
  2. Set KROGER_CLIENT_ID and KROGER_CLIENT_SECRET
  3. Ask the agent to run kroger_find_stores, then set KROGER_LOCATION_ID tothe store you use (or pass location_id per call)

kroger_find_stores accepts everyday chain names — "Harris Teeter" works, andso does Kroger's internal code for it (HART). Matching happens client-sidebecause Kroger's own filter.chain takes undocumented codes and answers anunrecognized one with an empty list rather than an error.

Free tier allows 10,000 calls/day. Everything else in this server workswithout it.

How it works, and what that implies

Circular data comes from Flipp's backend — the service behind the weekly-ad appused by most large US grocers. These endpoints are undocumented andunofficial. They require no key and are the same calls Flipp's own web appmakes, but there is no API contract behind them: they can change shape ordisappear without notice, and this project isn't affiliated with or endorsed byFlipp or any retailer.

Accordingly, the server caches aggressively and fetches rarely — one refreshper ZIP per 12 hours by default, six concurrent requests at most. Please don'tlower those defaults to hammer someone else's servers.

Some real limits worth knowing:

  • Trader Joe's will never appear. They don't run weekly sales or publish acircular. That's a fact about Trader Joe's, not a gap in the data.
  • Prices are what the ad claims. Loyalty-card qualifiers (MVP, with card), digital-coupon requirements and quantity limits are captured when thead states them, but the ad is the source of truth, not the register.
  • Flyer dumps lack units. A store's full circular gives names and prices;search_deals falls back to Flipp's search index, which adds LB/EA unitsand loyalty qualifiers, when a term is thin locally.
  • A ZIP's feed can include chains that aren't local. Flipp's radius isgenerous. Use GROCERY_STORES to pin it down to stores you'd actually driveto.

Privacy

Nothing leaves your machine except circular requests to Flipp (a ZIP code andsearch terms) and, if you enable it, product lookups to Kroger.

The SQLite database records your ZIP and accumulated price history. It lives indata/ and is gitignored. So is .env and .mcp.json — if you set a defaultZIP, that's where it should go.

License

MIT

MCP Server · Populars

MCP Server · New

    Laksh-star

    Screenward

    Movie and TV discovery, watch planning, and streaming availability—for browsers and MCP clients.

    Community Laksh-star
    codescene-oss

    CodeHealth MCP Server

    The CodeScene MCP Server exposes CodeScene’s Code Health analysis as local AI-friendly tools.

    Community codescene-oss
    Fan-Pier-Labs

    OpenRecord

    Let Claude read and manage your Epic MyChart health records — labs, meds, messages, refills, imaging. Claude Desktop extension (MCP server), iOS app, and CLI. Runs on your device.

    Community Fan-Pier-Labs
    video-db

    skills

    Server-side video workflows for agents: ingest, understand, search, edit, stream.

    Community video-db
    cognicore-dev

    CogniCore

    Persistent memory, reflection & safety for AI agents. No vector DB, no embedding server — BM25 + multi-hop retrieval runs in-process. MCP server with 10 tools. Apache 2.0.

    Community cognicore-dev