@scavio/mcp-server 0.15.5 → 0.16.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 +46 -11
- package/dist/lib/trim-platforms.d.ts +24 -0
- package/dist/lib/trim-platforms.js +196 -0
- package/dist/lib/trim-platforms.js.map +1 -0
- package/dist/lib/trim-response.d.ts +52 -1
- package/dist/lib/trim-response.js +151 -8
- package/dist/lib/trim-response.js.map +1 -1
- package/dist/tools/amazon.js +6 -3
- package/dist/tools/amazon.js.map +1 -1
- package/dist/tools/costco.d.ts +3 -0
- package/dist/tools/costco.js +166 -0
- package/dist/tools/costco.js.map +1 -0
- package/dist/tools/google.js +44 -9
- package/dist/tools/google.js.map +1 -1
- package/dist/tools/index.d.ts +5 -5
- package/dist/tools/index.js +8 -6
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/instagram.js +25 -16
- package/dist/tools/instagram.js.map +1 -1
- package/dist/tools/tiktok.js +26 -18
- package/dist/tools/tiktok.js.map +1 -1
- package/dist/tools/walmart.js +5 -3
- package/dist/tools/walmart.js.map +1 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|

|
|
4
4
|

|
|
5
5
|
|
|
6
|
-
[Scavio](https://scavio.dev) is a unified [Web Search API](https://scavio.dev/docs/search-api) and MCP server that gives AI agents web search, page extraction, and structured data from e-commerce, social, travel, jobs, real-estate, app-store, ad-library and company-filing sources.
|
|
6
|
+
[Scavio](https://scavio.dev) is a unified [Web Search API](https://scavio.dev/docs/search-api) and MCP server that gives AI agents web search, page extraction, and structured data from e-commerce, social, travel, jobs, real-estate, app-store, ad-library and company-filing sources. 205 tools across 32 platforms plus Extract, one API key.
|
|
7
7
|
|
|
8
|
-
**The 22 platforms added in 0.13.0 are opt-in.** Registering all
|
|
8
|
+
**The 22 platforms added in 0.13.0 are opt-in.** Registering all 205 tools puts 183KB of tool definitions — roughly 45k tokens — into every session before you type anything. So the default is the surface 0.12.x already had, plus Extract: 107 tools, 82KB. Upgrading never removes a tool you were using. Everything else is one env var away: see [Choosing which tools load](#choosing-which-tools-load).
|
|
9
9
|
|
|
10
10
|
## Remote MCP Server
|
|
11
11
|
|
|
@@ -207,8 +207,8 @@ Add to settings (`Cmd+,`):
|
|
|
207
207
|
|
|
208
208
|
## Choosing which tools load
|
|
209
209
|
|
|
210
|
-
Scavio exposes
|
|
211
|
-
roughly
|
|
210
|
+
Scavio exposes 205 tools. Loading all of them costs 183KB of `tools/list` —
|
|
211
|
+
roughly 45k tokens of context in every session before the user has said anything,
|
|
212
212
|
and more tools than some clients will accept at all. So the server registers a
|
|
213
213
|
curated subset by default and lets you pick the rest. The sizes below are
|
|
214
214
|
measured, not estimated: `npm run toolslist` reproduces them.
|
|
@@ -217,10 +217,10 @@ measured, not estimated: `npm run toolslist` reproduces them.
|
|
|
217
217
|
|
|
218
218
|
| Value | Registers |
|
|
219
219
|
|-------|-----------|
|
|
220
|
-
| *(unset)* or `default` | Everything 0.12.x had, plus `extract` — **107 tools,
|
|
221
|
-
| `all` | every platform — **
|
|
222
|
-
| `extract,sec,g2` | just those platforms — 11 tools,
|
|
223
|
-
| `default,zillow,metaads` | the default set plus two more — 113 tools,
|
|
220
|
+
| *(unset)* or `default` | Everything 0.12.x had, plus `extract` — **107 tools, 82KB** |
|
|
221
|
+
| `all` | every platform — **205 tools, 183KB** |
|
|
222
|
+
| `extract,sec,g2` | just those platforms — 11 tools, 12KB |
|
|
223
|
+
| `default,zillow,metaads` | the default set plus two more — 113 tools, 89KB |
|
|
224
224
|
| `none` | no platform tools, only `get_usage` |
|
|
225
225
|
|
|
226
226
|
Keys are matched case- and punctuation-insensitively, so `meta-ads`, `metaads`
|
|
@@ -232,8 +232,8 @@ tells you to call to check the server works.
|
|
|
232
232
|
|
|
233
233
|
**Platform keys:** `extract`, `google`, `youtube`, `tiktok`, `instagram`,
|
|
234
234
|
`reddit`, `x`, `linkedin`, `threads`, `kuaishou`, `amazon`, `walmart`, `ebay`,
|
|
235
|
-
`target`, `homedepot`, `tiktok-shop`, `booking`, `airbnb`,
|
|
236
|
-
`yelp`, `zillow`, `redfin`, `indeed`, `glassdoor`, `appstore`, `googleplay`,
|
|
235
|
+
`target`, `homedepot`, `costco`, `tiktok-shop`, `booking`, `airbnb`,
|
|
236
|
+
`tripadvisor`, `yelp`, `zillow`, `redfin`, `indeed`, `glassdoor`, `appstore`, `googleplay`,
|
|
237
237
|
`g2`, `capterra`, `googleads`, `metaads`, `sec`, `companieshouse`
|
|
238
238
|
|
|
239
239
|
### Local (stdio)
|
|
@@ -595,6 +595,41 @@ Kuaishou is priced per endpoint, not at a flat rate: `get_kuaishou_profile` and
|
|
|
595
595
|
|
|
596
596
|
2 credits per call. Search page size is fixed at 12 and cannot be changed. Reviews return 30 per page; `total_pages` is the last page that exists and asking past it is a 404.
|
|
597
597
|
|
|
598
|
+
### Costco
|
|
599
|
+
|
|
600
|
+
| Tool | Description |
|
|
601
|
+
|------|-------------|
|
|
602
|
+
| `search_costco` | Search by keyword or item number: online and original price, rating, member-only and stock flags, promotions, facets |
|
|
603
|
+
| `get_costco_category` | Products in a category, same filters and shape as search |
|
|
604
|
+
| `get_costco_categories` | Department list, or the full subcategory tree under one department |
|
|
605
|
+
| `get_costco_product` | Full detail for up to 20 items: description, features, specs, variants, purchase limits, delivery fee, promotion dates |
|
|
606
|
+
| `get_costco_prices` | Online vs in-warehouse price at up to 10 warehouses: discount, final price, promotion dates, per-member limits, price code |
|
|
607
|
+
| `get_costco_availability` | In-warehouse stock status for one item at up to 10 warehouses, plus pickup and same-day delivery |
|
|
608
|
+
| `get_costco_reviews` | Reviews with rating distribution and recommend count; sort, star filter, up to 100 per page |
|
|
609
|
+
| `get_costco_warehouses` | Warehouses near a US zip or coordinates: `warehouse_id`, address, hours, departments, services, gas prices |
|
|
610
|
+
| `get_costco_gas_prices` | Regular, premium and diesel prices at Costco gas stations near a location or at given warehouses |
|
|
611
|
+
| `get_costco_coupons` | The current member coupon book: item number, amount off, final price, scope, limits, valid dates |
|
|
612
|
+
| `get_costco_deals` | Deal feeds: new, while supplies last, treasure hunt, member favorites, online only, on sale |
|
|
613
|
+
| `get_costco_clearance` | Clearance and manager-markdown items at one warehouse, decoded from the shelf price ending |
|
|
614
|
+
| `get_costco_search_suggestions` | Search suggestions for a partial query, plus matching warehouses |
|
|
615
|
+
|
|
616
|
+
1 credit per call, except the multi-warehouse tools: `get_costco_prices` makes one
|
|
617
|
+
lookup per two locations (online counts as one) and `get_costco_availability` one per
|
|
618
|
+
warehouse, billed 1 credit per 5 lookups, so 10 warehouses cost 2 credits.
|
|
619
|
+
`get_costco_warehouses` and `get_costco_gas_prices` cost 2 for `country: "ca"`; gas by
|
|
620
|
+
`warehouse_ids` is 1 credit per 5 warehouses (2 per warehouse on ca).
|
|
621
|
+
|
|
622
|
+
`search_costco`, `get_costco_category` and `get_costco_deals` take `warehouse_id` to add
|
|
623
|
+
that warehouse's in-store price, stock and price code to every result. Get the id from
|
|
624
|
+
`get_costco_warehouses`. `country` is `us` (default) or `ca` everywhere except
|
|
625
|
+
`get_costco_coupons` (US only); `search_costco`, `get_costco_product` and
|
|
626
|
+
`get_costco_warehouses` also accept `uk`, `au`, `mx`, `jp`, `kr` and `tw` for keyword,
|
|
627
|
+
sort and paging only. Price codes in `get_costco_clearance` are the member-community
|
|
628
|
+
decode (.97 clearance, .00/.88 manager markdown; .49/.79/.89 special buy on request),
|
|
629
|
+
not something Costco publishes, and only items Costco lists online are covered.
|
|
630
|
+
`get_costco_coupons` returns the first 50 offers of a ~200-offer book by default; pass
|
|
631
|
+
`limit` for more.
|
|
632
|
+
|
|
598
633
|
### [Booking.com](https://scavio.dev/docs/booking-search)
|
|
599
634
|
|
|
600
635
|
| Tool | Description |
|
|
@@ -776,7 +811,7 @@ Kuaishou is priced per endpoint, not at a flat rate: `get_kuaishou_profile` and
|
|
|
776
811
|
|
|
777
812
|
- [Google Search API](https://scavio.dev/google-search-api) — SERP results, news, images, maps, and knowledge graph
|
|
778
813
|
- [Extract](https://scavio.dev/docs/extract) — read any URL as Markdown, plain text or raw HTML
|
|
779
|
-
- [Amazon Product API](https://scavio.dev/amazon-product-api) and [Walmart Product API](https://scavio.dev/walmart-product-api) — product search and details, alongside [eBay](https://scavio.dev/docs/ebay-search), [Target](https://scavio.dev/docs/target-search)
|
|
814
|
+
- [Amazon Product API](https://scavio.dev/amazon-product-api) and [Walmart Product API](https://scavio.dev/walmart-product-api) — product search and details, alongside [eBay](https://scavio.dev/docs/ebay-search), [Target](https://scavio.dev/docs/target-search), [Home Depot](https://scavio.dev/docs/home-depot-search) and Costco (per-warehouse prices, stock, gas prices, coupon book)
|
|
780
815
|
- [TikTok API](https://scavio.dev/tiktok-api), [Instagram API](https://scavio.dev/instagram-api), [Reddit API](https://scavio.dev/reddit-api), [X API](https://scavio.dev/x-api), [LinkedIn API](https://scavio.dev/linkedin-api), and [YouTube API](https://scavio.dev/youtube-transcript-api) — social and video data
|
|
781
816
|
- Travel and local — [Booking.com](https://scavio.dev/docs/booking-search), [Airbnb](https://scavio.dev/docs/airbnb-search), [Tripadvisor](https://scavio.dev/docs/tripadvisor-locations), [Yelp](https://scavio.dev/docs/yelp-search)
|
|
782
817
|
- Real estate — [Zillow](https://scavio.dev/docs/zillow-search), [Redfin](https://scavio.dev/docs/redfin-search)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-platform record projections for trimResponse (see trim-response.ts).
|
|
3
|
+
*
|
|
4
|
+
* TikTok and Instagram are the two platforms whose MCP tools pass upstream
|
|
5
|
+
* app-API records through nearly raw: a single TikTok video record has ~155
|
|
6
|
+
* keys (77KB), an Instagram media record ~130 keys (24KB). Generic rules can
|
|
7
|
+
* only shave those, so each recognised record type is projected onto the
|
|
8
|
+
* fields an agent actually uses: ids, text, author, counts, timestamps,
|
|
9
|
+
* canonical URL, one playable/display URL, and every cursor.
|
|
10
|
+
*
|
|
11
|
+
* Projection only ever REMOVES keys from a record. Paths an agent already
|
|
12
|
+
* relies on (data.aweme_list[].statistics.digg_count, video.play_addr.url_list[0],
|
|
13
|
+
* items[].caption.text, ...) keep working unchanged.
|
|
14
|
+
*
|
|
15
|
+
* Records are recognised by signature, not by path, so the same projector
|
|
16
|
+
* covers search, feeds, hashtag lists, detail and comments alike. Projectors
|
|
17
|
+
* are applied only when a tool opts in with `platform`, which is why the
|
|
18
|
+
* profile tools (a single, already-small record whose bio fields matter) do
|
|
19
|
+
* not pass it.
|
|
20
|
+
*/
|
|
21
|
+
import type { JsonObject, JsonValue } from "./trim-response.js";
|
|
22
|
+
export type Platform = "tiktok" | "instagram";
|
|
23
|
+
export declare const PLATFORM_PROJECTORS: Record<Platform, (o: JsonObject) => JsonObject>;
|
|
24
|
+
export declare const PLATFORM_PREPARE: Record<Platform, (root: JsonValue) => JsonValue>;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
const isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
2
|
+
function pick(o, keys) {
|
|
3
|
+
const out = {};
|
|
4
|
+
for (const k of keys)
|
|
5
|
+
if (k in o)
|
|
6
|
+
out[k] = o[k];
|
|
7
|
+
return out;
|
|
8
|
+
}
|
|
9
|
+
/** `{uri, url_list:[a,b,c], width, height, url_key, data_size, ...}` -> `{url_list:[a]}`. */
|
|
10
|
+
function firstUrl(m) {
|
|
11
|
+
if (!isObj(m) || !Array.isArray(m.url_list) || m.url_list.length === 0)
|
|
12
|
+
return undefined;
|
|
13
|
+
return { url_list: [m.url_list[0]] };
|
|
14
|
+
}
|
|
15
|
+
/** Share URLs carry per-request tracking params; the path is the canonical link. */
|
|
16
|
+
function stripQuery(u) {
|
|
17
|
+
return typeof u === "string" ? u.split("?")[0] : u;
|
|
18
|
+
}
|
|
19
|
+
// ---------------------------------------------------------------- TikTok
|
|
20
|
+
const TT_AWEME_KEEP = [
|
|
21
|
+
"aweme_id", "desc", "create_time", "region", "desc_language", "content_type", "aweme_type",
|
|
22
|
+
"is_top", "is_ads", "share_url", "statistics", "author", "video", "music", "text_extra",
|
|
23
|
+
"cha_list", "image_post_info", "poi_info", "item_title",
|
|
24
|
+
];
|
|
25
|
+
const TT_USER_KEEP = [
|
|
26
|
+
"uid", "sec_uid", "unique_id", "nickname", "signature", "avatar_thumb", "follower_count",
|
|
27
|
+
"following_count", "total_favorited", "aweme_count", "favoriting_count", "verification_type",
|
|
28
|
+
"custom_verify", "enterprise_verify_reason", "region", "language", "secret", "create_time",
|
|
29
|
+
"ins_id", "twitter_name", "youtube_channel_id", "youtube_channel_title", "bio_url",
|
|
30
|
+
];
|
|
31
|
+
const TT_COMMENT_KEEP = [
|
|
32
|
+
"cid", "text", "create_time", "digg_count", "reply_comment_total", "user", "aweme_id",
|
|
33
|
+
"reply_id", "reply_to_reply_id", "is_author_digged", "comment_language", "label_text",
|
|
34
|
+
"stick_position", "reply_comment",
|
|
35
|
+
];
|
|
36
|
+
function tiktokAweme(o) {
|
|
37
|
+
const out = pick(o, TT_AWEME_KEEP);
|
|
38
|
+
if ("share_url" in out)
|
|
39
|
+
out.share_url = stripQuery(out.share_url) ?? null;
|
|
40
|
+
else if (isObj(o.share_info) && typeof o.share_info.share_url === "string")
|
|
41
|
+
out.share_url = stripQuery(o.share_info.share_url) ?? null;
|
|
42
|
+
if (isObj(o.video)) {
|
|
43
|
+
const v = pick(o.video, ["duration", "width", "height", "ratio"]);
|
|
44
|
+
const cover = firstUrl(o.video.cover);
|
|
45
|
+
const play = firstUrl(o.video.play_addr);
|
|
46
|
+
if (cover)
|
|
47
|
+
v.cover = cover;
|
|
48
|
+
if (play)
|
|
49
|
+
v.play_addr = play;
|
|
50
|
+
out.video = v;
|
|
51
|
+
}
|
|
52
|
+
if (isObj(o.music)) {
|
|
53
|
+
const m = pick(o.music, ["id", "id_str", "mid", "title", "author", "owner_handle", "duration", "original", "is_original_sound"]);
|
|
54
|
+
const play = firstUrl(o.music.play_url);
|
|
55
|
+
if (play)
|
|
56
|
+
m.play_url = play;
|
|
57
|
+
out.music = m;
|
|
58
|
+
}
|
|
59
|
+
if (Array.isArray(o.text_extra)) {
|
|
60
|
+
out.text_extra = o.text_extra.map((t) => (isObj(t) ? pick(t, ["hashtag_name", "hashtag_id", "user_id", "sec_uid", "type"]) : t));
|
|
61
|
+
}
|
|
62
|
+
if (Array.isArray(o.cha_list)) {
|
|
63
|
+
out.cha_list = o.cha_list.map((c) => (isObj(c) ? pick(c, ["cid", "cha_name"]) : c));
|
|
64
|
+
}
|
|
65
|
+
if (isObj(o.image_post_info) && Array.isArray(o.image_post_info.images)) {
|
|
66
|
+
out.image_post_info = {
|
|
67
|
+
images: o.image_post_info.images.map((i) => (isObj(i) ? { display_image: firstUrl(i.display_image) ?? null } : i)),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
if (isObj(o.poi_info))
|
|
71
|
+
out.poi_info = pick(o.poi_info, ["poi_id", "poi_name"]);
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
function tiktokUser(o) {
|
|
75
|
+
const out = pick(o, TT_USER_KEEP);
|
|
76
|
+
if ("avatar_thumb" in out)
|
|
77
|
+
out.avatar_thumb = firstUrl(out.avatar_thumb) ?? null;
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
function projectTiktok(o) {
|
|
81
|
+
if ("cid" in o && "text" in o)
|
|
82
|
+
return pick(o, TT_COMMENT_KEEP);
|
|
83
|
+
if ("aweme_id" in o && ("video" in o || "author" in o || "desc" in o))
|
|
84
|
+
return tiktokAweme(o);
|
|
85
|
+
if ("sec_uid" in o && ("unique_id" in o || "nickname" in o))
|
|
86
|
+
return tiktokUser(o);
|
|
87
|
+
return o;
|
|
88
|
+
}
|
|
89
|
+
/** Envelope noise that sits beside the result list on every TikTok page. */
|
|
90
|
+
function prepareTiktok(root) {
|
|
91
|
+
if (isObj(root) && isObj(root.data)) {
|
|
92
|
+
for (const k of ["extra", "global_doodle_config", "backtrace", "feedback_type", "ad_info"])
|
|
93
|
+
delete root.data[k];
|
|
94
|
+
}
|
|
95
|
+
return root;
|
|
96
|
+
}
|
|
97
|
+
// ---------------------------------------------------------------- Instagram
|
|
98
|
+
const IG_MEDIA_KEEP = [
|
|
99
|
+
"id", "pk", "code", "shortcode", "media_type", "product_type", "is_video", "taken_at",
|
|
100
|
+
"taken_at_date", "expiring_at", "caption", "caption_text", "accessibility_caption", "title",
|
|
101
|
+
"like_count", "comment_count", "play_count", "ig_play_count", "view_count", "video_view_count",
|
|
102
|
+
"share_count", "reshare_count", "save_count", "video_duration", "is_paid_partnership", "is_pinned",
|
|
103
|
+
"user", "owner", "coauthor_producers", "usertags", "tagged_users", "sponsor_tags", "location",
|
|
104
|
+
"thumbnail_url", "display_uri", "display_url", "video_url", "image_versions2", "image_versions",
|
|
105
|
+
"video_versions", "carousel_media", "carousel_media_count",
|
|
106
|
+
];
|
|
107
|
+
const IG_USER_KEEP = ["pk", "id", "username", "full_name", "is_verified", "is_private", "profile_pic_url", "follower_count"];
|
|
108
|
+
function instagramMedia(o) {
|
|
109
|
+
const out = pick(o, IG_MEDIA_KEEP);
|
|
110
|
+
if (isObj(out.caption))
|
|
111
|
+
out.caption = pick(out.caption, ["text", "created_at"]);
|
|
112
|
+
if (isObj(out.location))
|
|
113
|
+
out.location = pick(out.location, ["pk", "name", "short_name", "city", "address", "lat", "lng"]);
|
|
114
|
+
// One display image and one video URL is enough. When the flat
|
|
115
|
+
// thumbnail_url / video_url is present the ladders are pure duplicates.
|
|
116
|
+
const hasThumb = typeof out.thumbnail_url === "string" || typeof out.display_uri === "string" || typeof out.display_url === "string";
|
|
117
|
+
if (hasThumb) {
|
|
118
|
+
delete out.image_versions2;
|
|
119
|
+
delete out.image_versions;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
if (isObj(out.image_versions2))
|
|
123
|
+
out.image_versions2 = pick(out.image_versions2, ["candidates"]);
|
|
124
|
+
if (isObj(out.image_versions))
|
|
125
|
+
out.image_versions = pick(out.image_versions, ["items", "candidates"]);
|
|
126
|
+
}
|
|
127
|
+
if (typeof out.video_url === "string")
|
|
128
|
+
delete out.video_versions;
|
|
129
|
+
else if (Array.isArray(out.video_versions) && out.video_versions.length) {
|
|
130
|
+
const v = out.video_versions[0];
|
|
131
|
+
out.video_versions = [isObj(v) ? pick(v, ["url", "width", "height"]) : v];
|
|
132
|
+
}
|
|
133
|
+
return out;
|
|
134
|
+
}
|
|
135
|
+
function projectInstagram(o) {
|
|
136
|
+
if (("pk" in o || "id" in o) && "media_type" in o && ("code" in o || "taken_at" in o || "shortcode" in o))
|
|
137
|
+
return instagramMedia(o);
|
|
138
|
+
if ("username" in o && ("pk" in o || "id" in o) && !("media_type" in o))
|
|
139
|
+
return pick(o, IG_USER_KEEP);
|
|
140
|
+
return o;
|
|
141
|
+
}
|
|
142
|
+
const IG_CURSOR_KEYS = ["page_info", "next_max_id", "more_available", "has_more", "pagination_token", "end_cursor"];
|
|
143
|
+
function findKey(node, key, depth = 0) {
|
|
144
|
+
if (depth > 6)
|
|
145
|
+
return undefined;
|
|
146
|
+
if (Array.isArray(node))
|
|
147
|
+
return undefined;
|
|
148
|
+
if (!isObj(node))
|
|
149
|
+
return undefined;
|
|
150
|
+
if (key in node && node[key] !== null)
|
|
151
|
+
return node[key];
|
|
152
|
+
for (const v of Object.values(node)) {
|
|
153
|
+
const hit = findKey(v, key, depth + 1);
|
|
154
|
+
if (hit !== undefined)
|
|
155
|
+
return hit;
|
|
156
|
+
}
|
|
157
|
+
return undefined;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Instagram list responses carry the same records two or three times: the
|
|
161
|
+
* normalized `data.items`, the raw `data.edges`, and the raw GraphQL envelope
|
|
162
|
+
* under `data.data` (e.g. data.data.xdt_api__v1__clips__user__connection_v2.edges).
|
|
163
|
+
* Keep `items`, hoist any cursor that only lived in the raw copy, drop the rest.
|
|
164
|
+
*/
|
|
165
|
+
function prepareInstagram(root) {
|
|
166
|
+
if (!isObj(root) || !isObj(root.data))
|
|
167
|
+
return root;
|
|
168
|
+
const d = root.data;
|
|
169
|
+
if (!Array.isArray(d.items))
|
|
170
|
+
return root;
|
|
171
|
+
if (isObj(d.data)) {
|
|
172
|
+
for (const k of IG_CURSOR_KEYS) {
|
|
173
|
+
if (k === "end_cursor" && isObj(d.page_info))
|
|
174
|
+
continue;
|
|
175
|
+
if (d[k] === undefined || d[k] === null) {
|
|
176
|
+
const hit = findKey(d.data, k);
|
|
177
|
+
if (hit !== undefined)
|
|
178
|
+
d[k] = hit;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
delete d.data;
|
|
182
|
+
}
|
|
183
|
+
if (Array.isArray(d.edges))
|
|
184
|
+
delete d.edges;
|
|
185
|
+
return root;
|
|
186
|
+
}
|
|
187
|
+
// ---------------------------------------------------------------- registry
|
|
188
|
+
export const PLATFORM_PROJECTORS = {
|
|
189
|
+
tiktok: projectTiktok,
|
|
190
|
+
instagram: projectInstagram,
|
|
191
|
+
};
|
|
192
|
+
export const PLATFORM_PREPARE = {
|
|
193
|
+
tiktok: prepareTiktok,
|
|
194
|
+
instagram: prepareInstagram,
|
|
195
|
+
};
|
|
196
|
+
//# sourceMappingURL=trim-platforms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trim-platforms.js","sourceRoot":"","sources":["../../src/lib/trim-platforms.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,55 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Shapes an API response for a model's context window.
|
|
3
|
+
*
|
|
4
|
+
* The REST API returns upstream JSON close to raw, which is right for code and
|
|
5
|
+
* wrong for an agent: a 3-video TikTok search was 225KB, a 3-post Instagram
|
|
6
|
+
* page 291KB, a Google Shopping page 294KB. Almost all of it is media ladders
|
|
7
|
+
* (the same video at five bitrates, the same avatar at five sizes, three CDN
|
|
8
|
+
* mirrors of each URL), inline base64 thumbnails, DASH XML, tracking blobs and
|
|
9
|
+
* session cookies. None of it helps an agent answer a question, and every byte
|
|
10
|
+
* is paid for in context.
|
|
11
|
+
*
|
|
12
|
+
* Everything here is MCP-only. The REST API response is untouched.
|
|
13
|
+
*
|
|
14
|
+
* Rules, in the order they run:
|
|
15
|
+
* 1. limit - result lists named in `listKeys` are sliced to `limit`,
|
|
16
|
+
* and the cut is reported in a top-level `_truncated` note
|
|
17
|
+
* so the model knows there was more.
|
|
18
|
+
* 2. platform - a platform's record projector (src/lib/trim-platforms.ts)
|
|
19
|
+
* keeps the agent-useful fields of each recognised record.
|
|
20
|
+
* Ids, cursors and has_more flags are never dropped.
|
|
21
|
+
* 3. generic - anywhere in the tree: known-noise keys are dropped, CDN
|
|
22
|
+
* mirror lists keep one URL, media-variant ladders keep one
|
|
23
|
+
* variant, inline data: URIs and XML manifests are dropped.
|
|
24
|
+
* 4. stripEmpty - null, "", [] and {} are removed (the original behaviour).
|
|
25
|
+
*
|
|
26
|
+
* Deterministic and offline: no network, no randomness, no clock.
|
|
27
|
+
*/
|
|
28
|
+
import { type Platform } from "./trim-platforms.js";
|
|
29
|
+
export type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
30
|
+
[key: string]: JsonValue;
|
|
31
|
+
};
|
|
32
|
+
export type JsonObject = {
|
|
33
|
+
[key: string]: JsonValue;
|
|
34
|
+
};
|
|
35
|
+
export type { Platform };
|
|
36
|
+
export interface TrimOptions {
|
|
37
|
+
/** Max items kept in each result list named by `listKeys`. */
|
|
38
|
+
limit?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Keys of the result lists `limit` applies to. Looked up in the top three
|
|
41
|
+
* object levels only (root, root.data, root.data.data), never deep, so a
|
|
42
|
+
* nested `comments` inside a record is not mistaken for the page's list.
|
|
43
|
+
*/
|
|
44
|
+
listKeys?: string[];
|
|
45
|
+
/** Apply that platform's record projections. */
|
|
46
|
+
platform?: Platform;
|
|
47
|
+
/** Extra keys dropped wherever they appear, for one tool's known noise. */
|
|
48
|
+
dropKeys?: string[];
|
|
49
|
+
}
|
|
50
|
+
/** Shape a parsed API response for the model. Exported for scripts/trim-check.mjs. */
|
|
51
|
+
export declare function shapeResponse(data: unknown, opts?: TrimOptions): JsonValue;
|
|
52
|
+
export declare function trimResponse(data: unknown, opts?: TrimOptions): {
|
|
2
53
|
content: [{
|
|
3
54
|
type: "text";
|
|
4
55
|
text: string;
|
|
@@ -1,15 +1,116 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Shapes an API response for a model's context window.
|
|
3
|
+
*
|
|
4
|
+
* The REST API returns upstream JSON close to raw, which is right for code and
|
|
5
|
+
* wrong for an agent: a 3-video TikTok search was 225KB, a 3-post Instagram
|
|
6
|
+
* page 291KB, a Google Shopping page 294KB. Almost all of it is media ladders
|
|
7
|
+
* (the same video at five bitrates, the same avatar at five sizes, three CDN
|
|
8
|
+
* mirrors of each URL), inline base64 thumbnails, DASH XML, tracking blobs and
|
|
9
|
+
* session cookies. None of it helps an agent answer a question, and every byte
|
|
10
|
+
* is paid for in context.
|
|
11
|
+
*
|
|
12
|
+
* Everything here is MCP-only. The REST API response is untouched.
|
|
13
|
+
*
|
|
14
|
+
* Rules, in the order they run:
|
|
15
|
+
* 1. limit - result lists named in `listKeys` are sliced to `limit`,
|
|
16
|
+
* and the cut is reported in a top-level `_truncated` note
|
|
17
|
+
* so the model knows there was more.
|
|
18
|
+
* 2. platform - a platform's record projector (src/lib/trim-platforms.ts)
|
|
19
|
+
* keeps the agent-useful fields of each recognised record.
|
|
20
|
+
* Ids, cursors and has_more flags are never dropped.
|
|
21
|
+
* 3. generic - anywhere in the tree: known-noise keys are dropped, CDN
|
|
22
|
+
* mirror lists keep one URL, media-variant ladders keep one
|
|
23
|
+
* variant, inline data: URIs and XML manifests are dropped.
|
|
24
|
+
* 4. stripEmpty - null, "", [] and {} are removed (the original behaviour).
|
|
25
|
+
*
|
|
26
|
+
* Deterministic and offline: no network, no randomness, no clock.
|
|
27
|
+
*/
|
|
28
|
+
import { PLATFORM_PREPARE, PLATFORM_PROJECTORS } from "./trim-platforms.js";
|
|
29
|
+
/**
|
|
30
|
+
* Keys that never carry agent-useful data on any platform we serve. Dropped
|
|
31
|
+
* at any depth. Kept deliberately short: a key belongs here only if it is
|
|
32
|
+
* noise everywhere it can appear, otherwise it goes in a platform projector
|
|
33
|
+
* or a tool's `dropKeys`.
|
|
34
|
+
*/
|
|
35
|
+
const GLOBAL_DROP_KEYS = new Set([
|
|
36
|
+
// Session / tracking echoed back from the upstream request.
|
|
37
|
+
"cookie",
|
|
38
|
+
"tt_chain_token",
|
|
39
|
+
"log_pb",
|
|
40
|
+
// Streaming manifests and bitrate ladders: XML or many-URL blobs that only
|
|
41
|
+
// a video player can use. One playable URL survives elsewhere in the record.
|
|
42
|
+
"video_dash_manifest",
|
|
43
|
+
"dash_manifest",
|
|
44
|
+
"bit_rate",
|
|
45
|
+
"bit_rate_audio",
|
|
46
|
+
"misc_download_addrs",
|
|
47
|
+
// Instagram ML embedding vector and video scrubber sprite sheets.
|
|
48
|
+
"xray_visual_2025_100d_embed",
|
|
49
|
+
"scrubber_spritesheet_info_candidates",
|
|
50
|
+
]);
|
|
51
|
+
/** Lists of variants of one asset: keep the first (the largest / default). */
|
|
52
|
+
const FIRST_ONLY_KEYS = new Set(["url_list", "candidates", "video_versions"]);
|
|
53
|
+
const DATA_URI_MIN = 200;
|
|
54
|
+
function isPlainObject(v) {
|
|
55
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Inline base64 images (Google Shopping thumbnails are 4-5KB each) and inline
|
|
59
|
+
* DASH manifests. Generic XML is deliberately NOT matched: extract and SEC
|
|
60
|
+
* can legitimately return an XML document as their payload.
|
|
61
|
+
*/
|
|
62
|
+
function isDroppableString(s) {
|
|
63
|
+
if (s.length >= DATA_URI_MIN && s.startsWith("data:"))
|
|
64
|
+
return true;
|
|
65
|
+
return s.length > 1000 && s.slice(0, 200).includes("<MPD");
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The same image at several sizes, e.g. YouTube community posts list
|
|
69
|
+
* `...=s288-c...`, `...=s400-c...` through `...=s5464-c...` for ONE image.
|
|
70
|
+
* Grouped by the URL up to the size token; one URL kept per group, the
|
|
71
|
+
* largest at or under 1080px (or the smallest when all are larger).
|
|
72
|
+
*/
|
|
73
|
+
const SIZE_TOKEN = /=s(\d+)(?=[-&]|$)/;
|
|
74
|
+
function collapseSizeLadder(arr) {
|
|
75
|
+
if (arr.length < 3 || !arr.every((v) => typeof v === "string" && v.startsWith("http") && SIZE_TOKEN.test(v)))
|
|
76
|
+
return arr;
|
|
77
|
+
const groups = new Map();
|
|
78
|
+
for (const url of arr) {
|
|
79
|
+
const m = SIZE_TOKEN.exec(url);
|
|
80
|
+
const base = url.slice(0, m.index);
|
|
81
|
+
const list = groups.get(base) ?? [];
|
|
82
|
+
list.push({ url, size: Number(m[1]) });
|
|
83
|
+
groups.set(base, list);
|
|
84
|
+
}
|
|
85
|
+
if (groups.size === arr.length)
|
|
86
|
+
return arr;
|
|
87
|
+
const out = [];
|
|
88
|
+
for (const list of groups.values()) {
|
|
89
|
+
const fit = list.filter((x) => x.size <= 1080).sort((a, b) => b.size - a.size)[0];
|
|
90
|
+
out.push((fit ?? list.sort((a, b) => a.size - b.size)[0]).url);
|
|
91
|
+
}
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
function compact(val, drop, project) {
|
|
2
95
|
if (val === null || val === undefined || val === "")
|
|
3
96
|
return undefined;
|
|
97
|
+
if (typeof val === "string")
|
|
98
|
+
return isDroppableString(val) ? undefined : val;
|
|
4
99
|
if (Array.isArray(val)) {
|
|
5
|
-
const
|
|
6
|
-
|
|
100
|
+
const out = collapseSizeLadder(val)
|
|
101
|
+
.map((v) => compact(v, drop, project))
|
|
102
|
+
.filter((v) => v !== undefined);
|
|
103
|
+
return out.length ? out : undefined;
|
|
7
104
|
}
|
|
8
105
|
if (typeof val === "object") {
|
|
106
|
+
const obj = project ? project(val) : val;
|
|
9
107
|
const out = {};
|
|
10
108
|
let hasKey = false;
|
|
11
|
-
for (const [k, v] of Object.entries(
|
|
12
|
-
|
|
109
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
110
|
+
if (drop.has(k))
|
|
111
|
+
continue;
|
|
112
|
+
const src = FIRST_ONLY_KEYS.has(k) && Array.isArray(v) && v.length > 1 ? [v[0]] : v;
|
|
113
|
+
const clean = compact(src, drop, project);
|
|
13
114
|
if (clean !== undefined) {
|
|
14
115
|
out[k] = clean;
|
|
15
116
|
hasKey = true;
|
|
@@ -19,8 +120,50 @@ function stripEmpty(val) {
|
|
|
19
120
|
}
|
|
20
121
|
return val;
|
|
21
122
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
123
|
+
/**
|
|
124
|
+
* Slice the named result lists in the top three object levels. Returns
|
|
125
|
+
* "path: kept of received" notes for the lists that were cut.
|
|
126
|
+
*/
|
|
127
|
+
function applyLimit(root, keys, limit) {
|
|
128
|
+
const notes = {};
|
|
129
|
+
const want = new Set(keys);
|
|
130
|
+
const visit = (node, path, depth) => {
|
|
131
|
+
if (!isPlainObject(node) || depth > 2)
|
|
132
|
+
return;
|
|
133
|
+
for (const [k, v] of Object.entries(node)) {
|
|
134
|
+
const p = path ? `${path}.${k}` : k;
|
|
135
|
+
if (want.has(k) && Array.isArray(v)) {
|
|
136
|
+
if (v.length > limit) {
|
|
137
|
+
notes[p] = `${limit} of ${v.length} returned; raise count/limit for the rest (a next-page cursor or page continues after all ${v.length})`;
|
|
138
|
+
node[k] = v.slice(0, limit);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
else if (isPlainObject(v)) {
|
|
142
|
+
visit(v, p, depth + 1);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
visit(root, "", 0);
|
|
147
|
+
return notes;
|
|
148
|
+
}
|
|
149
|
+
/** Shape a parsed API response for the model. Exported for scripts/trim-check.mjs. */
|
|
150
|
+
export function shapeResponse(data, opts = {}) {
|
|
151
|
+
// Work on a copy: limit and the platform prepare step mutate.
|
|
152
|
+
let root = structuredClone(data ?? {});
|
|
153
|
+
let notes = {};
|
|
154
|
+
if (opts.platform)
|
|
155
|
+
root = PLATFORM_PREPARE[opts.platform]?.(root) ?? root;
|
|
156
|
+
if (opts.limit !== undefined && opts.listKeys?.length)
|
|
157
|
+
notes = applyLimit(root, opts.listKeys, opts.limit);
|
|
158
|
+
const drop = opts.dropKeys?.length ? new Set([...GLOBAL_DROP_KEYS, ...opts.dropKeys]) : GLOBAL_DROP_KEYS;
|
|
159
|
+
const project = opts.platform ? PLATFORM_PROJECTORS[opts.platform] : undefined;
|
|
160
|
+
const out = (compact(root, drop, project) ?? {});
|
|
161
|
+
if (Object.keys(notes).length && isPlainObject(out)) {
|
|
162
|
+
return { ...out, _truncated: notes };
|
|
163
|
+
}
|
|
164
|
+
return out;
|
|
165
|
+
}
|
|
166
|
+
export function trimResponse(data, opts = {}) {
|
|
167
|
+
return { content: [{ type: "text", text: JSON.stringify(shapeResponse(data, opts)) }] };
|
|
25
168
|
}
|
|
26
169
|
//# sourceMappingURL=trim-response.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trim-response.js","sourceRoot":"","sources":["../../src/lib/trim-response.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"trim-response.js","sourceRoot":"","sources":["../../src/lib/trim-response.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAiB,MAAM,qBAAqB,CAAC;AAsB3F;;;;;GAKG;AACH,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAS;IACvC,4DAA4D;IAC5D,QAAQ;IACR,gBAAgB;IAChB,QAAQ;IACR,2EAA2E;IAC3E,6EAA6E;IAC7E,qBAAqB;IACrB,eAAe;IACf,UAAU;IACV,gBAAgB;IAChB,qBAAqB;IACrB,kEAAkE;IAClE,6BAA6B;IAC7B,sCAAsC;CACvC,CAAC,CAAC;AAEH,8EAA8E;AAC9E,MAAM,eAAe,GAAG,IAAI,GAAG,CAAS,CAAC,UAAU,EAAE,YAAY,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAEtF,MAAM,YAAY,GAAG,GAAG,CAAC;AAEzB,SAAS,aAAa,CAAC,CAAU;IAC/B,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AAED;;;;GAIG;AACH,SAAS,iBAAiB,CAAC,CAAS;IAClC,IAAI,CAAC,CAAC,MAAM,IAAI,YAAY,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACnE,OAAO,CAAC,CAAC,MAAM,GAAG,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,GAAG,mBAAmB,CAAC;AACvC,SAAS,kBAAkB,CAAC,GAAgB;IAC1C,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,GAAG,CAAC;IACzH,MAAM,MAAM,GAAG,IAAI,GAAG,EAA2C,CAAC;IAClE,KAAK,MAAM,GAAG,IAAI,GAAe,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAE,CAAC;QAChC,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACpC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACvC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACzB,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,KAAK,GAAG,CAAC,MAAM;QAAE,OAAO,GAAG,CAAC;IAC3C,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAClF,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,OAAO,CAAC,GAAc,EAAE,IAAiB,EAAE,OAAuC;IACzF,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IAEtE,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC;IAE7E,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,kBAAkB,CAAC,GAAG,CAAC;aAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;aACrC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAgB,CAAC;QACjD,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IACtC,CAAC;IAED,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QACzC,MAAM,GAAG,GAAe,EAAE,CAAC;QAC3B,IAAI,MAAM,GAAG,KAAK,CAAC;QACnB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACzC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAE,SAAS;YAC1B,MAAM,GAAG,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACpF,MAAM,KAAK,GAAG,OAAO,CAAC,GAAgB,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;YACvD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;gBACf,MAAM,GAAG,IAAI,CAAC;YAChB,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IAClC,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;GAGG;AACH,SAAS,UAAU,CAAC,IAAe,EAAE,IAAc,EAAE,KAAa;IAChE,MAAM,KAAK,GAA2B,EAAE,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;IAC3B,MAAM,KAAK,GAAG,CAAC,IAAe,EAAE,IAAY,EAAE,KAAa,EAAE,EAAE;QAC7D,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,KAAK,GAAG,CAAC;YAAE,OAAO;QAC9C,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1C,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACpC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpC,IAAI,CAAC,CAAC,MAAM,GAAG,KAAK,EAAE,CAAC;oBACrB,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,OAAO,CAAC,CAAC,MAAM,6FAA6F,CAAC,CAAC,MAAM,GAAG,CAAC;oBAC3I,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC;iBAAM,IAAI,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5B,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IACnB,OAAO,KAAK,CAAC;AACf,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,aAAa,CAAC,IAAa,EAAE,OAAoB,EAAE;IACjE,8DAA8D;IAC9D,IAAI,IAAI,GAAG,eAAe,CAAC,IAAI,IAAI,EAAE,CAAc,CAAC;IAEpD,IAAI,KAAK,GAA2B,EAAE,CAAC;IACvC,IAAI,IAAI,CAAC,QAAQ;QAAE,IAAI,GAAG,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;IAC1E,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,EAAE,MAAM;QAAE,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAE3G,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,gBAAgB,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC;IACzG,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/E,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAc,CAAC;IAE9D,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,IAAI,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;QACpD,OAAO,EAAE,GAAG,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IACvC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAa,EAAE,OAAoB,EAAE;IAChE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AAC1F,CAAC"}
|
package/dist/tools/amazon.js
CHANGED
|
@@ -35,10 +35,10 @@ const asinField = z
|
|
|
35
35
|
.length(10)
|
|
36
36
|
.describe("ASIN, e.g. 'B09V3KXJPB'.");
|
|
37
37
|
export function registerAmazonTools(server, getClient) {
|
|
38
|
-
const call = (path) => async (params) => {
|
|
38
|
+
const call = (path, opts) => async (params) => {
|
|
39
39
|
try {
|
|
40
40
|
const data = await getClient().post(path, params);
|
|
41
|
-
return trimResponse(data);
|
|
41
|
+
return trimResponse(data, opts);
|
|
42
42
|
}
|
|
43
43
|
catch (err) {
|
|
44
44
|
return handleApiError(err);
|
|
@@ -50,7 +50,10 @@ export function registerAmazonTools(server, getClient) {
|
|
|
50
50
|
country: countryField,
|
|
51
51
|
page: z.number().int().min(1).optional()
|
|
52
52
|
.describe("Page, 1-based."),
|
|
53
|
-
},
|
|
53
|
+
},
|
|
54
|
+
// data.filters is ~60% of a search page: refinement links for filters
|
|
55
|
+
// this tool cannot apply (no category/price params). Dropped from MCP output.
|
|
56
|
+
call("/api/v1/amazon/search", { dropKeys: ["filters"] }));
|
|
54
57
|
server.tool("get_amazon_product", `Full Amazon product page for an ASIN. Price is buy-box price; use get_amazon_offers for competing sellers. 1 credit.`, {
|
|
55
58
|
asin: asinField,
|
|
56
59
|
country: countryField,
|
package/dist/tools/amazon.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"amazon.js","sourceRoot":"","sources":["../../src/tools/amazon.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"amazon.js","sourceRoot":"","sources":["../../src/tools/amazon.ts"],"names":[],"mappings":"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"}
|