meta-ads-mcp 0.4.8__py3-none-any.whl → 0.5.0__py3-none-any.whl
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.
- meta_ads_mcp/__init__.py +1 -1
- meta_ads_mcp/core/ads.py +49 -10
- {meta_ads_mcp-0.4.8.dist-info → meta_ads_mcp-0.5.0.dist-info}/METADATA +1 -1
- {meta_ads_mcp-0.4.8.dist-info → meta_ads_mcp-0.5.0.dist-info}/RECORD +7 -7
- {meta_ads_mcp-0.4.8.dist-info → meta_ads_mcp-0.5.0.dist-info}/WHEEL +0 -0
- {meta_ads_mcp-0.4.8.dist-info → meta_ads_mcp-0.5.0.dist-info}/entry_points.txt +0 -0
- {meta_ads_mcp-0.4.8.dist-info → meta_ads_mcp-0.5.0.dist-info}/licenses/LICENSE +0 -0
meta_ads_mcp/__init__.py
CHANGED
meta_ads_mcp/core/ads.py
CHANGED
|
@@ -250,11 +250,9 @@ async def get_ad_image(access_token: str = None, ad_id: str = None) -> Image:
|
|
|
250
250
|
|
|
251
251
|
if not image_hashes:
|
|
252
252
|
# If no hashes found, try to extract from the first creative we found in the API
|
|
253
|
-
#
|
|
253
|
+
# and also check for direct URLs as fallback
|
|
254
254
|
creative_json = await get_ad_creatives(access_token=access_token, ad_id=ad_id)
|
|
255
|
-
|
|
256
|
-
creative_wrapper = json.loads(creative_json)
|
|
257
|
-
creative_data = json.loads(creative_wrapper["data"])
|
|
255
|
+
creative_data = json.loads(creative_json)
|
|
258
256
|
|
|
259
257
|
# Try to extract hash from data array
|
|
260
258
|
if "data" in creative_data and creative_data["data"]:
|
|
@@ -272,9 +270,52 @@ async def get_ad_image(access_token: str = None, ad_id: str = None) -> Image:
|
|
|
272
270
|
images = creative["asset_feed_spec"]["images"]
|
|
273
271
|
if images and len(images) > 0 and "hash" in images[0]:
|
|
274
272
|
image_hashes.append(images[0]["hash"])
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
273
|
+
|
|
274
|
+
# If still no image hashes found, try direct URL fallback approach
|
|
275
|
+
if not image_hashes:
|
|
276
|
+
print("No image hashes found, trying direct URL fallback...")
|
|
277
|
+
|
|
278
|
+
image_url = None
|
|
279
|
+
if "data" in creative_data and creative_data["data"]:
|
|
280
|
+
creative = creative_data["data"][0]
|
|
281
|
+
|
|
282
|
+
# Try image_urls_for_viewing first (usually higher quality)
|
|
283
|
+
if "image_urls_for_viewing" in creative and creative["image_urls_for_viewing"]:
|
|
284
|
+
image_url = creative["image_urls_for_viewing"][0]
|
|
285
|
+
print(f"Using image_urls_for_viewing: {image_url}")
|
|
286
|
+
# Fall back to thumbnail_url
|
|
287
|
+
elif "thumbnail_url" in creative and creative["thumbnail_url"]:
|
|
288
|
+
image_url = creative["thumbnail_url"]
|
|
289
|
+
print(f"Using thumbnail_url: {image_url}")
|
|
290
|
+
|
|
291
|
+
if not image_url:
|
|
292
|
+
return "Error: No image URLs found in creative"
|
|
293
|
+
|
|
294
|
+
# Download the image directly
|
|
295
|
+
print(f"Downloading image from direct URL: {image_url}")
|
|
296
|
+
image_bytes = await download_image(image_url)
|
|
297
|
+
|
|
298
|
+
if not image_bytes:
|
|
299
|
+
return "Error: Failed to download image from direct URL"
|
|
300
|
+
|
|
301
|
+
try:
|
|
302
|
+
# Convert bytes to PIL Image
|
|
303
|
+
img = PILImage.open(io.BytesIO(image_bytes))
|
|
304
|
+
|
|
305
|
+
# Convert to RGB if needed
|
|
306
|
+
if img.mode != "RGB":
|
|
307
|
+
img = img.convert("RGB")
|
|
308
|
+
|
|
309
|
+
# Create a byte stream of the image data
|
|
310
|
+
byte_arr = io.BytesIO()
|
|
311
|
+
img.save(byte_arr, format="JPEG")
|
|
312
|
+
img_bytes = byte_arr.getvalue()
|
|
313
|
+
|
|
314
|
+
# Return as an Image object that LLM can directly analyze
|
|
315
|
+
return Image(data=img_bytes, format="jpeg")
|
|
316
|
+
|
|
317
|
+
except Exception as e:
|
|
318
|
+
return f"Error processing image from direct URL: {str(e)}"
|
|
278
319
|
|
|
279
320
|
print(f"Found image hashes: {image_hashes}")
|
|
280
321
|
|
|
@@ -393,9 +434,7 @@ async def save_ad_image_locally(access_token: str = None, ad_id: str = None, out
|
|
|
393
434
|
if not image_hashes:
|
|
394
435
|
# Fallback attempt (as in get_ad_image)
|
|
395
436
|
creative_json = await get_ad_creatives(ad_id=ad_id, access_token=access_token) # Ensure ad_id is passed correctly
|
|
396
|
-
|
|
397
|
-
creative_wrapper = json.loads(creative_json)
|
|
398
|
-
creative_data_list = json.loads(creative_wrapper["data"])
|
|
437
|
+
creative_data_list = json.loads(creative_json)
|
|
399
438
|
if 'data' in creative_data_list and creative_data_list['data']:
|
|
400
439
|
first_creative = creative_data_list['data'][0]
|
|
401
440
|
if 'object_story_spec' in first_creative and 'link_data' in first_creative['object_story_spec'] and 'image_hash' in first_creative['object_story_spec']['link_data']:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meta-ads-mcp
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: Model Context Protocol (MCP) plugin for interacting with Meta Ads API
|
|
5
5
|
Project-URL: Homepage, https://github.com/pipeboard-co/meta-ads-mcp
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/pipeboard-co/meta-ads-mcp/issues
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
meta_ads_mcp/__init__.py,sha256=
|
|
1
|
+
meta_ads_mcp/__init__.py,sha256=sEcedZMAxKadL65GY8HWRyv7PPaCxZ1QrVMtUMaCeh0,1182
|
|
2
2
|
meta_ads_mcp/__main__.py,sha256=XaQt3iXftG_7f0Zu7Wop9SeFgrD2WBn0EQOaPMc27d8,207
|
|
3
3
|
meta_ads_mcp/core/__init__.py,sha256=XVJjMOfdgnqxy3k8vCn2PCf7za8fMk4BdgJGiSFCVZY,1209
|
|
4
4
|
meta_ads_mcp/core/accounts.py,sha256=Nmp7lPxO9wmq25jWV7_H0LIqnEbBhpCVBlLGW2HUaq0,2277
|
|
5
|
-
meta_ads_mcp/core/ads.py,sha256=
|
|
5
|
+
meta_ads_mcp/core/ads.py,sha256=aaK70mgfhBJRXr4cdkKag5mjYzvHuHpRttJvTMzPk4Y,36156
|
|
6
6
|
meta_ads_mcp/core/ads_library.py,sha256=onStn9UkRqYDC60gOPS-iKDtP1plz6DygUb7hUZ0Jw8,2807
|
|
7
7
|
meta_ads_mcp/core/adsets.py,sha256=k76rm3rkhEebUzvBnM_QaVktrzGTKvTJOtWbBd6s3i8,10399
|
|
8
8
|
meta_ads_mcp/core/api.py,sha256=aAzM6Q75VQOFXtr5D-mDmBRhxWK4wsiODsJYnR3mpDI,14994
|
|
@@ -19,8 +19,8 @@ meta_ads_mcp/core/reports.py,sha256=Dv3hfsPOR7IZ9WrYrKd_6SNgZl-USIphg7knva3UYAw,
|
|
|
19
19
|
meta_ads_mcp/core/resources.py,sha256=-zIIfZulpo76vcKv6jhAlQq91cR2SZ3cjYZt3ek3x0w,1236
|
|
20
20
|
meta_ads_mcp/core/server.py,sha256=mmhtcyB7h1aO6jK4njLztPdAebPDmc3mhA7DksR1nlY,17583
|
|
21
21
|
meta_ads_mcp/core/utils.py,sha256=ofKUhyo-5SZoJVuBeTVFPPQCffk0UKpwmDMrd8qQxNc,8715
|
|
22
|
-
meta_ads_mcp-0.
|
|
23
|
-
meta_ads_mcp-0.
|
|
24
|
-
meta_ads_mcp-0.
|
|
25
|
-
meta_ads_mcp-0.
|
|
26
|
-
meta_ads_mcp-0.
|
|
22
|
+
meta_ads_mcp-0.5.0.dist-info/METADATA,sha256=o0vClv8CNhB8eXp9a7ZAnCBKVDo77S_EPBrvV52dMC0,17580
|
|
23
|
+
meta_ads_mcp-0.5.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
24
|
+
meta_ads_mcp-0.5.0.dist-info/entry_points.txt,sha256=Dv2RkoBjRJBqj6CyhwqGIiwPCD-SCL1-7B9-zmVRuv0,57
|
|
25
|
+
meta_ads_mcp-0.5.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
26
|
+
meta_ads_mcp-0.5.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|