@nooticr/mcp 1.26.57 → 1.26.59
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 +4 -1
- package/dist/shared/backend-only.js +1 -1
- package/dist/shared/loading-plans.js +5 -0
- package/dist/shared/marketplace.js +39 -0
- package/dist/shared/output-schemas.js +36 -0
- package/dist/shared/store-read.js +82 -0
- package/dist/shared/tools-def.js +18 -0
- package/dist/shared/tools.js +4 -1
- package/package.json +1 -1
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
|
+
93 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
|
|
@@ -151,6 +151,7 @@ a `scanId` for the rest.
|
|
|
151
151
|
| `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. |
|
|
152
152
|
| `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. |
|
|
153
153
|
| `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. |
|
|
154
|
+
| `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. |
|
|
154
155
|
| `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. |
|
|
155
156
|
| `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. |
|
|
156
157
|
| `show_marketplace_category_insights` | free | The same card for the other eleven marketplaces: your read beside that site's listings and reviews, labelled with the right site, re-read from the scan by `scanId` and `marketplace` so nothing is re-typed. |
|
|
@@ -181,6 +182,8 @@ a `scanId` for the rest.
|
|
|
181
182
|
| `nooticr_login` | free | Re-link the account when a call fails with an authentication error. |
|
|
182
183
|
| `list_social_connections` | free | What you have connected and what each connection is actually allowed to do — read the account, publish a post, manage comments — as yes, no or **unknown**. "Manage comments" reports the platform's grant; no nooticr tool posts or replies to a comment. Unknown means the grant predates scope recording: treat it as "try it", not as a refusal. Also says which platforms can be linked at all, which is a smaller set than the networks nooticr reads. |
|
|
183
184
|
| `connect_social_account` | free | A link the user opens to connect one account. They approve at the provider in their own browser; nothing is connected until they do, and no credential passes through the tool or the model's context. Each call mints a fresh link — an old one does not work twice. |
|
|
185
|
+
| `connect_store` | free | A link a workspace owner or admin opens to connect an Amazon seller account or a Shopify shop. They approve at the store; nothing is connected until they do, and no credential passes through the tool. |
|
|
186
|
+
| `list_store_products` | free | Read the connected store's own catalogue: title, description, status, price, and Amazon listing issues. Read-only. |
|
|
184
187
|
| `create_product` | free | Create a product in your own workspace — the row every other own-account tool needs before it has anything to work with. Always creates in the calling session's workspace, never one you could name. `name` and `slug` are required; every other field is snake_case and read by exact key, so a camelCase `websiteUrl` lands nowhere. Writes no brand playbook. |
|
|
185
188
|
| `update_product` | free | Patch a product's fields. An omitted argument leaves its column unchanged, so this cannot blank a field by not mentioning it, and the result lists what was actually written — a misspelled field shows up as one that did not change rather than as a silent no-op. |
|
|
186
189
|
|
|
@@ -20,7 +20,7 @@ export const BACKEND_ONLY_TOOLS = {
|
|
|
20
20
|
schedule_post: "Rendering and publishing stay in the dashboard (#92).",
|
|
21
21
|
get_batch_history: "History of the dashboard's compose batches, which only exist once rendering does; stays with #92.",
|
|
22
22
|
get_latest_analysis: "Returns the dashboard's stored AI fleet-analysis verdict; the public surface sells the evidence, not a judgement of ours.",
|
|
23
|
-
propose_listing_update: "Commerce writes (nooticr-server C1 3/4) stay in the dashboard until exposing store writes to hosts is a product decision.
|
|
23
|
+
propose_listing_update: "Commerce writes (nooticr-server C1 3/4) stay in the dashboard until exposing store writes to hosts is a product decision.",
|
|
24
24
|
apply_listing_update: "Commerce writes (nooticr-server C1 3/4) stay in the dashboard until exposing store writes to hosts is a product decision; applying a change edits the merchant's live store.",
|
|
25
25
|
propose_price_change: "Commerce writes (nooticr-server C1 3/4) stay in the dashboard until exposing store writes to hosts is a product decision.",
|
|
26
26
|
apply_price_change: "Commerce writes (nooticr-server C1 3/4) stay in the dashboard until exposing store writes to hosts is a product decision; applying a change edits the merchant's live prices.",
|
|
@@ -436,6 +436,8 @@ export const LOADING_PLANS = {
|
|
|
436
436
|
steps: [],
|
|
437
437
|
free: true,
|
|
438
438
|
},
|
|
439
|
+
// Free: reads two stored scans, fetches nothing.
|
|
440
|
+
marketplace_changes: { label: "Comparing the two scans", kind: "list", n: 6, steps: [], free: true },
|
|
439
441
|
get_marketplace_product: {
|
|
440
442
|
label: "Reading the product",
|
|
441
443
|
kind: "text",
|
|
@@ -477,6 +479,9 @@ export const LOADING_PLANS = {
|
|
|
477
479
|
list_brand_watches: { label: "Reading your watches", kind: "list", n: 3, steps: [], free: true },
|
|
478
480
|
stop_brand_watch: { label: "Stopping the watch", kind: "text", n: 1, steps: [], free: true },
|
|
479
481
|
update_watch_portfolio: { label: "Updating the portfolio", kind: "text", n: 1, steps: [], free: true },
|
|
482
|
+
// ─── Store connections (store-read.ts): a link, and a read of the store's own catalogue ───
|
|
483
|
+
connect_store: { label: "Minting a store link", kind: "text", n: 1, steps: [], free: true },
|
|
484
|
+
list_store_products: { label: "Reading your store's catalogue", kind: "list", n: 3, steps: [], free: true },
|
|
480
485
|
// ─── Own-account reads: nooticr's own stored rows, never an upstream call ───
|
|
481
486
|
list_own_apps: { label: "Reading your products", kind: "list", n: 3, steps: [], free: true },
|
|
482
487
|
get_content_plan: { label: "Reading the saved plan", kind: "text", n: 1, steps: [], free: true },
|
|
@@ -400,6 +400,45 @@ export function registerMarketplaceTools(server, makeClient) {
|
|
|
400
400
|
return toolError("marketplace_scan_status failed", err);
|
|
401
401
|
}
|
|
402
402
|
});
|
|
403
|
+
server.registerTool("marketplace_changes", {
|
|
404
|
+
title: "Marketplace Changes",
|
|
405
|
+
description: "What moved in a category since the run before: products that entered or left a search's " +
|
|
406
|
+
"results, and ones whose price or place changed. Compared from the two latest stored scans " +
|
|
407
|
+
"of the same marketplace and `query`, so it fetches nothing and never re-scans — run " +
|
|
408
|
+
"scan_marketplace_category first, and again later, to have two runs to compare. `new` and " +
|
|
409
|
+
"`gone` mean entered or left the results, not listed or delisted. A category scanned only " +
|
|
410
|
+
"once has no earlier run and says so. Free.",
|
|
411
|
+
annotations: {
|
|
412
|
+
readOnlyHint: true,
|
|
413
|
+
destructiveHint: false,
|
|
414
|
+
idempotentHint: true,
|
|
415
|
+
openWorldHint: false,
|
|
416
|
+
},
|
|
417
|
+
outputSchema: OUTPUT_SCHEMAS.marketplace_changes,
|
|
418
|
+
inputSchema: z
|
|
419
|
+
.object({
|
|
420
|
+
marketplace: marketplaceArg,
|
|
421
|
+
query: z.string().describe("The category search to compare, exactly as it was scanned."),
|
|
422
|
+
market: z.string().optional().describe("The storefront the scan read, if the site has several."),
|
|
423
|
+
})
|
|
424
|
+
.strict(),
|
|
425
|
+
}, async (args, extra) => {
|
|
426
|
+
const client = await makeClient({ ...extra, arguments: args });
|
|
427
|
+
const m = marketOf(args.marketplace);
|
|
428
|
+
if (!m)
|
|
429
|
+
return toolError("marketplace_changes failed", new Error(`unknown marketplace — one of ${SLUGS}`));
|
|
430
|
+
try {
|
|
431
|
+
const res = await client.callTool("marketplace_changes", args);
|
|
432
|
+
const payload = structured(res);
|
|
433
|
+
return {
|
|
434
|
+
content: [{ type: "text", text: JSON.stringify(payload) }],
|
|
435
|
+
structuredContent: payload,
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
catch (err) {
|
|
439
|
+
return toolError("marketplace_changes failed", err);
|
|
440
|
+
}
|
|
441
|
+
});
|
|
403
442
|
server.registerTool("get_marketplace_product", {
|
|
404
443
|
title: "Get Marketplace Product",
|
|
405
444
|
_meta: viewMeta("get_marketplace_product"),
|
|
@@ -1598,6 +1598,24 @@ export const OUTPUT_SCHEMAS = {
|
|
|
1598
1598
|
connectUrl: scalar().describe("Open this in a browser to approve the connection."),
|
|
1599
1599
|
message: scalar(),
|
|
1600
1600
|
}),
|
|
1601
|
+
// Store connections (nooticr-server C1). The catalogue rows are the platform's
|
|
1602
|
+
// own shape, so only the stable fields are named.
|
|
1603
|
+
connect_store: open({
|
|
1604
|
+
platform: scalar(),
|
|
1605
|
+
connectUrl: scalar().describe("Open this in a browser to approve the connection."),
|
|
1606
|
+
message: scalar(),
|
|
1607
|
+
}),
|
|
1608
|
+
list_store_products: open({
|
|
1609
|
+
products: listOf(anyObject()),
|
|
1610
|
+
nextCursor: scalar(),
|
|
1611
|
+
status: scalar(),
|
|
1612
|
+
reportId: scalar(),
|
|
1613
|
+
poll: anyObject().nullish(),
|
|
1614
|
+
nextCall: anyObject().nullish(),
|
|
1615
|
+
needsConnection: scalar(),
|
|
1616
|
+
connections: listOf(anyObject()),
|
|
1617
|
+
message: scalar(),
|
|
1618
|
+
}),
|
|
1601
1619
|
// Marketplace. One shape for all three collection tools: a status poll
|
|
1602
1620
|
// returns exactly what the scan that started it returns, and a single
|
|
1603
1621
|
// product is a scan of one — describing them differently would be three
|
|
@@ -1611,6 +1629,24 @@ export const OUTPUT_SCHEMAS = {
|
|
|
1611
1629
|
// the result does not have to know which site it asked.
|
|
1612
1630
|
scan_marketplace_category: marketplaceScan,
|
|
1613
1631
|
marketplace_scan_status: marketplaceScan,
|
|
1632
|
+
// A diff of two stored scans, drawn by no view: the rows are the answer.
|
|
1633
|
+
marketplace_changes: open({
|
|
1634
|
+
display: scalar(),
|
|
1635
|
+
hasBaseline: scalar(),
|
|
1636
|
+
since: scalar(),
|
|
1637
|
+
takenAt: scalar(),
|
|
1638
|
+
counts: open({ new: scalar(), gone: scalar(), moved: scalar() }).nullish(),
|
|
1639
|
+
totalChanges: scalar(),
|
|
1640
|
+
rows: listOf(open({
|
|
1641
|
+
change: scalar(),
|
|
1642
|
+
id: scalar(),
|
|
1643
|
+
title: scalar(),
|
|
1644
|
+
meta: scalar(),
|
|
1645
|
+
url: scalar(),
|
|
1646
|
+
move: scalar(),
|
|
1647
|
+
})),
|
|
1648
|
+
note: scalar(),
|
|
1649
|
+
}),
|
|
1614
1650
|
get_marketplace_product: open({
|
|
1615
1651
|
...marketplaceScanShape,
|
|
1616
1652
|
product: amazonProduct.nullish().describe("The single product, also present as products[0]."),
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Store connections (nooticr-server C1): get the link a workspace owner opens to
|
|
3
|
+
* connect an Amazon seller account or a Shopify shop, and read that store's own
|
|
4
|
+
* catalogue. Both are passthroughs to the server's `POST /mcp` dispatch; the
|
|
5
|
+
* server owns the owner/admin check, the one-time link and the platform calls.
|
|
6
|
+
*
|
|
7
|
+
* The store *write* tools (propose/apply listing and price changes) are not
|
|
8
|
+
* here: they stay in BACKEND_ONLY_TOOLS until exposing them to hosts is decided.
|
|
9
|
+
* Neither tool has a view yet: a catalogue would be a table the design system
|
|
10
|
+
* has no card for.
|
|
11
|
+
*/
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
import { OUTPUT_SCHEMAS } from "./output-schemas.js";
|
|
14
|
+
function toResult(proxy) {
|
|
15
|
+
const textBlock = proxy.contentBlocks.find((c) => c.type === "text");
|
|
16
|
+
const structured = proxy.structured;
|
|
17
|
+
// No view draws structuredContent here, so the model reads it from the text.
|
|
18
|
+
const text = structured ? JSON.stringify(structured) : String(textBlock?.text ?? "");
|
|
19
|
+
return { content: [{ type: "text", text }], structuredContent: structured };
|
|
20
|
+
}
|
|
21
|
+
function failed(prefix, err) {
|
|
22
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
23
|
+
return { content: [{ type: "text", text: `${prefix}: ${msg}` }], isError: true };
|
|
24
|
+
}
|
|
25
|
+
const platform = z.enum(["amazon", "shopify"]);
|
|
26
|
+
export function registerStoreReadTools(server, makeClient) {
|
|
27
|
+
const passthrough = (name) => async (args, extra) => {
|
|
28
|
+
const client = await makeClient({ ...extra, arguments: args });
|
|
29
|
+
try {
|
|
30
|
+
return toResult(await client.callTool(name, args));
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
return failed(`${name} failed`, err);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
server.registerTool("connect_store", {
|
|
37
|
+
title: "Connect Store",
|
|
38
|
+
description: "Get a link a workspace owner or admin opens to connect an Amazon seller account " +
|
|
39
|
+
"(platform \"amazon\", optional region na/eu/fe) or a Shopify shop (platform \"shopify\", " +
|
|
40
|
+
"shop \"your-store.myshopify.com\"). Optionally appId ties the store to one product. The " +
|
|
41
|
+
"owner approves at Amazon or Shopify; nothing is connected until they do, and no " +
|
|
42
|
+
"credential passes through this tool. Nooticr only asks for access to listing copy and " +
|
|
43
|
+
"prices. Each call mints a fresh link. No cost to call.",
|
|
44
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
45
|
+
inputSchema: z
|
|
46
|
+
.object({
|
|
47
|
+
platform: platform.describe("Which store platform to connect."),
|
|
48
|
+
shop: z.string().optional().describe("Shopify shop domain, e.g. your-store.myshopify.com."),
|
|
49
|
+
region: z.enum(["na", "eu", "fe"]).optional().describe("Amazon region; defaults to na."),
|
|
50
|
+
appId: z.string().optional().describe("Product id to tie the store to."),
|
|
51
|
+
})
|
|
52
|
+
.strict(),
|
|
53
|
+
outputSchema: OUTPUT_SCHEMAS.connect_store,
|
|
54
|
+
}, passthrough("connect_store"));
|
|
55
|
+
server.registerTool("list_store_products", {
|
|
56
|
+
title: "List Store Products",
|
|
57
|
+
description: "Read the connected store's own catalogue: title, bullets, description, status, price, " +
|
|
58
|
+
"currency and Amazon listing issues. connectionId is optional when one store is " +
|
|
59
|
+
"connected; with several, the answer lists them and asks you to choose. query (Amazon: " +
|
|
60
|
+
"exact SKU; Shopify: product search), limit (up to 50), cursor from nextCursor, " +
|
|
61
|
+
"productRef to read one product by SKU or GID, includeIssues, includePricing (Amazon). " +
|
|
62
|
+
"For Amazon, source \"report\" reads the whole catalogue through a report: it answers " +
|
|
63
|
+
"status in_progress with a reportId and poll arguments until done. Read-only. No cost to call.",
|
|
64
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
65
|
+
inputSchema: z
|
|
66
|
+
.object({
|
|
67
|
+
connectionId: z.string().optional().describe("Store connection id; optional when one store is connected."),
|
|
68
|
+
platform: platform.optional(),
|
|
69
|
+
query: z.string().optional().describe("Amazon: exact SKU. Shopify: product search query."),
|
|
70
|
+
limit: z.number().int().min(1).max(50).optional(),
|
|
71
|
+
cursor: z.string().optional().describe("nextCursor from the previous page."),
|
|
72
|
+
includeIssues: z.boolean().optional(),
|
|
73
|
+
includePricing: z.boolean().optional(),
|
|
74
|
+
productRef: z.string().optional().describe("Amazon SKU or Shopify product GID to read one product."),
|
|
75
|
+
marketplaceId: z.string().optional().describe("Amazon marketplace id; defaults to the first."),
|
|
76
|
+
source: z.enum(["live", "report"]).optional(),
|
|
77
|
+
reportId: z.string().optional().describe("Report id from an in_progress answer."),
|
|
78
|
+
})
|
|
79
|
+
.strict(),
|
|
80
|
+
outputSchema: OUTPUT_SCHEMAS.list_store_products,
|
|
81
|
+
}, passthrough("list_store_products"));
|
|
82
|
+
}
|
package/dist/shared/tools-def.js
CHANGED
|
@@ -402,6 +402,18 @@ export const TOOL_DEFINITIONS = [
|
|
|
402
402
|
description: "Get a link to open so you can connect one social account. The user approves at the provider; nothing is connected until they do, and no credential ever passes through this tool. For YouTube, pass capabilities [\"manage_comments\"] to also ask for the comment-management grant. No cost to call.",
|
|
403
403
|
inputSchema: z.object({ platform: z.string().describe("Which network to connect."), influencerId: z.number().int().optional(), appId: z.number().int().optional(), capabilities: z.array(z.enum(["manage_comments"])).optional().describe("YouTube only: [\"manage_comments\"] asks for the comment-management grant.") }).strict(),
|
|
404
404
|
},
|
|
405
|
+
{
|
|
406
|
+
name: "connect_store",
|
|
407
|
+
title: "Connect Store",
|
|
408
|
+
description: "Get a link a workspace owner or admin opens to connect an Amazon seller account (platform \"amazon\", optional region na/eu/fe) or a Shopify shop (platform \"shopify\", shop \"your-store.myshopify.com\"). Optionally appId ties the store to one product. The owner approves at Amazon or Shopify; nothing is connected until they do, and no credential passes through this tool. Nooticr only asks for access to listing copy and prices. Each call mints a fresh link. No cost to call.",
|
|
409
|
+
inputSchema: z.object({ platform: z.enum(["amazon", "shopify"]).describe("Which store platform to connect."), shop: z.string().optional().describe("Shopify shop domain, e.g. your-store.myshopify.com."), region: z.enum(["na", "eu", "fe"]).optional().describe("Amazon region; defaults to na."), appId: z.string().optional().describe("Product id to tie the store to.") }).strict(),
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
name: "list_store_products",
|
|
413
|
+
title: "List Store Products",
|
|
414
|
+
description: "Read the connected store's own catalogue: title, bullets, description, status, price, currency and Amazon listing issues. connectionId is optional when one store is connected; with several, the answer lists them and asks you to choose. query (Amazon: exact SKU; Shopify: product search), limit (up to 50), cursor from nextCursor, productRef to read one product by SKU or GID, includeIssues, includePricing (Amazon). For Amazon, source \"report\" reads the whole catalogue through a report: it answers status in_progress with a reportId and poll arguments until done. Read-only. No cost to call.",
|
|
415
|
+
inputSchema: z.object({ connectionId: z.string().optional().describe("Store connection id; optional when one store is connected."), platform: z.enum(["amazon", "shopify"]).optional(), query: z.string().optional().describe("Amazon: exact SKU. Shopify: product search query."), limit: z.number().int().min(1).max(50).optional(), cursor: z.string().optional().describe("nextCursor from the previous page."), includeIssues: z.boolean().optional(), includePricing: z.boolean().optional(), productRef: z.string().optional().describe("Amazon SKU or Shopify product GID to read one product."), marketplaceId: z.string().optional().describe("Amazon marketplace id; defaults to the first."), source: z.enum(["live", "report"]).optional(), reportId: z.string().optional().describe("Report id from an in_progress answer.") }).strict(),
|
|
416
|
+
},
|
|
405
417
|
{
|
|
406
418
|
name: "answer_my_audience",
|
|
407
419
|
title: "Answer My Audience",
|
|
@@ -510,6 +522,12 @@ export const TOOL_DEFINITIONS = [
|
|
|
510
522
|
description: "Pick up a scan_marketplace_category collection that was still running, by scanId and the same marketplace — the products and reviews collected since, with the same rollup and the same instructions for reading them. Free: it is the poll scan_marketplace_category asked for, and charging for the second half of one answer would bill a wait this server chose. Call it when a scan came back incomplete, and keep calling it until it reports complete: true; only then write your read, from the full set. Do not end your turn between polls.",
|
|
511
523
|
inputSchema: z.object({ marketplace: z.string().describe("The same site the scan ran against."), scanId: z.string().describe("The scanId scan_marketplace_category returned."), waitSeconds: z.number().int().optional().describe("How long to wait for more products before answering (default 30, max 55)."), focus: z.string().optional().describe("Same optional steer as scan_marketplace_category.") }).strict(),
|
|
512
524
|
},
|
|
525
|
+
{
|
|
526
|
+
name: "marketplace_changes",
|
|
527
|
+
title: "Marketplace Changes",
|
|
528
|
+
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.",
|
|
529
|
+
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(),
|
|
530
|
+
},
|
|
513
531
|
{
|
|
514
532
|
name: "get_marketplace_product",
|
|
515
533
|
title: "Get Marketplace Product",
|
package/dist/shared/tools.js
CHANGED
|
@@ -23,6 +23,7 @@ import { registerJobTools } from "./jobs.js";
|
|
|
23
23
|
import { registerBrandWatch } from "./brand-watch.js";
|
|
24
24
|
import { registerOwnAccountTools } from "./own-account.js";
|
|
25
25
|
import { registerConnectionTools } from "./connections.js";
|
|
26
|
+
import { registerStoreReadTools } from "./store-read.js";
|
|
26
27
|
import { registerGettingStarted, SERVER_INSTRUCTIONS } from "./getting-started.js";
|
|
27
28
|
import { loadingPlansJson } from "./loading-plans.js";
|
|
28
29
|
import { registerHandoff } from "./handoff.js";
|
|
@@ -31,7 +32,7 @@ import { registerAmazonTools } from "./amazon.js";
|
|
|
31
32
|
import { registerMarketplaceTools } from "./marketplace.js";
|
|
32
33
|
import { DEFAULT_NOOTICR_SETTINGS, DEFAULT_SOCIAL_PLATFORMS, MemorySettingsStore, SETTINGS_READ_TOOL, SETTINGS_UPDATE_TOOL, settingsOwnerFromAuth, } from "./settings.js";
|
|
33
34
|
/** Current MCP server version — bumped on every deploy for traceability. */
|
|
34
|
-
export const MCP_SERVER_VERSION = "1.26.
|
|
35
|
+
export const MCP_SERVER_VERSION = "1.26.59";
|
|
35
36
|
/** MCP Apps extension identifier */
|
|
36
37
|
const UI_EXTENSION = "io.modelcontextprotocol/ui";
|
|
37
38
|
/** MIME type for MCP Apps HTML resources */
|
|
@@ -2886,6 +2887,8 @@ export function createMcpServer(rawMakeClient, opts) {
|
|
|
2886
2887
|
registerBrandWatch(server, makeClient);
|
|
2887
2888
|
registerOwnAccountTools(server, makeClient);
|
|
2888
2889
|
registerConnectionTools(server, makeClient);
|
|
2890
|
+
// Store connections (store-read.ts): the connect link and the catalogue read.
|
|
2891
|
+
registerStoreReadTools(server, makeClient);
|
|
2889
2892
|
registerGettingStarted(server, makeClient, watchStore);
|
|
2890
2893
|
// Neither fetches, neither takes a client: one formats what the model
|
|
2891
2894
|
// classified for a tracker on another server, the other draws what it scored.
|
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.59",
|
|
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": {
|