bow-products-mcp
by SpunBeat
README.md
# bow-products-mcp
MCP server + CLI for Bow Beauty admins (and Claude) to populate, enrich and validate the products catalog without leaving the editor.
The MCP exposes the four admin-only endpoints introduced in the products module overhaul (`/enrich`, `/bulk`, `/import-from-url`, `/test-recommendations`) plus the regular product CRUD endpoints. Authentication is the same Bow Beauty JWT used by the `bow-admin` dashboard — your account must have role `Admin`.
## Requirements
- Node.js ≥ 20.
- An Admin account on a Bow Beauty API.
## Install
```bash
git clone https://github.com/<org>/bow-products-mcp.git
cd bow-products-mcp
npm install
npm run build
npm link # makes the `bow-products-mcp` bin available globally
```
The bin can also be invoked directly via `node /path/to/bow-products-mcp/dist/cli.js …`.
## Commands
| Command | Purpose |
|---|---|
| `bow-products-mcp login` | Interactive login (email + masked password). Persists JWT to `~/.bow-mcp/config.json` chmod 600. Rejects non-Admin accounts. |
| `bow-products-mcp whoami` | Prints the current session (email + API base URL + login timestamp). |
| `bow-products-mcp logout` | Removes the persisted config. |
| `bow-products-mcp run` | Starts the MCP server over stdio. This is what Claude Code invokes. |
| `bow-products-mcp help` | Usage summary. |
### Pointing at a different backend
The default API URL is the Bow Beauty dev backend. Override with the `BOW_API_BASE_URL` env var or `--api-base-url=<url>` flag when logging in:
```bash
BOW_API_BASE_URL=https://my-api.example.com bow-products-mcp login
```
## Wiring into Claude Code
After running `bow-products-mcp login` once, add the server to Claude Code:
```bash
claude mcp add bow-products bow-products-mcp run
```
Then in any Claude Code session you can ask Claude to:
- "Search the catalog for niacinamide serums under $30."
- "Enrich this draft product with brand X."
- "Import this product URL and test how it would rank for an oily-skin profile."
- "Bulk ingest these 12 products."
## MCP tools exposed
### Catalog read
- `search_products({ searchTerm?, category?, brand?, minPrice?, maxPrice?, inStock?, isFeatured?, page?, pageSize? })`
- `get_product({ id })`
### Catalog write (Admin)
- `create_product({ reference, name, description, price, brand, category, ... })`
- `update_product({ id, patch })` — partial update; only the fields in `patch` change.
- `delete_product({ id })`
### AI ingestion (Admin)
- `enrich_product_draft({ name, brand, category, ...hints })` — Gemini-enriched draft, **not persisted**.
- `bulk_ingest({ mode: 'Create' | 'Upsert' | 'EnrichAndCreate', products: [...] })` — max 50 items per call.
- `import_from_url({ url, dryRun })` — fetch + Gemini extract + enrich; persists as `IsActive=false` when `dryRun=false`.
### Test recommendations
- `test_recommendations({ profile, limit?, includeScoreBreakdown? })` — runs the engine against a synthetic user. `profile` accepts `skinType`, `concerns`, `hairTypes`, `colorSeason`, `undertone`, `preferredRoutineStep`, `categories`, `priceRange`, `ethical`. The breakdown surfaces every signal that fired and the points it added.
### Enum surfacing
The `list_*` tools return the valid string values for each enum, so Claude can construct correct inputs without a round-trip:
`list_categories`, `list_concerns`, `list_skin_types`, `list_hair_types`, `list_routine_steps`, `list_formulations`, `list_finishes`, `list_color_seasons`, `list_undertones`, `list_bulk_modes`.
## Auth and refresh
Login decodes the JWT locally just to short-circuit non-admin accounts (rejected with a clear message). The backend remains the authoritative role check on every request.
The HTTP client transparently refreshes the JWT on any `401` (using the persisted refresh token) and retries the request once. If the refresh itself fails, all subsequent tool calls return an error asking you to run `bow-products-mcp login` again.
## Security notes
- The config file is written with `chmod 600` so it is only readable by your user.
- Tokens are never sent to anywhere other than the configured API base URL.
- This is v1: the JWT is stored on disk in plain JSON. If you'd rather use the OS keychain, open an issue.
- Never commit `~/.bow-mcp/config.json` — it's a per-user secret.
## Development
```bash
npm run watch # tsc --watch
npm start # node dist/cli.js help
```
Lint and tests are pending in v1; this package targets a small operational footprint.
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing