cx-keepa 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/package.json +19 -4
- package/skills/keepa/SKILL.md +23 -0
- package/skills/keepa/references/mcp.md +29 -0
- package/skills/keepa/references/product-file.md +91 -0
- package/skills/keepa/references/raw-routes.md +35 -0
- package/README.md +0 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ComChatX
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/package.json
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cx-keepa",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/HS-Jack-YZY/ComChatX.git",
|
|
8
|
+
"directory": "src/source-packages/cx-keepa"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"pi-package"
|
|
12
|
+
],
|
|
13
|
+
"pi": {
|
|
14
|
+
"skills": [
|
|
15
|
+
"./skills"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
"comchatx": {
|
|
19
|
+
"mcp": "keepa"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: keepa
|
|
3
|
+
description: Amazon product facts from Keepa — current price and price history, coupons, sales rank, monthly sales, offers and Buy Box, listing and release dates — by ASIN or by product name, and a seller's profile by seller id, on Amazon US, UK, DE, FR, JP, CA, IT, ES, IN, MX or BR. Use for any question about a product or a seller on Amazon, including whether a product can be fetched or looked up, before the first data call. Needs cx-sources; if no cx-sources skill is listed, it is not installed, and the seller installs it in Plugins.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Keepa supplies Amazon product facts through `cx`; read cx-sources first. Keepa's own MCP tools are a second way: read [references/mcp.md](references/mcp.md) before calling one. An installed skill is not an enabled source: if Keepa is off, the seller turns its plugin on in Plugins.
|
|
7
|
+
|
|
8
|
+
## Find and fetch
|
|
9
|
+
|
|
10
|
+
Use the marketplace the seller named; if none was named, ask. Buy only an ASIN the seller gave or a search or fetched file shows, competitors and similar products too; search or ask about a recalled one. A product name is a search term: search it, verify the returned product's title and model, and let the seller choose between ambiguous matches.
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
cx raw keepa --method GET --path /search --query domain=1 --query type=product --query 'term=PRODUCT NAME' --query asins-only=1
|
|
14
|
+
cx get amazon/us/ASIN/product --source keepa
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`domain` and the market segment follow the seller's marketplace: `1` us, `2` uk, `3` de, `4` fr, `5` jp, `6` ca, `8` it, `9` es, `10` in, `11` mx, `12` br. Typed paths exist for `amazon/us/<asin>/product` and `amazon/jp/<asin>/product`; other markets use raw `GET /product` with `domain` and one ASIN. Search returns ASINs only and is a separate paid call. A seller is looked up by its id on raw `GET /seller`.
|
|
18
|
+
|
|
19
|
+
Typed requests include history, `stats=90`, `offers=20`, `buybox=1`, `rating=1`; each product path reserves 14 tokens, settling at stated consumption. `latest` accepts a copy up to 1h old. Every raw call reserves 50 tokens, settling likewise; reservations are not charges; tokens are Keepa's meter, not a price. Read the landed file rather than repeating a successful call. `cx raw keepa --record <id> [--part <n>]` reads a kept reply without another purchase. Never name `key`; the gate attaches the credential.
|
|
20
|
+
|
|
21
|
+
## Read the file
|
|
22
|
+
|
|
23
|
+
A product file is one product object from Keepa's `products` array, unchanged; a raw reply carries the whole array under `products`. A fetched product is answered with its facts: current price and coupon, rank in its named category, monthly sales, and listing and release timing. Each is computed by the conversions in [references/product-file.md](references/product-file.md), read before the first fact is stated — never `cat` the file whole; `listedSince` is the earliest listing, not a release date. Before a raw request other than the search above, read [references/raw-routes.md](references/raw-routes.md).
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Keepa's own MCP tools
|
|
2
|
+
|
|
3
|
+
Keepa runs an MCP server, and it is carried here whole: the tools, their descriptions and the token price each description states are Keepa's words. Its tools are named `mcp__keepa__<name>`.
|
|
4
|
+
|
|
5
|
+
## Calling a tool
|
|
6
|
+
|
|
7
|
+
Call a tool from a codemode script, as `await tools.mcp__keepa__<name>({ ... })`; the result arrives whole there. Called directly, outside a script, a tool answers `Tool mcp__keepa__<name> not found`. A script told `tools.mcp__keepa__<name> does not exist` means Keepa's server did not connect when the session started.
|
|
8
|
+
|
|
9
|
+
## Money
|
|
10
|
+
|
|
11
|
+
A call reserves the most its arguments can cost and settles at what the reply states in `apiTokens.consumedByThisCall`. `product_finder_fields` and `get_price_graph` reply without that figure and settle 0 and 1 tokens. A reservation is not a charge.
|
|
12
|
+
|
|
13
|
+
A refusal starting `MCP HTTP request failed with status 402` is the wallet's floor, not Keepa's: the balance is under the call's reservation.
|
|
14
|
+
|
|
15
|
+
Closed on the platform's key, and refused before any spend: `tracking_add`, `tracking_remove`, `tracking_list`, `tracking_get_notifications`, `tracking_set_webhook`. `get_products` by `codes` is refused the same way; look a product up by ASIN.
|
|
16
|
+
|
|
17
|
+
## The two ways to a product
|
|
18
|
+
|
|
19
|
+
| | `cx get amazon/<market>/<asin>/product` | `get_products` |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| Buys | history, statistics, offers, Buy Box and rating, always | the product; Buy Box and offers only when the arguments ask |
|
|
22
|
+
| Settled in the trial | 6 tokens | 1 token |
|
|
23
|
+
| Lands | an observation, cited by its path and reused while fresh | nothing; the reply is the script's result |
|
|
24
|
+
|
|
25
|
+
In the trial the MCP way was faster and cheaper per read, and most of its prompt went to finding the tools.
|
|
26
|
+
|
|
27
|
+
## What the compact reply leaves out
|
|
28
|
+
|
|
29
|
+
`get_products` replies in a compact form that carries `listedSince` and no release date. A release date comes only from `get_products` with `raw: true`, which returns Keepa's product object; read it by the conversions in [product-file.md](product-file.md). A seller is looked up by `get_seller` with its seller id.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Reading a Keepa product file
|
|
2
|
+
|
|
3
|
+
Run these JavaScript conversions on the file's values. UTC is the time basis. `null`, `0` and `-1` are absent field dates, not dates to display; other negative Keepa minutes predate 2011.
|
|
4
|
+
|
|
5
|
+
## Clocks and units
|
|
6
|
+
|
|
7
|
+
Keepa minutes (`listedSince`, `trackingSince`, `lastUpdate`, field-update stamps and history entry times):
|
|
8
|
+
```js
|
|
9
|
+
const keepaDate = n => n == null || n === 0 || n === -1 ? null : new Date((n + 21564000) * 60000).toISOString();
|
|
10
|
+
```
|
|
11
|
+
Packed dates (`releaseDate`, `publicationDate`) keep their stated precision: YYYY, YYYYMM or YYYYMMDD:
|
|
12
|
+
```js
|
|
13
|
+
const calendarDate = n => n == null || n <= 0 ? null : String(n).match(/^\d{4}|\d{2}/g).join('-').replace(/-00.*$/, '');
|
|
14
|
+
```
|
|
15
|
+
The reply's `timestamp` is Unix milliseconds:
|
|
16
|
+
```js
|
|
17
|
+
const replyDate = n => n == null || n <= 0 ? null : new Date(n).toISOString();
|
|
18
|
+
```
|
|
19
|
+
`refillIn` is milliseconds until refill, not days; `refillRate` is tokens per minute:
|
|
20
|
+
```js
|
|
21
|
+
const refillSeconds = n => n == null || n < 0 ? null : n / 1000;
|
|
22
|
+
```
|
|
23
|
+
Prices are minor units, except Japan's whole yen; `0` is a real price/count, `-1` absent, `-2` undetermined:
|
|
24
|
+
```js
|
|
25
|
+
const price = (n, domainId) => n == null || n < 0 ? null : n / (domainId === 5 ? 1 : 100);
|
|
26
|
+
```
|
|
27
|
+
`coupon` is a pair, one-time then subscribe-and-save, with its own sign convention; never pass it to `price` directly:
|
|
28
|
+
```js
|
|
29
|
+
const couponPart = (n, domainId) => n == null || n === 0 ? null : n < 0 ? { percent: -n } : { amount: price(n, domainId) };
|
|
30
|
+
const coupon = (pair, domainId) => pair == null ? null : { oneTime: couponPart(pair[0], domainId), subscribeAndSave: couponPart(pair[1], domainId) };
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`listedSince` is earliest listing, not release. Include listing and release timing in a product summary, stating absent dates plainly. For `releaseDate` `0` or `-1`, say “Keepa has no release date”. `lastUpdate: -1` is read here as no product data — the platform's reading, in no reply kept so far; the sidecar's arithmetic `as_of` is then not a valid observation time. `lastUpdate` records a check, `lastPriceChange` a change; an unchanged price is not stale just because its event is old. The sidecar's `as_of` is Keepa's `lastUpdate`, when Keepa last checked the product; tolerance is measured against `observed_at`, when the platform bought the observation. A newly bought observation need not contain newly checked product data.
|
|
34
|
+
|
|
35
|
+
## History and present state
|
|
36
|
+
|
|
37
|
+
`csv[i]` and `salesRanks[category]` are flat time/value pairs; delivered-price slots and `offerCSV` are time/price/shipping triples. Statistics use the same slot indices; `stats.min[i]` is `null` or time/value. Use Keepa's own statistics (`stats.min`, `stats.max`, `stats.isLowest`, `stats.outOfStockPercentage90`, `stats.salesRankDrops30`, `stats.totalOfferCount`), not recomputed extrema from change-only history. `stats.salesRankDrops30` is `-1` with no rank data; `0` is a real count. `stats.outOfStockPercentage90[i]` is `-1` with too little data or a non-price slot; `0` is never out of stock. Code converts the supplied values and dates; it does not reconstruct a 90-day low. A file without `stats` states the changes it holds, not a computed low. Unknown shipping stays unknown.
|
|
38
|
+
|
|
39
|
+
| Slots | Meaning |
|
|
40
|
+
|---|---|
|
|
41
|
+
| 0, 1, 2, 4, 5, 6, 8, 9, 10, 30, 33 | Amazon, new, used, list, collectible, refurbished, lightning, warehouse, FBA, trade-in, Prime prices |
|
|
42
|
+
| 7, 18, 19–22, 23–26, 27, 28, 29, 32 | FBM, Buy Box, used conditions, collectible conditions, refurbished, eBay new/used, used Buy Box; delivered prices |
|
|
43
|
+
| 3 | reference sales rank; `-1` is no rank at that time, as in `salesRanks[category]` |
|
|
44
|
+
| 11–14, 34, 35 | new/used/refurbished/collectible, FBA/FBM offer counts |
|
|
45
|
+
| 15 | offers fetched; negative means more existed, not absence |
|
|
46
|
+
| 16, 17 | rating in tenths (divide by 10 in code), rating count, not written reviews; `-1` in either is no data at that time, not zero |
|
|
47
|
+
|
|
48
|
+
The terminal entry is current, including a terminal absence. Do not revive a past positive price or a category ending in `-1`. Name rank categories from `categoryTree` where the id appears there; `salesRankReference` is not necessarily the leaf category. Rank drops are not unit sales. `monthlySold` is “at least” that many bought in the past month, not an exact estimate. With no current `monthlySold` there is no badge now, whatever the history held.
|
|
49
|
+
|
|
50
|
+
`couponHistory` is time/one-time/subscribe-and-save triples. An ended coupon means “no coupon now”, not the last discount. A null coupon is no current coupon reported.
|
|
51
|
+
|
|
52
|
+
Only `liveOffersOrder` indices identify current offers. If requested offers failed (`offersSuccessful: false`), their absence proves nothing. A null, `"-1"` or `"-2"` seller id in `stats.buyBoxSellerId` or `buyBoxSellerIdHistory` identifies no seller. Eligible offers are not a Buy Box winner. `stats.buyBoxPrice` is the item's price and `stats.buyBoxShipping` its shipping; `stats.current[18]` is the two together. `availabilityAmazon: -1` means no Amazon offer, not no marketplace offers.
|
|
53
|
+
|
|
54
|
+
Dimensions/weights are millimetres/grams; `0` or `-1` means unavailable. `fbaFees.pickAndPackFee` is money. `productType: 4` is no data; `5` is a variation parent.
|
|
55
|
+
|
|
56
|
+
## Codes
|
|
57
|
+
|
|
58
|
+
These codes describe the field, not the whole marketplace.
|
|
59
|
+
|
|
60
|
+
| Offer `condition` | Meaning |
|
|
61
|
+
|---|---|
|
|
62
|
+
| 0 | unknown |
|
|
63
|
+
| 1 | new |
|
|
64
|
+
| 2 | used, like new |
|
|
65
|
+
| 3 | used, very good |
|
|
66
|
+
| 4 | used, good |
|
|
67
|
+
| 5 | used, acceptable |
|
|
68
|
+
| 6 | refurbished |
|
|
69
|
+
| 7 | collectible, like new |
|
|
70
|
+
| 8 | collectible, very good |
|
|
71
|
+
| 9 | collectible, good |
|
|
72
|
+
| 10 | collectible, acceptable |
|
|
73
|
+
| 11 | rental |
|
|
74
|
+
|
|
75
|
+
| `availabilityAmazon` | Meaning |
|
|
76
|
+
|---|---|
|
|
77
|
+
| -1 | no Amazon offer, not no marketplace offers |
|
|
78
|
+
| 0 | in stock |
|
|
79
|
+
| 1 | preorderable |
|
|
80
|
+
| 2 | unknown |
|
|
81
|
+
| 3 | backorderable |
|
|
82
|
+
| 4 | delayed |
|
|
83
|
+
|
|
84
|
+
| `productType` | Meaning |
|
|
85
|
+
|---|---|
|
|
86
|
+
| 0 | standard |
|
|
87
|
+
| 1 | downloadable |
|
|
88
|
+
| 2 | ebook |
|
|
89
|
+
| 3 | inaccessible: no price, rating or offers data |
|
|
90
|
+
| 4 | no data (invalid or deprecated ASIN) |
|
|
91
|
+
| 5 | variation parent |
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Keepa raw routes
|
|
2
|
+
|
|
3
|
+
`domain`: `1` us, `2` uk, `3` de, `4` fr, `5` jp, `6` ca, `8` it, `9` es, `10` in, `11` mx, `12` br. Other Amazon marketplaces are unavailable here.
|
|
4
|
+
|
|
5
|
+
| Route | Parameters |
|
|
6
|
+
|---|---|
|
|
7
|
+
| `GET /product` | `domain`, `asin` (one ASIN only, never a list); optional `stats`, `update`, `history`, `days`, `offers`, `only-live-offers`, `rating`, `buybox`, `stock`, `aplus`, `videos` |
|
|
8
|
+
| `GET /query` | `domain`, `selection` (finder JSON) |
|
|
9
|
+
| `POST /query` | `domain`; finder selection in the `--body` file |
|
|
10
|
+
| `GET /search` | `domain`, `type=product`, `term`, `asins-only=1`, optional `page` |
|
|
11
|
+
| `GET /seller` | `domain`, `seller`, optional `storefront` |
|
|
12
|
+
| `GET /category` | `domain`, `category`, optional `parents` |
|
|
13
|
+
| `GET /bestsellers` | `domain`, `category`, optional `range` |
|
|
14
|
+
| `GET /deal` | `selection` (deal JSON) |
|
|
15
|
+
| `POST /deal` | deal selection in the `--body` file |
|
|
16
|
+
|
|
17
|
+
Never name `key`; the gate attaches the credential. Admission refusals state the parameter rule before spending. A route outside this table is unavailable. Raw `/product` accepts one ASIN only; typed product asks handle lists. A failed typed request may still name kept replies; `cx raw keepa --record <id> [--part <n>]` reads one back, part 0 first.
|
|
18
|
+
|
|
19
|
+
## Request units
|
|
20
|
+
|
|
21
|
+
`stats` is in days; `update` is in hours; `category` is one category id on `/bestsellers` and up to ten comma-separated ids on `/category`. `update=0` asks for a refresh and may cost one more token.
|
|
22
|
+
|
|
23
|
+
## Retained raw consumption
|
|
24
|
+
|
|
25
|
+
These amounts record past replies, not a price list for future requests. Every raw request reserves 50 tokens; settlement uses the supplier's stated consumption.
|
|
26
|
+
|
|
27
|
+
| Route | Retained consumption |
|
|
28
|
+
|---|---|
|
|
29
|
+
| `/query` finder page | 11 tokens |
|
|
30
|
+
| `/search` | 10 tokens |
|
|
31
|
+
| `/seller` with storefront | 10 tokens |
|
|
32
|
+
| `/bestsellers` | 50 tokens |
|
|
33
|
+
| `/deal` page | 5 tokens |
|
|
34
|
+
|
|
35
|
+
Raw `/product` consumption depends on requested data; do not infer a fixed charge from the raw reservation.
|
package/README.md
DELETED