@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 CHANGED
@@ -3,9 +3,9 @@
3
3
  ![GitHub Repo stars](https://img.shields.io/github/stars/scavio-ai/scavio-mcp?style=social)
4
4
  ![License](https://img.shields.io/github/license/scavio-ai/scavio-mcp)
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. 192 tools across 31 platforms plus Extract, one API key.
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 192 tools puts 138KB of tool definitions — roughly 35k tokens — into every session before you type anything. So the default is the surface 0.12.x already had, plus Extract: 107 tools, 65KB. Upgrading never removes a tool you were using. Everything else is one env var away: see [Choosing which tools load](#choosing-which-tools-load).
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 192 tools. Loading all of them costs 138KB of `tools/list` —
211
- roughly 35k tokens of context in every session before the user has said anything,
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, 65KB** |
221
- | `all` | every platform — **192 tools, 138KB** |
222
- | `extract,sec,g2` | just those platforms — 11 tools, 10KB |
223
- | `default,zillow,metaads` | the default set plus two more — 113 tools, 72KB |
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`, `tripadvisor`,
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) and [Home Depot](https://scavio.dev/docs/home-depot-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
- export declare function trimResponse(data: unknown): {
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
- function stripEmpty(val) {
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 filtered = val.map(stripEmpty).filter((v) => v !== undefined);
6
- return filtered.length ? filtered : undefined;
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(val)) {
12
- const clean = stripEmpty(v);
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
- export function trimResponse(data) {
23
- const trimmed = stripEmpty(data) ?? {};
24
- return { content: [{ type: "text", text: JSON.stringify(trimmed) }] };
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":"AAEA,SAAS,UAAU,CAAC,GAAc;IAChC,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IAEtE,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAgB,CAAC;QACnF,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IAChD,CAAC;IAED,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,GAAG,GAA8B,EAAE,CAAC;QAC1C,IAAI,MAAM,GAAG,KAAK,CAAC;QACnB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACzC,MAAM,KAAK,GAAG,UAAU,CAAC,CAAc,CAAC,CAAC;YACzC,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,MAAM,UAAU,YAAY,CAAC,IAAa;IACxC,MAAM,OAAO,GAAG,UAAU,CAAC,IAAiB,CAAC,IAAI,EAAE,CAAC;IACpD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;AACxE,CAAC"}
1
+ {"version":3,"file":"trim-response.js","sourceRoot":"","sources":["../../src/lib/trim-response.ts"],"names":[],"mappings":"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"}
@@ -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
- }, call("/api/v1/amazon/search"));
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,
@@ -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,EAAE,MAAM,yBAAyB,CAAC;AAEvD,6EAA6E;AAC7E,+EAA+E;AAC/E,EAAE;AACF,gFAAgF;AAChF,2EAA2E;AAC3E,iFAAiF;AACjF,8EAA8E;AAC9E,6EAA6E;AAC7E,6EAA6E;AAC7E,gFAAgF;AAChF,gFAAgF;AAChF,+EAA+E;AAC/E,iCAAiC;AACjC,EAAE;AACF,+EAA+E;AAC/E,2EAA2E;AAC3E,EAAE;AACF,gFAAgF;AAChF,+EAA+E;AAC/E,iBAAiB;AAEjB,gFAAgF;AAChF,0EAA0E;AAC1E,8EAA8E;AAC9E,MAAM,mBAAmB,GACvB,yEAAyE,CAAC;AAE5E,MAAM,YAAY,GAAG,CAAC;KACnB,MAAM,EAAE;KACR,KAAK,CAAC,eAAe,CAAC;KACtB,QAAQ,EAAE;KACV,QAAQ,CAAC,mBAAmB,CAAC,CAAC;AAEjC,MAAM,SAAS,GAAG,CAAC;KAChB,MAAM,EAAE;KACR,MAAM,CAAC,EAAE,CAAC;KACV,QAAQ,CAAC,0BAA0B,CAAC,CAAC;AAExC,MAAM,UAAU,mBAAmB,CAAC,MAAiB,EAAE,SAA6B;IAClF,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,EAAE,MAA+B,EAAE,EAAE;QACvE,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,SAAS,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAClD,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,cAAc,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,eAAe,EACf,qGAAqG,EACrG;QACE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;aAC9B,QAAQ,CAAC,gBAAgB,CAAC;QAC7B,OAAO,EAAE,YAAY;QACrB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;aACrC,QAAQ,CAAC,gBAAgB,CAAC;KAC9B,EACD,IAAI,CAAC,uBAAuB,CAAC,CAC9B,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB,sHAAsH,EACtH;QACE,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,YAAY;KACtB,EACD,IAAI,CAAC,wBAAwB,CAAC,CAC/B,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,sGAAsG,EACtG;QACE,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,YAAY;KACtB,EACD,IAAI,CAAC,uBAAuB,CAAC,CAC9B,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB,sEAAsE,EACtE,EAAE,EACF,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,SAAS,EAAE,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;YAC7D,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,cAAc,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"amazon.js","sourceRoot":"","sources":["../../src/tools/amazon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ScavioClient } from "../lib/client.js";
3
+ export declare function registerCostcoTools(server: McpServer, getClient: () => ScavioClient): void;