@nooticr/mcp 1.26.78 → 1.26.79
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
CHANGED
|
@@ -52,7 +52,7 @@ npx @nooticr/mcp login # one-time sign-in (Google)
|
|
|
52
52
|
|
|
53
53
|
## Tools
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
119 tools, grouped by what you are trying to do. Prices are in nooticr credits and
|
|
56
56
|
match what the server actually charges.
|
|
57
57
|
|
|
58
58
|
The job tools under **Answer a question you actually have** are not
|
|
@@ -168,6 +168,7 @@ a `scanId` for the rest.
|
|
|
168
168
|
| `get_amazon_product` | 3 | One listing by ASIN or URL: price, rating, the full star histogram, features, specs, Amazon's review digest and aspect breakdown, and the reviews. |
|
|
169
169
|
| `scan_marketplace_category` | 3 per product collected (30 by default) | The same category read on eleven more sites — AliExpress, Cdiscount, Flipkart, Mercado Libre, Lazada, Otto, Rakuten, Trendyol, Jumia, Vinted and Temu. Vinted is resale rather than retail, so its `rating` describes the seller and the scan says so in `ratingScope` — do not read it as a product's reviews. `marketplace` picks the site; `market` picks the storefront for the sites that have several, and the argument names the real set per site so a model cannot send Otto a Lazada region. Same rollup, same confirmation before spending. |
|
|
170
170
|
| `marketplace_scan_status` | free | Picks a running marketplace collection back up by `scanId` and the same `marketplace`. Free, for the same reason `amazon_scan_status` is. |
|
|
171
|
+
| `get_price_history` | free | One product's `price` over time, or its `rating`, `reviewCount` or `availability` with `metric`, from the observations stored each time it was scanned. `marketplace` and `id` name it as `get_marketplace_product` does; `from`/`to` default to the last 30 days. Returns the points oldest first with min, max, first, last and the change from first to last. Reads stored data only; a product never scanned answers `recorded: false`. |
|
|
171
172
|
| `marketplace_changes` | free | What moved in a category since the previous scan of the same `marketplace` and `query`: products that entered or left the results and ones whose price or place changed. Read from the two latest stored scans, so it fetches nothing; a category scanned once says it has no earlier run. |
|
|
172
173
|
| `get_marketplace_product` | 3 | One product from any of the twelve sites, by id or URL: price, rating, the full star histogram, specs and the reviews. |
|
|
173
174
|
| `show_amazon_category_insights` | free | Draws the read **your model** wrote — purchase drivers, barriers, what each brand does well, the gaps, the positioning angles — beside the listings and their reviews, so a person can click a product and check any claim against the text it came from. The conclusions are attributed to your model, never presented as a nooticr rating of anyone's product. Given the `scanId`, it re-reads the listings from the scan itself (free) instead of drawing whatever the model re-sends, and flags any ASIN the read cites that the scan does not contain; without one, the card says its listings were not checked. |
|
|
@@ -438,6 +438,7 @@ export const LOADING_PLANS = {
|
|
|
438
438
|
},
|
|
439
439
|
// Free: reads two stored scans, fetches nothing.
|
|
440
440
|
marketplace_changes: { label: "Comparing the two scans", kind: "list", n: 6, steps: [], free: true },
|
|
441
|
+
get_price_history: { label: "Reading the stored price history", kind: "text", n: 1, steps: [], free: true },
|
|
441
442
|
get_marketplace_product: {
|
|
442
443
|
label: "Reading the product",
|
|
443
444
|
kind: "text",
|
|
@@ -439,6 +439,53 @@ export function registerMarketplaceTools(server, makeClient) {
|
|
|
439
439
|
return toolError("marketplace_changes failed", err);
|
|
440
440
|
}
|
|
441
441
|
});
|
|
442
|
+
server.registerTool("get_price_history", {
|
|
443
|
+
title: "Get Price History",
|
|
444
|
+
description: "One product's price over time — or its rating, review count or availability with `metric` — " +
|
|
445
|
+
"from the observations stored each time the product was scanned. `marketplace` and `id` name " +
|
|
446
|
+
"the product the same way get_marketplace_product does; `from` and `to` take dates (default: " +
|
|
447
|
+
"the last 30 days). Returns the points oldest first with min, max, first, last and the " +
|
|
448
|
+
"percentage change from first to last. A point is stored only when something changed, so the " +
|
|
449
|
+
"last value held until `lastSeenAt`. Reads stored data only: it never fetches, and a product " +
|
|
450
|
+
"nobody has scanned yet says so (`recorded: false`) — run get_marketplace_product once to " +
|
|
451
|
+
"start its record. Free.",
|
|
452
|
+
annotations: {
|
|
453
|
+
readOnlyHint: true,
|
|
454
|
+
destructiveHint: false,
|
|
455
|
+
idempotentHint: true,
|
|
456
|
+
openWorldHint: false,
|
|
457
|
+
},
|
|
458
|
+
outputSchema: OUTPUT_SCHEMAS.get_price_history,
|
|
459
|
+
inputSchema: z
|
|
460
|
+
.object({
|
|
461
|
+
marketplace: marketplaceArg,
|
|
462
|
+
id: z.string().describe("The site's own product id, or a product URL from it."),
|
|
463
|
+
market: z.string().optional().describe("The storefront the product is on, if the site has several."),
|
|
464
|
+
from: z
|
|
465
|
+
.string()
|
|
466
|
+
.optional()
|
|
467
|
+
.describe("Start of the window, as a date (2026-09-01) or an ISO timestamp. Default: 30 days before `to`."),
|
|
468
|
+
to: z.string().optional().describe("End of the window, inclusive. Default: now."),
|
|
469
|
+
metric: z.enum(["price", "rating", "reviewCount", "availability"]).optional().describe("What to chart (default price)."),
|
|
470
|
+
})
|
|
471
|
+
.strict(),
|
|
472
|
+
}, async (args, extra) => {
|
|
473
|
+
const client = await makeClient({ ...extra, arguments: args });
|
|
474
|
+
const m = marketOf(args.marketplace);
|
|
475
|
+
if (!m)
|
|
476
|
+
return toolError("get_price_history failed", new Error(`unknown marketplace — one of ${SLUGS}`));
|
|
477
|
+
try {
|
|
478
|
+
const res = await client.callTool("get_price_history", args);
|
|
479
|
+
const payload = structured(res);
|
|
480
|
+
return {
|
|
481
|
+
content: [{ type: "text", text: JSON.stringify(payload) }],
|
|
482
|
+
structuredContent: payload,
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
catch (err) {
|
|
486
|
+
return toolError("get_price_history failed", err);
|
|
487
|
+
}
|
|
488
|
+
});
|
|
442
489
|
server.registerTool("get_marketplace_product", {
|
|
443
490
|
title: "Get Marketplace Product",
|
|
444
491
|
_meta: viewMeta("get_marketplace_product"),
|
|
@@ -1832,6 +1832,27 @@ export const OUTPUT_SCHEMAS = {
|
|
|
1832
1832
|
})),
|
|
1833
1833
|
note: scalar(),
|
|
1834
1834
|
}),
|
|
1835
|
+
// One product's stored observations as a series (nooticr-server marketplace_history.rs), drawn by no view yet.
|
|
1836
|
+
// min/max/deltaPct are absent for availability; an unknown product answers recorded: false.
|
|
1837
|
+
get_price_history: open({
|
|
1838
|
+
recorded: scalar(),
|
|
1839
|
+
metric: scalar(),
|
|
1840
|
+
series: listOf(open({ t: scalar(), value: scalar(), currency: scalar(), priceText: scalar() })),
|
|
1841
|
+
count: scalar(),
|
|
1842
|
+
first: scalar(),
|
|
1843
|
+
last: scalar(),
|
|
1844
|
+
min: scalar(),
|
|
1845
|
+
max: scalar(),
|
|
1846
|
+
deltaPct: scalar(),
|
|
1847
|
+
currency: scalar(),
|
|
1848
|
+
mixedCurrencies: scalar(),
|
|
1849
|
+
truncated: scalar(),
|
|
1850
|
+
title: scalar(),
|
|
1851
|
+
url: scalar(),
|
|
1852
|
+
lastSeenAt: scalar(),
|
|
1853
|
+
billable: scalar(),
|
|
1854
|
+
note: scalar(),
|
|
1855
|
+
}),
|
|
1835
1856
|
get_marketplace_product: open({
|
|
1836
1857
|
...marketplaceScanShape,
|
|
1837
1858
|
product: amazonProduct.nullish().describe("The single product, also present as products[0]."),
|
package/dist/shared/tools-def.js
CHANGED
|
@@ -678,6 +678,12 @@ export const TOOL_DEFINITIONS = [
|
|
|
678
678
|
description: "What moved in a category since the run before: products that entered or left a search's results, and ones whose price or place changed. Compared from the two latest stored scans of the same marketplace and `query`, so it fetches nothing and never re-scans — run scan_marketplace_category first, and again later, to have two runs to compare. `new` and `gone` mean entered or left the results, not listed or delisted. A category scanned only once has no earlier run and says so. Free.",
|
|
679
679
|
inputSchema: z.object({ marketplace: z.string().describe("Which site the scan read."), query: z.string().describe("The category search to compare, exactly as it was scanned."), market: z.string().optional().describe("The storefront the scan read, if the site has several.") }).strict(),
|
|
680
680
|
},
|
|
681
|
+
{
|
|
682
|
+
name: "get_price_history",
|
|
683
|
+
title: "Get Price History",
|
|
684
|
+
description: "One product's price over time — or its rating, review count or availability with `metric` — from the observations stored each time the product was scanned. `marketplace` and `id` name the product the same way get_marketplace_product does; `from` and `to` take dates (default: the last 30 days). Returns the points oldest first with min, max, first, last and the percentage change from first to last. A point is stored only when something changed, so the last value held until `lastSeenAt`. Reads stored data only: it never fetches, and a product nobody has scanned yet says so (`recorded: false`) — run get_marketplace_product once to start its record. Free.",
|
|
685
|
+
inputSchema: z.object({ marketplace: z.string().describe("Which site the product is on."), id: z.string().describe("The site's own product id, or a product URL from it."), market: z.string().optional().describe("The storefront the product is on, if the site has several."), from: z.string().optional().describe("Start of the window, as a date (2026-09-01) or an ISO timestamp. Default: 30 days before `to`."), to: z.string().optional().describe("End of the window, inclusive. Default: now."), metric: z.enum(["price", "rating", "reviewCount", "availability"]).optional().describe("What to chart (default price).") }).strict(),
|
|
686
|
+
},
|
|
681
687
|
{
|
|
682
688
|
name: "get_marketplace_product",
|
|
683
689
|
title: "Get Marketplace Product",
|
package/dist/shared/tools.js
CHANGED
|
@@ -36,7 +36,7 @@ import { registerAmazonTools } from "./amazon.js";
|
|
|
36
36
|
import { registerMarketplaceTools } from "./marketplace.js";
|
|
37
37
|
import { DEFAULT_NOOTICR_SETTINGS, DEFAULT_SOCIAL_PLATFORMS, MemorySettingsStore, SETTINGS_READ_TOOL, SETTINGS_UPDATE_TOOL, settingsOwnerFromAuth, } from "./settings.js";
|
|
38
38
|
/** Current MCP server version — bumped on every deploy for traceability. */
|
|
39
|
-
export const MCP_SERVER_VERSION = "1.26.
|
|
39
|
+
export const MCP_SERVER_VERSION = "1.26.79";
|
|
40
40
|
/** MCP Apps extension identifier */
|
|
41
41
|
const UI_EXTENSION = "io.modelcontextprotocol/ui";
|
|
42
42
|
/** MIME type for MCP Apps HTML resources */
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nooticr/mcp",
|
|
3
3
|
"mcpName": "com.nooticr/mcp",
|
|
4
|
-
"version": "1.26.
|
|
4
|
+
"version": "1.26.79",
|
|
5
5
|
"description": "MCP server for nooticr - fetch, discover and understand TikTok/Instagram/YouTube/X/Reddit/LinkedIn/Weibo posts with AI (media metadata, niche discovery, brand monitoring, hook & viral analysis)",
|
|
6
6
|
"homepage": "https://mcp.nooticr.com",
|
|
7
7
|
"repository": {
|