@datadive-tools/mcp 0.9.0 → 0.10.0
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/README.md +5 -0
- package/dist/index.js +24 -8
- package/dist/index.js.map +1 -1
- package/dist/lib.js +24 -8
- package/dist/lib.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -135,6 +135,11 @@ To skip the per-call confirmation (e.g. in an automated setup), set
|
|
|
135
135
|
`DATADIVE_AUTO_CONFIRM_WRITES=true` in your client config — then these tools run
|
|
136
136
|
without `confirm`.
|
|
137
137
|
|
|
138
|
+
None of the three is **safe to retry** — each call spends tokens again and
|
|
139
|
+
creates a separate dive / re-dive / Rank Radar, even with identical arguments. If
|
|
140
|
+
a call errors or times out, check `get_dive_status` / `list_niches` /
|
|
141
|
+
`list_rank_radars` for what already exists before calling again.
|
|
142
|
+
|
|
138
143
|
Dives are **asynchronous**. `create_niche_dive` returns a `diveId` and an
|
|
139
144
|
estimated completion time immediately; poll `get_dive_status` with that `diveId`
|
|
140
145
|
until it reports `success`, which carries the new `nicheId` you then feed to
|
package/dist/index.js
CHANGED
|
@@ -105,7 +105,7 @@ function extractMessage(body) {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
// package.json
|
|
108
|
-
var version = "0.
|
|
108
|
+
var version = "0.10.0";
|
|
109
109
|
|
|
110
110
|
// src/http/client.ts
|
|
111
111
|
var PKG_VERSION = version;
|
|
@@ -222,21 +222,37 @@ function isObject(v) {
|
|
|
222
222
|
}
|
|
223
223
|
|
|
224
224
|
// src/tools/list-niches.ts
|
|
225
|
+
var LIST_NICHES_MAX_PAGE_SIZE = 50;
|
|
225
226
|
var inputSchema = {
|
|
226
|
-
currentPage: z.number().int().min(1).optional().describe("Page number, 1-indexed. Defaults to 1."),
|
|
227
|
-
pageSize: z.number().int().min(1).max(
|
|
227
|
+
currentPage: z.number().int().min(1).optional().describe("Page number, 1-indexed. Defaults to 1. Keep requesting the next page while `hasNext` is true."),
|
|
228
|
+
pageSize: z.number().int().min(1).max(LIST_NICHES_MAX_PAGE_SIZE).optional().describe(`Items per page (max ${LIST_NICHES_MAX_PAGE_SIZE}). Defaults to 20.`),
|
|
229
|
+
searchText: z.string().trim().min(1).max(200).optional().describe(
|
|
230
|
+
"Case-insensitive partial match on the niche label or hero keyword. Prefer this over paging through everything when the user names a niche."
|
|
231
|
+
),
|
|
232
|
+
searchAsin: z.string().trim().regex(/^[A-Za-z0-9]{10}$/, "must be a 10-character ASIN").optional().describe("Only niches whose competitor set contains this ASIN (10 characters, e.g. B08N5WRWNW)."),
|
|
233
|
+
orderBy: z.enum(["lastDived", "name"]).optional().describe(
|
|
234
|
+
"Sort field: `lastDived` (by latestResearchDate, newest first by default) or `name` (by nicheLabel, A\u2192Z by default). Defaults to `lastDived`."
|
|
235
|
+
),
|
|
236
|
+
sortOrder: z.enum(["ASC", "DESC"]).optional().describe("Sort direction. Defaults to DESC for `lastDived` and ASC for `name`.")
|
|
228
237
|
};
|
|
229
238
|
var listNichesTool = {
|
|
230
239
|
name: "list_niches",
|
|
231
240
|
title: "List DataDive Niches",
|
|
232
|
-
description:
|
|
241
|
+
description: `Use this first when the user asks about their niches, or to find a \`nicheId\` for use with \`get_niche_keywords\`, \`get_niche_competitors\`, or \`get_ranking_juice\`. Retrieves a paginated list of Niches, newest dive first. Each Niche represents a market segment or product category being tracked. Returns nicheId, heroKeyword, nicheLabel, marketplace (com/uk/de/...), and latestResearchDate per niche, plus pagination metadata (currentPage, pageSize, total, lastPage, hasNext, hasPrev). Narrow with \`searchText\` (label/keyword) or \`searchAsin\` (a competitor ASIN) instead of scanning pages; a page holds at most ${LIST_NICHES_MAX_PAGE_SIZE} niches, so the full list of a large account needs several calls.`,
|
|
233
242
|
inputSchema,
|
|
234
243
|
annotations: { readOnlyHint: true },
|
|
235
244
|
handler: async (args, ctx) => {
|
|
236
245
|
return await httpGet(
|
|
237
246
|
{ config: ctx.config, toolName: "list_niches" },
|
|
238
247
|
"/v1/niches",
|
|
239
|
-
{
|
|
248
|
+
{
|
|
249
|
+
currentPage: args.currentPage,
|
|
250
|
+
pageSize: args.pageSize,
|
|
251
|
+
searchText: args.searchText,
|
|
252
|
+
searchAsin: args.searchAsin,
|
|
253
|
+
orderBy: args.orderBy,
|
|
254
|
+
sortOrder: args.sortOrder
|
|
255
|
+
}
|
|
240
256
|
);
|
|
241
257
|
}
|
|
242
258
|
};
|
|
@@ -426,7 +442,7 @@ var inputSchema8 = {
|
|
|
426
442
|
var createRankRadarTool = {
|
|
427
443
|
name: "create_rank_radar",
|
|
428
444
|
title: "Create a Rank Radar",
|
|
429
|
-
description: "Use this to start tracking organic and sponsored keyword rankings for an ASIN within a niche. \u26A0\uFE0F Spends Search Term tokens (cost scales with `numberOfKeywords`) and cannot be undone \u2014 set `confirm: true` only after the user approves the cost. Returns the new `rankRadarId`; read its data later with `get_rank_radar_data`. Requires `asin`, `numberOfKeywords` (min 1), and a `nicheId` from `list_niches`.",
|
|
445
|
+
description: "Use this to start tracking organic and sponsored keyword rankings for an ASIN within a niche. \u26A0\uFE0F Spends Search Term tokens (cost scales with `numberOfKeywords`) and cannot be undone \u2014 set `confirm: true` only after the user approves the cost. Not safe to retry: each call spends tokens again and creates a separate Rank Radar \u2014 if a call errors or times out, check `list_rank_radars` instead of re-calling. Returns the new `rankRadarId`; read its data later with `get_rank_radar_data`. Requires `asin`, `numberOfKeywords` (min 1), and a `nicheId` from `list_niches`.",
|
|
430
446
|
inputSchema: inputSchema8,
|
|
431
447
|
// destructiveHint is technically "additive" here (this creates a new Rank Radar, it
|
|
432
448
|
// doesn't destroy data), but we flag it destructive so clients prompt before the
|
|
@@ -464,7 +480,7 @@ var inputSchema9 = {
|
|
|
464
480
|
var createNicheDiveTool = {
|
|
465
481
|
name: "create_niche_dive",
|
|
466
482
|
title: "Create a Niche Dive",
|
|
467
|
-
description: "Use this to start new niche research from a seed ASIN. \u26A0\uFE0F Spends dive tokens (cost scales with `numberOfCompetitors`) and cannot be undone \u2014 set `confirm: true` only after the user approves the cost. The dive runs asynchronously: this returns immediately with a `diveId` and an `estimatedCompletionDate`. Poll `get_dive_status` with that `diveId` until it reports `success` (which carries the new `nicheId` for use with `list_niches`, `get_niche_keywords`, etc.). Requires `marketplace`, `asin`, and `numberOfCompetitors` (min 2).",
|
|
483
|
+
description: "Use this to start new niche research from a seed ASIN. \u26A0\uFE0F Spends dive tokens (cost scales with `numberOfCompetitors`) and cannot be undone \u2014 set `confirm: true` only after the user approves the cost. Not safe to retry: each call spends tokens again and starts a separate dive \u2014 if a call errors or times out, poll `get_dive_status` (or check `list_niches`) instead of re-calling. The dive runs asynchronously: this returns immediately with a `diveId` and an `estimatedCompletionDate`. Poll `get_dive_status` with that `diveId` until it reports `success` (which carries the new `nicheId` for use with `list_niches`, `get_niche_keywords`, etc.). Requires `marketplace`, `asin`, and `numberOfCompetitors` (min 2).",
|
|
468
484
|
inputSchema: inputSchema9,
|
|
469
485
|
// destructiveHint is technically "additive" here (a dive creates a new niche, it
|
|
470
486
|
// doesn't destroy data), but we flag it destructive so clients prompt before the
|
|
@@ -513,7 +529,7 @@ var inputSchema10 = {
|
|
|
513
529
|
var rediveNicheTool = {
|
|
514
530
|
name: "redive_niche",
|
|
515
531
|
title: "Re-dive an Existing Niche",
|
|
516
|
-
description: "Use this to refresh an existing niche's research with current Amazon data, instead of creating a new niche with `create_niche_dive`. \u26A0\uFE0F Spends dive tokens (one batch per ASIN dived) and cannot be undone \u2014 set `confirm: true` only after the user approves the cost. Two modes: `same_competitors` re-dives the niche's current competitor set (no other argument needed) and `discover` finds a fresh set, sized by `numberOfCompetitors` and steerable with `heroAsin` / `lockedAsins` / `excludedAsins`. Runs asynchronously: returns a `diveId` and an `estimatedCompletionDate` \u2014 poll `get_dive_status` with that `diveId` until it reports `success`. The niche keeps its `nicheId`, so existing rank radars and reports follow the refreshed data.",
|
|
532
|
+
description: "Use this to refresh an existing niche's research with current Amazon data, instead of creating a new niche with `create_niche_dive`. \u26A0\uFE0F Spends dive tokens (one batch per ASIN dived) and cannot be undone \u2014 set `confirm: true` only after the user approves the cost. Not safe to retry: each call spends tokens again and starts a separate re-dive \u2014 if a call errors or times out, poll `get_dive_status` instead of re-calling. Two modes: `same_competitors` re-dives the niche's current competitor set (no other argument needed) and `discover` finds a fresh set, sized by `numberOfCompetitors` and steerable with `heroAsin` / `lockedAsins` / `excludedAsins`. Runs asynchronously: returns a `diveId` and an `estimatedCompletionDate` \u2014 poll `get_dive_status` with that `diveId` until it reports `success`. The niche keeps its `nicheId`, so existing rank radars and reports follow the refreshed data.",
|
|
517
533
|
inputSchema: inputSchema10,
|
|
518
534
|
// Same reasoning as create_niche_dive: a re-dive is additive rather than destructive, but the
|
|
519
535
|
// irreversible token spend is what clients need to prompt on. The confirm gate enforces it regardless.
|