mcp-scraper 0.18.0 → 0.19.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.
Files changed (41) hide show
  1. package/README.md +2 -2
  2. package/dist/bin/api-server.cjs +448 -74
  3. package/dist/bin/api-server.cjs.map +1 -1
  4. package/dist/bin/api-server.js +2 -2
  5. package/dist/bin/mcp-scraper-cli.cjs +1 -1
  6. package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
  7. package/dist/bin/mcp-scraper-cli.js +1 -1
  8. package/dist/bin/mcp-scraper-install.cjs +2 -2
  9. package/dist/bin/mcp-scraper-install.cjs.map +1 -1
  10. package/dist/bin/mcp-scraper-install.js +2 -2
  11. package/dist/bin/mcp-stdio-server.cjs +2137 -1778
  12. package/dist/bin/mcp-stdio-server.cjs.map +1 -1
  13. package/dist/bin/mcp-stdio-server.js +5 -4
  14. package/dist/bin/mcp-stdio-server.js.map +1 -1
  15. package/dist/bin/paa-harvest.js +2 -2
  16. package/dist/{chunk-RMPPYKUV.js → chunk-2HDMYW4B.js} +7 -218
  17. package/dist/chunk-2HDMYW4B.js.map +1 -0
  18. package/dist/chunk-D7ZT27HY.js +244 -0
  19. package/dist/chunk-D7ZT27HY.js.map +1 -0
  20. package/dist/{chunk-FMEDPBIV.js → chunk-O2S5TOCG.js} +383 -22
  21. package/dist/chunk-O2S5TOCG.js.map +1 -0
  22. package/dist/chunk-OQHYDW4Q.js +7 -0
  23. package/dist/chunk-OQHYDW4Q.js.map +1 -0
  24. package/dist/{chunk-BX5RCOG5.js → chunk-Q44DN6T2.js} +2 -2
  25. package/dist/{chunk-BX5RCOG5.js.map → chunk-Q44DN6T2.js.map} +1 -1
  26. package/dist/index.js +4 -3
  27. package/dist/index.js.map +1 -1
  28. package/dist/{server-MQDCAR6I.js → server-VWXDE64Y.js} +69 -59
  29. package/dist/server-VWXDE64Y.js.map +1 -0
  30. package/dist/{worker-JQTS437L.js → worker-AM2DHUWG.js} +6 -6
  31. package/docs/mcp-tool-manifest.generated.json +401 -10
  32. package/docs/specs/meta-ad-creative-media-resolution-spec.md +31 -0
  33. package/package.json +1 -1
  34. package/dist/chunk-FMEDPBIV.js.map +0 -1
  35. package/dist/chunk-HPV4VOQX.js +0 -27
  36. package/dist/chunk-HPV4VOQX.js.map +0 -1
  37. package/dist/chunk-RLWCHLV3.js +0 -7
  38. package/dist/chunk-RLWCHLV3.js.map +0 -1
  39. package/dist/chunk-RMPPYKUV.js.map +0 -1
  40. package/dist/server-MQDCAR6I.js.map +0 -1
  41. /package/dist/{worker-JQTS437L.js.map → worker-AM2DHUWG.js.map} +0 -0
@@ -5,12 +5,12 @@ import {
5
5
  serializeHarvestProblem
6
6
  } from "./chunk-HE2LQPJ2.js";
7
7
  import {
8
- harvest,
9
- runWithCostContext
10
- } from "./chunk-RMPPYKUV.js";
8
+ harvest
9
+ } from "./chunk-2HDMYW4B.js";
11
10
  import {
12
- browserServiceApiKey
13
- } from "./chunk-HPV4VOQX.js";
11
+ browserServiceApiKey,
12
+ runWithCostContext
13
+ } from "./chunk-D7ZT27HY.js";
14
14
  import "./chunk-K443GQY5.js";
15
15
  import "./chunk-XGIPATLV.js";
16
16
  import {
@@ -132,4 +132,4 @@ export {
132
132
  startWorker,
133
133
  tickOnce
134
134
  };
135
- //# sourceMappingURL=worker-JQTS437L.js.map
135
+ //# sourceMappingURL=worker-AM2DHUWG.js.map
@@ -1,12 +1,12 @@
1
1
  {
2
- "generatedAt": "2026-07-13T01:12:59.720Z",
2
+ "generatedAt": "2026-07-13T04:02:37.913Z",
3
3
  "generatedFrom": "dist/bin/mcp-stdio-server.js",
4
4
  "serverInfo": {
5
5
  "name": "mcp-scraper",
6
- "version": "0.18.0"
6
+ "version": "0.19.0"
7
7
  },
8
8
  "counts": {
9
- "unified_stdio": 157
9
+ "unified_stdio": 158
10
10
  },
11
11
  "surfaces": {
12
12
  "unified_stdio": [
@@ -114,6 +114,7 @@
114
114
  "memory-search",
115
115
  "memory-suggest",
116
116
  "memory-upload",
117
+ "meta_ad_creative_media",
117
118
  "my-mentions",
118
119
  "pause-scheduled-action",
119
120
  "poll-channel",
@@ -7154,14 +7155,14 @@
7154
7155
  {
7155
7156
  "name": "facebook_ad_transcribe",
7156
7157
  "title": "Facebook Ad Transcription",
7157
- "description": "Transcribe audio from a Facebook ad video CDN URL returned by facebook_page_intel. Use only that direct videoUrl value do not pass public Facebook post/reel/share URLs (use facebook_video_transcribe for those).",
7158
+ "description": "Transcribe a direct Meta/Facebook CDN video source returned by facebook_page_intel or meta_ad_creative_media. CDN sources can expire, so use them immediately. Do not pass public post/reel/share URLs; use facebook_video_transcribe for those. For a paused/account-owned ad, start with meta_ad_creative_media: it selects the direct Graph source when available and otherwise returns the effective organic-post candidate.",
7158
7159
  "inputSchema": {
7159
7160
  "type": "object",
7160
7161
  "properties": {
7161
7162
  "videoUrl": {
7162
7163
  "type": "string",
7163
7164
  "format": "uri",
7164
- "description": "Direct Facebook CDN video URL from facebook_page_intel. Do not pass a public post/reel/share URL use facebook_video_transcribe for those."
7165
+ "description": "Direct Meta/Facebook CDN video URL from facebook_page_intel or meta_ad_creative_media. Use transient sources immediately. Do not pass a public post/reel/share URL—use facebook_video_transcribe for those."
7165
7166
  }
7166
7167
  },
7167
7168
  "required": [
@@ -7217,6 +7218,65 @@
7217
7218
  "additionalProperties": false
7218
7219
  }
7219
7220
  },
7221
+ "transcriptSignal": {
7222
+ "type": "object",
7223
+ "properties": {
7224
+ "status": {
7225
+ "type": "string",
7226
+ "enum": [
7227
+ "speech_detected",
7228
+ "low_speech_signal",
7229
+ "empty"
7230
+ ]
7231
+ },
7232
+ "speechDetected": {
7233
+ "type": "boolean"
7234
+ },
7235
+ "confidence": {
7236
+ "type": "string",
7237
+ "enum": [
7238
+ "medium",
7239
+ "low"
7240
+ ]
7241
+ },
7242
+ "basis": {
7243
+ "type": "string",
7244
+ "const": "transcript_word_count_and_timing"
7245
+ },
7246
+ "mediaDurationSec": {
7247
+ "type": [
7248
+ "number",
7249
+ "null"
7250
+ ]
7251
+ },
7252
+ "wordsPerMinute": {
7253
+ "type": [
7254
+ "number",
7255
+ "null"
7256
+ ]
7257
+ },
7258
+ "retryRecommended": {
7259
+ "type": "boolean"
7260
+ },
7261
+ "warnings": {
7262
+ "type": "array",
7263
+ "items": {
7264
+ "type": "string"
7265
+ }
7266
+ }
7267
+ },
7268
+ "required": [
7269
+ "status",
7270
+ "speechDetected",
7271
+ "confidence",
7272
+ "basis",
7273
+ "mediaDurationSec",
7274
+ "wordsPerMinute",
7275
+ "retryRecommended",
7276
+ "warnings"
7277
+ ],
7278
+ "additionalProperties": false
7279
+ },
7220
7280
  "resolvedInputs": {
7221
7281
  "type": "object",
7222
7282
  "properties": {
@@ -7238,6 +7298,7 @@
7238
7298
  "durationMs",
7239
7299
  "transcriptText",
7240
7300
  "chunks",
7301
+ "transcriptSignal",
7241
7302
  "resolvedInputs"
7242
7303
  ],
7243
7304
  "additionalProperties": false,
@@ -7257,7 +7318,7 @@
7257
7318
  {
7258
7319
  "name": "facebook_page_intel",
7259
7320
  "title": "Facebook Advertiser Ad Intel",
7260
- "description": "Harvest ads from a Facebook advertiser: copy, creative angles, CTAs, and direct video URLs ready for facebook_ad_transcribe. Accepts pageId, libraryId, or a brand/advertiser name.",
7321
+ "description": "Harvest public Ad Library creatives. Prefer exact pageId/libraryId; query is broad keyword discovery and can mix unrelated advertisers, so inspect matchConfidence/warnings before analysis. Paused or inactive non-political ads may be absent from Ad Library—use meta_ad_creative_media with the connected ad account for those. Direct Ad Library videoUrl values go to facebook_ad_transcribe.",
7261
7322
  "inputSchema": {
7262
7323
  "type": "object",
7263
7324
  "properties": {
@@ -7271,7 +7332,7 @@
7271
7332
  },
7272
7333
  "query": {
7273
7334
  "type": "string",
7274
- "description": "Advertiser or brand name when pageId/libraryId is not known. One of pageId, libraryId, or query is required."
7335
+ "description": "Broad Ad Library keyword discovery when pageId/libraryId is not known. Results can mix unrelated advertisers; inspect matchConfidence, matchedAdvertisers, and warnings before analysis. One of pageId, libraryId, or query is required."
7275
7336
  },
7276
7337
  "maxAds": {
7277
7338
  "type": "integer",
@@ -7300,6 +7361,51 @@
7300
7361
  "null"
7301
7362
  ]
7302
7363
  },
7364
+ "inputMode": {
7365
+ "type": "string",
7366
+ "enum": [
7367
+ "pageId",
7368
+ "libraryId",
7369
+ "query"
7370
+ ]
7371
+ },
7372
+ "matchConfidence": {
7373
+ "type": "string",
7374
+ "enum": [
7375
+ "high",
7376
+ "medium",
7377
+ "low"
7378
+ ]
7379
+ },
7380
+ "matchReason": {
7381
+ "type": "string"
7382
+ },
7383
+ "warnings": {
7384
+ "type": "array",
7385
+ "items": {
7386
+ "type": "string"
7387
+ }
7388
+ },
7389
+ "matchedAdvertisers": {
7390
+ "type": "array",
7391
+ "items": {
7392
+ "type": "object",
7393
+ "properties": {
7394
+ "name": {
7395
+ "type": "string"
7396
+ },
7397
+ "adCount": {
7398
+ "type": "integer",
7399
+ "minimum": 0
7400
+ }
7401
+ },
7402
+ "required": [
7403
+ "name",
7404
+ "adCount"
7405
+ ],
7406
+ "additionalProperties": false
7407
+ }
7408
+ },
7303
7409
  "totalAds": {
7304
7410
  "type": "integer",
7305
7411
  "minimum": 0
@@ -7389,6 +7495,11 @@
7389
7495
  },
7390
7496
  "required": [
7391
7497
  "advertiserName",
7498
+ "inputMode",
7499
+ "matchConfidence",
7500
+ "matchReason",
7501
+ "warnings",
7502
+ "matchedAdvertisers",
7392
7503
  "totalAds",
7393
7504
  "activeCount",
7394
7505
  "videoCount",
@@ -7412,14 +7523,14 @@
7412
7523
  {
7413
7524
  "name": "facebook_video_transcribe",
7414
7525
  "title": "Facebook Organic Video Transcription",
7415
- "description": "Transcribe audio from an organic Facebook reel/video/post/share URL (including fb.watch). Renders the page, selects the best public CDN MP4, and returns the transcript plus resolved video metadata.",
7526
+ "description": "Transcribe audio from a public Facebook reel/video/post/share URL (including fb.watch). Renders the public page, selects the best progressive MP4, and returns transcript plus resolved metadata and a low-speech signal. For a connected paused ad, use meta_ad_creative_media first; pass its public post/permalink candidate here only when no direct Graph source is available. Dark/unpublished ads may not have a public route.",
7416
7527
  "inputSchema": {
7417
7528
  "type": "object",
7418
7529
  "properties": {
7419
7530
  "url": {
7420
7531
  "type": "string",
7421
7532
  "format": "uri",
7422
- "description": "Organic Facebook reel/video/watch/post/share URL from facebook.com, m.facebook.com, or fb.watch."
7533
+ "description": "Public Facebook reel/video/watch/post/share URL from facebook.com, m.facebook.com, or fb.watch. For connected account ads, get the correct public candidate from meta_ad_creative_media instead of guessing URL structure."
7423
7534
  },
7424
7535
  "quality": {
7425
7536
  "type": "string",
@@ -7514,6 +7625,65 @@
7514
7625
  ],
7515
7626
  "additionalProperties": false
7516
7627
  }
7628
+ },
7629
+ "transcriptSignal": {
7630
+ "type": "object",
7631
+ "properties": {
7632
+ "status": {
7633
+ "type": "string",
7634
+ "enum": [
7635
+ "speech_detected",
7636
+ "low_speech_signal",
7637
+ "empty"
7638
+ ]
7639
+ },
7640
+ "speechDetected": {
7641
+ "type": "boolean"
7642
+ },
7643
+ "confidence": {
7644
+ "type": "string",
7645
+ "enum": [
7646
+ "medium",
7647
+ "low"
7648
+ ]
7649
+ },
7650
+ "basis": {
7651
+ "type": "string",
7652
+ "const": "transcript_word_count_and_timing"
7653
+ },
7654
+ "mediaDurationSec": {
7655
+ "type": [
7656
+ "number",
7657
+ "null"
7658
+ ]
7659
+ },
7660
+ "wordsPerMinute": {
7661
+ "type": [
7662
+ "number",
7663
+ "null"
7664
+ ]
7665
+ },
7666
+ "retryRecommended": {
7667
+ "type": "boolean"
7668
+ },
7669
+ "warnings": {
7670
+ "type": "array",
7671
+ "items": {
7672
+ "type": "string"
7673
+ }
7674
+ }
7675
+ },
7676
+ "required": [
7677
+ "status",
7678
+ "speechDetected",
7679
+ "confidence",
7680
+ "basis",
7681
+ "mediaDurationSec",
7682
+ "wordsPerMinute",
7683
+ "retryRecommended",
7684
+ "warnings"
7685
+ ],
7686
+ "additionalProperties": false
7517
7687
  }
7518
7688
  },
7519
7689
  "required": [
@@ -7528,7 +7698,8 @@
7528
7698
  "wordCount",
7529
7699
  "chunkCount",
7530
7700
  "transcriptText",
7531
- "chunks"
7701
+ "chunks",
7702
+ "transcriptSignal"
7532
7703
  ],
7533
7704
  "additionalProperties": false,
7534
7705
  "$schema": "http://json-schema.org/draft-07/schema#"
@@ -13295,6 +13466,226 @@
13295
13466
  "taskSupport": "forbidden"
13296
13467
  }
13297
13468
  },
13469
+ {
13470
+ "name": "meta_ad_creative_media",
13471
+ "title": "View Meta Ad Creative Media",
13472
+ "description": "Preferred connected-account path for viewing a Meta ad creative, especially paused or dark ads that may be absent from Ad Library. Given a tenant-owned Meta connectionId and adId, resolves the ad, creative, effective story/post candidate, image assets, video assets, and transient Graph playback source. Bounded creative images are returned as actual MCP image content for vision-capable clients. For video, follow the returned exact nextActions with facebook_ad_transcribe when Graph returned a direct source, facebook_video_transcribe when only a public post/video candidate is available, or video_frame_analysis for visual breakdown. This tool is read-only and does not itself spend transcription/analysis credits.",
13473
+ "inputSchema": {
13474
+ "type": "object",
13475
+ "properties": {
13476
+ "connectionId": {
13477
+ "type": "string",
13478
+ "minLength": 1,
13479
+ "description": "Tenant-owned Meta Marketing connectionId from list_service_connections."
13480
+ },
13481
+ "adId": {
13482
+ "type": "string",
13483
+ "pattern": "^\\d{5,30}$",
13484
+ "description": "Meta ad ID from the connected ad account. This is not an Ad Library archive ID."
13485
+ },
13486
+ "imageMode": {
13487
+ "type": "string",
13488
+ "enum": [
13489
+ "inline_preview",
13490
+ "resource_only",
13491
+ "none"
13492
+ ],
13493
+ "default": "inline_preview",
13494
+ "description": "inline_preview returns bounded MCP image content that a vision-capable client can inspect. resource_only returns descriptors/URLs only. none skips image delivery."
13495
+ },
13496
+ "maxInlineImages": {
13497
+ "type": "integer",
13498
+ "minimum": 1,
13499
+ "maximum": 4,
13500
+ "default": 2,
13501
+ "description": "Maximum creative image/thumbnail previews to attach as MCP image blocks. Default 2; maximum 4."
13502
+ }
13503
+ },
13504
+ "required": [
13505
+ "connectionId",
13506
+ "adId"
13507
+ ],
13508
+ "additionalProperties": false,
13509
+ "$schema": "http://json-schema.org/draft-07/schema#"
13510
+ },
13511
+ "outputSchema": {
13512
+ "type": "object",
13513
+ "properties": {
13514
+ "ok": {
13515
+ "type": "boolean"
13516
+ },
13517
+ "adId": {
13518
+ "type": "string"
13519
+ },
13520
+ "adName": {
13521
+ "type": [
13522
+ "string",
13523
+ "null"
13524
+ ]
13525
+ },
13526
+ "adAccountId": {
13527
+ "$ref": "#/properties/adName"
13528
+ },
13529
+ "creativeId": {
13530
+ "type": "string"
13531
+ },
13532
+ "creativeName": {
13533
+ "$ref": "#/properties/adName"
13534
+ },
13535
+ "effectiveObjectStoryId": {
13536
+ "$ref": "#/properties/adName"
13537
+ },
13538
+ "sourceFacebookPostId": {
13539
+ "$ref": "#/properties/adName"
13540
+ },
13541
+ "objectStoryId": {
13542
+ "$ref": "#/properties/adName"
13543
+ },
13544
+ "pageId": {
13545
+ "$ref": "#/properties/adName"
13546
+ },
13547
+ "postId": {
13548
+ "$ref": "#/properties/adName"
13549
+ },
13550
+ "publicPostCandidateUrl": {
13551
+ "$ref": "#/properties/adName"
13552
+ },
13553
+ "publicPostStatus": {
13554
+ "type": "string",
13555
+ "const": "unverified"
13556
+ },
13557
+ "mediaType": {
13558
+ "type": "string",
13559
+ "enum": [
13560
+ "image",
13561
+ "video",
13562
+ "carousel",
13563
+ "mixed",
13564
+ "unknown"
13565
+ ]
13566
+ },
13567
+ "images": {
13568
+ "type": "array",
13569
+ "items": {
13570
+ "type": "object",
13571
+ "additionalProperties": {}
13572
+ }
13573
+ },
13574
+ "videos": {
13575
+ "type": "array",
13576
+ "items": {
13577
+ "type": "object",
13578
+ "additionalProperties": {}
13579
+ }
13580
+ },
13581
+ "inlineImages": {
13582
+ "type": "array",
13583
+ "items": {
13584
+ "type": "object",
13585
+ "properties": {
13586
+ "sourceUrl": {
13587
+ "type": "string",
13588
+ "format": "uri"
13589
+ },
13590
+ "mimeType": {
13591
+ "type": "string"
13592
+ },
13593
+ "bytes": {
13594
+ "type": "integer",
13595
+ "minimum": 0
13596
+ },
13597
+ "contentIndex": {
13598
+ "type": "integer",
13599
+ "minimum": 1
13600
+ }
13601
+ },
13602
+ "required": [
13603
+ "sourceUrl",
13604
+ "mimeType",
13605
+ "bytes",
13606
+ "contentIndex"
13607
+ ],
13608
+ "additionalProperties": false
13609
+ }
13610
+ },
13611
+ "nextActions": {
13612
+ "type": "array",
13613
+ "items": {
13614
+ "type": "object",
13615
+ "properties": {
13616
+ "tool": {
13617
+ "type": "string",
13618
+ "enum": [
13619
+ "facebook_ad_transcribe",
13620
+ "facebook_video_transcribe",
13621
+ "video_frame_analysis"
13622
+ ]
13623
+ },
13624
+ "args": {
13625
+ "type": "object",
13626
+ "additionalProperties": {}
13627
+ },
13628
+ "reason": {
13629
+ "type": "string"
13630
+ }
13631
+ },
13632
+ "required": [
13633
+ "tool",
13634
+ "args",
13635
+ "reason"
13636
+ ],
13637
+ "additionalProperties": false
13638
+ }
13639
+ },
13640
+ "warnings": {
13641
+ "type": "array",
13642
+ "items": {
13643
+ "type": "string"
13644
+ }
13645
+ },
13646
+ "limitations": {
13647
+ "type": "array",
13648
+ "items": {
13649
+ "type": "string"
13650
+ }
13651
+ }
13652
+ },
13653
+ "required": [
13654
+ "ok",
13655
+ "adId",
13656
+ "adName",
13657
+ "adAccountId",
13658
+ "creativeId",
13659
+ "creativeName",
13660
+ "effectiveObjectStoryId",
13661
+ "sourceFacebookPostId",
13662
+ "objectStoryId",
13663
+ "pageId",
13664
+ "postId",
13665
+ "publicPostCandidateUrl",
13666
+ "publicPostStatus",
13667
+ "mediaType",
13668
+ "images",
13669
+ "videos",
13670
+ "inlineImages",
13671
+ "nextActions",
13672
+ "warnings",
13673
+ "limitations"
13674
+ ],
13675
+ "additionalProperties": false,
13676
+ "$schema": "http://json-schema.org/draft-07/schema#"
13677
+ },
13678
+ "annotations": {
13679
+ "title": "View Meta Ad Creative Media",
13680
+ "readOnlyHint": true,
13681
+ "destructiveHint": false,
13682
+ "idempotentHint": false,
13683
+ "openWorldHint": true
13684
+ },
13685
+ "execution": {
13686
+ "taskSupport": "forbidden"
13687
+ }
13688
+ },
13298
13689
  {
13299
13690
  "name": "my-mentions",
13300
13691
  "title": "My Mentions",
@@ -0,0 +1,31 @@
1
+ # Canonical Build Spec — Meta Ad Creative Media Resolution
2
+
3
+ - **Request:** Replace the brittle manual path from a connected Meta ad-account ad to visible creative images, playable/transcribable video, and trustworthy analysis signals. Preserve the generic connected-service tools, but make the correct path directly discoverable and callable from the external MCP and scheduled Mastra agents.
4
+ - **Lane:** MCP Build using Mastra, with a provider-native Nango read primitive and an external MCP composition tool.
5
+ - **Capability:** `meta_ad_creative_media` for media buyers, ad directors, analysts, and agents. Given a tenant-owned Meta connection plus an `adId` or creative reference, return the resolved creative media, render bounded images as MCP image content, and optionally transcribe or start frame analysis for the video.
6
+ - **Inputs:** This report; the MCP Scraper, scheduler, Nango integration, and SDK repositories; current Meta Graph API behavior; current MCP content/result specification; existing `facebook_page_intel`, `facebook_ad_transcribe`, `facebook_video_transcribe`, `video_frame_analysis`, `get-ad`, `get-ad-creative`, `get-ad-image`, and `get-ad-video` implementations.
7
+ - **Missing Context:** None that blocks implementation. Default behavior is read-only resolution with image inclusion. Transcription and frame analysis are explicit opt-ins because they spend credits; ad mutations remain outside this tool.
8
+ - **Evidence Plan:** Inspect current source and live schemas; verify Meta media fields against primary sources; verify MCP image content against the protocol/SDK; test a connected Meta ad when a safe fixture or user-owned ad ID is available; never run a write operation during verification.
9
+ - **Target Runtime:** `mcp-scraper` hosted MCP and npm stdio package; `mcp-scraper-scheduler` on Vercel/Mastra; source-controlled Nango functions deployed to the Meta Marketing integration; generated Node/Python/CLI/cURL SDK contracts.
10
+ - **Agents:** Existing scheduled-action Mastra agent receives the provider-native resolver through its per-run connection toolset. No new supervisor or model route is required; creative interpretation remains with the calling vision-capable model.
11
+ - **Skills:** Existing MCP Scraper and Mastra operating guidance. No new workspace skill is required.
12
+ - **Workflows:** Resolve ad and creative deterministically; collect bounded media descriptors; derive durable organic post/reel candidates; hydrate image/video metadata; attach safe image bytes; optionally call the appropriate transcription route or start the existing asynchronous video-frame analysis workflow.
13
+ - **Tools:**
14
+ - Provider read: `resolve-ad-creative-media` in the Meta Nango integration.
15
+ - External MCP composition: `meta_ad_creative_media`.
16
+ - Existing lower-level tools remain available and cross-reference the new path.
17
+ - **MCP:** `meta_ad_creative_media` returns text plus structured content. Successfully fetched creative images are additional MCP `image` content blocks with MIME type and base64 data. Videos remain URL/metadata plus transcript or asynchronous analysis receipt; raw video is not embedded in context.
18
+ - **Data Shape:** Stable media descriptor with ad/creative IDs, account/page/post IDs, public post URL, media type, image assets, video assets, selected transcription route, transcript signal, warnings, and next actions. Image content indices map descriptors to MCP content blocks.
19
+ - **Signals:** Not required. Video frame analysis continues through its existing asynchronous status tool.
20
+ - **Background Tasks:** Resolution and transcription are foreground bounded calls. Deep video analysis uses the existing asynchronous `video_frame_analysis` run/status path.
21
+ - **Guardrails:** Tenant ownership and live provider policy; read-only provider function; explicit opt-in for credit-spending work; SSRF-safe HTTPS image fetching; Meta/CDN host allowlist; redirect validation; MIME allowlist; per-image and image-count limits; no tokens or signed query strings in logs; untrusted-provider-data labeling; action switch is not required for reads.
22
+ - **Observability:** Existing MCP/API request logging, provider call logs, transcription cost telemetry, frame-analysis run IDs, plus structured warnings and route selection.
23
+ - **Enforcement:** Nango compile/source tests; resolver mapping tests; MCP registration/schema tests; image-fetch safety tests; transcript-signal tests; fuzzy advertiser-match warning tests; scheduler policy/binding tests; generated-manifest and SDK parity; local/remote MCP discovery and safe connected-account smoke test.
24
+ - **Done Contract:**
25
+ 1. A vision-capable MCP client receives actual image content for a connected Meta ad creative without manually fetching a URL.
26
+ 2. A paused ad with `effectiveObjectStoryId` produces a public post candidate and the correct organic transcription route automatically.
27
+ 3. Video-only/dark creatives return the best provider source available or an explicit non-playable limitation, never ambiguous partial success.
28
+ 4. Transcript results include a low-signal assessment and actionable warning.
29
+ 5. Query-based Ad Library results disclose match confidence and mixed-advertiser risk.
30
+ 6. The capability exists in the actual MCP, Mastra scheduled toolsets, Vercel production, npm, MCPB, and generated SDK contracts.
31
+ - **Receipt:** Report shipped tool names, callable surfaces, deployment/package versions, test evidence, live safe-read evidence, image delivery result, transcription routing result, and any Meta/provider limitations.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-scraper",
3
- "version": "0.18.0",
3
+ "version": "0.19.0",
4
4
  "description": "MCP server for MCP Scraper web intelligence tools",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",