{"_id":"@auckland-ai-collective/trundler-mcp","_rev":"6-04562367e4790a7faa94b19a46af8c76","name":"@auckland-ai-collective/trundler-mcp","dist-tags":{"latest":"0.1.12"},"versions":{"0.1.5":{"name":"@auckland-ai-collective/trundler-mcp","version":"0.1.5","author":{"name":"Michael Wells","email":"mike@aaic.nz"},"license":"MIT","_id":"@auckland-ai-collective/trundler-mcp@0.1.5","maintainers":[{"name":"memetican","email":"info@sygnal.com"}],"homepage":"https://github.com/auckland-ai-collective/trundler-mcp#readme","bugs":{"url":"https://github.com/auckland-ai-collective/trundler-mcp/issues"},"bin":{"trundler":"dist/cli.js","trundler-mcp":"dist/index.js"},"dist":{"shasum":"23e9f5f5356f7a5c78cbeaa274588c8871a99bee","tarball":"https://registry.npmjs.org/@auckland-ai-collective/trundler-mcp/-/trundler-mcp-0.1.5.tgz","fileCount":37,"integrity":"sha512-CJLOmeGXOaAAZ4Ag10Oz233UMF3cSsQGmDfPSOt1fUP3TfRPrkldgP+YYgGhrck/BRpqKkuyfQyH9ahvOywovg==","signatures":[{"sig":"MEQCIBaOyIgN3Is/qbrn9Jv4Bi+8lEoeSnIqgwiBW8bih3JsAiBQAyVspr4nS9RPz34m5oBp4KqwfnGDE2vhHANqFknr2w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":80160},"main":"dist/lib.js","type":"module","types":"dist/lib.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/lib.d.ts","import":"./dist/lib.js","default":"./dist/lib.js"},"./package.json":"./package.json"},"gitHead":"737cb0e369b190f911d2b38a124795c5c4cba980","scripts":{"cli":"tsx src/cli.ts","dev":"tsx src/index.ts","build":"tsc","start":"node dist/index.js","typecheck":"tsc --noEmit","prepublishOnly":"npm run typecheck && npm run build"},"_npmUser":{"name":"memetican","email":"info@sygnal.com"},"repository":{"url":"git+https://github.com/auckland-ai-collective/trundler-mcp.git","type":"git"},"_npmVersion":"10.9.2","description":"Local MCP server for grocery shopping providers (Countdown / Woolworths NZ) with browser-assisted login. Runs entirely on your own machine and residential connection. Extensible to other providers.","directories":{},"_nodeVersion":"22.15.0","dependencies":{"zod":"^3.23.8","playwright":"^1.48.0","@modelcontextprotocol/sdk":"^1.12.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.0","typescript":"^5.6.0","@types/node":"^22.7.0"},"_npmOperationalInternal":{"tmp":"tmp/trundler-mcp_0.1.5_1783230024458_0.8821416655288472","host":"s3://npm-registry-packages-npm-production"}},"0.1.6":{"name":"@auckland-ai-collective/trundler-mcp","version":"0.1.6","author":{"name":"Michael Wells","email":"mike@aaic.nz"},"license":"MIT","_id":"@auckland-ai-collective/trundler-mcp@0.1.6","maintainers":[{"name":"memetican","email":"info@sygnal.com"}],"homepage":"https://github.com/auckland-ai-collective/trundler-mcp#readme","bugs":{"url":"https://github.com/auckland-ai-collective/trundler-mcp/issues"},"bin":{"trundler":"dist/cli.js","trundler-mcp":"dist/index.js"},"dist":{"shasum":"9ac679aeeb8be43060106a040a82d31627c95d55","tarball":"https://registry.npmjs.org/@auckland-ai-collective/trundler-mcp/-/trundler-mcp-0.1.6.tgz","fileCount":37,"integrity":"sha512-UZ7bPEKpHhDADduz2DFKvQl6XPt1XLiyksnsOYWmibIeYgerIux1qj1sSm+mDxjW5i3u7WEOOg2umBeqyZWnFA==","signatures":[{"sig":"MEQCIGzcwPDUHqvgEgBomSnB01H27uHqkr6Ts1bCLftRV798AiB4PlCvBiVkwk940v6wS5Tl4Ye53+9aA24XGQVPlu6Irg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":81050},"main":"dist/lib.js","type":"module","types":"dist/lib.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/lib.d.ts","import":"./dist/lib.js","default":"./dist/lib.js"},"./package.json":"./package.json"},"gitHead":"2ea7b3cd04333a6f2b326310575411a3ae6a4e36","scripts":{"cli":"tsx src/cli.ts","dev":"tsx src/index.ts","build":"tsc","start":"node dist/index.js","typecheck":"tsc --noEmit","prepublishOnly":"npm run typecheck && npm run build"},"_npmUser":{"name":"memetican","email":"info@sygnal.com"},"repository":{"url":"git+https://github.com/auckland-ai-collective/trundler-mcp.git","type":"git"},"_npmVersion":"10.9.2","description":"Local MCP server for grocery shopping providers (Countdown / Woolworths NZ) with browser-assisted login. Runs entirely on your own machine and residential connection. Extensible to other providers.","directories":{},"_nodeVersion":"22.15.0","dependencies":{"zod":"^3.23.8","playwright":"^1.48.0","@modelcontextprotocol/sdk":"^1.12.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.0","typescript":"^5.6.0","@types/node":"^22.7.0"},"_npmOperationalInternal":{"tmp":"tmp/trundler-mcp_0.1.6_1783372358400_0.33014709123766095","host":"s3://npm-registry-packages-npm-production"}},"0.1.8":{"name":"@auckland-ai-collective/trundler-mcp","version":"0.1.8","author":{"name":"Michael Wells","email":"mike@aaic.nz"},"license":"MIT","_id":"@auckland-ai-collective/trundler-mcp@0.1.8","maintainers":[{"name":"memetican","email":"info@sygnal.com"}],"homepage":"https://github.com/auckland-ai-collective/trundler-mcp#readme","bugs":{"url":"https://github.com/auckland-ai-collective/trundler-mcp/issues"},"bin":{"trundler":"dist/cli.js","trundler-mcp":"dist/index.js"},"dist":{"shasum":"810d7e09ef8962368210d80736af07fe20134bfe","tarball":"https://registry.npmjs.org/@auckland-ai-collective/trundler-mcp/-/trundler-mcp-0.1.8.tgz","fileCount":37,"integrity":"sha512-9S63KJ9LfRpBvx7Cle4Fo7eT0so+HbiPR/CFOPCFpaSu2BTsC9wxYcJ1ZuJkmXaW02FjUC+PIsomb+wW3MR0yg==","signatures":[{"sig":"MEUCIQCGGz9xrKQCgNzc/v2MHwmje+Lj8I5vTquPjrKYRvVz2AIgUNHZxvrc0EPbfDZgoNjrhVTTSNlkIr/c4eoGfEgEQd8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":82429},"main":"dist/lib.js","type":"module","types":"dist/lib.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/lib.d.ts","import":"./dist/lib.js","default":"./dist/lib.js"},"./package.json":"./package.json"},"gitHead":"3ab5bd681b78cd3d5b8ecf29e43e54b037a5b3a6","scripts":{"cli":"tsx src/cli.ts","dev":"tsx src/index.ts","build":"tsc","start":"node dist/index.js","typecheck":"tsc --noEmit","prepublishOnly":"npm run typecheck && npm run build"},"_npmUser":{"name":"memetican","email":"info@sygnal.com"},"repository":{"url":"git+https://github.com/auckland-ai-collective/trundler-mcp.git","type":"git"},"_npmVersion":"10.9.2","description":"Local MCP server for grocery shopping providers (Countdown / Woolworths NZ) with browser-assisted login. Runs entirely on your own machine and residential connection. Extensible to other providers.","directories":{},"_nodeVersion":"22.15.0","dependencies":{"zod":"^3.23.8","playwright":"^1.48.0","@modelcontextprotocol/sdk":"^1.12.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.0","typescript":"^5.6.0","@types/node":"^22.7.0"},"_npmOperationalInternal":{"tmp":"tmp/trundler-mcp_0.1.8_1783408900507_0.6609503765692843","host":"s3://npm-registry-packages-npm-production"}},"0.1.10":{"name":"@auckland-ai-collective/trundler-mcp","version":"0.1.10","author":{"name":"Michael Wells","email":"mike@aaic.nz"},"license":"MIT","_id":"@auckland-ai-collective/trundler-mcp@0.1.10","maintainers":[{"name":"memetican","email":"info@sygnal.com"}],"homepage":"https://github.com/auckland-ai-collective/trundler-mcp#readme","bugs":{"url":"https://github.com/auckland-ai-collective/trundler-mcp/issues"},"bin":{"trundler":"dist/cli.js","trundler-mcp":"dist/index.js"},"dist":{"shasum":"f02d4424dd5880b9e34e4b312a0175f7a35bcda4","tarball":"https://registry.npmjs.org/@auckland-ai-collective/trundler-mcp/-/trundler-mcp-0.1.10.tgz","fileCount":37,"integrity":"sha512-s8SDNUcQP1F8VFoy274eSZHqeUzSyO+j9thQbZU6OTeC6Ae793DE1WjN20Uwvv2Zy3REEQqc7nCf8uzdtGzfSg==","signatures":[{"sig":"MEUCIQCJnys5ZAvxYFo0rcpqkuLpzUC/uUrxKWjneUHUcllUUQIgRc8FBmQ6F/pJD611s85/Gb9oYowE0drS/qDCv/x0O1A=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":85974},"main":"dist/lib.js","type":"module","types":"dist/lib.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/lib.d.ts","import":"./dist/lib.js","default":"./dist/lib.js"},"./package.json":"./package.json"},"gitHead":"e06ff32855bb1c0c1fa8c9b16a6ea0362f52c0d2","scripts":{"cli":"tsx src/cli.ts","dev":"tsx src/index.ts","build":"tsc","start":"node dist/index.js","typecheck":"tsc --noEmit","prepublishOnly":"npm run typecheck && npm run build"},"_npmUser":{"name":"memetican","email":"info@sygnal.com"},"repository":{"url":"git+https://github.com/auckland-ai-collective/trundler-mcp.git","type":"git"},"_npmVersion":"10.9.2","description":"Local MCP server for grocery shopping providers (Countdown / Woolworths NZ) with browser-assisted login. Runs entirely on your own machine and residential connection. Extensible to other providers.","directories":{},"_nodeVersion":"22.15.0","dependencies":{"zod":"^3.23.8","playwright":"^1.48.0","@modelcontextprotocol/sdk":"^1.12.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.0","typescript":"^5.6.0","@types/node":"^22.7.0"},"_npmOperationalInternal":{"tmp":"tmp/trundler-mcp_0.1.10_1784445448335_0.3685205972656138","host":"s3://npm-registry-packages-npm-production"}},"0.1.11":{"name":"@auckland-ai-collective/trundler-mcp","version":"0.1.11","author":{"name":"Michael Wells","email":"mike@aaic.nz"},"license":"MIT","_id":"@auckland-ai-collective/trundler-mcp@0.1.11","maintainers":[{"name":"memetican","email":"info@sygnal.com"}],"homepage":"https://github.com/auckland-ai-collective/trundler-mcp#readme","bugs":{"url":"https://github.com/auckland-ai-collective/trundler-mcp/issues"},"bin":{"trundler":"dist/cli.js","trundler-mcp":"dist/index.js"},"dist":{"shasum":"47e91f7c65ccfb847c2ad8144dea7c4cc7fe91ca","tarball":"https://registry.npmjs.org/@auckland-ai-collective/trundler-mcp/-/trundler-mcp-0.1.11.tgz","fileCount":39,"integrity":"sha512-ar1rVbiETFO3fX0SAgRTmSsbesMVyiYVSRXsWxoBcVi9CTEWRTT42+dC9Jn7+3HFjaYvCfKNPdSFxqUCjBrRXA==","signatures":[{"sig":"MEUCIQDPd2zgXrXA67l+lGMzob9hWwPrni5zN6+5lXj2s512mAIgCOMeF/OWAzXce9deBOV4GaJCjz56SdXse19i802XiG0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":109515},"main":"dist/lib.js","type":"module","types":"dist/lib.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/lib.d.ts","import":"./dist/lib.js","default":"./dist/lib.js"},"./package.json":"./package.json"},"gitHead":"4fdca61ba373e82c0a52fe81b6392b14a94a650f","scripts":{"cli":"tsx src/cli.ts","dev":"tsx src/index.ts","build":"tsc","start":"node dist/index.js","typecheck":"tsc --noEmit","prepublishOnly":"npm run typecheck && npm run build"},"_npmUser":{"name":"memetican","email":"info@sygnal.com"},"repository":{"url":"git+https://github.com/auckland-ai-collective/trundler-mcp.git","type":"git"},"_npmVersion":"10.9.2","description":"Local MCP server for grocery shopping providers (Countdown / Woolworths NZ) with browser-assisted login. Runs entirely on your own machine and residential connection. Extensible to other providers.","directories":{},"_nodeVersion":"22.15.0","dependencies":{"zod":"^3.23.8","playwright":"^1.48.0","@modelcontextprotocol/sdk":"^1.12.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.0","typescript":"^5.6.0","@types/node":"^22.7.0"},"_npmOperationalInternal":{"tmp":"tmp/trundler-mcp_0.1.11_1788772238207_0.9809619360262158","host":"s3://npm-registry-packages-npm-production"}},"0.1.12":{"name":"@auckland-ai-collective/trundler-mcp","version":"0.1.12","description":"Local MCP server for grocery shopping providers (Countdown / Woolworths NZ) with browser-assisted login. Runs entirely on your own machine and residential connection. Extensible to other providers.","type":"module","author":{"name":"Michael Wells","email":"mike@aaic.nz"},"license":"MIT","publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/auckland-ai-collective/trundler-mcp.git"},"homepage":"https://github.com/auckland-ai-collective/trundler-mcp#readme","bugs":{"url":"https://github.com/auckland-ai-collective/trundler-mcp/issues"},"main":"dist/lib.js","types":"dist/lib.d.ts","exports":{".":{"types":"./dist/lib.d.ts","import":"./dist/lib.js","default":"./dist/lib.js"},"./package.json":"./package.json"},"bin":{"trundler-mcp":"dist/index.js","trundler":"dist/cli.js"},"scripts":{"build":"tsc","start":"node dist/index.js","dev":"tsx src/index.ts","cli":"tsx src/cli.ts","typecheck":"tsc --noEmit","prepublishOnly":"npm run typecheck && npm run build"},"dependencies":{"@modelcontextprotocol/sdk":"^1.12.0","playwright":"^1.48.0","zod":"^3.23.8"},"devDependencies":{"@types/node":"^22.7.0","tsx":"^4.19.0","typescript":"^5.6.0"},"engines":{"node":">=20"},"_id":"@auckland-ai-collective/trundler-mcp@0.1.12","gitHead":"e68034e685e8cc4cee15919ff0299468acdcb937","_nodeVersion":"22.15.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-3xSN42DCRmxotKZvm3dc82R5zVgP3d8xqQZ70Hqq56ZhKsFvl5/EEWUczwkvF6YAtLUN3UjqXNlCvduVOMlM5Q==","shasum":"e915a04e6305314ccc5cd07ba1f84670c14ca04e","tarball":"https://registry.npmjs.org/@auckland-ai-collective/trundler-mcp/-/trundler-mcp-0.1.12.tgz","fileCount":39,"unpackedSize":109888,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIBSzKPl3VUosWMzaCGCkSM2Wubcznex1q51jcUNKWIh1AiEAqFJ0mmFxB4Ql7AOIQuMsH1WaxHvEb9cds5YxNkbSeiY="}]},"_npmUser":{"name":"memetican","email":"info@sygnal.com"},"directories":{},"maintainers":[{"name":"memetican","email":"info@sygnal.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/trundler-mcp_0.1.12_1788773467114_0.7500389121053406"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-05T05:40:24.254Z","modified":"2026-09-07T09:31:08.467Z","0.1.5":"2026-07-05T05:40:24.610Z","0.1.6":"2026-07-06T21:12:38.548Z","0.1.8":"2026-07-07T07:21:40.651Z","0.1.10":"2026-07-19T07:17:28.446Z","0.1.11":"2026-09-07T09:10:38.327Z","0.1.12":"2026-09-07T09:31:07.257Z"},"bugs":{"url":"https://github.com/auckland-ai-collective/trundler-mcp/issues"},"author":{"name":"Michael Wells","email":"mike@aaic.nz"},"license":"MIT","homepage":"https://github.com/auckland-ai-collective/trundler-mcp#readme","repository":{"type":"git","url":"git+https://github.com/auckland-ai-collective/trundler-mcp.git"},"description":"Local MCP server for grocery shopping providers (Countdown / Woolworths NZ) with browser-assisted login. Runs entirely on your own machine and residential connection. Extensible to other providers.","maintainers":[{"name":"memetican","email":"info@sygnal.com"}],"readme":"# trundler-mcp\n\n[![npm version](https://img.shields.io/npm/v/@auckland-ai-collective/trundler-mcp.svg)](https://www.npmjs.com/package/@auckland-ai-collective/trundler-mcp)\n[![npm downloads](https://img.shields.io/npm/dm/@auckland-ai-collective/trundler-mcp.svg)](https://www.npmjs.com/package/@auckland-ai-collective/trundler-mcp)\n[![license](https://img.shields.io/npm/l/@auckland-ai-collective/trundler-mcp.svg)](./LICENSE)\n\nA **local** MCP server for grocery shopping. Runs entirely on your own machine and\nresidential connection — no cloud services, no datacenter IPs, no bot-detection\nlogistics.\n\n> **Published on npm:** [`@auckland-ai-collective/trundler-mcp`](https://www.npmjs.com/package/@auckland-ai-collective/trundler-mcp)\n> (repo `trundler-mcp`). Install with `npm install @auckland-ai-collective/trundler-mcp`\n> or run it straight away with `npx @auckland-ai-collective/trundler-mcp`.\n>\n> The running server, its tools, and the on-disk session folder keep the shorter name\n> **`trundler`** (the MCP server id is `trundler`, sessions live under `…/trundler/`).\n\nSupported providers:\n\n- **Countdown / Woolworths NZ** — full account access (login + cart + order history)\n- **New World** (Foodstuffs) — anonymous price/product browsing\n- **Pak'nSave** (Foodstuffs) — anonymous price/product browsing\n\n## Providers at a glance\n\nDifferent chains expose different things, so trundler's capabilities vary by provider.\n\n| Provider | id | Login | Add to cart | Search / specials / browse | Store selection |\n|----------|-----|:-----:|:-----------:|:--------------------------:|-----------------|\n| Countdown / Woolworths NZ | `countdown` | **Required** (browser) | ✅ Yes | ✅ (after login) | Automatic (by fulfilment region) |\n| New World | `newworld` | Not required | ❌ No (read-only) | ✅ (anonymous) | **Per-store** — pick one with `set_store` |\n| Pak'nSave | `paknsave` | Not required | ❌ No (read-only) | ✅ (anonymous) | **Per-store** — pick one with `set_store` |\n\nIn short:\n\n- **Countdown / Woolworths** — you log in once in a real browser; after that you can\n  search, view specials, and **add items to a real cart** and read your order history.\n- **New World & Pak'nSave** — **no login needed** to search and compare prices, but\n  they are **read-only**: you cannot add to a cart or see order history (yet). Because\n  Foodstuffs pricing is per-store, you must choose a store first with `set_store`.\n\n> **Why the difference?** Countdown authenticates a real user session, which unlocks\n> the cart. The Foodstuffs (New World / Pak'nSave) read APIs serve anonymous guests,\n> so browsing needs no login — but the cart requires an authenticated session that\n> isn't wired up yet (see [Roadmap](#roadmap)).\n\n## How it works\n\nEverything lives in one local process over **stdio** — the agent launches trundler\nas a subprocess. No ports, no CORS, no session server. There are two auth models\ndepending on the provider:\n\n**Countdown / Woolworths — browser-assisted login**\n\n- `login` opens a real browser window; you sign in yourself (handling any\n  MFA/captcha), and trundler captures the session. **No password is stored.** Because\n  the login happens in a real browser on your home connection, it's the most\n  bot-resistant approach.\n- After the session is captured the window **stays open** so you can accept Chrome's\n  \"Save password?\" prompt, then close it yourself to finish (a 2-minute fallback\n  closes it if you walk away). Set `TRUNDLER_LOGIN_AUTOCLOSE=1` to close immediately\n  on capture instead, or `TRUNDLER_LOGIN_KEEP_OPEN_MS` to change the fallback timeout.\n- Sign-in itself is Auth0 Universal Login (OIDC): the browser lands on\n  `auth.woolworths.co.nz`, then returns through `/auth/callback?code=…` which\n  exchanges the code for the session cookies trundler captures.\n- Everything after that is authenticated `fetch()` using the captured cookies — no\n  browser needed. Account data (cart, orders) goes to the site's GraphQL gateway;\n  product search, specials and browse still use the older REST endpoints.\n- The session is a **sliding** window: the gateway reissues its cookies on nearly\n  every response, so trundler folds each response's `Set-Cookie` back into the\n  stored session rather than replaying a frozen copy.\n- **Silent refresh** renews the session by briefly relaunching a headless browser\n  with the saved profile. A request that comes back unauthenticated triggers one\n  refresh and retry; if the session has fully expired, tools tell the agent to run\n  `login` again.\n\n**New World / Pak'nSave — anonymous guest token**\n\n- No login. trundler mints an anonymous guest token by loading the store homepage and\n  reading the session cookie it hands out, then calls the read API with plain\n  `fetch()`. The token is cached and refreshed automatically (~30-minute life).\n- The homepage sits behind Cloudflare bot-management that rejects Node's `fetch`, so\n  the token mint shells out to **`curl`** (which passes). `curl` ships with Windows 10\n  1803+, macOS, and Linux — no extra install needed on a normal machine.\n- Pricing is **per-store**: use `list_stores` to find one and `set_store` to select\n  it. Your choice is persisted per provider.\n\nSession/config data is stored per provider outside the repo:\n\n- Windows: `%LOCALAPPDATA%\\trundler\\<provider>\\`\n- macOS/Linux: `~/.config/trundler/<provider>/`\n\n## Install\n\nFrom npm (no build step needed — ships compiled):\n\n```bash\nnpm install @auckland-ai-collective/trundler-mcp\n```\n\nOr run the server directly without installing:\n\n```bash\nnpx @auckland-ai-collective/trundler-mcp\n```\n\nChromium (used **only** for the Countdown login) is **not** downloaded at install\ntime. The first time you run `login`, trundler fetches it once (~150 MB) if it's\nmissing — so merely depending on the package stays lightweight, and New World /\nPak'nSave (which never need a browser) pull nothing extra. To pre-fetch it yourself:\n`npx playwright install chromium`.\n\nBuilding from source instead:\n\n```bash\nnpm install\nnpm run build\n```\n\n## Register with your agent\n\nAdd to your MCP config (e.g. `.mcp.json`). The simplest form runs the published\nserver straight from npm — no clone, no build:\n\n```json\n{\n  \"mcpServers\": {\n    \"trundler\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@auckland-ai-collective/trundler-mcp\"]\n    }\n  }\n}\n```\n\nOr point at a local build:\n\n```json\n{\n  \"mcpServers\": {\n    \"trundler\": {\n      \"command\": \"node\",\n      \"args\": [\"D:/Projects/MCP/trundler-mcp/dist/index.js\"]\n    }\n  }\n}\n```\n\nDuring development you can point it at the TypeScript source instead:\n\n```json\n{\n  \"mcpServers\": {\n    \"trundler\": {\n      \"command\": \"npx\",\n      \"args\": [\"tsx\", \"D:/Projects/MCP/trundler-mcp/src/index.ts\"]\n    }\n  }\n}\n```\n\n> After changing server-level code (including the presentation instructions), rebuild\n> (`npm run build`) and **reconnect** the MCP — instructions and tool lists are sent\n> once at connection time.\n\n## Use as a library\n\nIf you're embedding trundler in your own app (e.g. a shell that mounts the MCP\nserver in-process rather than spawning it), import from the package root. This entry\npoint has **no side effects** — importing it starts nothing:\n\n```ts\nimport {\n  buildServer,        // -> McpServer, ready to .connect(transport)\n  buildRegistry,      // -> ProviderRegistry of all providers\n  DEFAULT_PROVIDER,   // -> \"countdown\"\n} from '@auckland-ai-collective/trundler-mcp';\n\n// Mount on your own transport:\nconst server = buildServer();\nawait server.connect(myTransport);\n\n// …or drive a provider directly, bypassing MCP entirely:\nconst cart = await buildRegistry().get('countdown').cartGet();\n```\n\nTypes (`ShoppingProvider`, `Cart`, `Product`, …) are exported too. The package ships\nits own `.d.ts` declarations. Prefer spawning the process instead? The published\n`trundler-mcp` bin is the stdio server; `trundler` is the setup CLI (below).\n\n## Setup per provider\n\n**Countdown / Woolworths** — log in once:\n\n```bash\ntrundler login             # installed package (bin)\n# or, from a source checkout:\nnpm run cli login          # or: node dist/cli.js login   (after build)\n```\n\nA browser window opens — sign in to Woolworths. Once the session is captured the\nwindow stays open so you can save your password if prompted; close it to finish.\nVerify any time with `trundler check` (or `npm run cli check`). The first `login`\nalso downloads Chromium once if it isn't already present.\n\n**New World / Pak'nSave** — no login; just pick a store. Via your agent:\n\n```\nlist_stores  { \"provider\": \"newworld\", \"query\": \"auckland\" }\nset_store    { \"provider\": \"newworld\", \"storeId\": \"<id from list_stores>\" }\n```\n\nDo the same with `\"provider\": \"paknsave\"` for Pak'nSave. Until a store is set, the\nread tools return a \"no store selected\" error.\n\nFor local testing you can pre-seed a store via env var instead of `set_store`:\n`TRUNDLER_NEWWORLD_STORE_ID` / `TRUNDLER_PAKNSAVE_STORE_ID`. These are test overrides\nonly — never a shipped default.\n\n## Tools\n\nEvery tool takes an optional `provider` argument (default: `countdown`).\n\n| Tool | Purpose | Providers |\n|------|---------|-----------|\n| `search_products` | Search by keyword | all |\n| `get_specials` | Current specials (paginated) | all |\n| `browse_products` | Browse by department / category | all |\n| `list_stores` | List a provider's stores (per-store-pricing providers) | newworld, paknsave |\n| `set_store` | Select the active store (persisted) | newworld, paknsave |\n| `login` | Open a browser to sign in | countdown |\n| `check_login` | Verify the stored session | countdown |\n| `logout` | End the session (clears in-memory cache + on-disk tokens) | countdown |\n| `cart_get` / `cart_add` / `cart_update` / `cart_remove` | Manage the cart | countdown |\n| `list_past_orders` / `list_past_order_items` / `get_order_items` | Order history | countdown |\n\nCalling a login/cart/order tool on New World or Pak'nSave returns a clear\n\"requires login — not yet supported\" error rather than failing silently.\n\n## Product listings\n\ntrundler ships server-level instructions telling the agent how to present product\nlists: label each item with a capital letter (A, B, C…) for easy quantity-picking,\nshow **price per unit** and sort cheapest-per-unit first, and include a link to open\neach product's photo/detail page. This makes cross-product and cross-chain price\ncomparison straightforward.\n\n## Adding a provider\n\nImplement `ShoppingProvider` (see `src/core/provider.ts`) in a new\n`src/providers/<name>/` folder and register it in `src/providers/index.ts`. The MCP\ntools are provider-agnostic and dispatch automatically. Foodstuffs banners (New\nWorld, Pak'nSave) share one `FoodstuffsProvider` parameterised by a banner config —\nadding another Foodstuffs banner is a few lines in `src/providers/foodstuffs/banners.ts`.\n\nCapabilities a provider doesn't support (e.g. cart on a read-only provider) simply\nthrow an error, which surfaces to the agent as a tool error.\n\n## Roadmap\n\n- **Foodstuffs cart & orders (Tier 2).** New World / Pak'nSave cart and order history\n  need an authenticated session. Their login exchange is Cloudflare-protected against\n  automated browsers, so it must be captured from a genuine browser (connect to your\n  real Chrome), not Playwright's bundled Chromium. Not yet implemented.\n\n## Trade-off\n\ntrundler refreshes on demand, not on a schedule — for Countdown it can't renew tokens\nwhile your machine is off, and an expired session needs a quick manual `login`. That's\nthe cost of staying local and on a residential IP. If you later need unattended\nscheduled runs, host it on an always-on machine at home (not a datacenter, or you\nreintroduce the bot-detection problem).\n","readmeFilename":"README.md"}