@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/dist/lib.js CHANGED
@@ -100,7 +100,7 @@ function extractMessage(body) {
100
100
  }
101
101
 
102
102
  // package.json
103
- var version = "0.9.0";
103
+ var version = "0.10.0";
104
104
 
105
105
  // src/http/client.ts
106
106
  var PKG_VERSION = version;
@@ -217,21 +217,37 @@ function isObject(v) {
217
217
  }
218
218
 
219
219
  // src/tools/list-niches.ts
220
+ var LIST_NICHES_MAX_PAGE_SIZE = 50;
220
221
  var inputSchema = {
221
- currentPage: z.number().int().min(1).optional().describe("Page number, 1-indexed. Defaults to 1."),
222
- pageSize: z.number().int().min(1).max(100).optional().describe("Items per page (max 100). Defaults to 20.")
222
+ currentPage: z.number().int().min(1).optional().describe("Page number, 1-indexed. Defaults to 1. Keep requesting the next page while `hasNext` is true."),
223
+ 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.`),
224
+ searchText: z.string().trim().min(1).max(200).optional().describe(
225
+ "Case-insensitive partial match on the niche label or hero keyword. Prefer this over paging through everything when the user names a niche."
226
+ ),
227
+ 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)."),
228
+ orderBy: z.enum(["lastDived", "name"]).optional().describe(
229
+ "Sort field: `lastDived` (by latestResearchDate, newest first by default) or `name` (by nicheLabel, A\u2192Z by default). Defaults to `lastDived`."
230
+ ),
231
+ sortOrder: z.enum(["ASC", "DESC"]).optional().describe("Sort direction. Defaults to DESC for `lastDived` and ASC for `name`.")
223
232
  };
224
233
  var listNichesTool = {
225
234
  name: "list_niches",
226
235
  title: "List DataDive Niches",
227
- 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. 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).",
236
+ 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.`,
228
237
  inputSchema,
229
238
  annotations: { readOnlyHint: true },
230
239
  handler: async (args, ctx) => {
231
240
  return await httpGet(
232
241
  { config: ctx.config, toolName: "list_niches" },
233
242
  "/v1/niches",
234
- { currentPage: args.currentPage, pageSize: args.pageSize }
243
+ {
244
+ currentPage: args.currentPage,
245
+ pageSize: args.pageSize,
246
+ searchText: args.searchText,
247
+ searchAsin: args.searchAsin,
248
+ orderBy: args.orderBy,
249
+ sortOrder: args.sortOrder
250
+ }
235
251
  );
236
252
  }
237
253
  };
@@ -421,7 +437,7 @@ var inputSchema8 = {
421
437
  var createRankRadarTool = {
422
438
  name: "create_rank_radar",
423
439
  title: "Create a Rank Radar",
424
- 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`.",
440
+ 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`.",
425
441
  inputSchema: inputSchema8,
426
442
  // destructiveHint is technically "additive" here (this creates a new Rank Radar, it
427
443
  // doesn't destroy data), but we flag it destructive so clients prompt before the
@@ -459,7 +475,7 @@ var inputSchema9 = {
459
475
  var createNicheDiveTool = {
460
476
  name: "create_niche_dive",
461
477
  title: "Create a Niche Dive",
462
- 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).",
478
+ 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).",
463
479
  inputSchema: inputSchema9,
464
480
  // destructiveHint is technically "additive" here (a dive creates a new niche, it
465
481
  // doesn't destroy data), but we flag it destructive so clients prompt before the
@@ -508,7 +524,7 @@ var inputSchema10 = {
508
524
  var rediveNicheTool = {
509
525
  name: "redive_niche",
510
526
  title: "Re-dive an Existing Niche",
511
- 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.",
527
+ 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.",
512
528
  inputSchema: inputSchema10,
513
529
  // Same reasoning as create_niche_dive: a re-dive is additive rather than destructive, but the
514
530
  // irreversible token spend is what clients need to prompt on. The confirm gate enforces it regardless.