fsastore-mcp
by darrengruber
README.md
# fsastore-mcp
An MCP server that lets an AI agent (Claude or Codex) **search FSA‑eligible
products on fsastore.com and add them to your shopping cart**, then place the
order only when you explicitly confirm the total.
- Runs with **one `uvx` command** — no clone, no manual install.
- **No password is ever stored.** You paste a short‑lived access token from your
browser via a one‑click bookmarklet.
- Search → cart is verified against the live store API.
---
## 1. Add it to your agent
You need [`uv`](https://docs.astral.sh/uv/) installed (`brew install uv`). `uvx`
then builds and runs the server straight from the repo.
> This repo is **private**, so `uvx` clones it with your Git credentials. Run
> `gh auth login` (or have SSH set up) first. If you use SSH, swap the URL for
> `git+ssh://git@github.com/darrengruber/fsastore-mcp`.
### Claude Code (CLI)
```bash
claude mcp add fsastore -- \
uvx --from git+https://github.com/darrengruber/fsastore-mcp fsastore-mcp
```
### Claude Desktop
Add to `claude_desktop_config.json` (Settings → Developer → Edit Config):
```json
{
"mcpServers": {
"fsastore": {
"command": "uvx",
"args": ["--from", "git+https://github.com/darrengruber/fsastore-mcp", "fsastore-mcp"]
}
}
}
```
### OpenAI Codex CLI
Add to `~/.codex/config.toml`:
```toml
[mcp_servers.fsastore]
command = "uvx"
args = ["--from", "git+https://github.com/darrengruber/fsastore-mcp", "fsastore-mcp"]
```
Restart the agent after editing config. To grab the latest code later, add
`--refresh` to the `uvx` args (e.g. `["--refresh", "--from", "git+...", "fsastore-mcp"]`).
---
## 2. Install the token bookmarklet (one minute, one time)
The store sits behind bot protection, so the server can't log in for you.
Instead you hand it a fresh token with one click. **Set this up once:**
1. **Copy** this entire line (it starts with `javascript:`):
```
javascript:(function(){var m=document.cookie.match(/scapi_access_token=([^;]+)/);if(!m){alert('No token yet — open your Cart once, then click again.');return;}var t=decodeURIComponent(m[1]);navigator.clipboard.writeText(t).then(function(){alert('FSA token copied ('+t.length+' chars). Paste it to your agent.');},function(){window.prompt('Copy this token:',t);});})();
```
2. **Create a bookmark** and paste that line as its **URL**:
- **Chrome / Edge:** ⭐ in the address bar → **Edit** → set **Name** to
`FSA token` and replace the **URL** with the copied line → **Save**.
(Or: menu → Bookmarks → **Bookmark Manager** → ⋮ → **Add new bookmark**.)
- **Firefox:** Bookmarks menu → **Manage Bookmarks** → right‑click a folder →
**Add Bookmark** → Name `FSA token`, **Location** = the copied line.
- **Safari:** add any bookmark, then Edit Bookmarks and paste the line as its
address.
That's it — you now have an **FSA token** button.
---
## 3. Use it
1. **Log in** at <https://www.fsastore.com> in your browser.
2. Click your **FSA token** bookmark. It copies a token to your clipboard.
(If it says *"No token yet"*, open your **Cart** page once and click again.)
3. In Claude/Codex, tell the agent to **set the access token**, and paste it:
> Use `set_access_token` with: `eyJ...` *(your copied token)*
4. Now just ask, e.g.:
> Search fsastore for sunscreen and add two of the cheapest eligible one to my cart.
When the token expires (~30 min), any tool replies `login_required` — just click
the bookmark and `set_access_token` again.
> **Tip:** ask the agent to run `auth_status`. It reports whether your token is
> for your **account** or a **Guest** session. If it says Guest, log in first,
> then re‑run the bookmark — otherwise you'll be editing a guest cart.
---
## Tools the agent can call
| Tool | Purpose |
|------|---------|
| `set_access_token` | Cache a token copied by the bookmarklet |
| `auth_status` | Whether a valid token is cached, who it's for, time left |
| `search_products` | Search; FSA‑eligible only by default, each tier‑labeled |
| `add_to_cart` | Add a product (master products auto‑resolve to a buyable variant) |
| `view_cart` | Show cart contents and total |
| `get_checkout_summary` | Show the total to confirm |
| `confirm_order` | Place the order — only if the live total matches the one you pass |
The server never places an order except through `confirm_order` with a matching
total.
---
## Run it directly (optional)
```bash
# from a clone
uvx --from . fsastore-mcp
# or
uv run fsastore-mcp
```
## Run as an HTTP server / container (optional)
For local use the stdio transport above is all you need. To run it persistently
behind an MCP gateway, set `FSASTORE_MCP_TRANSPORT=http` (host/port via
`FSASTORE_MCP_HOST` / `FSASTORE_MCP_PORT`). A `Dockerfile` is included:
```bash
docker build -t fsastore-mcp .
docker run --rm -p 9130:9130 -v fsastore-state:/state fsastore-mcp
```
State (the cached token, active basket id) lives in the process, so serve HTTP
with a **single replica**. The token is written under `XDG_STATE_HOME`
(`/state` in the image) — mount a writable volume there.
## Develop
```bash
uv sync
uv run pytest # tests
uv run ruff check . # lint
uv run ty check src # types
```
Design notes and decisions: [`CONTEXT.md`](CONTEXT.md) and [`docs/adr/`](docs/adr/).
## Status
Verified against the live store API: product search + FSA‑eligibility, cart reuse,
master→variant resolution, add‑to‑cart. **Checkout submission** (`confirm_order`)
is wired and gated but not yet exercised end‑to‑end — a saved shipping/payment
method may need to be applied to the cart first. The Confirm Gate prevents
accidental orders regardless.
TDQS
A3.9/5.0
Scored across 7 tools
Disambiguation5/5
Each tool has a clearly distinct purpose: auth, product search, cart manipulation, and order confirmation. No overlap in functionality.
Naming Consistency5/5
All tools follow a consistent verb_noun snake_case pattern (e.g., add_to_cart, search_products, view_cart), making it easy to predict tool names.
Tool Count5/5
With 7 tools, the set is concise yet covers the essential workflow of an FSA store checkout. No unnecessary tools or missing core actions for the apparent scope.
Completeness4/5
Covers the main flow (auth, search, cart add/view, checkout summary, confirm) but lacks cart modification tools like remove or update quantity, which agents might need.
Maintenance
ActivitySlowing
ResponsivenessSyncing